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