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