3 V5.18 3 Sep 2012 (c) 2000-2012 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.
9 MySQL code that does not support transactions. Use mysqlt if you need transactions.
10 Requires mysql client. Works on Windows and Unix.
12 21 October 2003: MySQLi extension implementation by Arjen de Rijke (a.de.rijke@xs4all.nl)
16 // security - hide paths
17 if (!defined('ADODB_DIR')) die();
19 if (! defined("_ADODB_MYSQLI_LAYER")) {
20 define("_ADODB_MYSQLI_LAYER", 1 );
23 if (! defined("MYSQLI_BINARY_FLAG")) define("MYSQLI_BINARY_FLAG", 128);
24 if (!defined('MYSQLI_READ_DEFAULT_GROUP')) define('MYSQLI_READ_DEFAULT_GROUP',1);
26 // disable adodb extension - currently incompatible.
27 global $ADODB_EXTENSION; $ADODB_EXTENSION = false;
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 TABLE_NAME, CASE WHEN TABLE_TYPE = 'VIEW' THEN 'V' ELSE 'T' END FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=SCHEMA()";
35 var $metaColumnsSQL = "SHOW COLUMNS FROM `%s`";
36 var $fmtTimeStamp = "'Y-m-d H:i:s'";
38 var $hasMoveFirst = 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;
47 var $substr = "substring";
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 var $arrayClass = 'ADORecordSet_array_mysqli';
54 var $multiQuery = false;
56 function ADODB_mysqli()
58 // if(!extension_loaded("mysqli"))
59 ;//trigger_error("You must have the mysqli extension installed.", E_USER_ERROR);
63 function SetTransactionMode( $transaction_mode )
65 $this->_transmode = $transaction_mode;
66 if (empty($transaction_mode)) {
67 $this->Execute('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ');
70 if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
71 $this->Execute("SET SESSION TRANSACTION ".$transaction_mode);
74 // returns true or false
75 // To add: parameter int $port,
76 // parameter string $socket
77 function _connect($argHostname = NULL,
80 $argDatabasename = NULL, $persist=false)
82 if(!extension_loaded("mysqli")) {
85 $this->_connectionID = @mysqli_init();
87 if (is_null($this->_connectionID)) {
88 // mysqli_init only fails if insufficient memory
90 ADOConnection::outp("mysqli_init() failed : " . $this->ErrorMsg());
94 I suggest a simple fix which would enable adodb and mysqli driver to
95 read connection options from the standard mysql configuration file
96 /etc/my.cnf - "Bastien Duclaux" <bduclaux#yahoo.com>
98 foreach($this->optionFlags as $arr) {
99 mysqli_options($this->_connectionID,$arr[0],$arr[1]);
102 //http ://php.net/manual/en/mysqli.persistconns.php
103 if ($persist && PHP_VERSION > 5.2 && strncmp($argHostname,'p:',2) != 0) $argHostname = 'p:'.$argHostname;
105 #if (!empty($this->port)) $argHostname .= ":".$this->port;
106 $ok = mysqli_real_connect($this->_connectionID,
116 if ($argDatabasename) return $this->SelectDB($argDatabasename);
120 ADOConnection::outp("Could't connect : " . $this->ErrorMsg());
121 $this->_connectionID = null;
126 // returns true or false
127 // How to force a persistent connection
128 function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
130 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true);
134 // When is this used? Close old connection first?
135 // In _connect(), check $this->forceNewConnect?
136 function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
138 $this->forceNewConnect = true;
139 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
142 function IfNull( $field, $ifNull )
144 return " IFNULL($field, $ifNull) "; // if MySQL
147 // do not use $ADODB_COUNTRECS
148 function GetOne($sql,$inputarr=false)
150 global $ADODB_GETONE_EOF;
153 $rs = $this->Execute($sql,$inputarr);
155 if ($rs->EOF) $ret = $ADODB_GETONE_EOF;
156 else $ret = reset($rs->fields);
162 function ServerInfo()
164 $arr['description'] = $this->GetOne("select version()");
165 $arr['version'] = ADOConnection::_findvers($arr['description']);
170 function BeginTrans()
172 if ($this->transOff) return true;
173 $this->transCnt += 1;
175 //$this->Execute('SET AUTOCOMMIT=0');
176 mysqli_autocommit($this->_connectionID, false);
177 $this->Execute('BEGIN');
181 function CommitTrans($ok=true)
183 if ($this->transOff) return true;
184 if (!$ok) return $this->RollbackTrans();
186 if ($this->transCnt) $this->transCnt -= 1;
187 $this->Execute('COMMIT');
189 //$this->Execute('SET AUTOCOMMIT=1');
190 mysqli_autocommit($this->_connectionID, true);
194 function RollbackTrans()
196 if ($this->transOff) return true;
197 if ($this->transCnt) $this->transCnt -= 1;
198 $this->Execute('ROLLBACK');
199 //$this->Execute('SET AUTOCOMMIT=1');
200 mysqli_autocommit($this->_connectionID, true);
204 function RowLock($tables,$where='',$col='1 as adodbignore')
206 if ($this->transCnt==0) $this->BeginTrans();
207 if ($where) $where = ' where '.$where;
208 $rs = $this->Execute("select $col from $tables $where for update");
212 // if magic quotes disabled, use mysql_real_escape_string()
214 // Quotes a string to be sent to the database. The $magic_quotes_enabled
215 // parameter may look funny, but the idea is if you are quoting a
216 // string extracted from a POST/GET variable, then
217 // pass get_magic_quotes_gpc() as the second parameter. This will
218 // ensure that the variable is not quoted twice, once by qstr and once
219 // by the magic_quotes_gpc.
221 //Eg. $s = $db->qstr(_GET['name'],get_magic_quotes_gpc());
222 function qstr($s, $magic_quotes = false)
224 if (is_null($s)) return 'NULL';
225 if (!$magic_quotes) {
226 if (PHP_VERSION >= 5)
227 return "'" . mysqli_real_escape_string($this->_connectionID, $s) . "'";
229 if ($this->replaceQuote[0] == '\\')
230 $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
231 return "'".str_replace("'",$this->replaceQuote,$s)."'";
233 // undo magic quotes for "
234 $s = str_replace('\\"','"',$s);
240 $result = @mysqli_insert_id($this->_connectionID);
242 if ($this->debug) ADOConnection::outp("mysqli_insert_id() failed : " . $this->ErrorMsg());
247 // Only works for INSERT, UPDATE and DELETE query's
248 function _affectedrows()
250 $result = @mysqli_affected_rows($this->_connectionID);
252 if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : " . $this->ErrorMsg());
257 // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html
258 // Reference on Last_Insert_ID on the recommended way to simulate sequences
259 var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
260 var $_genSeqSQL = "create table %s (id int not null)";
261 var $_genSeqCountSQL = "select count(*) from %s";
262 var $_genSeq2SQL = "insert into %s values (%s)";
263 var $_dropSeqSQL = "drop table %s";
265 function CreateSequence($seqname='adodbseq',$startID=1)
267 if (empty($this->_genSeqSQL)) return false;
268 $u = strtoupper($seqname);
270 $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
271 if (!$ok) return false;
272 return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
275 function GenID($seqname='adodbseq',$startID=1)
277 // post-nuke sets hasGenID to false
278 if (!$this->hasGenID) return false;
280 $getnext = sprintf($this->_genIDSQL,$seqname);
281 $holdtransOK = $this->_transOK; // save the current status
282 $rs = @$this->Execute($getnext);
284 if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset
285 $u = strtoupper($seqname);
286 $this->Execute(sprintf($this->_genSeqSQL,$seqname));
287 $cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seqname));
288 if (!$cnt) $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
289 $rs = $this->Execute($getnext);
293 $this->genID = mysqli_insert_id($this->_connectionID);
301 function MetaDatabases()
303 $query = "SHOW DATABASES";
304 $ret = $this->Execute($query);
305 if ($ret && is_object($ret)){
308 $db = $ret->Fields('Database');
309 if ($db != 'mysql') $arr[] = $db;
318 function MetaIndexes ($table, $primary = FALSE, $owner = false)
320 // save old fetch mode
321 global $ADODB_FETCH_MODE;
324 $save = $ADODB_FETCH_MODE;
325 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
326 if ($this->fetchMode !== FALSE) {
327 $savem = $this->SetFetchMode(FALSE);
331 $rs = $this->Execute(sprintf('SHOW INDEXES FROM %s',$table));
335 $this->SetFetchMode($savem);
337 $ADODB_FETCH_MODE = $save;
339 if (!is_object($rs)) {
345 // parse index data into array
346 while ($row = $rs->FetchRow()) {
347 if ($primary == FALSE AND $row[2] == 'PRIMARY') {
351 if (!isset($indexes[$row[2]])) {
352 $indexes[$row[2]] = array(
353 'unique' => ($row[1] == 0),
358 $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];
361 // sort columns by order in the index
362 foreach ( array_keys ($indexes) as $index )
364 ksort ($indexes[$index]['columns']);
371 // Format date column in sql string given an input format that understands Y M D
372 function SQLDate($fmt, $col=false)
374 if (!$col) $col = $this->sysTimeStamp;
375 $s = 'DATE_FORMAT('.$col.",'";
378 for ($i=0; $i < $len; $i++) {
387 $s .= "'),Quarter($col)";
389 if ($len > $i+1) $s .= ",DATE_FORMAT($col,'";
438 $ch = substr($fmt,$i,1);
445 if ($concat) $s = "CONCAT($s)";
449 // returns concatenated string
450 // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator
454 $arr = func_get_args();
456 // suggestion by andrew005@mnogo.ru
457 $s = implode(',',$arr);
458 if (strlen($s) > 0) return "CONCAT($s)";
462 // dayFraction is a day in floating point
463 function OffsetDate($dayFraction,$date=false)
465 if (!$date) $date = $this->sysDate;
467 $fraction = $dayFraction * 24 * 3600;
468 return $date . ' + INTERVAL ' . $fraction.' SECOND';
470 // return "from_unixtime(unix_timestamp($date)+$fraction)";
473 function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null)
475 // save old fetch mode
476 global $ADODB_FETCH_MODE;
479 $save = $ADODB_FETCH_MODE;
480 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
482 if ($this->fetchMode !== FALSE) {
483 $savem = $this->SetFetchMode(FALSE);
486 $procedures = array ();
492 $likepattern = " LIKE '".$NamePattern."'";
494 $rs = $this->Execute('SHOW PROCEDURE STATUS'.$likepattern);
495 if (is_object($rs)) {
497 // parse index data into array
498 while ($row = $rs->FetchRow()) {
499 $procedures[$row[1]] = array(
500 'type' => 'PROCEDURE',
504 'remarks' => $row[7],
509 $rs = $this->Execute('SHOW FUNCTION STATUS'.$likepattern);
510 if (is_object($rs)) {
511 // parse index data into array
512 while ($row = $rs->FetchRow()) {
513 $procedures[$row[1]] = array(
514 'type' => 'FUNCTION',
524 $this->SetFetchMode($savem);
527 $ADODB_FETCH_MODE = $save;
533 function MetaTables($ttype=false,$showSchema=false,$mask=false)
535 $save = $this->metaTablesSQL;
536 if ($showSchema && is_string($showSchema)) {
537 $this->metaTablesSQL .= " from $showSchema";
541 $mask = $this->qstr($mask);
542 $this->metaTablesSQL .= " like $mask";
544 $ret = ADOConnection::MetaTables($ttype,$showSchema);
546 $this->metaTablesSQL = $save;
550 // "Innox - Juan Carlos Gonzalez" <jgonzalez#innox.com.mx>
551 function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
553 global $ADODB_FETCH_MODE;
555 if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true;
557 if ( !empty($owner) ) {
558 $table = "$owner.$table";
560 $a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
562 $create_sql = isset($a_create_table["Create Table"]) ? $a_create_table["Create Table"] : $a_create_table["Create View"];
563 } else $create_sql = $a_create_table[1];
567 if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false;
568 $foreign_keys = array();
569 $num_keys = count($matches[0]);
570 for ( $i = 0; $i < $num_keys; $i ++ ) {
571 $my_field = explode('`, `', $matches[1][$i]);
572 $ref_table = $matches[2][$i];
573 $ref_field = explode('`, `', $matches[3][$i]);
576 $ref_table = strtoupper($ref_table);
579 // see https://sourceforge.net/tracker/index.php?func=detail&aid=2287278&group_id=42718&atid=433976
580 if (!isset($foreign_keys[$ref_table])) {
581 $foreign_keys[$ref_table] = array();
583 $num_fields = count($my_field);
584 for ( $j = 0; $j < $num_fields; $j ++ ) {
585 if ( $associative ) {
586 $foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j];
588 $foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}";
593 return $foreign_keys;
596 function MetaColumns($table, $normalize=true)
599 if (!$this->metaColumnsSQL)
602 global $ADODB_FETCH_MODE;
603 $save = $ADODB_FETCH_MODE;
604 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
605 if ($this->fetchMode !== false)
606 $savem = $this->SetFetchMode(false);
607 $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
608 if (isset($savem)) $this->SetFetchMode($savem);
609 $ADODB_FETCH_MODE = $save;
615 $fld = new ADOFieldObject();
616 $fld->name = $rs->fields[0];
617 $type = $rs->fields[1];
619 // split type into type(length):
621 if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {
622 $fld->type = $query_array[1];
623 $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
624 $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;
625 } elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {
626 $fld->type = $query_array[1];
627 $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
628 } elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) {
629 $fld->type = $query_array[1];
630 $arr = explode(",",$query_array[2]);
632 $zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6
633 $fld->max_length = ($zlen > 0) ? $zlen : 1;
636 $fld->max_length = -1;
638 $fld->not_null = ($rs->fields[2] != 'YES');
639 $fld->primary_key = ($rs->fields[3] == 'PRI');
640 $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
641 $fld->binary = (strpos($type,'blob') !== false);
642 $fld->unsigned = (strpos($type,'unsigned') !== false);
643 $fld->zerofill = (strpos($type,'zerofill') !== false);
647 if ($d != '' && $d != 'NULL') {
648 $fld->has_default = true;
649 $fld->default_value = $d;
651 $fld->has_default = false;
655 if ($save == ADODB_FETCH_NUM) {
658 $retarr[strtoupper($fld->name)] = $fld;
667 // returns true or false
668 function SelectDB($dbName)
670 // $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);
671 $this->database = $dbName;
672 $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
674 if ($this->_connectionID) {
675 $result = @mysqli_select_db($this->_connectionID, $dbName);
677 ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->ErrorMsg());
684 // parameters use PostgreSQL convention, not MySQL
685 function SelectLimit($sql,
691 $offsetStr = ($offset >= 0) ? "$offset," : '';
692 if ($nrows < 0) $nrows = '18446744073709551615';
695 $rs = $this->CacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr );
697 $rs = $this->Execute($sql . " LIMIT $offsetStr$nrows" , $inputarr );
703 function Prepare($sql)
706 $stmt = $this->_connectionID->prepare($sql);
708 echo $this->ErrorMsg();
711 return array($sql,$stmt);
715 // returns queryID or false
716 function _query($sql, $inputarr)
718 global $ADODB_COUNTRECS;
719 // Move to the next recordset, or return false if there is none. In a stored proc
720 // call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result
721 // returns false. I think this is because the last "recordset" is actually just the
722 // return value of the stored proc (ie the number of rows affected).
723 // Commented out for reasons of performance. You should retrieve every recordset yourself.
724 // if (!mysqli_next_result($this->connection->_connectionID)) return false;
726 if (is_array($sql)) {
728 // Prepare() not supported because mysqli_stmt_execute does not return a recordset, but
729 // returns as bound variables.
733 foreach($inputarr as $k => $v) {
734 if (is_string($v)) $a .= 's';
735 else if (is_integer($v)) $a .= 'i';
739 $fnarr = array_merge( array($stmt,$a) , $inputarr);
740 $ret = call_user_func_array('mysqli_stmt_bind_param',$fnarr);
741 $ret = mysqli_stmt_execute($stmt);
746 if (!$mysql_res = mysqli_query($this->_connectionID, $sql, ($ADODB_COUNTRECS) ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT)) {
747 if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());
754 if ($this->multiQuery) {
755 $rs = mysqli_multi_query($this->_connectionID, $sql.';');
757 $rs = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->_connectionID ) : @mysqli_use_result( $this->_connectionID );
758 return $rs ? $rs : true; // mysqli_more_results( $this->_connectionID )
761 $rs = mysqli_query($this->_connectionID, $sql, $ADODB_COUNTRECS ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT);
767 ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());
773 /* Returns: the last error message from previous database operation */
776 if (empty($this->_connectionID))
777 $this->_errorMsg = @mysqli_connect_error();
779 $this->_errorMsg = @mysqli_error($this->_connectionID);
780 return $this->_errorMsg;
783 /* Returns: the last error number from previous database operation */
786 if (empty($this->_connectionID))
787 return @mysqli_connect_errno();
789 return @mysqli_errno($this->_connectionID);
792 // returns true or false
795 @mysqli_close($this->_connectionID);
796 $this->_connectionID = false;
800 * Maximum size of C field
808 * Maximum size of X field
817 // this is a set of functions for managing client encoding - very important if the encodings
818 // of your database and your output target (i.e. HTML) don't match
819 // for instance, you may have UTF8 database and server it on-site as latin1 etc.
820 // GetCharSet - get the name of the character set the client is using now
821 // Under Windows, the functions should work with MySQL 4.1.11 and above, the set of charsets supported
822 // depends on compile flags of mysql distribution
824 function GetCharSet()
826 //we will use ADO's builtin property charSet
827 if (!method_exists($this->_connectionID,'character_set_name'))
830 $this->charSet = @$this->_connectionID->character_set_name();
831 if (!$this->charSet) {
834 return $this->charSet;
838 // SetCharSet - switch the client encoding
839 function SetCharSet($charset_name)
841 if (!method_exists($this->_connectionID,'set_charset'))
844 if ($this->charSet !== $charset_name) {
845 $if = @$this->_connectionID->set_charset($charset_name);
846 if ($if === true & $this->GetCharSet() == $charset_name) {
857 /*--------------------------------------------------------------------------------------
858 Class Name: Recordset
859 --------------------------------------------------------------------------------------*/
861 class ADORecordSet_mysqli extends ADORecordSet{
863 var $databaseType = "mysqli";
866 function ADORecordSet_mysqli($queryID, $mode = false)
870 global $ADODB_FETCH_MODE;
871 $mode = $ADODB_FETCH_MODE;
876 case ADODB_FETCH_NUM:
877 $this->fetchMode = MYSQLI_NUM;
879 case ADODB_FETCH_ASSOC:
880 $this->fetchMode = MYSQLI_ASSOC;
882 case ADODB_FETCH_DEFAULT:
883 case ADODB_FETCH_BOTH:
885 $this->fetchMode = MYSQLI_BOTH;
888 $this->adodbFetchMode = $mode;
889 $this->ADORecordSet($queryID);
894 global $ADODB_COUNTRECS;
896 $this->_numOfRows = $ADODB_COUNTRECS ? @mysqli_num_rows($this->_queryID) : -1;
897 $this->_numOfFields = @mysqli_num_fields($this->_queryID);
901 1 = MYSQLI_NOT_NULL_FLAG
902 2 = MYSQLI_PRI_KEY_FLAG
903 4 = MYSQLI_UNIQUE_KEY_FLAG
904 8 = MYSQLI_MULTIPLE_KEY_FLAG
905 16 = MYSQLI_BLOB_FLAG
906 32 = MYSQLI_UNSIGNED_FLAG
907 64 = MYSQLI_ZEROFILL_FLAG
908 128 = MYSQLI_BINARY_FLAG
909 256 = MYSQLI_ENUM_FLAG
910 512 = MYSQLI_AUTO_INCREMENT_FLAG
911 1024 = MYSQLI_TIMESTAMP_FLAG
912 2048 = MYSQLI_SET_FLAG
913 32768 = MYSQLI_NUM_FLAG
914 16384 = MYSQLI_PART_KEY_FLAG
915 32768 = MYSQLI_GROUP_FLAG
916 65536 = MYSQLI_UNIQUE_FLAG
917 131072 = MYSQLI_BINCMP_FLAG
920 function FetchField($fieldOffset = -1)
922 $fieldnr = $fieldOffset;
923 if ($fieldOffset != -1) {
924 $fieldOffset = @mysqli_field_seek($this->_queryID, $fieldnr);
926 $o = @mysqli_fetch_field($this->_queryID);
927 if (!$o) return false;
928 /* Properties of an ADOFieldObject as set by MetaColumns */
929 $o->primary_key = $o->flags & MYSQLI_PRI_KEY_FLAG;
930 $o->not_null = $o->flags & MYSQLI_NOT_NULL_FLAG;
931 $o->auto_increment = $o->flags & MYSQLI_AUTO_INCREMENT_FLAG;
932 $o->binary = $o->flags & MYSQLI_BINARY_FLAG;
933 // $o->blob = $o->flags & MYSQLI_BLOB_FLAG; /* not returned by MetaColumns */
934 $o->unsigned = $o->flags & MYSQLI_UNSIGNED_FLAG;
939 function GetRowAssoc($upper = true)
941 if ($this->fetchMode == MYSQLI_ASSOC && !$upper)
942 return $this->fields;
943 $row = ADORecordSet::GetRowAssoc($upper);
947 /* Use associative array to get fields array */
948 function Fields($colname)
950 if ($this->fetchMode != MYSQLI_NUM)
951 return @$this->fields[$colname];
954 $this->bind = array();
955 for ($i = 0; $i < $this->_numOfFields; $i++) {
956 $o = $this->FetchField($i);
957 $this->bind[strtoupper($o->name)] = $i;
960 return $this->fields[$this->bind[strtoupper($colname)]];
965 if ($this->_numOfRows == 0)
971 mysqli_data_seek($this->_queryID, $row);
977 function NextRecordSet()
979 global $ADODB_COUNTRECS;
981 mysqli_free_result($this->_queryID);
982 $this->_queryID = -1;
983 // Move to the next recordset, or return false if there is none. In a stored proc
984 // call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result
985 // returns false. I think this is because the last "recordset" is actually just the
986 // return value of the stored proc (ie the number of rows affected).
987 if(!mysqli_next_result($this->connection->_connectionID)) {
990 // CD: There is no $this->_connectionID variable, at least in the ADO version I'm using
991 $this->_queryID = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->connection->_connectionID )
992 : @mysqli_use_result( $this->connection->_connectionID );
993 if(!$this->_queryID) {
996 $this->_inited = false;
998 $this->_currentRow = -1;
1003 // 10% speedup to move MoveNext to child class
1004 // This is the only implementation that works now (23-10-2003).
1005 // Other functions return no or the wrong results.
1008 if ($this->EOF) return false;
1009 $this->_currentRow++;
1010 $this->fields = @mysqli_fetch_array($this->_queryID,$this->fetchMode);
1012 if (is_array($this->fields)) return true;
1019 $this->fields = mysqli_fetch_array($this->_queryID,$this->fetchMode);
1020 return is_array($this->fields);
1025 //if results are attached to this pointer from Stored Proceedure calls, the next standard query will die 2014
1026 //only a problem with persistant connections
1028 while(mysqli_more_results($this->connection->_connectionID)){
1029 @mysqli_next_result($this->connection->_connectionID);
1032 mysqli_free_result($this->_queryID);
1033 $this->_queryID = false;
1038 0 = MYSQLI_TYPE_DECIMAL
1039 1 = MYSQLI_TYPE_CHAR
1040 1 = MYSQLI_TYPE_TINY
1041 2 = MYSQLI_TYPE_SHORT
1042 3 = MYSQLI_TYPE_LONG
1043 4 = MYSQLI_TYPE_FLOAT
1044 5 = MYSQLI_TYPE_DOUBLE
1045 6 = MYSQLI_TYPE_NULL
1046 7 = MYSQLI_TYPE_TIMESTAMP
1047 8 = MYSQLI_TYPE_LONGLONG
1048 9 = MYSQLI_TYPE_INT24
1049 10 = MYSQLI_TYPE_DATE
1050 11 = MYSQLI_TYPE_TIME
1051 12 = MYSQLI_TYPE_DATETIME
1052 13 = MYSQLI_TYPE_YEAR
1053 14 = MYSQLI_TYPE_NEWDATE
1054 247 = MYSQLI_TYPE_ENUM
1055 248 = MYSQLI_TYPE_SET
1056 249 = MYSQLI_TYPE_TINY_BLOB
1057 250 = MYSQLI_TYPE_MEDIUM_BLOB
1058 251 = MYSQLI_TYPE_LONG_BLOB
1059 252 = MYSQLI_TYPE_BLOB
1060 253 = MYSQLI_TYPE_VAR_STRING
1061 254 = MYSQLI_TYPE_STRING
1062 255 = MYSQLI_TYPE_GEOMETRY
1065 function MetaType($t, $len = -1, $fieldobj = false)
1067 if (is_object($t)) {
1069 $t = $fieldobj->type;
1070 $len = $fieldobj->max_length;
1074 $len = -1; // mysql max_length is not accurate
1075 switch (strtoupper($t)) {
1084 case MYSQLI_TYPE_TINY_BLOB :
1085 #case MYSQLI_TYPE_CHAR :
1086 case MYSQLI_TYPE_STRING :
1087 case MYSQLI_TYPE_ENUM :
1088 case MYSQLI_TYPE_SET :
1090 if ($len <= $this->blobSize) return 'C';
1098 // php_mysql extension always returns 'blob' even if 'text'
1099 // so we have to check whether binary...
1105 case MYSQLI_TYPE_BLOB :
1106 case MYSQLI_TYPE_LONG_BLOB :
1107 case MYSQLI_TYPE_MEDIUM_BLOB :
1109 return !empty($fieldobj->binary) ? 'B' : 'X';
1112 case MYSQLI_TYPE_DATE :
1113 case MYSQLI_TYPE_YEAR :
1121 case MYSQLI_TYPE_DATETIME :
1122 case MYSQLI_TYPE_NEWDATE :
1123 case MYSQLI_TYPE_TIME :
1124 case MYSQLI_TYPE_TIMESTAMP :
1135 case MYSQLI_TYPE_INT24 :
1136 case MYSQLI_TYPE_LONG :
1137 case MYSQLI_TYPE_LONGLONG :
1138 case MYSQLI_TYPE_SHORT :
1139 case MYSQLI_TYPE_TINY :
1141 if (!empty($fieldobj->primary_key)) return 'R';
1146 // Added floating-point types
1147 // Maybe not necessery.
1150 // case 'DOUBLE PRECISION':
1155 //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>";
1165 class ADORecordSet_array_mysqli extends ADORecordSet_array {
1167 function ADORecordSet_array_mysqli($id=-1,$mode=false)
1169 $this->ADORecordSet_array($id,$mode);
1172 function MetaType($t, $len = -1, $fieldobj = false)
1174 if (is_object($t)) {
1176 $t = $fieldobj->type;
1177 $len = $fieldobj->max_length;
1181 $len = -1; // mysql max_length is not accurate
1182 switch (strtoupper($t)) {
1191 case MYSQLI_TYPE_TINY_BLOB :
1192 #case MYSQLI_TYPE_CHAR :
1193 case MYSQLI_TYPE_STRING :
1194 case MYSQLI_TYPE_ENUM :
1195 case MYSQLI_TYPE_SET :
1197 if ($len <= $this->blobSize) return 'C';
1205 // php_mysql extension always returns 'blob' even if 'text'
1206 // so we have to check whether binary...
1212 case MYSQLI_TYPE_BLOB :
1213 case MYSQLI_TYPE_LONG_BLOB :
1214 case MYSQLI_TYPE_MEDIUM_BLOB :
1216 return !empty($fieldobj->binary) ? 'B' : 'X';
1219 case MYSQLI_TYPE_DATE :
1220 case MYSQLI_TYPE_YEAR :
1228 case MYSQLI_TYPE_DATETIME :
1229 case MYSQLI_TYPE_NEWDATE :
1230 case MYSQLI_TYPE_TIME :
1231 case MYSQLI_TYPE_TIMESTAMP :
1242 case MYSQLI_TYPE_INT24 :
1243 case MYSQLI_TYPE_LONG :
1244 case MYSQLI_TYPE_LONGLONG :
1245 case MYSQLI_TYPE_SHORT :
1246 case MYSQLI_TYPE_TINY :
1248 if (!empty($fieldobj->primary_key)) return 'R';
1253 // Added floating-point types
1254 // Maybe not necessery.
1257 // case 'DOUBLE PRECISION':
1262 //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>";