Mysql.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. <?php
  2. Lib::loadClass('Core_StorageBase');
  3. Lib::loadClass('Core_StorageFactory');
  4. class Core_Storage_Mysql extends Core_StorageBase {
  5. protected $_databaseName = '';
  6. protected $_zasob_id = 0;
  7. protected $_pdo = null;
  8. public function __construct($pdo) {
  9. $this->_pdo = $pdo;
  10. $this->_databaseName = $pdo->getDatabaseName();
  11. $this->_zasob_id = $pdo->getZasobId();
  12. }
  13. public function fetchAllAssoc($sql) {
  14. if (empty($sql)) {
  15. throw new Exception("Empty query");
  16. }
  17. $stmt = $this->_pdo->query($sql);
  18. return $stmt->fetchAll(PDO::FETCH_ASSOC);
  19. }
  20. public function query($query) {
  21. throw new Exception("Storage " . __FUNCTION__ . " not defined");
  22. $res = mysql_query($query, $this->_conn);
  23. if (!$res) {
  24. $this->_set_error('SQL QUERY FAILED: '.mysql_error($this->_conn));
  25. return $null;
  26. }
  27. }
  28. public function getTableStruct($tblName) {
  29. $sql = "
  30. -- show fields from {$tblName}
  31. select cols.COLUMN_NAME as name
  32. , cols.DATA_TYPE as type
  33. , if('YES' = cols.IS_NULLABLE, 1, 0) as is_nullable
  34. , cols.COLUMN_DEFAULT as default_value
  35. , if(cols.COLUMN_DEFAULT is null, 1, 0) as default_is_null
  36. , cols.CHARACTER_MAXIMUM_LENGTH as max_length
  37. , cols.NUMERIC_PRECISION as num_precision
  38. , cols.NUMERIC_SCALE as num_scale
  39. , cols.CHARACTER_SET_NAME as char_encoding -- latin2
  40. , cols.COLLATION_NAME as char_collation -- latin2_general_ci
  41. , cols.EXTRA as extra
  42. , cols.COLUMN_TYPE as raw_storage_type
  43. -- , cols.*
  44. from INFORMATION_SCHEMA.COLUMNS cols
  45. where cols.TABLE_SCHEMA like :db_name
  46. and cols.TABLE_NAME like :tbl_name
  47. ";
  48. $sth = $this->_pdo->prepare($sql);
  49. $sth->bindValue(':db_name', $this->_pdo->getDatabaseName(), PDO::PARAM_STR);
  50. $sth->bindValue(':tbl_name', $tblName, PDO::PARAM_STR);
  51. $sth->execute();
  52. $structRaw = $sth->fetchAll();
  53. if (empty($structRaw)) throw new Exception("Empty struct for table '{$tblName}'");
  54. foreach ($structRaw as $field) {
  55. $struct[$field['name']] = $field;
  56. }
  57. return $struct;
  58. }
  59. protected function _getTableStruct($tblName) {
  60. $tblStructRaw = $this->getTableStructRaw($tblName);
  61. $tblStruct = array();
  62. foreach ($tblStructRaw as $fieldStruct) {
  63. $fldName = $fieldStruct['COLUMN_NAME'];
  64. $storageType = '';
  65. /*
  66. BOOLEAN xsd: {true, false, 1, 0}
  67. SERIAL is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE
  68. SET
  69. */
  70. if ('varchar' == $fieldStruct['DATA_TYPE']
  71. || 'char' == $fieldStruct['DATA_TYPE']
  72. ) {
  73. $storageType = Core_StorageFactory::getType('String');
  74. if ($fieldStruct['CHARACTER_MAXIMUM_LENGTH'] > 0) {
  75. $storageType->setMaxLength($fieldStruct['CHARACTER_MAXIMUM_LENGTH']);
  76. }
  77. }
  78. else if ('text' == $fieldStruct['DATA_TYPE']
  79. || 'longtext' == $fieldStruct['DATA_TYPE']
  80. || 'mediumtext' == $fieldStruct['DATA_TYPE']
  81. || 'tinytext' == $fieldStruct['DATA_TYPE']
  82. ) {
  83. $storageType = Core_StorageFactory::getType('Text');
  84. }
  85. else if ('int' == $fieldStruct['DATA_TYPE']
  86. || 'tinyint' == $fieldStruct['DATA_TYPE']
  87. || 'smallint' == $fieldStruct['DATA_TYPE']
  88. || 'mediumint' == $fieldStruct['DATA_TYPE']
  89. || 'bigint' == $fieldStruct['DATA_TYPE']
  90. || 'bit' == $fieldStruct['DATA_TYPE']
  91. ) {
  92. $storageType = Core_StorageFactory::getType('Integer');
  93. $storageType->setTotalDigits($fieldStruct['NUMERIC_PRECISION']);
  94. }
  95. else if ('decimal' == $fieldStruct['DATA_TYPE']) {
  96. $storageType = Core_StorageFactory::getType('Decimal');
  97. if ($fieldStruct['NUMERIC_SCALE'] > 0) {
  98. $storageType->setFractionDigits($fieldStruct['NUMERIC_SCALE']);
  99. }
  100. if ($fieldStruct['NUMERIC_PRECISION'] > 0) {
  101. $storageType->setTotalDigits($fieldStruct['NUMERIC_PRECISION']);
  102. }
  103. }
  104. else if ('double' == $fieldStruct['DATA_TYPE']
  105. || 'real' == $fieldStruct['DATA_TYPE']
  106. || 'float' == $fieldStruct['DATA_TYPE']
  107. ) {
  108. $storageType = Core_StorageFactory::getType('Double');
  109. }
  110. else if ('binary' == $fieldStruct['DATA_TYPE']
  111. || 'varbinary' == $fieldStruct['DATA_TYPE']
  112. || 'blob' == $fieldStruct['DATA_TYPE']
  113. || 'tinyblob' == $fieldStruct['DATA_TYPE']
  114. || 'longblob' == $fieldStruct['DATA_TYPE']
  115. || 'mediumblob' == $fieldStruct['DATA_TYPE']
  116. ) {
  117. $storageType = Core_StorageFactory::getType('Binary');
  118. $storageType->setRestriction('maxExclusive', $fieldStruct['CHARACTER_MAXIMUM_LENGTH']);
  119. }
  120. else if ('enum' == $fieldStruct['DATA_TYPE']) {
  121. $storageType = Core_StorageFactory::getType('Enumeration');
  122. $enumValues = explode(',', str_replace(array('(',')',"'",'"'), '', substr($fieldStruct['COLUMN_TYPE'], 5)));
  123. $enumList = array();
  124. foreach ($enumValues as $value) {
  125. $enumList[] = $value;
  126. }
  127. $storageType->setEnumeration($enumList);
  128. }
  129. else if ('timestamp' == $fieldStruct['DATA_TYPE']) {
  130. $storageType = Core_StorageFactory::getType('DateTime');
  131. $storageType->setFormat('yyyy-MM-dd hh:mm:ss');
  132. }
  133. else if ('datetime' == $fieldStruct['DATA_TYPE']) {
  134. $storageType = Core_StorageFactory::getType('DateTime');
  135. $storageType->setFormat('yyyy-MM-dd hh:mm');
  136. }
  137. else if ('date' == $fieldStruct['DATA_TYPE']) {
  138. $storageType = Core_StorageFactory::getType('Date');
  139. $storageType->setFormat('yyyy-MM-dd');
  140. }
  141. else if ('time' == $fieldStruct['DATA_TYPE']) {
  142. $storageType = Core_StorageFactory::getType('Time');
  143. $storageType->setFormat('hh:mm:ss');
  144. }
  145. else if ('year' == $fieldStruct['DATA_TYPE']) {
  146. $storageType = Core_StorageFactory::getType('Year');
  147. $storageType->setFormat('yyyy');
  148. }
  149. else if ('point' == $fieldStruct['DATA_TYPE']) {
  150. $storageType = Core_StorageFactory::getType('Point');
  151. }
  152. else if ('linestring' == $fieldStruct['DATA_TYPE']) {
  153. $storageType = Core_StorageFactory::getType('Linestring');
  154. }
  155. else if ('polygon' == $fieldStruct['DATA_TYPE']) {
  156. $storageType = Core_StorageFactory::getType('Polygon');
  157. }
  158. else if ('geometry' == $fieldStruct['DATA_TYPE']
  159. || 'multipoint' == $fieldStruct['DATA_TYPE']
  160. || 'multilinestring' == $fieldStruct['DATA_TYPE']
  161. || 'multipolygon' == $fieldStruct['DATA_TYPE']
  162. || 'geometrycollection' == $fieldStruct['DATA_TYPE']
  163. ) {
  164. $storageType = Core_StorageFactory::getType('Geometry');
  165. $storageType->setSpatialType($fieldStruct['COLUMN_TYPE']);
  166. }
  167. else {
  168. $storageType = Core_StorageFactory::getType('Unknown');
  169. $storageType->setRawType($fieldStruct['COLUMN_TYPE']);
  170. }
  171. if (!$storageType) {
  172. echo "<div class=\"alert alert-warning\">Storage type '{$fieldStruct['COLUMN_TYPE']}' not recognized</div>";
  173. //TODO: throw new Exception("Storage type '{$fieldStruct['COLUMN_TYPE']}' not recognized");
  174. }
  175. if ('PRI' == $fieldStruct['COLUMN_KEY']) {
  176. $storageType->setPrimaryKey(true);
  177. }
  178. $vFldNillable = false;
  179. if ('YES' == $fieldStruct['IS_NULLABLE']) {
  180. $vFldNillable = true;
  181. } else if ('NO' == $fieldStruct['IS_NULLABLE']
  182. && 'PRI' == $fieldStruct['COLUMN_KEY']
  183. && 'auto_increment' == $fieldStruct['EXTRA']
  184. ) {
  185. $vFldNillable = true;
  186. }
  187. $storageType->setNillable($vFldNillable);
  188. if (!empty($fieldStruct['COLUMN_DEFAULT'])) {
  189. $storageType->setDefault($fieldStruct['COLUMN_DEFAULT']);
  190. } else if ('0' === $fieldStruct['COLUMN_DEFAULT']) {
  191. $storageType->setDefault(0);
  192. } else if ('' === $fieldStruct['COLUMN_DEFAULT']) {
  193. $storageType->setDefault('');
  194. } else if (null === $fieldStruct['COLUMN_DEFAULT']
  195. && 'YES' == $fieldStruct['IS_NULLABLE']
  196. && 1 == $fieldStruct['COLUMN_DEFAULT_IS_NULL']
  197. ) {
  198. $storageType->setDefault(null);
  199. }
  200. $tblStruct[$fldName] = $storageType;
  201. }
  202. return $tblStruct;
  203. }
  204. public function getTableStructRaw($tblName) {
  205. $tblNamePattern = '/^[a-zA-Z0-9_]+$/';
  206. if (!preg_match($tblNamePattern, $tblName)) {
  207. throw new Exception("Table name not allowed");
  208. }
  209. $sqlTblName = $tblName;
  210. $sql = "show fields from `{$sqlTblName}` ";
  211. $sql = "select cols.*
  212. -- , `IS_NULLABLE` as `Nullable`
  213. -- , `COLUMN_DEFAULT` as `DEFAULT`
  214. , IF(cols.`IS_NULLABLE`='YES' and cols.`COLUMN_DEFAULT` is null, 1, 0) as `COLUMN_DEFAULT_IS_NULL`
  215. from `INFORMATION_SCHEMA`.`COLUMNS` cols
  216. where cols.`TABLE_NAME`='{$sqlTblName}'
  217. and cols.`TABLE_SCHEMA`='{$this->_databaseName}'
  218. ";
  219. return $this->fetchAllAssoc($sql);
  220. }
  221. public function getViewStructTODO($viewName) {// TODO: getViewStruct
  222. $viewNamePattern = '/^[a-zA-Z0-9_]+$/';
  223. if (!preg_match($viewNamePattern, $viewName)) {
  224. throw new Exception("View name not allowed");
  225. }
  226. }
  227. public function getViewStructRaw($viewName) {
  228. $viewNamePattern = '/^[a-zA-Z0-9_]+$/';
  229. if (!preg_match($viewNamePattern, $viewName)) {
  230. throw new Exception("View name not allowed");
  231. }
  232. $sqlViewName = $viewName;
  233. $sql = "show create view `{$sqlViewName}` ";
  234. return $this->fetchAllAssoc($sql);
  235. }
  236. public function getTableListWithInfo() {
  237. return $this->getTableFullList();
  238. }
  239. public function getTableList() {
  240. return array_filter($this->getTableFullList(), function($row) {
  241. return ('BASE TABLE' == $row['table_type']);
  242. });
  243. }
  244. public function getViewList() {
  245. return array_filter($this->getTableFullList(), function($row) {
  246. return ('VIEW' == $row['table_type']);
  247. });
  248. }
  249. public function getTableFullList() {
  250. return array_map(function($row) {
  251. $values = array_values($row);
  252. return array('table_name' => strtolower($values[0]), 'table_type' => $values[1]);
  253. }, $this->_pdo->fetchAll('show full tables'));
  254. }
  255. }