PageRenderTime 53ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/inc/MDB2/Driver/Datatype/mysql.php

https://github.com/chregu/fluxcms
PHP | 471 lines | 293 code | 22 blank | 156 comment | 40 complexity | ad57696110afc6ebf5830debd80e2696 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, Apache-2.0, LGPL-2.1
  1. <?php
  2. // vim: set et ts=4 sw=4 fdm=marker:
  3. // +----------------------------------------------------------------------+
  4. // | PHP versions 4 and 5 |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
  7. // | Stig. S. Bakken, Lukas Smith |
  8. // | All rights reserved. |
  9. // +----------------------------------------------------------------------+
  10. // | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
  11. // | API as well as database abstraction for PHP applications. |
  12. // | This LICENSE is in the BSD license style. |
  13. // | |
  14. // | Redistribution and use in source and binary forms, with or without |
  15. // | modification, are permitted provided that the following conditions |
  16. // | are met: |
  17. // | |
  18. // | Redistributions of source code must retain the above copyright |
  19. // | notice, this list of conditions and the following disclaimer. |
  20. // | |
  21. // | Redistributions in binary form must reproduce the above copyright |
  22. // | notice, this list of conditions and the following disclaimer in the |
  23. // | documentation and/or other materials provided with the distribution. |
  24. // | |
  25. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
  26. // | Lukas Smith nor the names of his contributors may be used to endorse |
  27. // | or promote products derived from this software without specific prior|
  28. // | written permission. |
  29. // | |
  30. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
  31. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
  32. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
  33. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
  34. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
  35. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  36. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  37. // | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
  38. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
  39. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  40. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
  41. // | POSSIBILITY OF SUCH DAMAGE. |
  42. // +----------------------------------------------------------------------+
  43. // | Author: Lukas Smith <smith@pooteeweet.org> |
  44. // +----------------------------------------------------------------------+
  45. //
  46. // $Id$
  47. //
  48. require_once 'MDB2/Driver/Datatype/Common.php';
  49. /**
  50. * MDB2 MySQL driver
  51. *
  52. * @package MDB2
  53. * @category Database
  54. * @author Lukas Smith <smith@pooteeweet.org>
  55. */
  56. class MDB2_Driver_Datatype_mysql extends MDB2_Driver_Datatype_Common
  57. {
  58. // {{{ _getCharsetFieldDeclaration()
  59. /**
  60. * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
  61. * of a field declaration to be used in statements like CREATE TABLE.
  62. *
  63. * @param string $charset name of the charset
  64. * @return string DBMS specific SQL code portion needed to set the CHARACTER SET
  65. * of a field declaration.
  66. */
  67. function _getCharsetFieldDeclaration($charset)
  68. {
  69. return 'CHARACTER SET '.$charset;
  70. }
  71. // }}}
  72. // {{{ _getCollationFieldDeclaration()
  73. /**
  74. * Obtain DBMS specific SQL code portion needed to set the COLLATION
  75. * of a field declaration to be used in statements like CREATE TABLE.
  76. *
  77. * @param string $collation name of the collation
  78. * @return string DBMS specific SQL code portion needed to set the COLLATION
  79. * of a field declaration.
  80. */
  81. function _getCollationFieldDeclaration($collation)
  82. {
  83. return 'COLLATE '.$collation;
  84. }
  85. // }}}
  86. // {{{ getTypeDeclaration()
  87. /**
  88. * Obtain DBMS specific SQL code portion needed to declare an text type
  89. * field to be used in statements like CREATE TABLE.
  90. *
  91. * @param array $field associative array with the name of the properties
  92. * of the field being declared as array indexes. Currently, the types
  93. * of supported field properties are as follows:
  94. *
  95. * length
  96. * Integer value that determines the maximum length of the text
  97. * field. If this argument is missing the field should be
  98. * declared to have the longest length allowed by the DBMS.
  99. *
  100. * default
  101. * Text value to be used as default for this field.
  102. *
  103. * notnull
  104. * Boolean flag that indicates whether this field is constrained
  105. * to not be set to null.
  106. * @return string DBMS specific SQL code portion that should be used to
  107. * declare the specified field.
  108. * @access public
  109. */
  110. function getTypeDeclaration($field)
  111. {
  112. $db =& $this->getDBInstance();
  113. if (PEAR::isError($db)) {
  114. return $db;
  115. }
  116. switch ($field['type']) {
  117. case 'text':
  118. if (empty($field['length']) && array_key_exists('default', $field)) {
  119. $field['length'] = $db->varchar_max_length;
  120. }
  121. $length = !empty($field['length']) ? $field['length'] : false;
  122. $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
  123. return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR(255)')
  124. : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
  125. case 'clob':
  126. if (!empty($field['length'])) {
  127. $length = $field['length'];
  128. if ($length <= 255) {
  129. return 'TINYTEXT';
  130. } elseif ($length <= 65532) {
  131. return 'TEXT';
  132. } elseif ($length <= 16777215) {
  133. return 'MEDIUMTEXT';
  134. }
  135. }
  136. return 'LONGTEXT';
  137. case 'blob':
  138. if (!empty($field['length'])) {
  139. $length = $field['length'];
  140. if ($length <= 255) {
  141. return 'TINYBLOB';
  142. } elseif ($length <= 65532) {
  143. return 'BLOB';
  144. } elseif ($length <= 16777215) {
  145. return 'MEDIUMBLOB';
  146. }
  147. }
  148. return 'LONGBLOB';
  149. case 'integer':
  150. if (!empty($field['length'])) {
  151. $length = $field['length'];
  152. if ($length <= 1) {
  153. return 'TINYINT';
  154. } elseif ($length == 2) {
  155. return 'SMALLINT';
  156. } elseif ($length == 3) {
  157. return 'MEDIUMINT';
  158. } elseif ($length == 4) {
  159. return 'INT';
  160. } elseif ($length > 4) {
  161. return 'BIGINT';
  162. }
  163. }
  164. return 'INT';
  165. case 'boolean':
  166. return 'TINYINT(1)';
  167. case 'date':
  168. return 'DATE';
  169. case 'time':
  170. return 'TIME';
  171. case 'timestamp':
  172. return 'DATETIME';
  173. case 'float':
  174. return 'DOUBLE';
  175. case 'decimal':
  176. $length = !empty($field['length']) ? $field['length'] : 18;
  177. $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
  178. return 'DECIMAL('.$length.','.$scale.')';
  179. }
  180. return '';
  181. }
  182. // }}}
  183. // {{{ _getIntegerDeclaration()
  184. /**
  185. * Obtain DBMS specific SQL code portion needed to declare an integer type
  186. * field to be used in statements like CREATE TABLE.
  187. *
  188. * @param string $name name the field to be declared.
  189. * @param string $field associative array with the name of the properties
  190. * of the field being declared as array indexes.
  191. * Currently, the types of supported field
  192. * properties are as follows:
  193. *
  194. * unsigned
  195. * Boolean flag that indicates whether the field
  196. * should be declared as unsigned integer if
  197. * possible.
  198. *
  199. * default
  200. * Integer value to be used as default for this
  201. * field.
  202. *
  203. * notnull
  204. * Boolean flag that indicates whether this field is
  205. * constrained to not be set to null.
  206. * @return string DBMS specific SQL code portion that should be used to
  207. * declare the specified field.
  208. * @access protected
  209. */
  210. function _getIntegerDeclaration($name, $field)
  211. {
  212. $db =& $this->getDBInstance();
  213. if (PEAR::isError($db)) {
  214. return $db;
  215. }
  216. $default = $autoinc = '';
  217. if (!empty($field['autoincrement'])) {
  218. $autoinc = ' AUTO_INCREMENT PRIMARY KEY';
  219. } elseif (array_key_exists('default', $field)) {
  220. if ($field['default'] === '') {
  221. $field['default'] = empty($field['notnull']) ? null : 0;
  222. }
  223. $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
  224. } elseif (empty($field['notnull'])) {
  225. $default = ' DEFAULT NULL';
  226. }
  227. $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
  228. $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
  229. $name = $db->quoteIdentifier($name, true);
  230. return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc;
  231. }
  232. // }}}
  233. // {{{ matchPattern()
  234. /**
  235. * build a pattern matching string
  236. *
  237. * EXPERIMENTAL
  238. *
  239. * WARNING: this function is experimental and may change signature at
  240. * any time until labelled as non-experimental
  241. *
  242. * @access public
  243. *
  244. * @param array $pattern even keys are strings, odd are patterns (% and _)
  245. * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
  246. * @param string $field optional field name that is being matched against
  247. * (might be required when emulating ILIKE)
  248. *
  249. * @return string SQL pattern
  250. */
  251. function matchPattern($pattern, $operator = null, $field = null)
  252. {
  253. $db =& $this->getDBInstance();
  254. if (PEAR::isError($db)) {
  255. return $db;
  256. }
  257. $match = '';
  258. if (!is_null($operator)) {
  259. $field = is_null($field) ? '' : $field.' ';
  260. $operator = strtoupper($operator);
  261. switch ($operator) {
  262. // case insensitive
  263. case 'ILIKE':
  264. $match = $field.'LIKE ';
  265. break;
  266. // case sensitive
  267. case 'LIKE':
  268. $match = $field.'LIKE BINARY ';
  269. break;
  270. default:
  271. return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
  272. 'not a supported operator type:'. $operator, __FUNCTION__);
  273. }
  274. }
  275. $match.= "'";
  276. foreach ($pattern as $key => $value) {
  277. if ($key % 2) {
  278. $match.= $value;
  279. } else {
  280. $match.= $db->escapePattern($db->escape($value));
  281. }
  282. }
  283. $match.= "'";
  284. $match.= $this->patternEscapeString();
  285. return $match;
  286. }
  287. // }}}
  288. // {{{ _mapNativeDatatype()
  289. /**
  290. * Maps a native array description of a field to a MDB2 datatype and length
  291. *
  292. * @param array $field native field description
  293. * @return array containing the various possible types, length, sign, fixed
  294. * @access public
  295. */
  296. function _mapNativeDatatype($field)
  297. {
  298. $db_type = strtolower($field['type']);
  299. $db_type = strtok($db_type, '(), ');
  300. if ($db_type == 'national') {
  301. $db_type = strtok('(), ');
  302. }
  303. if (!empty($field['length'])) {
  304. $length = strtok($field['length'], ', ');
  305. $decimal = strtok(', ');
  306. } else {
  307. $length = strtok('(), ');
  308. $decimal = strtok('(), ');
  309. }
  310. $type = array();
  311. $unsigned = $fixed = null;
  312. switch ($db_type) {
  313. case 'tinyint':
  314. $type[] = 'integer';
  315. $type[] = 'boolean';
  316. if (preg_match('/^(is|has)/', $field['name'])) {
  317. $type = array_reverse($type);
  318. }
  319. $unsigned = preg_match('/ unsigned/i', $field['type']);
  320. $length = 1;
  321. break;
  322. case 'smallint':
  323. $type[] = 'integer';
  324. $unsigned = preg_match('/ unsigned/i', $field['type']);
  325. $length = 2;
  326. break;
  327. case 'mediumint':
  328. $type[] = 'integer';
  329. $unsigned = preg_match('/ unsigned/i', $field['type']);
  330. $length = 3;
  331. break;
  332. case 'int':
  333. case 'integer':
  334. $type[] = 'integer';
  335. $unsigned = preg_match('/ unsigned/i', $field['type']);
  336. $length = 4;
  337. break;
  338. case 'bigint':
  339. $type[] = 'integer';
  340. $unsigned = preg_match('/ unsigned/i', $field['type']);
  341. $length = 8;
  342. break;
  343. case 'tinytext':
  344. case 'mediumtext':
  345. case 'longtext':
  346. case 'text':
  347. case 'text':
  348. case 'varchar':
  349. $fixed = false;
  350. case 'string':
  351. case 'char':
  352. $type[] = 'text';
  353. if ($length == '1') {
  354. $type[] = 'boolean';
  355. if (preg_match('/^(is|has)/', $field['name'])) {
  356. $type = array_reverse($type);
  357. }
  358. } elseif (strstr($db_type, 'text')) {
  359. $type[] = 'clob';
  360. if ($decimal == 'binary') {
  361. $type[] = 'blob';
  362. }
  363. }
  364. if ($fixed !== false) {
  365. $fixed = true;
  366. }
  367. break;
  368. case 'enum':
  369. $type[] = 'text';
  370. preg_match_all('/\'.+\'/U', $field['type'], $matches);
  371. $length = 0;
  372. $fixed = false;
  373. if (is_array($matches)) {
  374. foreach ($matches[0] as $value) {
  375. $length = max($length, strlen($value)-2);
  376. }
  377. if ($length == '1' && count($matches[0]) == 2) {
  378. $type[] = 'boolean';
  379. if (preg_match('/^(is|has)/', $field['name'])) {
  380. $type = array_reverse($type);
  381. }
  382. }
  383. }
  384. $type[] = 'integer';
  385. case 'set':
  386. $fixed = false;
  387. $type[] = 'text';
  388. $type[] = 'integer';
  389. break;
  390. case 'date':
  391. $type[] = 'date';
  392. $length = null;
  393. break;
  394. case 'datetime':
  395. case 'timestamp':
  396. $type[] = 'timestamp';
  397. $length = null;
  398. break;
  399. case 'time':
  400. $type[] = 'time';
  401. $length = null;
  402. break;
  403. case 'float':
  404. case 'double':
  405. case 'real':
  406. $type[] = 'float';
  407. $unsigned = preg_match('/ unsigned/i', $field['type']);
  408. break;
  409. case 'unknown':
  410. case 'decimal':
  411. case 'numeric':
  412. $type[] = 'decimal';
  413. $unsigned = preg_match('/ unsigned/i', $field['type']);
  414. if ($decimal !== false) {
  415. $length = $length.','.$decimal;
  416. }
  417. break;
  418. case 'tinyblob':
  419. case 'mediumblob':
  420. case 'longblob':
  421. case 'blob':
  422. $type[] = 'blob';
  423. $length = null;
  424. break;
  425. case 'binary':
  426. case 'varbinary':
  427. $type[] = 'blob';
  428. break;
  429. case 'year':
  430. $type[] = 'integer';
  431. $type[] = 'date';
  432. $length = null;
  433. break;
  434. default:
  435. $db =& $this->getDBInstance();
  436. if (PEAR::isError($db)) {
  437. return $db;
  438. }
  439. return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
  440. 'unknown database attribute type: '.$db_type, __FUNCTION__);
  441. }
  442. if ((int)$length <= 0) {
  443. $length = null;
  444. }
  445. return array($type, $length, $unsigned, $fixed);
  446. }
  447. // }}}
  448. }
  449. ?>