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