PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/adodb/drivers/adodb-mysql.inc.php

http://github.com/moodle/moodle
PHP | 893 lines | 677 code | 127 blank | 89 comment | 138 complexity | fbd6aee56332b8596a8e7a4437868626 MD5 | raw file
Possible License(s): MIT, AGPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, Apache-2.0, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /*
  3. @version v5.20.16 12-Jan-2020
  4. @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
  5. @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
  6. Released under both BSD license and Lesser GPL library license.
  7. Whenever there is any discrepancy between the two licenses,
  8. the BSD license will take precedence.
  9. Set tabs to 8.
  10. This driver only supports the original non-transactional MySQL driver. It
  11. is deprected in PHP version 5.5 and removed in PHP version 7. It is deprecated
  12. as of ADOdb version 5.20.0. Use the mysqli driver instead, which supports both
  13. transactional and non-transactional updates
  14. Requires mysql client. Works on Windows and Unix.
  15. 28 Feb 2001: MetaColumns bug fix - suggested by Freek Dijkstra (phpeverywhere@macfreek.com)
  16. */
  17. // security - hide paths
  18. if (!defined('ADODB_DIR')) die();
  19. if (! defined("_ADODB_MYSQL_LAYER")) {
  20. define("_ADODB_MYSQL_LAYER", 1 );
  21. class ADODB_mysql extends ADOConnection {
  22. var $databaseType = 'mysql';
  23. var $dataProvider = 'mysql';
  24. var $hasInsertID = true;
  25. var $hasAffectedRows = true;
  26. var $metaTablesSQL = "SELECT
  27. TABLE_NAME,
  28. CASE WHEN TABLE_TYPE = 'VIEW' THEN 'V' ELSE 'T' END
  29. FROM INFORMATION_SCHEMA.TABLES
  30. WHERE TABLE_SCHEMA=";
  31. var $metaColumnsSQL = "SHOW COLUMNS FROM `%s`";
  32. var $fmtTimeStamp = "'Y-m-d H:i:s'";
  33. var $hasLimit = true;
  34. var $hasMoveFirst = true;
  35. var $hasGenID = true;
  36. var $isoDates = true; // accepts dates in ISO format
  37. var $sysDate = 'CURDATE()';
  38. var $sysTimeStamp = 'NOW()';
  39. var $hasTransactions = false;
  40. var $forceNewConnect = false;
  41. var $poorAffectedRows = true;
  42. var $clientFlags = 0;
  43. var $charSet = '';
  44. var $substr = "substring";
  45. var $nameQuote = '`'; /// string to use to quote identifiers and names
  46. var $compat323 = false; // true if compat with mysql 3.23
  47. function __construct()
  48. {
  49. if (defined('ADODB_EXTENSION')) $this->rsPrefix .= 'ext_';
  50. }
  51. // SetCharSet - switch the client encoding
  52. function SetCharSet($charset_name)
  53. {
  54. if (!function_exists('mysql_set_charset')) {
  55. return false;
  56. }
  57. if ($this->charSet !== $charset_name) {
  58. $ok = @mysql_set_charset($charset_name,$this->_connectionID);
  59. if ($ok) {
  60. $this->charSet = $charset_name;
  61. return true;
  62. }
  63. return false;
  64. }
  65. return true;
  66. }
  67. function ServerInfo()
  68. {
  69. $arr['description'] = ADOConnection::GetOne("select version()");
  70. $arr['version'] = ADOConnection::_findvers($arr['description']);
  71. return $arr;
  72. }
  73. function IfNull( $field, $ifNull )
  74. {
  75. return " IFNULL($field, $ifNull) "; // if MySQL
  76. }
  77. function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null)
  78. {
  79. // save old fetch mode
  80. global $ADODB_FETCH_MODE;
  81. $false = false;
  82. $save = $ADODB_FETCH_MODE;
  83. $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
  84. if ($this->fetchMode !== FALSE) {
  85. $savem = $this->SetFetchMode(FALSE);
  86. }
  87. $procedures = array ();
  88. // get index details
  89. $likepattern = '';
  90. if ($NamePattern) {
  91. $likepattern = " LIKE '".$NamePattern."'";
  92. }
  93. $rs = $this->Execute('SHOW PROCEDURE STATUS'.$likepattern);
  94. if (is_object($rs)) {
  95. // parse index data into array
  96. while ($row = $rs->FetchRow()) {
  97. $procedures[$row[1]] = array(
  98. 'type' => 'PROCEDURE',
  99. 'catalog' => '',
  100. 'schema' => '',
  101. 'remarks' => $row[7],
  102. );
  103. }
  104. }
  105. $rs = $this->Execute('SHOW FUNCTION STATUS'.$likepattern);
  106. if (is_object($rs)) {
  107. // parse index data into array
  108. while ($row = $rs->FetchRow()) {
  109. $procedures[$row[1]] = array(
  110. 'type' => 'FUNCTION',
  111. 'catalog' => '',
  112. 'schema' => '',
  113. 'remarks' => $row[7]
  114. );
  115. }
  116. }
  117. // restore fetchmode
  118. if (isset($savem)) {
  119. $this->SetFetchMode($savem);
  120. }
  121. $ADODB_FETCH_MODE = $save;
  122. return $procedures;
  123. }
  124. /**
  125. * Retrieves a list of tables based on given criteria
  126. *
  127. * @param string $ttype Table type = 'TABLE', 'VIEW' or false=both (default)
  128. * @param string $showSchema schema name, false = current schema (default)
  129. * @param string $mask filters the table by name
  130. *
  131. * @return array list of tables
  132. */
  133. function MetaTables($ttype=false,$showSchema=false,$mask=false)
  134. {
  135. $save = $this->metaTablesSQL;
  136. if ($showSchema && is_string($showSchema)) {
  137. $this->metaTablesSQL .= $this->qstr($showSchema);
  138. } else {
  139. $this->metaTablesSQL .= "schema()";
  140. }
  141. if ($mask) {
  142. $mask = $this->qstr($mask);
  143. $this->metaTablesSQL .= " AND table_name LIKE $mask";
  144. }
  145. $ret = ADOConnection::MetaTables($ttype,$showSchema);
  146. $this->metaTablesSQL = $save;
  147. return $ret;
  148. }
  149. function MetaIndexes ($table, $primary = FALSE, $owner=false)
  150. {
  151. // save old fetch mode
  152. global $ADODB_FETCH_MODE;
  153. $false = false;
  154. $save = $ADODB_FETCH_MODE;
  155. $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
  156. if ($this->fetchMode !== FALSE) {
  157. $savem = $this->SetFetchMode(FALSE);
  158. }
  159. // get index details
  160. $rs = $this->Execute(sprintf('SHOW INDEX FROM %s',$table));
  161. // restore fetchmode
  162. if (isset($savem)) {
  163. $this->SetFetchMode($savem);
  164. }
  165. $ADODB_FETCH_MODE = $save;
  166. if (!is_object($rs)) {
  167. return $false;
  168. }
  169. $indexes = array ();
  170. // parse index data into array
  171. while ($row = $rs->FetchRow()) {
  172. if ($primary == FALSE AND $row[2] == 'PRIMARY') {
  173. continue;
  174. }
  175. if (!isset($indexes[$row[2]])) {
  176. $indexes[$row[2]] = array(
  177. 'unique' => ($row[1] == 0),
  178. 'columns' => array()
  179. );
  180. }
  181. $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];
  182. }
  183. // sort columns by order in the index
  184. foreach ( array_keys ($indexes) as $index )
  185. {
  186. ksort ($indexes[$index]['columns']);
  187. }
  188. return $indexes;
  189. }
  190. // if magic quotes disabled, use mysql_real_escape_string()
  191. function qstr($s,$magic_quotes=false)
  192. {
  193. if (is_null($s)) return 'NULL';
  194. if (!$magic_quotes) {
  195. if (ADODB_PHPVER >= 0x4300) {
  196. if (is_resource($this->_connectionID))
  197. return "'".mysql_real_escape_string($s,$this->_connectionID)."'";
  198. }
  199. if ($this->replaceQuote[0] == '\\'){
  200. $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
  201. }
  202. return "'".str_replace("'",$this->replaceQuote,$s)."'";
  203. }
  204. // undo magic quotes for "
  205. $s = str_replace('\\"','"',$s);
  206. return "'$s'";
  207. }
  208. function _insertid()
  209. {
  210. return ADOConnection::GetOne('SELECT LAST_INSERT_ID()');
  211. //return mysql_insert_id($this->_connectionID);
  212. }
  213. function GetOne($sql,$inputarr=false)
  214. {
  215. global $ADODB_GETONE_EOF;
  216. if ($this->compat323 == false && strncasecmp($sql,'sele',4) == 0) {
  217. $rs = $this->SelectLimit($sql,1,-1,$inputarr);
  218. if ($rs) {
  219. $rs->Close();
  220. if ($rs->EOF) return $ADODB_GETONE_EOF;
  221. return reset($rs->fields);
  222. }
  223. } else {
  224. return ADOConnection::GetOne($sql,$inputarr);
  225. }
  226. return false;
  227. }
  228. function BeginTrans()
  229. {
  230. if ($this->debug) ADOConnection::outp("Transactions not supported in 'mysql' driver. Use 'mysqlt' or 'mysqli' driver");
  231. }
  232. function _affectedrows()
  233. {
  234. return mysql_affected_rows($this->_connectionID);
  235. }
  236. // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html
  237. // Reference on Last_Insert_ID on the recommended way to simulate sequences
  238. var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
  239. var $_genSeqSQL = "create table if not exists %s (id int not null)";
  240. var $_genSeqCountSQL = "select count(*) from %s";
  241. var $_genSeq2SQL = "insert into %s values (%s)";
  242. var $_dropSeqSQL = "drop table if exists %s";
  243. function CreateSequence($seqname='adodbseq',$startID=1)
  244. {
  245. if (empty($this->_genSeqSQL)) return false;
  246. $u = strtoupper($seqname);
  247. $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
  248. if (!$ok) return false;
  249. return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
  250. }
  251. function GenID($seqname='adodbseq',$startID=1)
  252. {
  253. // post-nuke sets hasGenID to false
  254. if (!$this->hasGenID) return false;
  255. $savelog = $this->_logsql;
  256. $this->_logsql = false;
  257. $getnext = sprintf($this->_genIDSQL,$seqname);
  258. $holdtransOK = $this->_transOK; // save the current status
  259. $rs = @$this->Execute($getnext);
  260. if (!$rs) {
  261. if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset
  262. $u = strtoupper($seqname);
  263. $this->Execute(sprintf($this->_genSeqSQL,$seqname));
  264. $cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seqname));
  265. if (!$cnt) $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
  266. $rs = $this->Execute($getnext);
  267. }
  268. if ($rs) {
  269. $this->genID = mysql_insert_id($this->_connectionID);
  270. $rs->Close();
  271. } else
  272. $this->genID = 0;
  273. $this->_logsql = $savelog;
  274. return $this->genID;
  275. }
  276. function MetaDatabases()
  277. {
  278. $qid = mysql_list_dbs($this->_connectionID);
  279. $arr = array();
  280. $i = 0;
  281. $max = mysql_num_rows($qid);
  282. while ($i < $max) {
  283. $db = mysql_tablename($qid,$i);
  284. if ($db != 'mysql') $arr[] = $db;
  285. $i += 1;
  286. }
  287. return $arr;
  288. }
  289. // Format date column in sql string given an input format that understands Y M D
  290. function SQLDate($fmt, $col=false)
  291. {
  292. if (!$col) $col = $this->sysTimeStamp;
  293. $s = 'DATE_FORMAT('.$col.",'";
  294. $concat = false;
  295. $len = strlen($fmt);
  296. for ($i=0; $i < $len; $i++) {
  297. $ch = $fmt[$i];
  298. switch($ch) {
  299. default:
  300. if ($ch == '\\') {
  301. $i++;
  302. $ch = substr($fmt,$i,1);
  303. }
  304. /** FALL THROUGH */
  305. case '-':
  306. case '/':
  307. $s .= $ch;
  308. break;
  309. case 'Y':
  310. case 'y':
  311. $s .= '%Y';
  312. break;
  313. case 'M':
  314. $s .= '%b';
  315. break;
  316. case 'm':
  317. $s .= '%m';
  318. break;
  319. case 'D':
  320. case 'd':
  321. $s .= '%d';
  322. break;
  323. case 'Q':
  324. case 'q':
  325. $s .= "'),Quarter($col)";
  326. if ($len > $i+1) $s .= ",DATE_FORMAT($col,'";
  327. else $s .= ",('";
  328. $concat = true;
  329. break;
  330. case 'H':
  331. $s .= '%H';
  332. break;
  333. case 'h':
  334. $s .= '%I';
  335. break;
  336. case 'i':
  337. $s .= '%i';
  338. break;
  339. case 's':
  340. $s .= '%s';
  341. break;
  342. case 'a':
  343. case 'A':
  344. $s .= '%p';
  345. break;
  346. case 'w':
  347. $s .= '%w';
  348. break;
  349. case 'W':
  350. $s .= '%U';
  351. break;
  352. case 'l':
  353. $s .= '%W';
  354. break;
  355. }
  356. }
  357. $s.="')";
  358. if ($concat) $s = "CONCAT($s)";
  359. return $s;
  360. }
  361. // returns concatenated string
  362. // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator
  363. function Concat()
  364. {
  365. $s = "";
  366. $arr = func_get_args();
  367. // suggestion by andrew005@mnogo.ru
  368. $s = implode(',',$arr);
  369. if (strlen($s) > 0) return "CONCAT($s)";
  370. else return '';
  371. }
  372. function OffsetDate($dayFraction,$date=false)
  373. {
  374. if (!$date) $date = $this->sysDate;
  375. $fraction = $dayFraction * 24 * 3600;
  376. return '('. $date . ' + INTERVAL ' . $fraction.' SECOND)';
  377. // return "from_unixtime(unix_timestamp($date)+$fraction)";
  378. }
  379. // returns true or false
  380. function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
  381. {
  382. if (!empty($this->port)) $argHostname .= ":".$this->port;
  383. if (ADODB_PHPVER >= 0x4300)
  384. $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword,
  385. $this->forceNewConnect,$this->clientFlags);
  386. else if (ADODB_PHPVER >= 0x4200)
  387. $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword,
  388. $this->forceNewConnect);
  389. else
  390. $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword);
  391. if ($this->_connectionID === false) return false;
  392. if ($argDatabasename) return $this->SelectDB($argDatabasename);
  393. return true;
  394. }
  395. // returns true or false
  396. function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
  397. {
  398. if (!empty($this->port)) $argHostname .= ":".$this->port;
  399. if (ADODB_PHPVER >= 0x4300)
  400. $this->_connectionID = mysql_pconnect($argHostname,$argUsername,$argPassword,$this->clientFlags);
  401. else
  402. $this->_connectionID = mysql_pconnect($argHostname,$argUsername,$argPassword);
  403. if ($this->_connectionID === false) return false;
  404. if ($this->autoRollback) $this->RollbackTrans();
  405. if ($argDatabasename) return $this->SelectDB($argDatabasename);
  406. return true;
  407. }
  408. function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
  409. {
  410. $this->forceNewConnect = true;
  411. return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
  412. }
  413. function MetaColumns($table, $normalize=true)
  414. {
  415. $this->_findschema($table,$schema);
  416. if ($schema) {
  417. $dbName = $this->database;
  418. $this->SelectDB($schema);
  419. }
  420. global $ADODB_FETCH_MODE;
  421. $save = $ADODB_FETCH_MODE;
  422. $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
  423. if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
  424. $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
  425. if ($schema) {
  426. $this->SelectDB($dbName);
  427. }
  428. if (isset($savem)) $this->SetFetchMode($savem);
  429. $ADODB_FETCH_MODE = $save;
  430. if (!is_object($rs)) {
  431. $false = false;
  432. return $false;
  433. }
  434. $retarr = array();
  435. while (!$rs->EOF){
  436. $fld = new ADOFieldObject();
  437. $fld->name = $rs->fields[0];
  438. $type = $rs->fields[1];
  439. // split type into type(length):
  440. $fld->scale = null;
  441. if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {
  442. $fld->type = $query_array[1];
  443. $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
  444. $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;
  445. } elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {
  446. $fld->type = $query_array[1];
  447. $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
  448. } elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) {
  449. $fld->type = $query_array[1];
  450. $arr = explode(",",$query_array[2]);
  451. $fld->enums = $arr;
  452. $zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6
  453. $fld->max_length = ($zlen > 0) ? $zlen : 1;
  454. } else {
  455. $fld->type = $type;
  456. $fld->max_length = -1;
  457. }
  458. $fld->not_null = ($rs->fields[2] != 'YES');
  459. $fld->primary_key = ($rs->fields[3] == 'PRI');
  460. $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
  461. $fld->binary = (strpos($type,'blob') !== false || strpos($type,'binary') !== false);
  462. $fld->unsigned = (strpos($type,'unsigned') !== false);
  463. $fld->zerofill = (strpos($type,'zerofill') !== false);
  464. if (!$fld->binary) {
  465. $d = $rs->fields[4];
  466. if ($d != '' && $d != 'NULL') {
  467. $fld->has_default = true;
  468. $fld->default_value = $d;
  469. } else {
  470. $fld->has_default = false;
  471. }
  472. }
  473. if ($save == ADODB_FETCH_NUM) {
  474. $retarr[] = $fld;
  475. } else {
  476. $retarr[strtoupper($fld->name)] = $fld;
  477. }
  478. $rs->MoveNext();
  479. }
  480. $rs->Close();
  481. return $retarr;
  482. }
  483. // returns true or false
  484. function SelectDB($dbName)
  485. {
  486. $this->database = $dbName;
  487. $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
  488. if ($this->_connectionID) {
  489. return @mysql_select_db($dbName,$this->_connectionID);
  490. }
  491. else return false;
  492. }
  493. // parameters use PostgreSQL convention, not MySQL
  494. function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs=0)
  495. {
  496. $nrows = (int) $nrows;
  497. $offset = (int) $offset;
  498. $offsetStr =($offset>=0) ? ((integer)$offset)."," : '';
  499. // jason judge, see http://phplens.com/lens/lensforum/msgs.php?id=9220
  500. if ($nrows < 0) $nrows = '18446744073709551615';
  501. if ($secs)
  502. $rs = $this->CacheExecute($secs,$sql." LIMIT $offsetStr".((integer)$nrows),$inputarr);
  503. else
  504. $rs = $this->Execute($sql." LIMIT $offsetStr".((integer)$nrows),$inputarr);
  505. return $rs;
  506. }
  507. // returns queryID or false
  508. function _query($sql,$inputarr=false)
  509. {
  510. return mysql_query($sql,$this->_connectionID);
  511. /*
  512. global $ADODB_COUNTRECS;
  513. if($ADODB_COUNTRECS)
  514. return mysql_query($sql,$this->_connectionID);
  515. else
  516. return @mysql_unbuffered_query($sql,$this->_connectionID); // requires PHP >= 4.0.6
  517. */
  518. }
  519. /* Returns: the last error message from previous database operation */
  520. function ErrorMsg()
  521. {
  522. if ($this->_logsql) return $this->_errorMsg;
  523. if (empty($this->_connectionID)) $this->_errorMsg = @mysql_error();
  524. else $this->_errorMsg = @mysql_error($this->_connectionID);
  525. return $this->_errorMsg;
  526. }
  527. /* Returns: the last error number from previous database operation */
  528. function ErrorNo()
  529. {
  530. if ($this->_logsql) return $this->_errorCode;
  531. if (empty($this->_connectionID)) return @mysql_errno();
  532. else return @mysql_errno($this->_connectionID);
  533. }
  534. // returns true or false
  535. function _close()
  536. {
  537. @mysql_close($this->_connectionID);
  538. $this->charSet = '';
  539. $this->_connectionID = false;
  540. }
  541. /*
  542. * Maximum size of C field
  543. */
  544. function CharMax()
  545. {
  546. return 255;
  547. }
  548. /*
  549. * Maximum size of X field
  550. */
  551. function TextMax()
  552. {
  553. return 4294967295;
  554. }
  555. // "Innox - Juan Carlos Gonzalez" <jgonzalez#innox.com.mx>
  556. function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
  557. {
  558. global $ADODB_FETCH_MODE;
  559. if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true;
  560. if ( !empty($owner) ) {
  561. $table = "$owner.$table";
  562. }
  563. $a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
  564. if ($associative) {
  565. $create_sql = isset($a_create_table["Create Table"]) ? $a_create_table["Create Table"] : $a_create_table["Create View"];
  566. } else {
  567. $create_sql = $a_create_table[1];
  568. }
  569. $matches = array();
  570. if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false;
  571. $foreign_keys = array();
  572. $num_keys = count($matches[0]);
  573. for ( $i = 0; $i < $num_keys; $i ++ ) {
  574. $my_field = explode('`, `', $matches[1][$i]);
  575. $ref_table = $matches[2][$i];
  576. $ref_field = explode('`, `', $matches[3][$i]);
  577. if ( $upper ) {
  578. $ref_table = strtoupper($ref_table);
  579. }
  580. // see https://sourceforge.net/p/adodb/bugs/100/
  581. if (!isset($foreign_keys[$ref_table])) {
  582. $foreign_keys[$ref_table] = array();
  583. }
  584. $num_fields = count($my_field);
  585. for ( $j = 0; $j < $num_fields; $j ++ ) {
  586. if ( $associative ) {
  587. $foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j];
  588. } else {
  589. $foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}";
  590. }
  591. }
  592. }
  593. return $foreign_keys;
  594. }
  595. }
  596. /*--------------------------------------------------------------------------------------
  597. Class Name: Recordset
  598. --------------------------------------------------------------------------------------*/
  599. class ADORecordSet_mysql extends ADORecordSet{
  600. var $databaseType = "mysql";
  601. var $canSeek = true;
  602. function __construct($queryID,$mode=false)
  603. {
  604. if ($mode === false) {
  605. global $ADODB_FETCH_MODE;
  606. $mode = $ADODB_FETCH_MODE;
  607. }
  608. switch ($mode)
  609. {
  610. case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break;
  611. case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break;
  612. case ADODB_FETCH_DEFAULT:
  613. case ADODB_FETCH_BOTH:
  614. default:
  615. $this->fetchMode = MYSQL_BOTH; break;
  616. }
  617. $this->adodbFetchMode = $mode;
  618. parent::__construct($queryID);
  619. }
  620. function _initrs()
  621. {
  622. //GLOBAL $ADODB_COUNTRECS;
  623. // $this->_numOfRows = ($ADODB_COUNTRECS) ? @mysql_num_rows($this->_queryID):-1;
  624. $this->_numOfRows = @mysql_num_rows($this->_queryID);
  625. $this->_numOfFields = @mysql_num_fields($this->_queryID);
  626. }
  627. function FetchField($fieldOffset = -1)
  628. {
  629. if ($fieldOffset != -1) {
  630. $o = @mysql_fetch_field($this->_queryID, $fieldOffset);
  631. $f = @mysql_field_flags($this->_queryID,$fieldOffset);
  632. if ($o) $o->max_length = @mysql_field_len($this->_queryID,$fieldOffset); // suggested by: Jim Nicholson (jnich#att.com)
  633. //$o->max_length = -1; // mysql returns the max length less spaces -- so it is unrealiable
  634. if ($o) $o->binary = (strpos($f,'binary')!== false);
  635. }
  636. else { /* The $fieldOffset argument is not provided thus its -1 */
  637. $o = @mysql_fetch_field($this->_queryID);
  638. //if ($o) $o->max_length = @mysql_field_len($this->_queryID); // suggested by: Jim Nicholson (jnich#att.com)
  639. $o->max_length = -1; // mysql returns the max length less spaces -- so it is unrealiable
  640. }
  641. return $o;
  642. }
  643. function GetRowAssoc($upper = ADODB_ASSOC_CASE)
  644. {
  645. if ($this->fetchMode == MYSQL_ASSOC && $upper == ADODB_ASSOC_CASE_LOWER) {
  646. $row = $this->fields;
  647. }
  648. else {
  649. $row = ADORecordSet::GetRowAssoc($upper);
  650. }
  651. return $row;
  652. }
  653. /* Use associative array to get fields array */
  654. function Fields($colname)
  655. {
  656. // added @ by "Michael William Miller" <mille562@pilot.msu.edu>
  657. if ($this->fetchMode != MYSQL_NUM) return @$this->fields[$colname];
  658. if (!$this->bind) {
  659. $this->bind = array();
  660. for ($i=0; $i < $this->_numOfFields; $i++) {
  661. $o = $this->FetchField($i);
  662. $this->bind[strtoupper($o->name)] = $i;
  663. }
  664. }
  665. return $this->fields[$this->bind[strtoupper($colname)]];
  666. }
  667. function _seek($row)
  668. {
  669. if ($this->_numOfRows == 0) return false;
  670. return @mysql_data_seek($this->_queryID,$row);
  671. }
  672. function MoveNext()
  673. {
  674. //return adodb_movenext($this);
  675. //if (defined('ADODB_EXTENSION')) return adodb_movenext($this);
  676. if (@$this->fields = mysql_fetch_array($this->_queryID,$this->fetchMode)) {
  677. $this->_updatefields();
  678. $this->_currentRow += 1;
  679. return true;
  680. }
  681. if (!$this->EOF) {
  682. $this->_currentRow += 1;
  683. $this->EOF = true;
  684. }
  685. return false;
  686. }
  687. function _fetch()
  688. {
  689. $this->fields = @mysql_fetch_array($this->_queryID,$this->fetchMode);
  690. $this->_updatefields();
  691. return is_array($this->fields);
  692. }
  693. function _close() {
  694. @mysql_free_result($this->_queryID);
  695. $this->_queryID = false;
  696. }
  697. function MetaType($t,$len=-1,$fieldobj=false)
  698. {
  699. if (is_object($t)) {
  700. $fieldobj = $t;
  701. $t = $fieldobj->type;
  702. $len = $fieldobj->max_length;
  703. }
  704. $len = -1; // mysql max_length is not accurate
  705. switch (strtoupper($t)) {
  706. case 'STRING':
  707. case 'CHAR':
  708. case 'VARCHAR':
  709. case 'TINYBLOB':
  710. case 'TINYTEXT':
  711. case 'ENUM':
  712. case 'SET':
  713. if ($len <= $this->blobSize) return 'C';
  714. case 'TEXT':
  715. case 'LONGTEXT':
  716. case 'MEDIUMTEXT':
  717. return 'X';
  718. // php_mysql extension always returns 'blob' even if 'text'
  719. // so we have to check whether binary...
  720. case 'IMAGE':
  721. case 'LONGBLOB':
  722. case 'BLOB':
  723. case 'MEDIUMBLOB':
  724. case 'BINARY':
  725. return !empty($fieldobj->binary) ? 'B' : 'X';
  726. case 'YEAR':
  727. case 'DATE': return 'D';
  728. case 'TIME':
  729. case 'DATETIME':
  730. case 'TIMESTAMP': return 'T';
  731. case 'INT':
  732. case 'INTEGER':
  733. case 'BIGINT':
  734. case 'TINYINT':
  735. case 'MEDIUMINT':
  736. case 'SMALLINT':
  737. if (!empty($fieldobj->primary_key)) return 'R';
  738. else return 'I';
  739. default: return 'N';
  740. }
  741. }
  742. }
  743. class ADORecordSet_ext_mysql extends ADORecordSet_mysql {
  744. function __construct($queryID,$mode=false)
  745. {
  746. parent::__construct($queryID,$mode);
  747. }
  748. function MoveNext()
  749. {
  750. return @adodb_movenext($this);
  751. }
  752. }
  753. }