Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 311] [Versions 39 and 400]

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