a6b0602ff0b8f49a2c3a4ff11360b89dcf0e46dc
[Packages/TYPO3.CMS.git] / typo3 / sysext / adodb / adodb / drivers / adodb-mysqli.inc.php
1 <?php
2 /*
3 V4.81 3 May 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
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 (!method_exists($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 (!method_exists($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
717 class 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 /*
757 1 = MYSQLI_NOT_NULL_FLAG
758 2 = MYSQLI_PRI_KEY_FLAG
759 4 = MYSQLI_UNIQUE_KEY_FLAG
760 8 = MYSQLI_MULTIPLE_KEY_FLAG
761 16 = MYSQLI_BLOB_FLAG
762 32 = MYSQLI_UNSIGNED_FLAG
763 64 = MYSQLI_ZEROFILL_FLAG
764 128 = MYSQLI_BINARY_FLAG
765 256 = MYSQLI_ENUM_FLAG
766 512 = MYSQLI_AUTO_INCREMENT_FLAG
767 1024 = MYSQLI_TIMESTAMP_FLAG
768 2048 = MYSQLI_SET_FLAG
769 32768 = MYSQLI_NUM_FLAG
770 16384 = MYSQLI_PART_KEY_FLAG
771 32768 = MYSQLI_GROUP_FLAG
772 65536 = MYSQLI_UNIQUE_FLAG
773 131072 = 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
859 0 = MYSQLI_TYPE_DECIMAL
860 1 = MYSQLI_TYPE_CHAR
861 1 = MYSQLI_TYPE_TINY
862 2 = MYSQLI_TYPE_SHORT
863 3 = MYSQLI_TYPE_LONG
864 4 = MYSQLI_TYPE_FLOAT
865 5 = MYSQLI_TYPE_DOUBLE
866 6 = MYSQLI_TYPE_NULL
867 7 = MYSQLI_TYPE_TIMESTAMP
868 8 = MYSQLI_TYPE_LONGLONG
869 9 = MYSQLI_TYPE_INT24
870 10 = MYSQLI_TYPE_DATE
871 11 = MYSQLI_TYPE_TIME
872 12 = MYSQLI_TYPE_DATETIME
873 13 = MYSQLI_TYPE_YEAR
874 14 = MYSQLI_TYPE_NEWDATE
875 247 = MYSQLI_TYPE_ENUM
876 248 = MYSQLI_TYPE_SET
877 249 = MYSQLI_TYPE_TINY_BLOB
878 250 = MYSQLI_TYPE_MEDIUM_BLOB
879 251 = MYSQLI_TYPE_LONG_BLOB
880 252 = MYSQLI_TYPE_BLOB
881 253 = MYSQLI_TYPE_VAR_STRING
882 254 = MYSQLI_TYPE_STRING
883 255 = 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 ?>