PageRenderTime 26ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/scalr-2/tags/scalr-2.0.0/app/src/Lib/Data/DB/adodb_lite/adodbSQL_drivers/mysqli/mysqli_meta_module.inc

http://scalr.googlecode.com/
PHP | 624 lines | 439 code | 72 blank | 113 comment | 78 complexity | 68d9e454ee60fa950c80b1b62b89884d MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, GPL-3.0
  1. <?php
  2. /**
  3. * ADOdb Lite Meta Module for Mysql
  4. *
  5. * Portions of the Meta Coding came from ADOdb
  6. */
  7. /*
  8. (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
  9. Released under both BSD license and Lesser GPL library license.
  10. Whenever there is any discrepancy between the two licenses,
  11. the BSD license will take precedence. See License.txt.
  12. */
  13. eval('class mysqli_meta_EXTENDER extends '. $last_module . '_ADOConnection { }');
  14. class mysqli_meta_ADOConnection extends mysqli_meta_EXTENDER
  15. {
  16. var $metaTablesSQL = "SHOW TABLES";
  17. var $metaColumnsSQL = "SHOW COLUMNS FROM %s";
  18. function MetaError($err=false)
  19. {
  20. include_once(ADODB_DIR . "/adodb-error.inc.php");
  21. if ($err === false)
  22. $err = $this->ErrorNo();
  23. return adodb_error($this->dataProvider,$this->databaseType,$err);
  24. }
  25. function MetaErrorMsg($errno)
  26. {
  27. include_once(ADODB_DIR . "/adodb-error.inc.php");
  28. return adodb_errormsg($errno);
  29. }
  30. /**
  31. * @returns an array with the primary key columns in it.
  32. */
  33. function MetaPrimaryKeys($table, $owner=false)
  34. {
  35. // owner not used in base class - see oci8
  36. $p = array();
  37. $objs =& $this->MetaColumns($table);
  38. if ($objs) {
  39. foreach($objs as $v) {
  40. if (!empty($v->primary_key))
  41. $p[] = $v->name;
  42. }
  43. }
  44. if (sizeof($p))
  45. return $p;
  46. if (function_exists('ADODB_VIEW_PRIMARYKEYS'))
  47. return ADODB_VIEW_PRIMARYKEYS($this->databaseType, $this->database, $table, $owner);
  48. return false;
  49. }
  50. /**
  51. * @returns assoc array where keys are tables, and values are foreign keys
  52. */
  53. function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
  54. {
  55. if ( !empty($owner) ) {
  56. $table = "$owner.$table";
  57. }
  58. $a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
  59. if ($associative) $create_sql = $a_create_table["Create Table"];
  60. else $create_sql = $a_create_table[1];
  61. $matches = array();
  62. if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false;
  63. $foreign_keys = array();
  64. $num_keys = count($matches[0]);
  65. for ( $i = 0; $i < $num_keys; $i ++ ) {
  66. $my_field = explode('`, `', $matches[1][$i]);
  67. $ref_table = $matches[2][$i];
  68. $ref_field = explode('`, `', $matches[3][$i]);
  69. if ( $upper ) {
  70. $ref_table = strtoupper($ref_table);
  71. }
  72. $foreign_keys[$ref_table] = array();
  73. $num_fields = count($my_field);
  74. for ( $j = 0; $j < $num_fields; $j ++ ) {
  75. if ( $associative ) {
  76. $foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j];
  77. } else {
  78. $foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}";
  79. }
  80. }
  81. }
  82. return $foreign_keys;
  83. }
  84. // not the fastest implementation - quick and dirty - jlim
  85. // for best performance, use the actual $rs->MetaType().
  86. function MetaType($t,$len=-1,$fieldobj=false)
  87. {
  88. if (empty($this->_metars)) {
  89. $rsclass = $this->last_module_name . "_ResultSet";
  90. $this->_metars =& new $rsclass(false, $this->fetchMode);
  91. }
  92. return $this->_metars->MetaType($t,$len,$fieldobj);
  93. }
  94. /**
  95. * return the databases that the driver can connect to.
  96. * Some databases will return an empty array.
  97. *
  98. * @return an array of database names.
  99. */
  100. function &MetaDatabases()
  101. {
  102. $qid = mysql_list_dbs($this->connectionId);
  103. $arr = array();
  104. $i = 0;
  105. $max = mysql_num_rows($qid);
  106. while ($i < $max) {
  107. $db = mysql_tablename($qid,$i);
  108. if ($db != 'mysql') $arr[] = $db;
  109. $i += 1;
  110. }
  111. return $arr;
  112. }
  113. /**
  114. * @param ttype can either be 'VIEW' or 'TABLE' or false.
  115. * If false, both views and tables are returned.
  116. * "VIEW" returns only views
  117. * "TABLE" returns only tables
  118. * @param showSchema returns the schema/user with the table name, eg. USER.TABLE
  119. * @param mask is the input mask - only supported by oci8 and postgresql
  120. *
  121. * @return array of tables for current database.
  122. */
  123. function &MetaTables($ttype=false,$showSchema=false,$mask=false)
  124. {
  125. $save = $this->metaTablesSQL;
  126. if ($showSchema && is_string($showSchema)) {
  127. $this->metaTablesSQL .= " from $showSchema";
  128. }
  129. if ($mask) {
  130. $mask = $this->qstr($mask);
  131. $this->metaTablesSQL .= " like $mask";
  132. }
  133. $ret =& $this->_MetaTables($ttype,$showSchema);
  134. $this->metaTablesSQL = $save;
  135. return $ret;
  136. }
  137. function &_MetaTables($ttype=false,$showSchema=false,$mask=false)
  138. {
  139. global $ADODB_FETCH_MODE;
  140. $false = false;
  141. if ($mask) {
  142. return $false;
  143. }
  144. if ($this->metaTablesSQL) {
  145. $save = $ADODB_FETCH_MODE;
  146. $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
  147. if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
  148. $rs = $this->Execute($this->metaTablesSQL);
  149. if (isset($savem)) $this->SetFetchMode($savem);
  150. $ADODB_FETCH_MODE = $save;
  151. if ($rs === false) return $false;
  152. $arr =& $rs->GetArray();
  153. $arr2 = array();
  154. if ($hast = ($ttype && isset($arr[0][1]))) {
  155. $showt = strncmp($ttype,'T',1);
  156. }
  157. for ($i=0; $i < sizeof($arr); $i++) {
  158. if ($hast) {
  159. if ($showt == 0) {
  160. if (strncmp($arr[$i][1],'T',1) == 0) $arr2[] = trim($arr[$i][0]);
  161. } else {
  162. if (strncmp($arr[$i][1],'V',1) == 0) $arr2[] = trim($arr[$i][0]);
  163. }
  164. } else
  165. $arr2[] = trim($arr[$i][0]);
  166. }
  167. $rs->Close();
  168. return $arr2;
  169. }
  170. return $false;
  171. }
  172. function _findschema(&$table,&$schema)
  173. {
  174. if (!$schema && ($at = strpos($table,'.')) !== false) {
  175. $schema = substr($table,0,$at);
  176. $table = substr($table,$at+1);
  177. }
  178. }
  179. /**
  180. * List columns in a database as an array of ADOFieldObjects.
  181. * See top of file for definition of object.
  182. *
  183. * @param $table table name to query
  184. * @param $normalize makes table name case-insensitive (required by some databases)
  185. * @schema is optional database schema to use - not supported by all databases.
  186. *
  187. * @return array of ADOFieldObjects for current table.
  188. */
  189. function MetaColumns($table)
  190. {
  191. $this->_findschema($table,$schema);
  192. if ($schema) {
  193. $dbName = $this->database;
  194. $this->connection->SelectDB($schema);
  195. }
  196. global $ADODB_FETCH_MODE;
  197. $save = $ADODB_FETCH_MODE;
  198. $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
  199. if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
  200. $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
  201. if ($schema) {
  202. $this->SelectDB($dbName);
  203. }
  204. if (isset($savem)) $this->SetFetchMode($savem);
  205. $ADODB_FETCH_MODE = $save;
  206. if (!is_object($rs)) {
  207. $false = false;
  208. return $false;
  209. }
  210. $retarr = array();
  211. while (!$rs->EOF){
  212. $fld = new ADOFieldObject();
  213. $fld->name = $rs->fields[0];
  214. $type = $rs->fields[1];
  215. // split type into type(length):
  216. $fld->scale = null;
  217. if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {
  218. $fld->type = $query_array[1];
  219. $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
  220. $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;
  221. } elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {
  222. $fld->type = $query_array[1];
  223. $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
  224. } elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) {
  225. $fld->type = $query_array[1];
  226. $arr = explode(",",$query_array[2]);
  227. $fld->enums = $arr;
  228. $zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6
  229. $fld->max_length = ($zlen > 0) ? $zlen : 1;
  230. } else {
  231. $fld->type = $type;
  232. $fld->max_length = -1;
  233. }
  234. $fld->not_null = ($rs->fields[2] != 'YES');
  235. $fld->primary_key = ($rs->fields[3] == 'PRI');
  236. $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
  237. $fld->binary = (strpos($type,'blob') !== false);
  238. $fld->unsigned = (strpos($type,'unsigned') !== false);
  239. if (!$fld->binary) {
  240. $d = $rs->fields[4];
  241. if ($d != '' && $d != 'NULL') {
  242. $fld->has_default = true;
  243. $fld->default_value = $d;
  244. } else {
  245. $fld->has_default = false;
  246. }
  247. }
  248. if ($save == ADODB_FETCH_NUM) {
  249. $retarr[] = $fld;
  250. } else {
  251. $retarr[strtoupper($fld->name)] = $fld;
  252. }
  253. $rs->MoveNext();
  254. }
  255. $rs->Close();
  256. return $retarr;
  257. }
  258. /**
  259. * List indexes on a table as an array.
  260. * @param table table name to query
  261. * @param primary true to only show primary keys. Not actually used for most databases
  262. *
  263. * @return array of indexes on current table. Each element represents an index, and is itself an associative array.
  264. Array (
  265. [name_of_index] => Array
  266. (
  267. [unique] => true or false
  268. [columns] => Array
  269. (
  270. [0] => firstname
  271. [1] => lastname
  272. )
  273. )
  274. */
  275. function MetaIndexes ($table, $primary = FALSE, $owner=false)
  276. {
  277. // save old fetch mode
  278. global $ADODB_FETCH_MODE;
  279. $false = false;
  280. $save = $ADODB_FETCH_MODE;
  281. $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
  282. if ($this->fetchMode !== FALSE) {
  283. $savem = $this->SetFetchMode(FALSE);
  284. }
  285. // get index details
  286. $rs =& $this->Execute(sprintf('SHOW INDEX FROM %s',$table));
  287. // restore fetchmode
  288. if (isset($savem)) {
  289. $this->SetFetchMode($savem);
  290. }
  291. $ADODB_FETCH_MODE = $save;
  292. if (!is_object($rs)) {
  293. return $false;
  294. }
  295. $indexes = array ();
  296. // parse index data into array
  297. while (!$rs->EOF)
  298. {
  299. if ($primary == FALSE AND $rs->fields[2] == 'PRIMARY') {
  300. $rs->MoveNext();
  301. continue;
  302. }
  303. if (!isset($indexes[$rs->fields[2]])) {
  304. $indexes[$rs->fields[2]] = array(
  305. 'unique' => ($rs->fields[1] == 0),
  306. 'columns' => array()
  307. );
  308. }
  309. $indexes[$rs->fields[2]]['columns'][$rs->fields[3] - 1] = $rs->fields[4];
  310. $rs->MoveNext();
  311. }
  312. // sort columns by order in the index
  313. foreach ( array_keys ($indexes) as $index )
  314. {
  315. ksort ($indexes[$index]['columns']);
  316. }
  317. return $indexes;
  318. }
  319. /**
  320. * List columns names in a table as an array.
  321. * @param table table name to query
  322. *
  323. * @return array of column names for current table.
  324. */
  325. function &MetaColumnNames($table, $numIndexes=false)
  326. {
  327. $objarr =& $this->MetaColumns($table);
  328. if (!is_array($objarr)) {
  329. $false = false;
  330. return $false;
  331. }
  332. $arr = array();
  333. if ($numIndexes) {
  334. $i = 0;
  335. foreach($objarr as $v) $arr[$i++] = $v->name;
  336. } else
  337. foreach($objarr as $v) $arr[strtoupper($v->name)] = $v->name;
  338. return $arr;
  339. }
  340. function MetaTransaction($mode,$db)
  341. {
  342. $mode = strtoupper($mode);
  343. $mode = str_replace('ISOLATION LEVEL ','',$mode);
  344. switch($mode) {
  345. case 'READ UNCOMMITTED':
  346. switch($db) {
  347. case 'oci8':
  348. case 'oracle':
  349. return 'ISOLATION LEVEL READ COMMITTED';
  350. default:
  351. return 'ISOLATION LEVEL READ UNCOMMITTED';
  352. }
  353. break;
  354. case 'READ COMMITTED':
  355. return 'ISOLATION LEVEL READ COMMITTED';
  356. break;
  357. case 'REPEATABLE READ':
  358. switch($db) {
  359. case 'oci8':
  360. case 'oracle':
  361. return 'ISOLATION LEVEL SERIALIZABLE';
  362. default:
  363. return 'ISOLATION LEVEL REPEATABLE READ';
  364. }
  365. break;
  366. case 'SERIALIZABLE':
  367. return 'ISOLATION LEVEL SERIALIZABLE';
  368. break;
  369. default:
  370. return $mode;
  371. }
  372. }
  373. }
  374. eval('class mysqli_meta_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
  375. class mysqli_meta_ResultSet extends mysqli_meta_resultset_EXTENDER
  376. {
  377. /**
  378. * Get the metatype of the column. This is used for formatting. This is because
  379. * many databases use different names for the same type, so we transform the original
  380. * type to our standardised version which uses 1 character codes:
  381. *
  382. * @param t is the type passed in. Normally is ADOFieldObject->type.
  383. * @param len is the maximum length of that field. This is because we treat character
  384. * fields bigger than a certain size as a 'B' (blob).
  385. * @param fieldobj is the field object returned by the database driver. Can hold
  386. * additional info (eg. primary_key for mysql).
  387. *
  388. * @return the general type of the data:
  389. * C for character < 250 chars
  390. * X for teXt (>= 250 chars)
  391. * B for Binary
  392. * N for numeric or floating point
  393. * D for date
  394. * T for timestamp
  395. * L for logical/Boolean
  396. * I for integer
  397. * R for autoincrement counter/integer
  398. *
  399. *
  400. */
  401. function MetaType($t,$len=-1,$fieldobj=false)
  402. {
  403. if (is_object($t)) {
  404. $fieldobj = $t;
  405. $t = $fieldobj->type;
  406. $len = $fieldobj->max_length;
  407. }
  408. $len = -1; // mysql max_length is not accurate
  409. switch (strtoupper($t)) {
  410. case 'STRING':
  411. case 'CHAR':
  412. case 'VARCHAR':
  413. case 'TINYBLOB':
  414. case 'TINYTEXT':
  415. case 'ENUM':
  416. case 'SET':
  417. if ($len <= $this->blobSize) return 'C';
  418. case 'TEXT':
  419. case 'LONGTEXT':
  420. case 'MEDIUMTEXT':
  421. return 'X';
  422. // php_mysql extension always returns 'blob' even if 'text'
  423. // so we have to check whether binary...
  424. case 'IMAGE':
  425. case 'LONGBLOB':
  426. case 'BLOB':
  427. case 'MEDIUMBLOB':
  428. return !empty($fieldobj->binary) ? 'B' : 'X';
  429. case 'YEAR':
  430. case 'DATE': return 'D';
  431. case 'TIME':
  432. case 'DATETIME':
  433. case 'TIMESTAMP': return 'T';
  434. case 'INT':
  435. case 'INTEGER':
  436. case 'BIGINT':
  437. case 'TINYINT':
  438. case 'MEDIUMINT':
  439. case 'SMALLINT':
  440. if (!empty($fieldobj->primary_key)) return 'R';
  441. else return 'I';
  442. default:
  443. static $typeMap = array(
  444. 'VARCHAR' => 'C',
  445. 'VARCHAR2' => 'C',
  446. 'CHAR' => 'C',
  447. 'C' => 'C',
  448. 'STRING' => 'C',
  449. 'NCHAR' => 'C',
  450. 'NVARCHAR' => 'C',
  451. 'VARYING' => 'C',
  452. 'BPCHAR' => 'C',
  453. 'CHARACTER' => 'C',
  454. 'INTERVAL' => 'C', # Postgres
  455. 'MACADDR' => 'C', # postgres
  456. ##
  457. 'LONGCHAR' => 'X',
  458. 'TEXT' => 'X',
  459. 'NTEXT' => 'X',
  460. 'M' => 'X',
  461. 'X' => 'X',
  462. 'CLOB' => 'X',
  463. 'NCLOB' => 'X',
  464. 'LVARCHAR' => 'X',
  465. ##
  466. 'BLOB' => 'B',
  467. 'IMAGE' => 'B',
  468. 'BINARY' => 'B',
  469. 'VARBINARY' => 'B',
  470. 'LONGBINARY' => 'B',
  471. 'B' => 'B',
  472. ##
  473. 'YEAR' => 'D', // mysql
  474. 'DATE' => 'D',
  475. 'D' => 'D',
  476. ##
  477. 'UNIQUEIDENTIFIER' => 'C', # MS SQL Server
  478. ##
  479. 'TIME' => 'T',
  480. 'TIMESTAMP' => 'T',
  481. 'DATETIME' => 'T',
  482. 'TIMESTAMPTZ' => 'T',
  483. 'T' => 'T',
  484. 'TIMESTAMP WITHOUT TIME ZONE' => 'T', // postgresql
  485. ##
  486. 'BOOL' => 'L',
  487. 'BOOLEAN' => 'L',
  488. 'BIT' => 'L',
  489. 'L' => 'L',
  490. ##
  491. 'COUNTER' => 'R',
  492. 'R' => 'R',
  493. 'SERIAL' => 'R', // ifx
  494. 'INT IDENTITY' => 'R',
  495. ##
  496. 'INT' => 'I',
  497. 'INT2' => 'I',
  498. 'INT4' => 'I',
  499. 'INT8' => 'I',
  500. 'INTEGER' => 'I',
  501. 'INTEGER UNSIGNED' => 'I',
  502. 'SHORT' => 'I',
  503. 'TINYINT' => 'I',
  504. 'SMALLINT' => 'I',
  505. 'I' => 'I',
  506. ##
  507. 'LONG' => 'N', // interbase is numeric, oci8 is blob
  508. 'BIGINT' => 'N', // this is bigger than PHP 32-bit integers
  509. 'DECIMAL' => 'N',
  510. 'DEC' => 'N',
  511. 'REAL' => 'N',
  512. 'DOUBLE' => 'N',
  513. 'DOUBLE PRECISION' => 'N',
  514. 'SMALLFLOAT' => 'N',
  515. 'FLOAT' => 'N',
  516. 'NUMBER' => 'N',
  517. 'NUM' => 'N',
  518. 'NUMERIC' => 'N',
  519. 'MONEY' => 'N',
  520. ## informix 9.2
  521. 'SQLINT' => 'I',
  522. 'SQLSERIAL' => 'I',
  523. 'SQLSMINT' => 'I',
  524. 'SQLSMFLOAT' => 'N',
  525. 'SQLFLOAT' => 'N',
  526. 'SQLMONEY' => 'N',
  527. 'SQLDECIMAL' => 'N',
  528. 'SQLDATE' => 'D',
  529. 'SQLVCHAR' => 'C',
  530. 'SQLCHAR' => 'C',
  531. 'SQLDTIME' => 'T',
  532. 'SQLINTERVAL' => 'N',
  533. 'SQLBYTES' => 'B',
  534. 'SQLTEXT' => 'X',
  535. ## informix 10
  536. "SQLINT8" => 'I8',
  537. "SQLSERIAL8" => 'I8',
  538. "SQLNCHAR" => 'C',
  539. "SQLNVCHAR" => 'C',
  540. "SQLLVARCHAR" => 'X',
  541. "SQLBOOL" => 'L'
  542. );
  543. $tmap = false;
  544. $t = strtoupper($t);
  545. $tmap = (isset($typeMap[$t])) ? $typeMap[$t] : 'N';
  546. if ($t == 'LONG' && $this->dataProvider == 'oci8') return 'B';
  547. return $tmap;
  548. }
  549. }
  550. }
  551. ?>