1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
class Ajde_Db_Adapter_Mysql extends Ajde_Db_Adapter_Abstract |
4
|
|
|
{ |
5
|
|
|
protected $_connection = null; |
6
|
|
|
protected $_dbname = null; |
7
|
|
|
|
8
|
|
|
public static $_cache = []; |
9
|
|
|
|
10
|
|
|
public function __construct($dsn, $user, $password) |
11
|
|
|
{ |
12
|
|
|
$dsnString = 'mysql:'; |
13
|
|
|
foreach ($dsn as $k => $v) { |
14
|
|
|
if ($k === 'dbname') { |
15
|
|
|
$this->_dbname = $v; |
16
|
|
|
} |
17
|
|
|
$dsnString .= $k.'='.$v.';'; |
18
|
|
|
} |
19
|
|
|
parent::__construct( |
20
|
|
|
$dsnString, |
21
|
|
|
$user, |
22
|
|
|
$password, |
23
|
|
|
[ |
24
|
|
|
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', // Modern, please |
25
|
|
|
PDO::ATTR_EMULATE_PREPARES => true, // Better caching |
26
|
|
|
] |
27
|
|
|
); |
28
|
|
|
} |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @return PDO |
32
|
|
|
*/ |
33
|
|
|
public function getConnection() |
34
|
|
|
{ |
35
|
|
|
return $this->_connection; |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
public static function getCache($sql) |
39
|
|
|
{ |
40
|
|
|
if (array_key_exists($sql, self::$_cache)) { |
41
|
|
|
return self::$_cache[$sql]; |
42
|
|
|
} else { |
43
|
|
|
return; |
44
|
|
|
} |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
public static function saveCache($sql, $result) |
48
|
|
|
{ |
49
|
|
|
self::$_cache[$sql] = $result; |
50
|
|
|
|
51
|
|
|
return $result; |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
public function getTableStructure($tableName) |
55
|
|
|
{ |
56
|
|
|
$sql = 'SHOW FULL COLUMNS FROM '.$tableName; |
57
|
|
|
$cache = self::getCache($sql); |
58
|
|
|
if (isset($cache)) { |
59
|
|
|
return $cache; |
60
|
|
|
} |
61
|
|
|
$statement = $this->getConnection()->query($sql); |
62
|
|
|
|
63
|
|
|
return self::saveCache($sql, $statement->fetchAll()); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
View Code Duplication |
public function getForeignKey($childTable, $childColumn) |
|
|
|
|
67
|
|
|
{ |
68
|
|
|
$sql = sprintf('SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE COLUMN_NAME = %s AND TABLE_NAME = %s AND TABLE_SCHEMA = %s', |
69
|
|
|
$this->getConnection()->quote($childColumn), |
70
|
|
|
$this->getConnection()->quote($childTable), |
71
|
|
|
$this->getConnection()->quote($this->_dbname) |
72
|
|
|
); |
73
|
|
|
$cache = self::getCache($sql); |
74
|
|
|
if (isset($cache)) { |
75
|
|
|
return $cache; |
76
|
|
|
} |
77
|
|
|
$statement = $this->getConnection()->query($sql); |
78
|
|
|
|
79
|
|
|
return self::saveCache($sql, $statement->fetch()); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
View Code Duplication |
public function getParents($childTable) |
|
|
|
|
83
|
|
|
{ |
84
|
|
|
$sql = sprintf('SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_NAME = %s AND TABLE_SCHEMA = %s', |
85
|
|
|
$this->getConnection()->quote($childTable), |
86
|
|
|
$this->getConnection()->quote($this->_dbname) |
87
|
|
|
); |
88
|
|
|
$cache = self::getCache($sql); |
89
|
|
|
if (isset($cache)) { |
90
|
|
|
return $cache; |
91
|
|
|
} |
92
|
|
|
$statement = $this->getConnection()->query($sql); |
93
|
|
|
|
94
|
|
|
return self::saveCache($sql, $statement->fetchAll()); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
public static function getFieldType($type) |
98
|
|
|
{ |
99
|
|
|
// TODO: Quite naive, rough implementation |
100
|
|
|
// @see http://dev.mysql.com/doc/refman/5.0/en/data-types.html |
101
|
|
|
|
102
|
|
|
$types = [ |
103
|
|
|
Ajde_Db::FIELD_TYPE_NUMERIC => 'tinyint smallint mediumint int bigint decimal float double real bit boolean serial', |
104
|
|
|
Ajde_Db::FIELD_TYPE_TEXT => 'char varchar tinytext mediumtext text longtext binary varbinary tinyblob mediumblob blob longblob', |
105
|
|
|
Ajde_Db::FIELD_TYPE_DATE => 'date datetime timestamp time year', |
106
|
|
|
Ajde_Db::FIELD_TYPE_ENUM => 'enum set', |
107
|
|
|
Ajde_Db::FIELD_TYPE_SPATIAL => 'geometry point linestring polygon multipoint multilinestring multipolygon geometrycollection', |
108
|
|
|
]; |
109
|
|
|
|
110
|
|
|
// Get normalized type |
111
|
|
|
//$typeName = Ajde_Db::FIELD_TYPE_STRING; |
112
|
|
|
$typeName = $type; |
113
|
|
|
$start = strpos($type, '('); |
114
|
|
|
$mysqlName = $start > 0 ? trim(substr($type, 0, $start)) : $type; |
115
|
|
|
foreach ($types as $typeKey => $haystack) { |
116
|
|
|
if (substr_count($haystack, $mysqlName) > 0) { |
117
|
|
|
$typeName = $typeKey; |
118
|
|
|
break; |
119
|
|
|
} |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
// Get length/values |
123
|
|
|
$length = strpos($type, ')') - $start; |
124
|
|
|
$typeLength = $start > 0 ? trim(substr($type, $start + 1, $length - 1)) : null; |
125
|
|
|
|
126
|
|
|
// TODO: precision and limits |
127
|
|
|
return [ |
128
|
|
|
'type' => $typeName, |
129
|
|
|
'length' => $typeLength, |
130
|
|
|
]; |
131
|
|
|
} |
132
|
|
|
} |
133
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.