[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 /* 3 V5.19 23-Apr-2014 (c) 2000-2014 John Lim (jlim#natsoft.com). All rights reserved. 4 Released under both BSD license and Lesser GPL library license. 5 Whenever there is any discrepancy between the two licenses, 6 the BSD license will take precedence. 7 Set tabs to 8. 8 9 MySQL code that does not support transactions. Use mysqlt if you need transactions. 10 Requires mysql client. Works on Windows and Unix. 11 12 21 October 2003: MySQLi extension implementation by Arjen de Rijke ([email protected]) 13 Based on adodb 3.40 14 */ 15 16 // security - hide paths 17 if (!defined('ADODB_DIR')) die(); 18 19 if (! defined("_ADODB_MYSQLI_LAYER")) { 20 define("_ADODB_MYSQLI_LAYER", 1 ); 21 22 // PHP5 compat... 23 if (! defined("MYSQLI_BINARY_FLAG")) define("MYSQLI_BINARY_FLAG", 128); 24 if (!defined('MYSQLI_READ_DEFAULT_GROUP')) define('MYSQLI_READ_DEFAULT_GROUP',1); 25 26 // disable adodb extension - currently incompatible. 27 global $ADODB_EXTENSION; $ADODB_EXTENSION = false; 28 29 class ADODB_mysqli extends ADOConnection { 30 var $databaseType = 'mysqli'; 31 var $dataProvider = 'mysql'; 32 var $hasInsertID = true; 33 var $hasAffectedRows = true; 34 var $metaTablesSQL = "SELECT 35 TABLE_NAME, 36 CASE WHEN TABLE_TYPE = 'VIEW' THEN 'V' ELSE 'T' END 37 FROM INFORMATION_SCHEMA.TABLES 38 WHERE TABLE_SCHEMA="; 39 var $metaColumnsSQL = "SHOW COLUMNS FROM `%s`"; 40 var $fmtTimeStamp = "'Y-m-d H:i:s'"; 41 var $hasLimit = true; 42 var $hasMoveFirst = true; 43 var $hasGenID = true; 44 var $isoDates = true; // accepts dates in ISO format 45 var $sysDate = 'CURDATE()'; 46 var $sysTimeStamp = 'NOW()'; 47 var $hasTransactions = true; 48 var $forceNewConnect = false; 49 var $poorAffectedRows = true; 50 var $clientFlags = 0; 51 var $substr = "substring"; 52 var $port = false; 53 var $socket = false; 54 var $_bindInputArray = false; 55 var $nameQuote = '`'; /// string to use to quote identifiers and names 56 var $optionFlags = array(array(MYSQLI_READ_DEFAULT_GROUP,0)); 57 var $arrayClass = 'ADORecordSet_array_mysqli'; 58 var $multiQuery = false; 59 60 function ADODB_mysqli() 61 { 62 // if(!extension_loaded("mysqli")) 63 ;//trigger_error("You must have the mysqli extension installed.", E_USER_ERROR); 64 65 } 66 67 function SetTransactionMode( $transaction_mode ) 68 { 69 $this->_transmode = $transaction_mode; 70 if (empty($transaction_mode)) { 71 $this->Execute('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ'); 72 return; 73 } 74 if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode; 75 $this->Execute("SET SESSION TRANSACTION ".$transaction_mode); 76 } 77 78 // returns true or false 79 // To add: parameter int $port, 80 // parameter string $socket 81 function _connect($argHostname = NULL, 82 $argUsername = NULL, 83 $argPassword = NULL, 84 $argDatabasename = NULL, $persist=false) 85 { 86 if(!extension_loaded("mysqli")) { 87 return null; 88 } 89 $this->_connectionID = @mysqli_init(); 90 91 if (is_null($this->_connectionID)) { 92 // mysqli_init only fails if insufficient memory 93 if ($this->debug) 94 ADOConnection::outp("mysqli_init() failed : " . $this->ErrorMsg()); 95 return false; 96 } 97 /* 98 I suggest a simple fix which would enable adodb and mysqli driver to 99 read connection options from the standard mysql configuration file 100 /etc/my.cnf - "Bastien Duclaux" <bduclaux#yahoo.com> 101 */ 102 foreach($this->optionFlags as $arr) { 103 mysqli_options($this->_connectionID,$arr[0],$arr[1]); 104 } 105 106 //http ://php.net/manual/en/mysqli.persistconns.php 107 if ($persist && PHP_VERSION > 5.2 && strncmp($argHostname,'p:',2) != 0) $argHostname = 'p:'.$argHostname; 108 109 #if (!empty($this->port)) $argHostname .= ":".$this->port; 110 $ok = mysqli_real_connect($this->_connectionID, 111 $argHostname, 112 $argUsername, 113 $argPassword, 114 $argDatabasename, 115 $this->port, 116 $this->socket, 117 $this->clientFlags); 118 119 if ($ok) { 120 if ($argDatabasename) return $this->SelectDB($argDatabasename); 121 return true; 122 } else { 123 if ($this->debug) 124 ADOConnection::outp("Could't connect : " . $this->ErrorMsg()); 125 $this->_connectionID = null; 126 return false; 127 } 128 } 129 130 // returns true or false 131 // How to force a persistent connection 132 function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) 133 { 134 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true); 135 136 } 137 138 // When is this used? Close old connection first? 139 // In _connect(), check $this->forceNewConnect? 140 function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename) 141 { 142 $this->forceNewConnect = true; 143 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename); 144 } 145 146 function IfNull( $field, $ifNull ) 147 { 148 return " IFNULL($field, $ifNull) "; // if MySQL 149 } 150 151 // do not use $ADODB_COUNTRECS 152 function GetOne($sql,$inputarr=false) 153 { 154 global $ADODB_GETONE_EOF; 155 156 $ret = false; 157 $rs = $this->Execute($sql,$inputarr); 158 if ($rs) { 159 if ($rs->EOF) $ret = $ADODB_GETONE_EOF; 160 else $ret = reset($rs->fields); 161 $rs->Close(); 162 } 163 return $ret; 164 } 165 166 function ServerInfo() 167 { 168 $arr['description'] = $this->GetOne("select version()"); 169 $arr['version'] = ADOConnection::_findvers($arr['description']); 170 return $arr; 171 } 172 173 174 function BeginTrans() 175 { 176 if ($this->transOff) return true; 177 $this->transCnt += 1; 178 179 //$this->Execute('SET AUTOCOMMIT=0'); 180 mysqli_autocommit($this->_connectionID, false); 181 $this->Execute('BEGIN'); 182 return true; 183 } 184 185 function CommitTrans($ok=true) 186 { 187 if ($this->transOff) return true; 188 if (!$ok) return $this->RollbackTrans(); 189 190 if ($this->transCnt) $this->transCnt -= 1; 191 $this->Execute('COMMIT'); 192 193 //$this->Execute('SET AUTOCOMMIT=1'); 194 mysqli_autocommit($this->_connectionID, true); 195 return true; 196 } 197 198 function RollbackTrans() 199 { 200 if ($this->transOff) return true; 201 if ($this->transCnt) $this->transCnt -= 1; 202 $this->Execute('ROLLBACK'); 203 //$this->Execute('SET AUTOCOMMIT=1'); 204 mysqli_autocommit($this->_connectionID, true); 205 return true; 206 } 207 208 function RowLock($tables,$where='',$col='1 as adodbignore') 209 { 210 if ($this->transCnt==0) $this->BeginTrans(); 211 if ($where) $where = ' where '.$where; 212 $rs = $this->Execute("select $col from $tables $where for update"); 213 return !empty($rs); 214 } 215 216 // if magic quotes disabled, use mysql_real_escape_string() 217 // From docs-adodb.htm: 218 // Quotes a string to be sent to the database. The $magic_quotes_enabled 219 // parameter may look funny, but the idea is if you are quoting a 220 // string extracted from a POST/GET variable, then 221 // pass get_magic_quotes_gpc() as the second parameter. This will 222 // ensure that the variable is not quoted twice, once by qstr and once 223 // by the magic_quotes_gpc. 224 // 225 //Eg. $s = $db->qstr(_GET['name'],get_magic_quotes_gpc()); 226 function qstr($s, $magic_quotes = false) 227 { 228 if (is_null($s)) return 'NULL'; 229 if (!$magic_quotes) { 230 if (PHP_VERSION >= 5) 231 return "'" . mysqli_real_escape_string($this->_connectionID, $s) . "'"; 232 233 if ($this->replaceQuote[0] == '\\') 234 $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s); 235 return "'".str_replace("'",$this->replaceQuote,$s)."'"; 236 } 237 // undo magic quotes for " 238 $s = str_replace('\\"','"',$s); 239 return "'$s'"; 240 } 241 242 function _insertid() 243 { 244 $result = @mysqli_insert_id($this->_connectionID); 245 if ($result == -1){ 246 if ($this->debug) ADOConnection::outp("mysqli_insert_id() failed : " . $this->ErrorMsg()); 247 } 248 return $result; 249 } 250 251 // Only works for INSERT, UPDATE and DELETE query's 252 function _affectedrows() 253 { 254 $result = @mysqli_affected_rows($this->_connectionID); 255 if ($result == -1) { 256 if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : " . $this->ErrorMsg()); 257 } 258 return $result; 259 } 260 261 // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html 262 // Reference on Last_Insert_ID on the recommended way to simulate sequences 263 var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);"; 264 var $_genSeqSQL = "create table %s (id int not null)"; 265 var $_genSeqCountSQL = "select count(*) from %s"; 266 var $_genSeq2SQL = "insert into %s values (%s)"; 267 var $_dropSeqSQL = "drop table %s"; 268 269 function CreateSequence($seqname='adodbseq',$startID=1) 270 { 271 if (empty($this->_genSeqSQL)) return false; 272 $u = strtoupper($seqname); 273 274 $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname)); 275 if (!$ok) return false; 276 return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1)); 277 } 278 279 function GenID($seqname='adodbseq',$startID=1) 280 { 281 // post-nuke sets hasGenID to false 282 if (!$this->hasGenID) return false; 283 284 $getnext = sprintf($this->_genIDSQL,$seqname); 285 $holdtransOK = $this->_transOK; // save the current status 286 $rs = @$this->Execute($getnext); 287 if (!$rs) { 288 if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset 289 $u = strtoupper($seqname); 290 $this->Execute(sprintf($this->_genSeqSQL,$seqname)); 291 $cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seqname)); 292 if (!$cnt) $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1)); 293 $rs = $this->Execute($getnext); 294 } 295 296 if ($rs) { 297 $this->genID = mysqli_insert_id($this->_connectionID); 298 $rs->Close(); 299 } else 300 $this->genID = 0; 301 302 return $this->genID; 303 } 304 305 function MetaDatabases() 306 { 307 $query = "SHOW DATABASES"; 308 $ret = $this->Execute($query); 309 if ($ret && is_object($ret)){ 310 $arr = array(); 311 while (!$ret->EOF){ 312 $db = $ret->Fields('Database'); 313 if ($db != 'mysql') $arr[] = $db; 314 $ret->MoveNext(); 315 } 316 return $arr; 317 } 318 return $ret; 319 } 320 321 322 function MetaIndexes ($table, $primary = FALSE, $owner = false) 323 { 324 // save old fetch mode 325 global $ADODB_FETCH_MODE; 326 327 $false = false; 328 $save = $ADODB_FETCH_MODE; 329 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 330 if ($this->fetchMode !== FALSE) { 331 $savem = $this->SetFetchMode(FALSE); 332 } 333 334 // get index details 335 $rs = $this->Execute(sprintf('SHOW INDEXES FROM %s',$table)); 336 337 // restore fetchmode 338 if (isset($savem)) { 339 $this->SetFetchMode($savem); 340 } 341 $ADODB_FETCH_MODE = $save; 342 343 if (!is_object($rs)) { 344 return $false; 345 } 346 347 $indexes = array (); 348 349 // parse index data into array 350 while ($row = $rs->FetchRow()) { 351 if ($primary == FALSE AND $row[2] == 'PRIMARY') { 352 continue; 353 } 354 355 if (!isset($indexes[$row[2]])) { 356 $indexes[$row[2]] = array( 357 'unique' => ($row[1] == 0), 358 'columns' => array() 359 ); 360 } 361 362 $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4]; 363 } 364 365 // sort columns by order in the index 366 foreach ( array_keys ($indexes) as $index ) 367 { 368 ksort ($indexes[$index]['columns']); 369 } 370 371 return $indexes; 372 } 373 374 375 // Format date column in sql string given an input format that understands Y M D 376 function SQLDate($fmt, $col=false) 377 { 378 if (!$col) $col = $this->sysTimeStamp; 379 $s = 'DATE_FORMAT('.$col.",'"; 380 $concat = false; 381 $len = strlen($fmt); 382 for ($i=0; $i < $len; $i++) { 383 $ch = $fmt[$i]; 384 switch($ch) { 385 case 'Y': 386 case 'y': 387 $s .= '%Y'; 388 break; 389 case 'Q': 390 case 'q': 391 $s .= "'),Quarter($col)"; 392 393 if ($len > $i+1) $s .= ",DATE_FORMAT($col,'"; 394 else $s .= ",('"; 395 $concat = true; 396 break; 397 case 'M': 398 $s .= '%b'; 399 break; 400 401 case 'm': 402 $s .= '%m'; 403 break; 404 case 'D': 405 case 'd': 406 $s .= '%d'; 407 break; 408 409 case 'H': 410 $s .= '%H'; 411 break; 412 413 case 'h': 414 $s .= '%I'; 415 break; 416 417 case 'i': 418 $s .= '%i'; 419 break; 420 421 case 's': 422 $s .= '%s'; 423 break; 424 425 case 'a': 426 case 'A': 427 $s .= '%p'; 428 break; 429 430 case 'w': 431 $s .= '%w'; 432 break; 433 434 case 'l': 435 $s .= '%W'; 436 break; 437 438 default: 439 440 if ($ch == '\\') { 441 $i++; 442 $ch = substr($fmt,$i,1); 443 } 444 $s .= $ch; 445 break; 446 } 447 } 448 $s.="')"; 449 if ($concat) $s = "CONCAT($s)"; 450 return $s; 451 } 452 453 // returns concatenated string 454 // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator 455 function Concat() 456 { 457 $s = ""; 458 $arr = func_get_args(); 459 460 // suggestion by [email protected] 461 $s = implode(',',$arr); 462 if (strlen($s) > 0) return "CONCAT($s)"; 463 else return ''; 464 } 465 466 // dayFraction is a day in floating point 467 function OffsetDate($dayFraction,$date=false) 468 { 469 if (!$date) $date = $this->sysDate; 470 471 $fraction = $dayFraction * 24 * 3600; 472 return $date . ' + INTERVAL ' . $fraction.' SECOND'; 473 474 // return "from_unixtime(unix_timestamp($date)+$fraction)"; 475 } 476 477 function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null) 478 { 479 // save old fetch mode 480 global $ADODB_FETCH_MODE; 481 482 $false = false; 483 $save = $ADODB_FETCH_MODE; 484 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 485 486 if ($this->fetchMode !== FALSE) { 487 $savem = $this->SetFetchMode(FALSE); 488 } 489 490 $procedures = array (); 491 492 // get index details 493 494 $likepattern = ''; 495 if ($NamePattern) { 496 $likepattern = " LIKE '".$NamePattern."'"; 497 } 498 $rs = $this->Execute('SHOW PROCEDURE STATUS'.$likepattern); 499 if (is_object($rs)) { 500 501 // parse index data into array 502 while ($row = $rs->FetchRow()) { 503 $procedures[$row[1]] = array( 504 'type' => 'PROCEDURE', 505 'catalog' => '', 506 507 'schema' => '', 508 'remarks' => $row[7], 509 ); 510 } 511 } 512 513 $rs = $this->Execute('SHOW FUNCTION STATUS'.$likepattern); 514 if (is_object($rs)) { 515 // parse index data into array 516 while ($row = $rs->FetchRow()) { 517 $procedures[$row[1]] = array( 518 'type' => 'FUNCTION', 519 'catalog' => '', 520 'schema' => '', 521 'remarks' => $row[7] 522 ); 523 } 524 } 525 526 // restore fetchmode 527 if (isset($savem)) { 528 $this->SetFetchMode($savem); 529 530 } 531 $ADODB_FETCH_MODE = $save; 532 533 534 return $procedures; 535 } 536 537 /** 538 * Retrieves a list of tables based on given criteria 539 * 540 * @param string $ttype Table type = 'TABLE', 'VIEW' or false=both (default) 541 * @param string $showSchema schema name, false = current schema (default) 542 * @param string $mask filters the table by name 543 * 544 * @return array list of tables 545 */ 546 function MetaTables($ttype=false,$showSchema=false,$mask=false) 547 { 548 $save = $this->metaTablesSQL; 549 if ($showSchema && is_string($showSchema)) { 550 $this->metaTablesSQL .= $this->qstr($showSchema); 551 } else { 552 $this->metaTablesSQL .= "schema()"; 553 } 554 555 if ($mask) { 556 $mask = $this->qstr($mask); 557 $this->metaTablesSQL .= " AND table_name LIKE $mask"; 558 } 559 $ret = ADOConnection::MetaTables($ttype,$showSchema); 560 561 $this->metaTablesSQL = $save; 562 return $ret; 563 } 564 565 // "Innox - Juan Carlos Gonzalez" <jgonzalez#innox.com.mx> 566 function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE ) 567 { 568 global $ADODB_FETCH_MODE; 569 570 if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true; 571 572 if ( !empty($owner) ) { 573 $table = "$owner.$table"; 574 } 575 $a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table)); 576 if ($associative) { 577 $create_sql = isset($a_create_table["Create Table"]) ? $a_create_table["Create Table"] : $a_create_table["Create View"]; 578 } else $create_sql = $a_create_table[1]; 579 580 $matches = array(); 581 582 if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false; 583 $foreign_keys = array(); 584 $num_keys = count($matches[0]); 585 for ( $i = 0; $i < $num_keys; $i ++ ) { 586 $my_field = explode('`, `', $matches[1][$i]); 587 $ref_table = $matches[2][$i]; 588 $ref_field = explode('`, `', $matches[3][$i]); 589 590 if ( $upper ) { 591 $ref_table = strtoupper($ref_table); 592 } 593 594 // see https://sourceforge.net/tracker/index.php?func=detail&aid=2287278&group_id=42718&atid=433976 595 if (!isset($foreign_keys[$ref_table])) { 596 $foreign_keys[$ref_table] = array(); 597 } 598 $num_fields = count($my_field); 599 for ( $j = 0; $j < $num_fields; $j ++ ) { 600 if ( $associative ) { 601 $foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j]; 602 } else { 603 $foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}"; 604 } 605 } 606 } 607 608 return $foreign_keys; 609 } 610 611 function MetaColumns($table, $normalize=true) 612 { 613 $false = false; 614 if (!$this->metaColumnsSQL) 615 return $false; 616 617 global $ADODB_FETCH_MODE; 618 $save = $ADODB_FETCH_MODE; 619 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 620 if ($this->fetchMode !== false) 621 $savem = $this->SetFetchMode(false); 622 $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table)); 623 if (isset($savem)) $this->SetFetchMode($savem); 624 $ADODB_FETCH_MODE = $save; 625 if (!is_object($rs)) 626 return $false; 627 628 $retarr = array(); 629 while (!$rs->EOF) { 630 $fld = new ADOFieldObject(); 631 $fld->name = $rs->fields[0]; 632 $type = $rs->fields[1]; 633 634 // split type into type(length): 635 $fld->scale = null; 636 if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) { 637 $fld->type = $query_array[1]; 638 $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1; 639 $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1; 640 } elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) { 641 $fld->type = $query_array[1]; 642 $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1; 643 } elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) { 644 $fld->type = $query_array[1]; 645 $arr = explode(",",$query_array[2]); 646 $fld->enums = $arr; 647 $zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6 648 $fld->max_length = ($zlen > 0) ? $zlen : 1; 649 } else { 650 $fld->type = $type; 651 $fld->max_length = -1; 652 } 653 $fld->not_null = ($rs->fields[2] != 'YES'); 654 $fld->primary_key = ($rs->fields[3] == 'PRI'); 655 $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false); 656 $fld->binary = (strpos($type,'blob') !== false); 657 $fld->unsigned = (strpos($type,'unsigned') !== false); 658 $fld->zerofill = (strpos($type,'zerofill') !== false); 659 660 if (!$fld->binary) { 661 $d = $rs->fields[4]; 662 if ($d != '' && $d != 'NULL') { 663 $fld->has_default = true; 664 $fld->default_value = $d; 665 } else { 666 $fld->has_default = false; 667 } 668 } 669 670 if ($save == ADODB_FETCH_NUM) { 671 $retarr[] = $fld; 672 } else { 673 $retarr[strtoupper($fld->name)] = $fld; 674 } 675 $rs->MoveNext(); 676 } 677 678 $rs->Close(); 679 return $retarr; 680 } 681 682 // returns true or false 683 function SelectDB($dbName) 684 { 685 // $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID); 686 $this->database = $dbName; 687 $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions 688 689 if ($this->_connectionID) { 690 $result = @mysqli_select_db($this->_connectionID, $dbName); 691 if (!$result) { 692 ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->ErrorMsg()); 693 } 694 return $result; 695 } 696 return false; 697 } 698 699 // parameters use PostgreSQL convention, not MySQL 700 function SelectLimit($sql, 701 $nrows = -1, 702 $offset = -1, 703 $inputarr = false, 704 $secs = 0) 705 { 706 $offsetStr = ($offset >= 0) ? "$offset," : ''; 707 if ($nrows < 0) $nrows = '18446744073709551615'; 708 709 if ($secs) 710 $rs = $this->CacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr ); 711 else 712 $rs = $this->Execute($sql . " LIMIT $offsetStr$nrows" , $inputarr ); 713 714 return $rs; 715 } 716 717 718 function Prepare($sql) 719 { 720 return $sql; 721 $stmt = $this->_connectionID->prepare($sql); 722 if (!$stmt) { 723 echo $this->ErrorMsg(); 724 return $sql; 725 } 726 return array($sql,$stmt); 727 } 728 729 730 // returns queryID or false 731 function _query($sql, $inputarr) 732 { 733 global $ADODB_COUNTRECS; 734 // Move to the next recordset, or return false if there is none. In a stored proc 735 // call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result 736 // returns false. I think this is because the last "recordset" is actually just the 737 // return value of the stored proc (ie the number of rows affected). 738 // Commented out for reasons of performance. You should retrieve every recordset yourself. 739 // if (!mysqli_next_result($this->connection->_connectionID)) return false; 740 741 if (is_array($sql)) { 742 743 // Prepare() not supported because mysqli_stmt_execute does not return a recordset, but 744 // returns as bound variables. 745 746 $stmt = $sql[1]; 747 $a = ''; 748 foreach($inputarr as $k => $v) { 749 if (is_string($v)) $a .= 's'; 750 else if (is_integer($v)) $a .= 'i'; 751 else $a .= 'd'; 752 } 753 754 $fnarr = array_merge( array($stmt,$a) , $inputarr); 755 $ret = call_user_func_array('mysqli_stmt_bind_param',$fnarr); 756 $ret = mysqli_stmt_execute($stmt); 757 return $ret; 758 } 759 760 /* 761 if (!$mysql_res = mysqli_query($this->_connectionID, $sql, ($ADODB_COUNTRECS) ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT)) { 762 if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg()); 763 return false; 764 } 765 766 return $mysql_res; 767 */ 768 769 if ($this->multiQuery) { 770 $rs = mysqli_multi_query($this->_connectionID, $sql.';'); 771 if ($rs) { 772 $rs = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->_connectionID ) : @mysqli_use_result( $this->_connectionID ); 773 return $rs ? $rs : true; // mysqli_more_results( $this->_connectionID ) 774 } 775 } else { 776 $rs = mysqli_query($this->_connectionID, $sql, $ADODB_COUNTRECS ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT); 777 778 if ($rs) return $rs; 779 } 780 781 if($this->debug) 782 ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg()); 783 784 return false; 785 786 } 787 788 /* Returns: the last error message from previous database operation */ 789 function ErrorMsg() 790 { 791 if (empty($this->_connectionID)) 792 $this->_errorMsg = @mysqli_connect_error(); 793 else 794 $this->_errorMsg = @mysqli_error($this->_connectionID); 795 return $this->_errorMsg; 796 } 797 798 /* Returns: the last error number from previous database operation */ 799 function ErrorNo() 800 { 801 if (empty($this->_connectionID)) 802 return @mysqli_connect_errno(); 803 else 804 return @mysqli_errno($this->_connectionID); 805 } 806 807 // returns true or false 808 function _close() 809 { 810 @mysqli_close($this->_connectionID); 811 $this->_connectionID = false; 812 } 813 814 /* 815 * Maximum size of C field 816 */ 817 function CharMax() 818 { 819 return 255; 820 } 821 822 /* 823 * Maximum size of X field 824 */ 825 function TextMax() 826 { 827 return 4294967295; 828 } 829 830 831 832 // this is a set of functions for managing client encoding - very important if the encodings 833 // of your database and your output target (i.e. HTML) don't match 834 // for instance, you may have UTF8 database and server it on-site as latin1 etc. 835 // GetCharSet - get the name of the character set the client is using now 836 // Under Windows, the functions should work with MySQL 4.1.11 and above, the set of charsets supported 837 // depends on compile flags of mysql distribution 838 839 function GetCharSet() 840 { 841 //we will use ADO's builtin property charSet 842 if (!method_exists($this->_connectionID,'character_set_name')) 843 return false; 844 845 $this->charSet = @$this->_connectionID->character_set_name(); 846 if (!$this->charSet) { 847 return false; 848 } else { 849 return $this->charSet; 850 } 851 } 852 853 // SetCharSet - switch the client encoding 854 function SetCharSet($charset_name) 855 { 856 if (!method_exists($this->_connectionID,'set_charset')) 857 return false; 858 859 if ($this->charSet !== $charset_name) { 860 $if = @$this->_connectionID->set_charset($charset_name); 861 if ($if === true & $this->GetCharSet() == $charset_name) { 862 return true; 863 } else return false; 864 } else return true; 865 } 866 867 868 869 870 } 871 872 /*-------------------------------------------------------------------------------------- 873 Class Name: Recordset 874 --------------------------------------------------------------------------------------*/ 875 876 class ADORecordSet_mysqli extends ADORecordSet{ 877 878 var $databaseType = "mysqli"; 879 var $canSeek = true; 880 881 function ADORecordSet_mysqli($queryID, $mode = false) 882 { 883 if ($mode === false) 884 { 885 global $ADODB_FETCH_MODE; 886 $mode = $ADODB_FETCH_MODE; 887 } 888 889 switch ($mode) 890 { 891 case ADODB_FETCH_NUM: 892 $this->fetchMode = MYSQLI_NUM; 893 break; 894 case ADODB_FETCH_ASSOC: 895 $this->fetchMode = MYSQLI_ASSOC; 896 break; 897 case ADODB_FETCH_DEFAULT: 898 case ADODB_FETCH_BOTH: 899 default: 900 $this->fetchMode = MYSQLI_BOTH; 901 break; 902 } 903 $this->adodbFetchMode = $mode; 904 $this->ADORecordSet($queryID); 905 } 906 907 function _initrs() 908 { 909 global $ADODB_COUNTRECS; 910 911 $this->_numOfRows = $ADODB_COUNTRECS ? @mysqli_num_rows($this->_queryID) : -1; 912 $this->_numOfFields = @mysqli_num_fields($this->_queryID); 913 } 914 915 /* 916 1 = MYSQLI_NOT_NULL_FLAG 917 2 = MYSQLI_PRI_KEY_FLAG 918 4 = MYSQLI_UNIQUE_KEY_FLAG 919 8 = MYSQLI_MULTIPLE_KEY_FLAG 920 16 = MYSQLI_BLOB_FLAG 921 32 = MYSQLI_UNSIGNED_FLAG 922 64 = MYSQLI_ZEROFILL_FLAG 923 128 = MYSQLI_BINARY_FLAG 924 256 = MYSQLI_ENUM_FLAG 925 512 = MYSQLI_AUTO_INCREMENT_FLAG 926 1024 = MYSQLI_TIMESTAMP_FLAG 927 2048 = MYSQLI_SET_FLAG 928 32768 = MYSQLI_NUM_FLAG 929 16384 = MYSQLI_PART_KEY_FLAG 930 32768 = MYSQLI_GROUP_FLAG 931 65536 = MYSQLI_UNIQUE_FLAG 932 131072 = MYSQLI_BINCMP_FLAG 933 */ 934 935 function FetchField($fieldOffset = -1) 936 { 937 $fieldnr = $fieldOffset; 938 if ($fieldOffset != -1) { 939 $fieldOffset = @mysqli_field_seek($this->_queryID, $fieldnr); 940 } 941 $o = @mysqli_fetch_field($this->_queryID); 942 if (!$o) return false; 943 /* Properties of an ADOFieldObject as set by MetaColumns */ 944 $o->primary_key = $o->flags & MYSQLI_PRI_KEY_FLAG; 945 $o->not_null = $o->flags & MYSQLI_NOT_NULL_FLAG; 946 $o->auto_increment = $o->flags & MYSQLI_AUTO_INCREMENT_FLAG; 947 $o->binary = $o->flags & MYSQLI_BINARY_FLAG; 948 // $o->blob = $o->flags & MYSQLI_BLOB_FLAG; /* not returned by MetaColumns */ 949 $o->unsigned = $o->flags & MYSQLI_UNSIGNED_FLAG; 950 951 return $o; 952 } 953 954 function GetRowAssoc($upper = true) 955 { 956 if ($this->fetchMode == MYSQLI_ASSOC && !$upper) 957 return $this->fields; 958 $row = ADORecordSet::GetRowAssoc($upper); 959 return $row; 960 } 961 962 /* Use associative array to get fields array */ 963 function Fields($colname) 964 { 965 if ($this->fetchMode != MYSQLI_NUM) 966 return @$this->fields[$colname]; 967 968 if (!$this->bind) { 969 $this->bind = array(); 970 for ($i = 0; $i < $this->_numOfFields; $i++) { 971 $o = $this->FetchField($i); 972 $this->bind[strtoupper($o->name)] = $i; 973 } 974 } 975 return $this->fields[$this->bind[strtoupper($colname)]]; 976 } 977 978 function _seek($row) 979 { 980 if ($this->_numOfRows == 0) 981 return false; 982 983 if ($row < 0) 984 return false; 985 986 mysqli_data_seek($this->_queryID, $row); 987 $this->EOF = false; 988 return true; 989 } 990 991 992 function NextRecordSet() 993 { 994 global $ADODB_COUNTRECS; 995 996 mysqli_free_result($this->_queryID); 997 $this->_queryID = -1; 998 // Move to the next recordset, or return false if there is none. In a stored proc 999 // call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result 1000 // returns false. I think this is because the last "recordset" is actually just the 1001 // return value of the stored proc (ie the number of rows affected). 1002 if(!mysqli_next_result($this->connection->_connectionID)) { 1003 return false; 1004 } 1005 // CD: There is no $this->_connectionID variable, at least in the ADO version I'm using 1006 $this->_queryID = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->connection->_connectionID ) 1007 : @mysqli_use_result( $this->connection->_connectionID ); 1008 if(!$this->_queryID) { 1009 return false; 1010 } 1011 $this->_inited = false; 1012 $this->bind = false; 1013 $this->_currentRow = -1; 1014 $this->Init(); 1015 return true; 1016 } 1017 1018 // 10% speedup to move MoveNext to child class 1019 // This is the only implementation that works now (23-10-2003). 1020 // Other functions return no or the wrong results. 1021 function MoveNext() 1022 { 1023 if ($this->EOF) return false; 1024 $this->_currentRow++; 1025 $this->fields = @mysqli_fetch_array($this->_queryID,$this->fetchMode); 1026 1027 if (is_array($this->fields)) return true; 1028 $this->EOF = true; 1029 return false; 1030 } 1031 1032 function _fetch() 1033 { 1034 $this->fields = mysqli_fetch_array($this->_queryID,$this->fetchMode); 1035 return is_array($this->fields); 1036 } 1037 1038 function _close() 1039 { 1040 //if results are attached to this pointer from Stored Proceedure calls, the next standard query will die 2014 1041 //only a problem with persistant connections 1042 1043 while(mysqli_more_results($this->connection->_connectionID)){ 1044 @mysqli_next_result($this->connection->_connectionID); 1045 } 1046 1047 mysqli_free_result($this->_queryID); 1048 $this->_queryID = false; 1049 } 1050 1051 /* 1052 1053 0 = MYSQLI_TYPE_DECIMAL 1054 1 = MYSQLI_TYPE_CHAR 1055 1 = MYSQLI_TYPE_TINY 1056 2 = MYSQLI_TYPE_SHORT 1057 3 = MYSQLI_TYPE_LONG 1058 4 = MYSQLI_TYPE_FLOAT 1059 5 = MYSQLI_TYPE_DOUBLE 1060 6 = MYSQLI_TYPE_NULL 1061 7 = MYSQLI_TYPE_TIMESTAMP 1062 8 = MYSQLI_TYPE_LONGLONG 1063 9 = MYSQLI_TYPE_INT24 1064 10 = MYSQLI_TYPE_DATE 1065 11 = MYSQLI_TYPE_TIME 1066 12 = MYSQLI_TYPE_DATETIME 1067 13 = MYSQLI_TYPE_YEAR 1068 14 = MYSQLI_TYPE_NEWDATE 1069 247 = MYSQLI_TYPE_ENUM 1070 248 = MYSQLI_TYPE_SET 1071 249 = MYSQLI_TYPE_TINY_BLOB 1072 250 = MYSQLI_TYPE_MEDIUM_BLOB 1073 251 = MYSQLI_TYPE_LONG_BLOB 1074 252 = MYSQLI_TYPE_BLOB 1075 253 = MYSQLI_TYPE_VAR_STRING 1076 254 = MYSQLI_TYPE_STRING 1077 255 = MYSQLI_TYPE_GEOMETRY 1078 */ 1079 1080 function MetaType($t, $len = -1, $fieldobj = false) 1081 { 1082 if (is_object($t)) { 1083 $fieldobj = $t; 1084 $t = $fieldobj->type; 1085 $len = $fieldobj->max_length; 1086 } 1087 1088 1089 $len = -1; // mysql max_length is not accurate 1090 switch (strtoupper($t)) { 1091 case 'STRING': 1092 case 'CHAR': 1093 case 'VARCHAR': 1094 case 'TINYBLOB': 1095 case 'TINYTEXT': 1096 case 'ENUM': 1097 case 'SET': 1098 1099 case MYSQLI_TYPE_TINY_BLOB : 1100 #case MYSQLI_TYPE_CHAR : 1101 case MYSQLI_TYPE_STRING : 1102 case MYSQLI_TYPE_ENUM : 1103 case MYSQLI_TYPE_SET : 1104 case 253 : 1105 if ($len <= $this->blobSize) return 'C'; 1106 1107 case 'TEXT': 1108 case 'LONGTEXT': 1109 case 'MEDIUMTEXT': 1110 return 'X'; 1111 1112 1113 // php_mysql extension always returns 'blob' even if 'text' 1114 // so we have to check whether binary... 1115 case 'IMAGE': 1116 case 'LONGBLOB': 1117 case 'BLOB': 1118 case 'MEDIUMBLOB': 1119 1120 case MYSQLI_TYPE_BLOB : 1121 case MYSQLI_TYPE_LONG_BLOB : 1122 case MYSQLI_TYPE_MEDIUM_BLOB : 1123 1124 return !empty($fieldobj->binary) ? 'B' : 'X'; 1125 case 'YEAR': 1126 case 'DATE': 1127 case MYSQLI_TYPE_DATE : 1128 case MYSQLI_TYPE_YEAR : 1129 1130 return 'D'; 1131 1132 case 'TIME': 1133 case 'DATETIME': 1134 case 'TIMESTAMP': 1135 1136 case MYSQLI_TYPE_DATETIME : 1137 case MYSQLI_TYPE_NEWDATE : 1138 case MYSQLI_TYPE_TIME : 1139 case MYSQLI_TYPE_TIMESTAMP : 1140 1141 return 'T'; 1142 1143 case 'INT': 1144 case 'INTEGER': 1145 case 'BIGINT': 1146 case 'TINYINT': 1147 case 'MEDIUMINT': 1148 case 'SMALLINT': 1149 1150 case MYSQLI_TYPE_INT24 : 1151 case MYSQLI_TYPE_LONG : 1152 case MYSQLI_TYPE_LONGLONG : 1153 case MYSQLI_TYPE_SHORT : 1154 case MYSQLI_TYPE_TINY : 1155 1156 if (!empty($fieldobj->primary_key)) return 'R'; 1157 1158 return 'I'; 1159 1160 1161 // Added floating-point types 1162 // Maybe not necessery. 1163 case 'FLOAT': 1164 case 'DOUBLE': 1165 // case 'DOUBLE PRECISION': 1166 case 'DECIMAL': 1167 case 'DEC': 1168 case 'FIXED': 1169 default: 1170 //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>"; 1171 return 'N'; 1172 } 1173 } // function 1174 1175 1176 } // rs class 1177 1178 } 1179 1180 class ADORecordSet_array_mysqli extends ADORecordSet_array { 1181 1182 function ADORecordSet_array_mysqli($id=-1,$mode=false) 1183 { 1184 $this->ADORecordSet_array($id,$mode); 1185 } 1186 1187 function MetaType($t, $len = -1, $fieldobj = false) 1188 { 1189 if (is_object($t)) { 1190 $fieldobj = $t; 1191 $t = $fieldobj->type; 1192 $len = $fieldobj->max_length; 1193 } 1194 1195 1196 $len = -1; // mysql max_length is not accurate 1197 switch (strtoupper($t)) { 1198 case 'STRING': 1199 case 'CHAR': 1200 case 'VARCHAR': 1201 case 'TINYBLOB': 1202 case 'TINYTEXT': 1203 case 'ENUM': 1204 case 'SET': 1205 1206 case MYSQLI_TYPE_TINY_BLOB : 1207 #case MYSQLI_TYPE_CHAR : 1208 case MYSQLI_TYPE_STRING : 1209 case MYSQLI_TYPE_ENUM : 1210 case MYSQLI_TYPE_SET : 1211 case 253 : 1212 if ($len <= $this->blobSize) return 'C'; 1213 1214 case 'TEXT': 1215 case 'LONGTEXT': 1216 case 'MEDIUMTEXT': 1217 return 'X'; 1218 1219 1220 // php_mysql extension always returns 'blob' even if 'text' 1221 // so we have to check whether binary... 1222 case 'IMAGE': 1223 case 'LONGBLOB': 1224 case 'BLOB': 1225 case 'MEDIUMBLOB': 1226 1227 case MYSQLI_TYPE_BLOB : 1228 case MYSQLI_TYPE_LONG_BLOB : 1229 case MYSQLI_TYPE_MEDIUM_BLOB : 1230 1231 return !empty($fieldobj->binary) ? 'B' : 'X'; 1232 case 'YEAR': 1233 case 'DATE': 1234 case MYSQLI_TYPE_DATE : 1235 case MYSQLI_TYPE_YEAR : 1236 1237 return 'D'; 1238 1239 case 'TIME': 1240 case 'DATETIME': 1241 case 'TIMESTAMP': 1242 1243 case MYSQLI_TYPE_DATETIME : 1244 case MYSQLI_TYPE_NEWDATE : 1245 case MYSQLI_TYPE_TIME : 1246 case MYSQLI_TYPE_TIMESTAMP : 1247 1248 return 'T'; 1249 1250 case 'INT': 1251 case 'INTEGER': 1252 case 'BIGINT': 1253 case 'TINYINT': 1254 case 'MEDIUMINT': 1255 case 'SMALLINT': 1256 1257 case MYSQLI_TYPE_INT24 : 1258 case MYSQLI_TYPE_LONG : 1259 case MYSQLI_TYPE_LONGLONG : 1260 case MYSQLI_TYPE_SHORT : 1261 case MYSQLI_TYPE_TINY : 1262 1263 if (!empty($fieldobj->primary_key)) return 'R'; 1264 1265 return 'I'; 1266 1267 1268 // Added floating-point types 1269 // Maybe not necessery. 1270 case 'FLOAT': 1271 case 'DOUBLE': 1272 // case 'DOUBLE PRECISION': 1273 case 'DECIMAL': 1274 case 'DEC': 1275 case 'FIXED': 1276 default: 1277 //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>"; 1278 return 'N'; 1279 } 1280 } // function 1281 1282 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |