1<?php 2/* 3V4.94 23 Jan 2007 (c) 2000-2007 John Lim (jlim#natsoft.com.my). 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 1221 October 2003: MySQLi extension implementation by Arjen de Rijke (a.de.rijke@xs4all.nl) 13Based on adodb 3.40 14*/ 15 16// security - hide paths 17if (!defined('ADODB_DIR')) die(); 18 19if (! 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 29class ADODB_mysqli extends ADOConnection { 30 var $databaseType = 'mysqli'; 31 var $dataProvider = 'native'; 32 var $hasInsertID = true; 33 var $hasAffectedRows = true; 34 var $metaTablesSQL = "SHOW TABLES"; 35 var $metaColumnsSQL = "SHOW COLUMNS FROM `%s`"; 36 var $fmtTimeStamp = "'Y-m-d H:i:s'"; 37 var $hasLimit = true; 38 var $hasMoveFirst = true; 39 var $hasGenID = true; 40 var $isoDates = true; // accepts dates in ISO format 41 var $sysDate = 'CURDATE()'; 42 var $sysTimeStamp = 'NOW()'; 43 var $hasTransactions = true; 44 var $forceNewConnect = false; 45 var $poorAffectedRows = true; 46 var $clientFlags = 0; 47 var $substr = "substring"; 48 var $port = false; 49 var $socket = false; 50 var $_bindInputArray = false; 51 var $nameQuote = '`'; /// string to use to quote identifiers and names 52 var $optionFlags = array(array(MYSQLI_READ_DEFAULT_GROUP,0)); 53 54 function ADODB_mysqli() 55 { 56 // if(!extension_loaded("mysqli")) 57 ;//trigger_error("You must have the mysqli extension installed.", E_USER_ERROR); 58 59 } 60 61 function SetTransactionMode( $transaction_mode ) 62 { 63 $this->_transmode = $transaction_mode; 64 if (empty($transaction_mode)) { 65 $this->Execute('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ'); 66 return; 67 } 68 if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode; 69 $this->Execute("SET SESSION TRANSACTION ".$transaction_mode); 70 } 71 72 // returns true or false 73 // To add: parameter int $port, 74 // parameter string $socket 75 function _connect($argHostname = NULL, 76 $argUsername = NULL, 77 $argPassword = NULL, 78 $argDatabasename = NULL, $persist=false) 79 { 80 if(!extension_loaded("mysqli")) { 81 return null; 82 } 83 $this->_connectionID = @mysqli_init(); 84 85 if (is_null($this->_connectionID)) { 86 // mysqli_init only fails if insufficient memory 87 if ($this->debug) 88 ADOConnection::outp("mysqli_init() failed : " . $this->ErrorMsg()); 89 return false; 90 } 91 /* 92 I suggest a simple fix which would enable adodb and mysqli driver to 93 read connection options from the standard mysql configuration file 94 /etc/my.cnf - "Bastien Duclaux" <bduclaux#yahoo.com> 95 */ 96 foreach($this->optionFlags as $arr) { 97 mysqli_options($this->_connectionID,$arr[0],$arr[1]); 98 } 99 100 #if (!empty($this->port)) $argHostname .= ":".$this->port; 101 $ok = mysqli_real_connect($this->_connectionID, 102 $argHostname, 103 $argUsername, 104 $argPassword, 105 $argDatabasename, 106 $this->port, 107 $this->socket, 108 $this->clientFlags); 109 110 if ($ok) { 111 if ($argDatabasename) return $this->SelectDB($argDatabasename); 112 return true; 113 } else { 114 if ($this->debug) 115 ADOConnection::outp("Could't connect : " . $this->ErrorMsg()); 116 return false; 117 } 118 } 119 120 // returns true or false 121 // How to force a persistent connection 122 function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) 123 { 124 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true); 125 126 } 127 128 // When is this used? Close old connection first? 129 // In _connect(), check $this->forceNewConnect? 130 function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename) 131 { 132 $this->forceNewConnect = true; 133 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename); 134 } 135 136 function IfNull( $field, $ifNull ) 137 { 138 return " IFNULL($field, $ifNull) "; // if MySQL 139 } 140 141 // do not use $ADODB_COUNTRECS 142 function GetOne($sql,$inputarr=false) 143 { 144 $ret = false; 145 $rs = &$this->Execute($sql,$inputarr); 146 if ($rs) { 147 if (!$rs->EOF) $ret = reset($rs->fields); 148 $rs->Close(); 149 } 150 return $ret; 151 } 152 153 function ServerInfo() 154 { 155 $arr['description'] = $this->GetOne("select version()"); 156 $arr['version'] = ADOConnection::_findvers($arr['description']); 157 return $arr; 158 } 159 160 161 function BeginTrans() 162 { 163 if ($this->transOff) return true; 164 $this->transCnt += 1; 165 166 //$this->Execute('SET AUTOCOMMIT=0'); 167 mysqli_autocommit($this->_connectionID, false); 168 $this->Execute('BEGIN'); 169 return true; 170 } 171 172 function CommitTrans($ok=true) 173 { 174 if ($this->transOff) return true; 175 if (!$ok) return $this->RollbackTrans(); 176 177 if ($this->transCnt) $this->transCnt -= 1; 178 $this->Execute('COMMIT'); 179 180 //$this->Execute('SET AUTOCOMMIT=1'); 181 mysqli_autocommit($this->_connectionID, true); 182 return true; 183 } 184 185 function RollbackTrans() 186 { 187 if ($this->transOff) return true; 188 if ($this->transCnt) $this->transCnt -= 1; 189 $this->Execute('ROLLBACK'); 190 //$this->Execute('SET AUTOCOMMIT=1'); 191 mysqli_autocommit($this->_connectionID, true); 192 return true; 193 } 194 195 function RowLock($tables,$where='',$flds='1 as adodb_ignore') 196 { 197 if ($this->transCnt==0) $this->BeginTrans(); 198 if ($where) $where = ' where '.$where; 199 $rs =& $this->Execute("select $flds from $tables $where for update"); 200 return !empty($rs); 201 } 202 203 // if magic quotes disabled, use mysql_real_escape_string() 204 // From readme.htm: 205 // Quotes a string to be sent to the database. The $magic_quotes_enabled 206 // parameter may look funny, but the idea is if you are quoting a 207 // string extracted from a POST/GET variable, then 208 // pass get_magic_quotes_gpc() as the second parameter. This will 209 // ensure that the variable is not quoted twice, once by qstr and once 210 // by the magic_quotes_gpc. 211 // 212 //Eg. $s = $db->qstr(_GET['name'],get_magic_quotes_gpc()); 213 function qstr($s, $magic_quotes = false) 214 { 215 if (!$magic_quotes) { 216 if (PHP_VERSION >= 5) 217 return "'" . mysqli_real_escape_string($this->_connectionID, $s) . "'"; 218 219 if ($this->replaceQuote[0] == '\\') 220 $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s); 221 return "'".str_replace("'",$this->replaceQuote,$s)."'"; 222 } 223 // undo magic quotes for " 224 $s = str_replace('\\"','"',$s); 225 return "'$s'"; 226 } 227 228 function _insertid() 229 { 230 $result = @mysqli_insert_id($this->_connectionID); 231 if ($result == -1){ 232 if ($this->debug) ADOConnection::outp("mysqli_insert_id() failed : " . $this->ErrorMsg()); 233 } 234 return $result; 235 } 236 237 // Only works for INSERT, UPDATE and DELETE query's 238 function _affectedrows() 239 { 240 $result = @mysqli_affected_rows($this->_connectionID); 241 if ($result == -1) { 242 if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : " . $this->ErrorMsg()); 243 } 244 return $result; 245 } 246 247 // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html 248 // Reference on Last_Insert_ID on the recommended way to simulate sequences 249 var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);"; 250 var $_genSeqSQL = "create table %s (id int not null)"; 251 var $_genSeq2SQL = "insert into %s values (%s)"; 252 var $_dropSeqSQL = "drop table %s"; 253 254 function CreateSequence($seqname='adodbseq',$startID=1) 255 { 256 if (empty($this->_genSeqSQL)) return false; 257 $u = strtoupper($seqname); 258 259 $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname)); 260 if (!$ok) return false; 261 return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1)); 262 } 263 264 function GenID($seqname='adodbseq',$startID=1) 265 { 266 // post-nuke sets hasGenID to false 267 if (!$this->hasGenID) return false; 268 269 $getnext = sprintf($this->_genIDSQL,$seqname); 270 $holdtransOK = $this->_transOK; // save the current status 271 $rs = @$this->Execute($getnext); 272 if (!$rs) { 273 if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset 274 $u = strtoupper($seqname); 275 $this->Execute(sprintf($this->_genSeqSQL,$seqname)); 276 $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1)); 277 $rs = $this->Execute($getnext); 278 } 279 $this->genID = mysqli_insert_id($this->_connectionID); 280 281 if ($rs) $rs->Close(); 282 283 return $this->genID; 284 } 285 286 function &MetaDatabases() 287 { 288 $query = "SHOW DATABASES"; 289 $ret =& $this->Execute($query); 290 if ($ret && is_object($ret)){ 291 $arr = array(); 292 while (!$ret->EOF){ 293 $db = $ret->Fields('Database'); 294 if ($db != 'mysql') $arr[] = $db; 295 $ret->MoveNext(); 296 } 297 return $arr; 298 } 299 return $ret; 300 } 301 302 303 function &MetaIndexes ($table, $primary = FALSE) 304 { 305 // save old fetch mode 306 global $ADODB_FETCH_MODE; 307 308 $false = false; 309 $save = $ADODB_FETCH_MODE; 310 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 311 if ($this->fetchMode !== FALSE) { 312 $savem = $this->SetFetchMode(FALSE); 313 } 314 315 // get index details 316 $rs = $this->Execute(sprintf('SHOW INDEXES FROM %s',$table)); 317 318 // restore fetchmode 319 if (isset($savem)) { 320 $this->SetFetchMode($savem); 321 } 322 $ADODB_FETCH_MODE = $save; 323 324 if (!is_object($rs)) { 325 return $false; 326 } 327 328 $indexes = array (); 329 330 // parse index data into array 331 while ($row = $rs->FetchRow()) { 332 if ($primary == FALSE AND $row[2] == 'PRIMARY') { 333 continue; 334 } 335 336 if (!isset($indexes[$row[2]])) { 337 $indexes[$row[2]] = array( 338 'unique' => ($row[1] == 0), 339 'columns' => array() 340 ); 341 } 342 343 $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4]; 344 } 345 346 // sort columns by order in the index 347 foreach ( array_keys ($indexes) as $index ) 348 { 349 ksort ($indexes[$index]['columns']); 350 } 351 352 return $indexes; 353 } 354 355 356 // Format date column in sql string given an input format that understands Y M D 357 function SQLDate($fmt, $col=false) 358 { 359 if (!$col) $col = $this->sysTimeStamp; 360 $s = 'DATE_FORMAT('.$col.",'"; 361 $concat = false; 362 $len = strlen($fmt); 363 for ($i=0; $i < $len; $i++) { 364 $ch = $fmt[$i]; 365 switch($ch) { 366 case 'Y': 367 case 'y': 368 $s .= '%Y'; 369 break; 370 case 'Q': 371 case 'q': 372 $s .= "'),Quarter($col)"; 373 374 if ($len > $i+1) $s .= ",DATE_FORMAT($col,'"; 375 else $s .= ",('"; 376 $concat = true; 377 break; 378 case 'M': 379 $s .= '%b'; 380 break; 381 382 case 'm': 383 $s .= '%m'; 384 break; 385 case 'D': 386 case 'd': 387 $s .= '%d'; 388 break; 389 390 case 'H': 391 $s .= '%H'; 392 break; 393 394 case 'h': 395 $s .= '%I'; 396 break; 397 398 case 'i': 399 $s .= '%i'; 400 break; 401 402 case 's': 403 $s .= '%s'; 404 break; 405 406 case 'a': 407 case 'A': 408 $s .= '%p'; 409 break; 410 411 case 'w': 412 $s .= '%w'; 413 break; 414 415 case 'l': 416 $s .= '%W'; 417 break; 418 419 default: 420 421 if ($ch == '\\') { 422 $i++; 423 $ch = substr($fmt,$i,1); 424 } 425 $s .= $ch; 426 break; 427 } 428 } 429 $s.="')"; 430 if ($concat) $s = "CONCAT($s)"; 431 return $s; 432 } 433 434 // returns concatenated string 435 // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator 436 function Concat() 437 { 438 $s = ""; 439 $arr = func_get_args(); 440 441 // suggestion by andrew005@mnogo.ru 442 $s = implode(',',$arr); 443 if (strlen($s) > 0) return "CONCAT($s)"; 444 else return ''; 445 } 446 447 // dayFraction is a day in floating point 448 function OffsetDate($dayFraction,$date=false) 449 { 450 if (!$date) $date = $this->sysDate; 451 452 $fraction = $dayFraction * 24 * 3600; 453 return $date . ' + INTERVAL ' . $fraction.' SECOND'; 454 455// return "from_unixtime(unix_timestamp($date)+$fraction)"; 456 } 457 458 function &MetaTables($ttype=false,$showSchema=false,$mask=false) 459 { 460 $save = $this->metaTablesSQL; 461 if ($showSchema && is_string($showSchema)) { 462 $this->metaTablesSQL .= " from $showSchema"; 463 } 464 465 if ($mask) { 466 $mask = $this->qstr($mask); 467 $this->metaTablesSQL .= " like $mask"; 468 } 469 $ret =& ADOConnection::MetaTables($ttype,$showSchema); 470 471 $this->metaTablesSQL = $save; 472 return $ret; 473 } 474 475 // "Innox - Juan Carlos Gonzalez" <jgonzalez#innox.com.mx> 476 function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE ) 477 { 478 global $ADODB_FETCH_MODE; 479 480 if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true; 481 482 if ( !empty($owner) ) { 483 $table = "$owner.$table"; 484 } 485 $a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table)); 486 if ($associative) $create_sql = $a_create_table["Create Table"]; 487 else $create_sql = $a_create_table[1]; 488 489 $matches = array(); 490 491 if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false; 492 $foreign_keys = array(); 493 $num_keys = count($matches[0]); 494 for ( $i = 0; $i < $num_keys; $i ++ ) { 495 $my_field = explode('`, `', $matches[1][$i]); 496 $ref_table = $matches[2][$i]; 497 $ref_field = explode('`, `', $matches[3][$i]); 498 499 if ( $upper ) { 500 $ref_table = strtoupper($ref_table); 501 } 502 503 $foreign_keys[$ref_table] = array(); 504 $num_fields = count($my_field); 505 for ( $j = 0; $j < $num_fields; $j ++ ) { 506 if ( $associative ) { 507 $foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j]; 508 } else { 509 $foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}"; 510 } 511 } 512 } 513 514 return $foreign_keys; 515 } 516 517 function &MetaColumns($table) 518 { 519 $false = false; 520 if (!$this->metaColumnsSQL) 521 return $false; 522 523 global $ADODB_FETCH_MODE; 524 $save = $ADODB_FETCH_MODE; 525 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 526 if ($this->fetchMode !== false) 527 $savem = $this->SetFetchMode(false); 528 $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table)); 529 if (isset($savem)) $this->SetFetchMode($savem); 530 $ADODB_FETCH_MODE = $save; 531 if (!is_object($rs)) 532 return $false; 533 534 $retarr = array(); 535 while (!$rs->EOF) { 536 $fld = new ADOFieldObject(); 537 $fld->name = $rs->fields[0]; 538 $type = $rs->fields[1]; 539 540 // split type into type(length): 541 $fld->scale = null; 542 if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) { 543 $fld->type = $query_array[1]; 544 $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1; 545 $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1; 546 } elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) { 547 $fld->type = $query_array[1]; 548 $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1; 549 } elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) { 550 $fld->type = $query_array[1]; 551 $fld->max_length = max(array_map("strlen",explode(",",$query_array[2]))) - 2; // PHP >= 4.0.6 552 $fld->max_length = ($fld->max_length == 0 ? 1 : $fld->max_length); 553 } else { 554 $fld->type = $type; 555 $fld->max_length = -1; 556 } 557 $fld->not_null = ($rs->fields[2] != 'YES'); 558 $fld->primary_key = ($rs->fields[3] == 'PRI'); 559 $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false); 560 $fld->binary = (strpos($type,'blob') !== false); 561 $fld->unsigned = (strpos($type,'unsigned') !== false); 562 563 if (!$fld->binary) { 564 $d = $rs->fields[4]; 565 if ($d != '' && $d != 'NULL') { 566 $fld->has_default = true; 567 $fld->default_value = $d; 568 } else { 569 $fld->has_default = false; 570 } 571 } 572 573 if ($save == ADODB_FETCH_NUM) { 574 $retarr[] = $fld; 575 } else { 576 $retarr[strtoupper($fld->name)] = $fld; 577 } 578 $rs->MoveNext(); 579 } 580 581 $rs->Close(); 582 return $retarr; 583 } 584 585 // returns true or false 586 function SelectDB($dbName) 587 { 588// $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID); 589 $this->database = $dbName; 590 $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions 591 592 if ($this->_connectionID) { 593 $result = @mysqli_select_db($this->_connectionID, $dbName); 594 if (!$result) { 595 ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->ErrorMsg()); 596 } 597 return $result; 598 } 599 return false; 600 } 601 602 // parameters use PostgreSQL convention, not MySQL 603 function &SelectLimit($sql, 604 $nrows = -1, 605 $offset = -1, 606 $inputarr = false, 607 $arg3 = false, 608 $secs = 0) 609 { 610 $offsetStr = ($offset >= 0) ? "$offset," : ''; 611 if ($nrows < 0) $nrows = '18446744073709551615'; 612 613 if ($secs) 614 $rs =& $this->CacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr , $arg3); 615 else 616 $rs =& $this->Execute($sql . " LIMIT $offsetStr$nrows" , $inputarr , $arg3); 617 618 return $rs; 619 } 620 621 622 function Prepare($sql) 623 { 624 return $sql; 625 626 $stmt = $this->_connectionID->prepare($sql); 627 if (!$stmt) { 628 echo $this->ErrorMsg(); 629 return $sql; 630 } 631 return array($sql,$stmt); 632 } 633 634 635 // returns queryID or false 636 function _query($sql, $inputarr) 637 { 638 global $ADODB_COUNTRECS; 639 640 if (is_array($sql)) { 641 $stmt = $sql[1]; 642 $a = ''; 643 foreach($inputarr as $k => $v) { 644 if (is_string($v)) $a .= 's'; 645 else if (is_integer($v)) $a .= 'i'; 646 else $a .= 'd'; 647 } 648 649 $fnarr = array_merge( array($stmt,$a) , $inputarr); 650 $ret = call_user_func_array('mysqli_stmt_bind_param',$fnarr); 651 652 $ret = mysqli_stmt_execute($stmt); 653 return $ret; 654 } 655 if (!$mysql_res = mysqli_query($this->_connectionID, $sql, ($ADODB_COUNTRECS) ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT)) { 656 if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg()); 657 return false; 658 } 659 660 return $mysql_res; 661 } 662 663 /* Returns: the last error message from previous database operation */ 664 function ErrorMsg() 665 { 666 if (empty($this->_connectionID)) 667 $this->_errorMsg = @mysqli_connect_error(); 668 else 669 $this->_errorMsg = @mysqli_error($this->_connectionID); 670 return $this->_errorMsg; 671 } 672 673 /* Returns: the last error number from previous database operation */ 674 function ErrorNo() 675 { 676 if (empty($this->_connectionID)) 677 return @mysqli_connect_errno(); 678 else 679 return @mysqli_errno($this->_connectionID); 680 } 681 682 // returns true or false 683 function _close() 684 { 685 @mysqli_close($this->_connectionID); 686 $this->_connectionID = false; 687 } 688 689 /* 690 * Maximum size of C field 691 */ 692 function CharMax() 693 { 694 return 255; 695 } 696 697 /* 698 * Maximum size of X field 699 */ 700 function TextMax() 701 { 702 return 4294967295; 703 } 704 705 706 707 // this is a set of functions for managing client encoding - very important if the encodings 708 // of your database and your output target (i.e. HTML) don't match 709 // for instance, you may have UTF8 database and server it on-site as latin1 etc. 710 // GetCharSet - get the name of the character set the client is using now 711 // Under Windows, the functions should work with MySQL 4.1.11 and above, the set of charsets supported 712 // depends on compile flags of mysql distribution 713 714 function GetCharSet() 715 { 716 //we will use ADO's builtin property charSet 717 if (!method_exists($this->_connectionID,'character_set_name')) 718 return false; 719 720 $this->charSet = @$this->_connectionID->character_set_name(); 721 if (!$this->charSet) { 722 return false; 723 } else { 724 return $this->charSet; 725 } 726 } 727 728 // SetCharSet - switch the client encoding 729 function SetCharSet($charset_name) 730 { 731 if (!method_exists($this->_connectionID,'set_charset')) 732 return false; 733 734 if ($this->charSet !== $charset_name) { 735 $if = @$this->_connectionID->set_charset($charset_name); 736 if ($if == "0" & $this->GetCharSet() == $charset_name) { 737 return true; 738 } else return false; 739 } else return true; 740 } 741 742 743 744 745} 746 747/*-------------------------------------------------------------------------------------- 748 Class Name: Recordset 749--------------------------------------------------------------------------------------*/ 750 751class ADORecordSet_mysqli extends ADORecordSet{ 752 753 var $databaseType = "mysqli"; 754 var $canSeek = true; 755 756 function ADORecordSet_mysqli($queryID, $mode = false) 757 { 758 if ($mode === false) 759 { 760 global $ADODB_FETCH_MODE; 761 $mode = $ADODB_FETCH_MODE; 762 } 763 764 switch ($mode) 765 { 766 case ADODB_FETCH_NUM: 767 $this->fetchMode = MYSQLI_NUM; 768 break; 769 case ADODB_FETCH_ASSOC: 770 $this->fetchMode = MYSQLI_ASSOC; 771 break; 772 case ADODB_FETCH_DEFAULT: 773 case ADODB_FETCH_BOTH: 774 default: 775 $this->fetchMode = MYSQLI_BOTH; 776 break; 777 } 778 $this->adodbFetchMode = $mode; 779 $this->ADORecordSet($queryID); 780 } 781 782 function _initrs() 783 { 784 global $ADODB_COUNTRECS; 785 786 $this->_numOfRows = $ADODB_COUNTRECS ? @mysqli_num_rows($this->_queryID) : -1; 787 $this->_numOfFields = @mysqli_num_fields($this->_queryID); 788 } 789 790/* 7911 = MYSQLI_NOT_NULL_FLAG 7922 = MYSQLI_PRI_KEY_FLAG 7934 = MYSQLI_UNIQUE_KEY_FLAG 7948 = MYSQLI_MULTIPLE_KEY_FLAG 79516 = MYSQLI_BLOB_FLAG 79632 = MYSQLI_UNSIGNED_FLAG 79764 = MYSQLI_ZEROFILL_FLAG 798128 = MYSQLI_BINARY_FLAG 799256 = MYSQLI_ENUM_FLAG 800512 = MYSQLI_AUTO_INCREMENT_FLAG 8011024 = MYSQLI_TIMESTAMP_FLAG 8022048 = MYSQLI_SET_FLAG 80332768 = MYSQLI_NUM_FLAG 80416384 = MYSQLI_PART_KEY_FLAG 80532768 = MYSQLI_GROUP_FLAG 80665536 = MYSQLI_UNIQUE_FLAG 807131072 = MYSQLI_BINCMP_FLAG 808*/ 809 810 function &FetchField($fieldOffset = -1) 811 { 812 $fieldnr = $fieldOffset; 813 if ($fieldOffset != -1) { 814 $fieldOffset = mysqli_field_seek($this->_queryID, $fieldnr); 815 } 816 $o = mysqli_fetch_field($this->_queryID); 817 /* Properties of an ADOFieldObject as set by MetaColumns */ 818 $o->primary_key = $o->flags & MYSQLI_PRI_KEY_FLAG; 819 $o->not_null = $o->flags & MYSQLI_NOT_NULL_FLAG; 820 $o->auto_increment = $o->flags & MYSQLI_AUTO_INCREMENT_FLAG; 821 $o->binary = $o->flags & MYSQLI_BINARY_FLAG; 822 // $o->blob = $o->flags & MYSQLI_BLOB_FLAG; /* not returned by MetaColumns */ 823 $o->unsigned = $o->flags & MYSQLI_UNSIGNED_FLAG; 824 825 return $o; 826 } 827 828 function &GetRowAssoc($upper = true) 829 { 830 if ($this->fetchMode == MYSQLI_ASSOC && !$upper) 831 return $this->fields; 832 $row =& ADORecordSet::GetRowAssoc($upper); 833 return $row; 834 } 835 836 /* Use associative array to get fields array */ 837 function Fields($colname) 838 { 839 if ($this->fetchMode != MYSQLI_NUM) 840 return @$this->fields[$colname]; 841 842 if (!$this->bind) { 843 $this->bind = array(); 844 for ($i = 0; $i < $this->_numOfFields; $i++) { 845 $o = $this->FetchField($i); 846 $this->bind[strtoupper($o->name)] = $i; 847 } 848 } 849 return $this->fields[$this->bind[strtoupper($colname)]]; 850 } 851 852 function _seek($row) 853 { 854 if ($this->_numOfRows == 0) 855 return false; 856 857 if ($row < 0) 858 return false; 859 860 mysqli_data_seek($this->_queryID, $row); 861 $this->EOF = false; 862 return true; 863 } 864 865 // 10% speedup to move MoveNext to child class 866 // This is the only implementation that works now (23-10-2003). 867 // Other functions return no or the wrong results. 868 function MoveNext() 869 { 870 if ($this->EOF) return false; 871 $this->_currentRow++; 872 $this->fields = @mysqli_fetch_array($this->_queryID,$this->fetchMode); 873 874 if (is_array($this->fields)) return true; 875 $this->EOF = true; 876 return false; 877 } 878 879 function _fetch() 880 { 881 $this->fields = mysqli_fetch_array($this->_queryID,$this->fetchMode); 882 return is_array($this->fields); 883 } 884 885 function _close() 886 { 887 mysqli_free_result($this->_queryID); 888 $this->_queryID = false; 889 } 890 891/* 892 8930 = MYSQLI_TYPE_DECIMAL 8941 = MYSQLI_TYPE_CHAR 8951 = MYSQLI_TYPE_TINY 8962 = MYSQLI_TYPE_SHORT 8973 = MYSQLI_TYPE_LONG 8984 = MYSQLI_TYPE_FLOAT 8995 = MYSQLI_TYPE_DOUBLE 9006 = MYSQLI_TYPE_NULL 9017 = MYSQLI_TYPE_TIMESTAMP 9028 = MYSQLI_TYPE_LONGLONG 9039 = MYSQLI_TYPE_INT24 90410 = MYSQLI_TYPE_DATE 90511 = MYSQLI_TYPE_TIME 90612 = MYSQLI_TYPE_DATETIME 90713 = MYSQLI_TYPE_YEAR 90814 = MYSQLI_TYPE_NEWDATE 909247 = MYSQLI_TYPE_ENUM 910248 = MYSQLI_TYPE_SET 911249 = MYSQLI_TYPE_TINY_BLOB 912250 = MYSQLI_TYPE_MEDIUM_BLOB 913251 = MYSQLI_TYPE_LONG_BLOB 914252 = MYSQLI_TYPE_BLOB 915253 = MYSQLI_TYPE_VAR_STRING 916254 = MYSQLI_TYPE_STRING 917255 = MYSQLI_TYPE_GEOMETRY 918*/ 919 920 function MetaType($t, $len = -1, $fieldobj = false) 921 { 922 if (is_object($t)) { 923 $fieldobj = $t; 924 $t = $fieldobj->type; 925 $len = $fieldobj->max_length; 926 } 927 928 929 $len = -1; // mysql max_length is not accurate 930 switch (strtoupper($t)) { 931 case 'STRING': 932 case 'CHAR': 933 case 'VARCHAR': 934 case 'TINYBLOB': 935 case 'TINYTEXT': 936 case 'ENUM': 937 case 'SET': 938 939 case MYSQLI_TYPE_TINY_BLOB : 940 case MYSQLI_TYPE_CHAR : 941 case MYSQLI_TYPE_STRING : 942 case MYSQLI_TYPE_ENUM : 943 case MYSQLI_TYPE_SET : 944 case 253 : 945 if ($len <= $this->blobSize) return 'C'; 946 947 case 'TEXT': 948 case 'LONGTEXT': 949 case 'MEDIUMTEXT': 950 return 'X'; 951 952 953 // php_mysql extension always returns 'blob' even if 'text' 954 // so we have to check whether binary... 955 case 'IMAGE': 956 case 'LONGBLOB': 957 case 'BLOB': 958 case 'MEDIUMBLOB': 959 960 case MYSQLI_TYPE_BLOB : 961 case MYSQLI_TYPE_LONG_BLOB : 962 case MYSQLI_TYPE_MEDIUM_BLOB : 963 964 return !empty($fieldobj->binary) ? 'B' : 'X'; 965 case 'YEAR': 966 case 'DATE': 967 case MYSQLI_TYPE_DATE : 968 case MYSQLI_TYPE_YEAR : 969 970 return 'D'; 971 972 case 'TIME': 973 case 'DATETIME': 974 case 'TIMESTAMP': 975 976 case MYSQLI_TYPE_DATETIME : 977 case MYSQLI_TYPE_NEWDATE : 978 case MYSQLI_TYPE_TIME : 979 case MYSQLI_TYPE_TIMESTAMP : 980 981 return 'T'; 982 983 case 'INT': 984 case 'INTEGER': 985 case 'BIGINT': 986 case 'TINYINT': 987 case 'MEDIUMINT': 988 case 'SMALLINT': 989 990 case MYSQLI_TYPE_INT24 : 991 case MYSQLI_TYPE_LONG : 992 case MYSQLI_TYPE_LONGLONG : 993 case MYSQLI_TYPE_SHORT : 994 case MYSQLI_TYPE_TINY : 995 996 if (!empty($fieldobj->primary_key)) return 'R'; 997 998 return 'I'; 999 1000 1001 // Added floating-point types 1002 // Maybe not necessery. 1003 case 'FLOAT': 1004 case 'DOUBLE': 1005 // case 'DOUBLE PRECISION': 1006 case 'DECIMAL': 1007 case 'DEC': 1008 case 'FIXED': 1009 default: 1010 //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>"; 1011 return 'N'; 1012 } 1013 } // function 1014 1015 1016} // rs class 1017 1018} 1019 1020?>