00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 if (!defined('ADODB_DIR')) die();
00017
00018 if (! defined("_ADODB_MYSQL_LAYER")) {
00019 define("_ADODB_MYSQL_LAYER", 1 );
00020
00021 class ADODB_mysql extends ADOConnection {
00022 var $databaseType = 'mysql';
00023 var $dataProvider = 'mysql';
00024 var $hasInsertID = true;
00025 var $hasAffectedRows = true;
00026 var $metaTablesSQL = "SHOW TABLES";
00027 var $metaColumnsSQL = "SHOW COLUMNS FROM %s";
00028 var $fmtTimeStamp = "'Y-m-d H:i:s'";
00029 var $hasLimit = true;
00030 var $hasMoveFirst = true;
00031 var $hasGenID = true;
00032 var $isoDates = true;
00033 var $sysDate = 'CURDATE()';
00034 var $sysTimeStamp = 'NOW()';
00035 var $hasTransactions = false;
00036 var $forceNewConnect = false;
00037 var $poorAffectedRows = true;
00038 var $clientFlags = 0;
00039 var $substr = "substring";
00040 var $nameQuote = '`';
00041 var $compat323 = false;
00042
00043 function ADODB_mysql()
00044 {
00045 if (defined('ADODB_EXTENSION')) $this->rsPrefix .= 'ext_';
00046 }
00047
00048 function ServerInfo()
00049 {
00050 $arr['description'] = ADOConnection::GetOne("select version()");
00051 $arr['version'] = ADOConnection::_findvers($arr['description']);
00052 return $arr;
00053 }
00054
00055 function IfNull( $field, $ifNull )
00056 {
00057 return " IFNULL($field, $ifNull) ";
00058 }
00059
00060
00061 function &MetaTables($ttype=false,$showSchema=false,$mask=false)
00062 {
00063 $save = $this->metaTablesSQL;
00064 if ($showSchema && is_string($showSchema)) {
00065 $this->metaTablesSQL .= " from $showSchema";
00066 }
00067
00068 if ($mask) {
00069 $mask = $this->qstr($mask);
00070 $this->metaTablesSQL .= " like $mask";
00071 }
00072 $ret =& ADOConnection::MetaTables($ttype,$showSchema);
00073
00074 $this->metaTablesSQL = $save;
00075 return $ret;
00076 }
00077
00078
00079 function &MetaIndexes ($table, $primary = FALSE, $owner=false)
00080 {
00081
00082 global $ADODB_FETCH_MODE;
00083
00084 $false = false;
00085 $save = $ADODB_FETCH_MODE;
00086 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00087 if ($this->fetchMode !== FALSE) {
00088 $savem = $this->SetFetchMode(FALSE);
00089 }
00090
00091
00092 $rs = $this->Execute(sprintf('SHOW INDEX FROM %s',$table));
00093
00094
00095 if (isset($savem)) {
00096 $this->SetFetchMode($savem);
00097 }
00098 $ADODB_FETCH_MODE = $save;
00099
00100 if (!is_object($rs)) {
00101 return $false;
00102 }
00103
00104 $indexes = array ();
00105
00106
00107 while ($row = $rs->FetchRow()) {
00108 if ($primary == FALSE AND $row[2] == 'PRIMARY') {
00109 continue;
00110 }
00111
00112 if (!isset($indexes[$row[2]])) {
00113 $indexes[$row[2]] = array(
00114 'unique' => ($row[1] == 0),
00115 'columns' => array()
00116 );
00117 }
00118
00119 $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];
00120 }
00121
00122
00123 foreach ( array_keys ($indexes) as $index )
00124 {
00125 ksort ($indexes[$index]['columns']);
00126 }
00127
00128 return $indexes;
00129 }
00130
00131
00132
00133 function qstr($s,$magic_quotes=false)
00134 {
00135 if (!$magic_quotes) {
00136
00137 if (ADODB_PHPVER >= 0x4300) {
00138 if (is_resource($this->_connectionID))
00139 return "'".mysql_real_escape_string($s,$this->_connectionID)."'";
00140 }
00141 if ($this->replaceQuote[0] == '\\'){
00142 $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
00143 }
00144 return "'".str_replace("'",$this->replaceQuote,$s)."'";
00145 }
00146
00147
00148 $s = str_replace('\\"','"',$s);
00149 return "'$s'";
00150 }
00151
00152 function _insertid()
00153 {
00154 return ADOConnection::GetOne('SELECT LAST_INSERT_ID()');
00155
00156 }
00157
00158 function GetOne($sql,$inputarr=false)
00159 {
00160 if ($this->compat323 == false && strncasecmp($sql,'sele',4) == 0) {
00161 $rs =& $this->SelectLimit($sql,1,-1,$inputarr);
00162 if ($rs) {
00163 $rs->Close();
00164 if ($rs->EOF) return false;
00165 return reset($rs->fields);
00166 }
00167 } else {
00168 return ADOConnection::GetOne($sql,$inputarr);
00169 }
00170 return false;
00171 }
00172
00173 function BeginTrans()
00174 {
00175 if ($this->debug) ADOConnection::outp("Transactions not supported in 'mysql' driver. Use 'mysqlt' or 'mysqli' driver");
00176 }
00177
00178 function _affectedrows()
00179 {
00180 return mysql_affected_rows($this->_connectionID);
00181 }
00182
00183
00184
00185 var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
00186 var $_genSeqSQL = "create table %s (id int not null)";
00187 var $_genSeq2SQL = "insert into %s values (%s)";
00188 var $_dropSeqSQL = "drop table %s";
00189
00190 function CreateSequence($seqname='adodbseq',$startID=1)
00191 {
00192 if (empty($this->_genSeqSQL)) return false;
00193 $u = strtoupper($seqname);
00194
00195 $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
00196 if (!$ok) return false;
00197 return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
00198 }
00199
00200
00201 function GenID($seqname='adodbseq',$startID=1)
00202 {
00203
00204 if (!$this->hasGenID) return false;
00205
00206 $savelog = $this->_logsql;
00207 $this->_logsql = false;
00208 $getnext = sprintf($this->_genIDSQL,$seqname);
00209 $holdtransOK = $this->_transOK;
00210 $rs = @$this->Execute($getnext);
00211 if (!$rs) {
00212 if ($holdtransOK) $this->_transOK = true;
00213 $u = strtoupper($seqname);
00214 $this->Execute(sprintf($this->_genSeqSQL,$seqname));
00215 $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
00216 $rs = $this->Execute($getnext);
00217 }
00218 $this->genID = mysql_insert_id($this->_connectionID);
00219
00220 if ($rs) $rs->Close();
00221
00222 $this->_logsql = $savelog;
00223 return $this->genID;
00224 }
00225
00226 function &MetaDatabases()
00227 {
00228 $qid = mysql_list_dbs($this->_connectionID);
00229 $arr = array();
00230 $i = 0;
00231 $max = mysql_num_rows($qid);
00232 while ($i < $max) {
00233 $db = mysql_tablename($qid,$i);
00234 if ($db != 'mysql') $arr[] = $db;
00235 $i += 1;
00236 }
00237 return $arr;
00238 }
00239
00240
00241
00242 function SQLDate($fmt, $col=false)
00243 {
00244 if (!$col) $col = $this->sysTimeStamp;
00245 $s = 'DATE_FORMAT('.$col.",'";
00246 $concat = false;
00247 $len = strlen($fmt);
00248 for ($i=0; $i < $len; $i++) {
00249 $ch = $fmt[$i];
00250 switch($ch) {
00251
00252 default:
00253 if ($ch == '\\') {
00254 $i++;
00255 $ch = substr($fmt,$i,1);
00256 }
00258 case '-':
00259 case '/':
00260 $s .= $ch;
00261 break;
00262
00263 case 'Y':
00264 case 'y':
00265 $s .= '%Y';
00266 break;
00267 case 'M':
00268 $s .= '%b';
00269 break;
00270
00271 case 'm':
00272 $s .= '%m';
00273 break;
00274 case 'D':
00275 case 'd':
00276 $s .= '%d';
00277 break;
00278
00279 case 'Q':
00280 case 'q':
00281 $s .= "'),Quarter($col)";
00282
00283 if ($len > $i+1) $s .= ",DATE_FORMAT($col,'";
00284 else $s .= ",('";
00285 $concat = true;
00286 break;
00287
00288 case 'H':
00289 $s .= '%H';
00290 break;
00291
00292 case 'h':
00293 $s .= '%I';
00294 break;
00295
00296 case 'i':
00297 $s .= '%i';
00298 break;
00299
00300 case 's':
00301 $s .= '%s';
00302 break;
00303
00304 case 'a':
00305 case 'A':
00306 $s .= '%p';
00307 break;
00308
00309 case 'w':
00310 $s .= '%w';
00311 break;
00312
00313 case 'W':
00314 $s .= '%U';
00315 break;
00316
00317 case 'l':
00318 $s .= '%W';
00319 break;
00320 }
00321 }
00322 $s.="')";
00323 if ($concat) $s = "CONCAT($s)";
00324 return $s;
00325 }
00326
00327
00328
00329
00330 function Concat()
00331 {
00332 $s = "";
00333 $arr = func_get_args();
00334
00335
00336 $s = implode(',',$arr);
00337 if (strlen($s) > 0) return "CONCAT($s)";
00338 else return '';
00339 }
00340
00341 function OffsetDate($dayFraction,$date=false)
00342 {
00343 if (!$date) $date = $this->sysDate;
00344 $fraction = $dayFraction * 24 * 3600;
00345 return "from_unixtime(unix_timestamp($date)+$fraction)";
00346 }
00347
00348
00349 function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
00350 {
00351 if (!empty($this->port)) $argHostname .= ":".$this->port;
00352
00353 if (ADODB_PHPVER >= 0x4300)
00354 $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword,
00355 $this->forceNewConnect,$this->clientFlags);
00356 else if (ADODB_PHPVER >= 0x4200)
00357 $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword,
00358 $this->forceNewConnect);
00359 else
00360 $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword);
00361
00362 if ($this->_connectionID === false) return false;
00363 if ($argDatabasename) return $this->SelectDB($argDatabasename);
00364 return true;
00365 }
00366
00367
00368 function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
00369 {
00370 if (!empty($this->port)) $argHostname .= ":".$this->port;
00371
00372 if (ADODB_PHPVER >= 0x4300)
00373 $this->_connectionID = mysql_pconnect($argHostname,$argUsername,$argPassword,$this->clientFlags);
00374 else
00375 $this->_connectionID = mysql_pconnect($argHostname,$argUsername,$argPassword);
00376 if ($this->_connectionID === false) return false;
00377 if ($this->autoRollback) $this->RollbackTrans();
00378 if ($argDatabasename) return $this->SelectDB($argDatabasename);
00379 return true;
00380 }
00381
00382 function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
00383 {
00384 $this->forceNewConnect = true;
00385 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
00386 }
00387
00388 function &MetaColumns($table)
00389 {
00390 $this->_findschema($table,$schema);
00391 if ($schema) {
00392 $dbName = $this->database;
00393 $this->SelectDB($schema);
00394 }
00395 global $ADODB_FETCH_MODE;
00396 $save = $ADODB_FETCH_MODE;
00397 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00398
00399 if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
00400 $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
00401
00402 if ($schema) {
00403 $this->SelectDB($dbName);
00404 }
00405
00406 if (isset($savem)) $this->SetFetchMode($savem);
00407 $ADODB_FETCH_MODE = $save;
00408 if (!is_object($rs)) {
00409 $false = false;
00410 return $false;
00411 }
00412
00413 $retarr = array();
00414 while (!$rs->EOF){
00415 $fld = new ADOFieldObject();
00416 $fld->name = $rs->fields[0];
00417 $type = $rs->fields[1];
00418
00419
00420 $fld->scale = null;
00421 if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {
00422 $fld->type = $query_array[1];
00423 $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
00424 $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;
00425 } elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {
00426 $fld->type = $query_array[1];
00427 $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
00428 } elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) {
00429 $fld->type = $query_array[1];
00430 $arr = explode(",",$query_array[2]);
00431 $fld->enums = $arr;
00432 $zlen = max(array_map("strlen",$arr)) - 2;
00433 $fld->max_length = ($zlen > 0) ? $zlen : 1;
00434 } else {
00435 $fld->type = $type;
00436 $fld->max_length = -1;
00437 }
00438 $fld->not_null = ($rs->fields[2] != 'YES');
00439 $fld->primary_key = ($rs->fields[3] == 'PRI');
00440 $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
00441 $fld->binary = (strpos($type,'blob') !== false);
00442 $fld->unsigned = (strpos($type,'unsigned') !== false);
00443
00444 if (!$fld->binary) {
00445 $d = $rs->fields[4];
00446 if ($d != '' && $d != 'NULL') {
00447 $fld->has_default = true;
00448 $fld->default_value = $d;
00449 } else {
00450 $fld->has_default = false;
00451 }
00452 }
00453
00454 if ($save == ADODB_FETCH_NUM) {
00455 $retarr[] = $fld;
00456 } else {
00457 $retarr[strtoupper($fld->name)] = $fld;
00458 }
00459 $rs->MoveNext();
00460 }
00461
00462 $rs->Close();
00463 return $retarr;
00464 }
00465
00466
00467 function SelectDB($dbName)
00468 {
00469 $this->database = $dbName;
00470 $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
00471 if ($this->_connectionID) {
00472 return @mysql_select_db($dbName,$this->_connectionID);
00473 }
00474 else return false;
00475 }
00476
00477
00478 function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs=0)
00479 {
00480 $offsetStr =($offset>=0) ? ((integer)$offset)."," : '';
00481
00482 if ($nrows < 0) $nrows = '18446744073709551615';
00483
00484 if ($secs)
00485 $rs =& $this->CacheExecute($secs,$sql." LIMIT $offsetStr".((integer)$nrows),$inputarr);
00486 else
00487 $rs =& $this->Execute($sql." LIMIT $offsetStr".((integer)$nrows),$inputarr);
00488 return $rs;
00489 }
00490
00491
00492 function _query($sql,$inputarr)
00493 {
00494
00495
00496 return mysql_query($sql,$this->_connectionID);
00497
00498 }
00499
00500
00501 function ErrorMsg()
00502 {
00503
00504 if ($this->_logsql) return $this->_errorMsg;
00505 if (empty($this->_connectionID)) $this->_errorMsg = @mysql_error();
00506 else $this->_errorMsg = @mysql_error($this->_connectionID);
00507 return $this->_errorMsg;
00508 }
00509
00510
00511 function ErrorNo()
00512 {
00513 if ($this->_logsql) return $this->_errorCode;
00514 if (empty($this->_connectionID)) return @mysql_errno();
00515 else return @mysql_errno($this->_connectionID);
00516 }
00517
00518
00519 function _close()
00520 {
00521 @mysql_close($this->_connectionID);
00522 $this->_connectionID = false;
00523 }
00524
00525
00526
00527
00528
00529 function CharMax()
00530 {
00531 return 255;
00532 }
00533
00534
00535
00536
00537 function TextMax()
00538 {
00539 return 4294967295;
00540 }
00541
00542
00543 function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
00544 {
00545 if ( !empty($owner) ) {
00546 $table = "$owner.$table";
00547 }
00548 $a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
00549 if ($associative) $create_sql = $a_create_table["Create Table"];
00550 else $create_sql = $a_create_table[1];
00551
00552 $matches = array();
00553
00554 if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false;
00555 $foreign_keys = array();
00556 $num_keys = count($matches[0]);
00557 for ( $i = 0; $i < $num_keys; $i ++ ) {
00558 $my_field = explode('`, `', $matches[1][$i]);
00559 $ref_table = $matches[2][$i];
00560 $ref_field = explode('`, `', $matches[3][$i]);
00561
00562 if ( $upper ) {
00563 $ref_table = strtoupper($ref_table);
00564 }
00565
00566 $foreign_keys[$ref_table] = array();
00567 $num_fields = count($my_field);
00568 for ( $j = 0; $j < $num_fields; $j ++ ) {
00569 if ( $associative ) {
00570 $foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j];
00571 } else {
00572 $foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}";
00573 }
00574 }
00575 }
00576
00577 return $foreign_keys;
00578 }
00579
00580
00581 }
00582
00583
00584
00585
00586
00587
00588 class ADORecordSet_mysql extends ADORecordSet{
00589
00590 var $databaseType = "mysql";
00591 var $canSeek = true;
00592
00593 function ADORecordSet_mysql($queryID,$mode=false)
00594 {
00595 if ($mode === false) {
00596 global $ADODB_FETCH_MODE;
00597 $mode = $ADODB_FETCH_MODE;
00598 }
00599 switch ($mode)
00600 {
00601 case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break;
00602 case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break;
00603 case ADODB_FETCH_DEFAULT:
00604 case ADODB_FETCH_BOTH:
00605 default:
00606 $this->fetchMode = MYSQL_BOTH; break;
00607 }
00608 $this->adodbFetchMode = $mode;
00609 $this->ADORecordSet($queryID);
00610 }
00611
00612 function _initrs()
00613 {
00614
00615
00616 $this->_numOfRows = @mysql_num_rows($this->_queryID);
00617 $this->_numOfFields = @mysql_num_fields($this->_queryID);
00618 }
00619
00620 function &FetchField($fieldOffset = -1)
00621 {
00622 if ($fieldOffset != -1) {
00623 $o = @mysql_fetch_field($this->_queryID, $fieldOffset);
00624 $f = @mysql_field_flags($this->_queryID,$fieldOffset);
00625 $o->max_length = @mysql_field_len($this->_queryID,$fieldOffset);
00626
00627 $o->binary = (strpos($f,'binary')!== false);
00628 }
00629 else if ($fieldOffset == -1) {
00630 $o = @mysql_fetch_field($this->_queryID);
00631 $o->max_length = @mysql_field_len($this->_queryID);
00632
00633 }
00634
00635 return $o;
00636 }
00637
00638 function &GetRowAssoc($upper=true)
00639 {
00640 if ($this->fetchMode == MYSQL_ASSOC && !$upper) return $this->fields;
00641 $row =& ADORecordSet::GetRowAssoc($upper);
00642 return $row;
00643 }
00644
00645
00646 function Fields($colname)
00647 {
00648
00649 if ($this->fetchMode != MYSQL_NUM) return @$this->fields[$colname];
00650
00651 if (!$this->bind) {
00652 $this->bind = array();
00653 for ($i=0; $i < $this->_numOfFields; $i++) {
00654 $o = $this->FetchField($i);
00655 $this->bind[strtoupper($o->name)] = $i;
00656 }
00657 }
00658 return $this->fields[$this->bind[strtoupper($colname)]];
00659 }
00660
00661 function _seek($row)
00662 {
00663 if ($this->_numOfRows == 0) return false;
00664 return @mysql_data_seek($this->_queryID,$row);
00665 }
00666
00667 function MoveNext()
00668 {
00669
00670
00671 if (@$this->fields = mysql_fetch_array($this->_queryID,$this->fetchMode)) {
00672 $this->_currentRow += 1;
00673 return true;
00674 }
00675 if (!$this->EOF) {
00676 $this->_currentRow += 1;
00677 $this->EOF = true;
00678 }
00679 return false;
00680 }
00681
00682 function _fetch()
00683 {
00684 $this->fields = @mysql_fetch_array($this->_queryID,$this->fetchMode);
00685 return is_array($this->fields);
00686 }
00687
00688 function _close() {
00689 @mysql_free_result($this->_queryID);
00690 $this->_queryID = false;
00691 }
00692
00693 function MetaType($t,$len=-1,$fieldobj=false)
00694 {
00695 if (is_object($t)) {
00696 $fieldobj = $t;
00697 $t = $fieldobj->type;
00698 $len = $fieldobj->max_length;
00699 }
00700
00701 $len = -1;
00702 switch (strtoupper($t)) {
00703 case 'STRING':
00704 case 'CHAR':
00705 case 'VARCHAR':
00706 case 'TINYBLOB':
00707 case 'TINYTEXT':
00708 case 'ENUM':
00709 case 'SET':
00710 if ($len <= $this->blobSize) return 'C';
00711
00712 case 'TEXT':
00713 case 'LONGTEXT':
00714 case 'MEDIUMTEXT':
00715 return 'X';
00716
00717
00718
00719 case 'IMAGE':
00720 case 'LONGBLOB':
00721 case 'BLOB':
00722 case 'MEDIUMBLOB':
00723 return !empty($fieldobj->binary) ? 'B' : 'X';
00724
00725 case 'YEAR':
00726 case 'DATE': return 'D';
00727
00728 case 'TIME':
00729 case 'DATETIME':
00730 case 'TIMESTAMP': return 'T';
00731
00732 case 'INT':
00733 case 'INTEGER':
00734 case 'BIGINT':
00735 case 'TINYINT':
00736 case 'MEDIUMINT':
00737 case 'SMALLINT':
00738
00739 if (!empty($fieldobj->primary_key)) return 'R';
00740 else return 'I';
00741
00742 default: return 'N';
00743 }
00744 }
00745
00746 }
00747
00748 class ADORecordSet_ext_mysql extends ADORecordSet_mysql {
00749 function ADORecordSet_ext_mysql($queryID,$mode=false)
00750 {
00751 if ($mode === false) {
00752 global $ADODB_FETCH_MODE;
00753 $mode = $ADODB_FETCH_MODE;
00754 }
00755 switch ($mode)
00756 {
00757 case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break;
00758 case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break;
00759 case ADODB_FETCH_DEFAULT:
00760 case ADODB_FETCH_BOTH:
00761 default:
00762 $this->fetchMode = MYSQL_BOTH; break;
00763 }
00764 $this->adodbFetchMode = $mode;
00765 $this->ADORecordSet($queryID);
00766 }
00767
00768 function MoveNext()
00769 {
00770 return @adodb_movenext($this);
00771 }
00772 }
00773
00774
00775 }
00776 ?>