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