source: sandbox/2.5.1-evolucao/phpgwapi/inc/adodb/drivers/adodb-mysqli.inc.php @ 8222

Revision 8222, 32.7 KB checked in by angelo, 11 years ago (diff)

Ticket #3491 - Compatibilizar Expresso com novas versoes do PHP

  • Property svn:eol-style set to native
  • Property svn:executable set to *
Line 
1<?php
2/*
3V5.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.
7  Set tabs to 8.
8 
9  MySQL code that does not support transactions. Use mysqlt if you need transactions.
10  Requires mysql client. Works on Windows and Unix.
11 
1221 October 2003: MySQLi extension implementation by Arjen de Rijke (a.de.rijke@xs4all.nl)
13Based on adodb 3.40
14*/
15
16// security - hide paths
17if (!defined('ADODB_DIR')) die();
18
19if (! defined("_ADODB_MYSQLI_LAYER")) {
20 define("_ADODB_MYSQLI_LAYER", 1 );
21 
22 // PHP5 compat...
23 if (! defined("MYSQLI_BINARY_FLAG"))  define("MYSQLI_BINARY_FLAG", 128);
24 if (!defined('MYSQLI_READ_DEFAULT_GROUP')) define('MYSQLI_READ_DEFAULT_GROUP',1);
25
26 // disable adodb extension - currently incompatible.
27 global $ADODB_EXTENSION; $ADODB_EXTENSION = false;
28
29class ADODB_mysqli extends ADOConnection {
30        var $databaseType = 'mysqli';
31        var $dataProvider = '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'";
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        var $arrayClass = 'ADORecordSet_array_mysqli';
54        var $multiQuery = false;
55       
56        function ADODB_mysqli()
57        {                       
58         // if(!extension_loaded("mysqli"))
59              ;//trigger_error("You must have the mysqli extension installed.", E_USER_ERROR);
60           
61        }
62       
63        function SetTransactionMode( $transaction_mode )
64        {
65                $this->_transmode  = $transaction_mode;
66                if (empty($transaction_mode)) {
67                        $this->Execute('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ');
68                        return;
69                }
70                if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
71                $this->Execute("SET SESSION TRANSACTION ".$transaction_mode);
72        }
73
74        // returns true or false
75        // To add: parameter int $port,
76        //         parameter string $socket
77        function _connect($argHostname = NULL,
78                          $argUsername = NULL,
79                          $argPassword = NULL,
80                          $argDatabasename = NULL, $persist=false)
81          {
82                 if(!extension_loaded("mysqli")) {
83                        return null;
84                 }
85            $this->_connectionID = @mysqli_init();
86           
87            if (is_null($this->_connectionID)) {
88              // mysqli_init only fails if insufficient memory
89              if ($this->debug)
90                                ADOConnection::outp("mysqli_init() failed : "  . $this->ErrorMsg());
91              return false;
92            }
93                /*
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>
97                */
98                foreach($this->optionFlags as $arr) {   
99                        mysqli_options($this->_connectionID,$arr[0],$arr[1]);
100                }
101
102                //http ://php.net/manual/en/mysqli.persistconns.php
103                if ($persist && PHP_VERSION > 5.2 && strncmp($argHostname,'p:',2) != 0) $argHostname = 'p:'.$argHostname;
104
105                #if (!empty($this->port)) $argHostname .= ":".$this->port;
106                $ok = mysqli_real_connect($this->_connectionID,
107                                    $argHostname,
108                                    $argUsername,
109                                    $argPassword,
110                                    $argDatabasename,
111                                        $this->port,
112                                        $this->socket,
113                                        $this->clientFlags);
114             
115                if ($ok) {
116                        if ($argDatabasename)  return $this->SelectDB($argDatabasename);
117                        return true;
118           } else {
119                        if ($this->debug)
120                                ADOConnection::outp("Could't connect : "  . $this->ErrorMsg());
121                        $this->_connectionID = null;
122                        return false;
123           }
124        }
125       
126        // returns true or false
127        // How to force a persistent connection
128        function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
129        {
130                return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true);
131
132        }
133       
134        // When is this used? Close old connection first?
135        // In _connect(), check $this->forceNewConnect?
136        function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
137          {
138            $this->forceNewConnect = true;
139            return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
140          }
141       
142        function IfNull( $field, $ifNull )
143        {
144                return " IFNULL($field, $ifNull) "; // if MySQL
145        }
146       
147        // do not use $ADODB_COUNTRECS
148        function GetOne($sql,$inputarr=false)
149        {
150        global $ADODB_GETONE_EOF;
151       
152                $ret = false;
153                $rs = $this->Execute($sql,$inputarr);
154                if ($rs) {
155                        if ($rs->EOF) $ret = $ADODB_GETONE_EOF;
156                        else $ret = reset($rs->fields);
157                        $rs->Close();
158                }
159                return $ret;
160        }
161       
162        function ServerInfo()
163        {
164                $arr['description'] = $this->GetOne("select version()");
165                $arr['version'] = ADOConnection::_findvers($arr['description']);
166                return $arr;
167        }
168       
169       
170        function BeginTrans()
171        {         
172                if ($this->transOff) return true;
173                $this->transCnt += 1;
174               
175                //$this->Execute('SET AUTOCOMMIT=0');
176                mysqli_autocommit($this->_connectionID, false);
177                $this->Execute('BEGIN');
178                return true;
179        }
180       
181        function CommitTrans($ok=true)
182        {
183                if ($this->transOff) return true;
184                if (!$ok) return $this->RollbackTrans();
185               
186                if ($this->transCnt) $this->transCnt -= 1;
187                $this->Execute('COMMIT');
188               
189                //$this->Execute('SET AUTOCOMMIT=1');
190                mysqli_autocommit($this->_connectionID, true);
191                return true;
192        }
193       
194        function RollbackTrans()
195        {
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);
201                return true;
202        }
203       
204        function RowLock($tables,$where='',$col='1 as adodbignore')
205        {
206                if ($this->transCnt==0) $this->BeginTrans();
207                if ($where) $where = ' where '.$where;
208                $rs = $this->Execute("select $col from $tables $where for update");
209                return !empty($rs);
210        }
211       
212        // if magic quotes disabled, use mysql_real_escape_string()
213        // From readme.htm:
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.
220        //
221        //Eg. $s = $db->qstr(_GET['name'],get_magic_quotes_gpc());
222        function qstr($s, $magic_quotes = false)
223        {
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) . "'";   
228           
229                if ($this->replaceQuote[0] == '\\')
230                        $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
231            return  "'".str_replace("'",$this->replaceQuote,$s)."'";
232          }
233          // undo magic quotes for "
234          $s = str_replace('\\"','"',$s);
235          return "'$s'";
236        }
237       
238        function _insertid()
239        {
240          $result = @mysqli_insert_id($this->_connectionID);
241          if ($result == -1){
242              if ($this->debug) ADOConnection::outp("mysqli_insert_id() failed : "  . $this->ErrorMsg());
243          }
244          return $result;
245        }
246       
247        // Only works for INSERT, UPDATE and DELETE query's
248        function _affectedrows()
249        {
250          $result =  @mysqli_affected_rows($this->_connectionID);
251          if ($result == -1) {
252              if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : "  . $this->ErrorMsg());
253          }
254          return $result;
255        }
256 
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";
264       
265        function CreateSequence($seqname='adodbseq',$startID=1)
266        {
267                if (empty($this->_genSeqSQL)) return false;
268                $u = strtoupper($seqname);
269               
270                $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
271                if (!$ok) return false;
272                return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
273        }
274       
275        function GenID($seqname='adodbseq',$startID=1)
276        {
277                // post-nuke sets hasGenID to false
278                if (!$this->hasGenID) return false;
279               
280                $getnext = sprintf($this->_genIDSQL,$seqname);
281                $holdtransOK = $this->_transOK; // save the current status
282                $rs = @$this->Execute($getnext);
283                if (!$rs) {
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);
290                }
291               
292                if ($rs) {
293                        $this->genID = mysqli_insert_id($this->_connectionID);
294                        $rs->Close();
295                } else
296                        $this->genID = 0;
297                       
298                return $this->genID;
299        }
300       
301        function MetaDatabases()
302        {
303                $query = "SHOW DATABASES";
304                $ret = $this->Execute($query);
305                if ($ret && is_object($ret)){
306                   $arr = array();
307                        while (!$ret->EOF){
308                                $db = $ret->Fields('Database');
309                                if ($db != 'mysql') $arr[] = $db;
310                                $ret->MoveNext();
311                        }
312                   return $arr;
313                }
314        return $ret;
315        }
316
317         
318        function MetaIndexes ($table, $primary = FALSE, $owner = false)
319        {
320                // save old fetch mode
321                global $ADODB_FETCH_MODE;
322               
323                $false = false;
324                $save = $ADODB_FETCH_MODE;
325                $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
326                if ($this->fetchMode !== FALSE) {
327                       $savem = $this->SetFetchMode(FALSE);
328                }
329               
330                // get index details
331                $rs = $this->Execute(sprintf('SHOW INDEXES FROM %s',$table));
332               
333                // restore fetchmode
334                if (isset($savem)) {
335                        $this->SetFetchMode($savem);
336                }
337                $ADODB_FETCH_MODE = $save;
338               
339                if (!is_object($rs)) {
340                        return $false;
341                }
342               
343                $indexes = array ();
344               
345                // parse index data into array
346                while ($row = $rs->FetchRow()) {
347                        if ($primary == FALSE AND $row[2] == 'PRIMARY') {
348                                continue;
349                        }
350                       
351                        if (!isset($indexes[$row[2]])) {
352                                $indexes[$row[2]] = array(
353                                        'unique' => ($row[1] == 0),
354                                        'columns' => array()
355                                );
356                        }
357                       
358                        $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];
359                }
360               
361                // sort columns by order in the index
362                foreach ( array_keys ($indexes) as $index )
363                {
364                        ksort ($indexes[$index]['columns']);
365                }
366               
367                return $indexes;
368        }
369
370       
371        // Format date column in sql string given an input format that understands Y M D
372        function SQLDate($fmt, $col=false)
373        {       
374                if (!$col) $col = $this->sysTimeStamp;
375                $s = 'DATE_FORMAT('.$col.",'";
376                $concat = false;
377                $len = strlen($fmt);
378                for ($i=0; $i < $len; $i++) {
379                        $ch = $fmt[$i];
380                        switch($ch) {
381                        case 'Y':
382                        case 'y':
383                                $s .= '%Y';
384                                break;
385                        case 'Q':
386                        case 'q':
387                                $s .= "'),Quarter($col)";
388                               
389                                if ($len > $i+1) $s .= ",DATE_FORMAT($col,'";
390                                else $s .= ",('";
391                                $concat = true;
392                                break;
393                        case 'M':
394                                $s .= '%b';
395                                break;
396                               
397                        case 'm':
398                                $s .= '%m';
399                                break;
400                        case 'D':
401                        case 'd':
402                                $s .= '%d';
403                                break;
404                       
405                        case 'H':
406                                $s .= '%H';
407                                break;
408                               
409                        case 'h':
410                                $s .= '%I';
411                                break;
412                               
413                        case 'i':
414                                $s .= '%i';
415                                break;
416                               
417                        case 's':
418                                $s .= '%s';
419                                break;
420                               
421                        case 'a':
422                        case 'A':
423                                $s .= '%p';
424                                break;
425                       
426                        case 'w':
427                                $s .= '%w';
428                                break;
429                               
430                        case 'l':
431                                $s .= '%W';
432                                break;
433                               
434                        default:
435                               
436                                if ($ch == '\\') {
437                                        $i++;
438                                        $ch = substr($fmt,$i,1);
439                                }
440                                $s .= $ch;
441                                break;
442                        }
443                }
444                $s.="')";
445                if ($concat) $s = "CONCAT($s)";
446                return $s;
447        }
448       
449        // returns concatenated string
450        // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator
451        function Concat()
452        {
453                $s = "";
454                $arr = func_get_args();
455               
456                // suggestion by andrew005@mnogo.ru
457                $s = implode(',',$arr);
458                if (strlen($s) > 0) return "CONCAT($s)";
459                else return '';
460        }
461       
462        // dayFraction is a day in floating point
463        function OffsetDate($dayFraction,$date=false)
464        {               
465                if (!$date) $date = $this->sysDate;
466               
467                $fraction = $dayFraction * 24 * 3600;
468                return $date . ' + INTERVAL ' .  $fraction.' SECOND';
469               
470//              return "from_unixtime(unix_timestamp($date)+$fraction)";
471        }
472       
473    function MetaProcedures($NamePattern = false, $catalog  = null, $schemaPattern  = null)
474    {
475        // save old fetch mode
476        global $ADODB_FETCH_MODE;
477
478        $false = false;
479        $save = $ADODB_FETCH_MODE;
480        $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
481
482        if ($this->fetchMode !== FALSE) {
483               $savem = $this->SetFetchMode(FALSE);
484        }
485
486        $procedures = array ();
487
488        // get index details
489
490        $likepattern = '';
491        if ($NamePattern) {
492           $likepattern = " LIKE '".$NamePattern."'";
493        }
494        $rs = $this->Execute('SHOW PROCEDURE STATUS'.$likepattern);
495        if (is_object($rs)) {
496
497            // parse index data into array
498            while ($row = $rs->FetchRow()) {
499                    $procedures[$row[1]] = array(
500                                    'type' => 'PROCEDURE',
501                                    'catalog' => '',
502
503                                    'schema' => '',
504                                    'remarks' => $row[7],
505                            );
506            }
507        }
508
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',
515                        'catalog' => '',
516                        'schema' => '',
517                        'remarks' => $row[7]
518                    );
519            }
520            }
521
522        // restore fetchmode
523        if (isset($savem)) {
524                $this->SetFetchMode($savem);
525
526        }
527        $ADODB_FETCH_MODE = $save;
528
529
530        return $procedures;
531    }
532       
533        function MetaTables($ttype=false,$showSchema=false,$mask=false)
534        {       
535                $save = $this->metaTablesSQL;
536                if ($showSchema && is_string($showSchema)) {
537                        $this->metaTablesSQL .= " from $showSchema";
538                }
539               
540                if ($mask) {
541                        $mask = $this->qstr($mask);
542                        $this->metaTablesSQL .= " like $mask";
543                }
544                $ret = ADOConnection::MetaTables($ttype,$showSchema);
545               
546                $this->metaTablesSQL = $save;
547                return $ret;
548        }
549       
550        // "Innox - Juan Carlos Gonzalez" <jgonzalez#innox.com.mx>
551        function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
552        {
553         global $ADODB_FETCH_MODE;
554               
555                if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true;
556               
557            if ( !empty($owner) ) {
558               $table = "$owner.$table";
559            }
560            $a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
561                if ($associative) {
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];
564       
565            $matches = array();
566       
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]);
574       
575                if ( $upper ) {
576                    $ref_table = strtoupper($ref_table);
577                }
578       
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();
582                        }
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];
587                    } else {
588                        $foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}";
589                    }
590                }
591            }
592           
593            return  $foreign_keys;
594        }
595       
596        function MetaColumns($table, $normalize=true)
597        {
598                $false = false;
599                if (!$this->metaColumnsSQL)
600                        return $false;
601               
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;
610                if (!is_object($rs))
611                        return $false;
612               
613                $retarr = array();
614                while (!$rs->EOF) {
615                        $fld = new ADOFieldObject();
616                        $fld->name = $rs->fields[0];
617                        $type = $rs->fields[1];
618                       
619                        // split type into type(length):
620                        $fld->scale = null;
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]);
631                                $fld->enums = $arr;
632                                $zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6
633                                $fld->max_length = ($zlen > 0) ? $zlen : 1;
634                        } else {
635                                $fld->type = $type;
636                                $fld->max_length = -1;
637                        }
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);
644
645                        if (!$fld->binary) {
646                                $d = $rs->fields[4];
647                                if ($d != '' && $d != 'NULL') {
648                                        $fld->has_default = true;
649                                        $fld->default_value = $d;
650                                } else {
651                                        $fld->has_default = false;
652                                }
653                        }
654                       
655                        if ($save == ADODB_FETCH_NUM) {
656                                $retarr[] = $fld;
657                        } else {
658                                $retarr[strtoupper($fld->name)] = $fld;
659                        }
660                        $rs->MoveNext();
661                }
662               
663                $rs->Close();
664                return $retarr;
665        }
666               
667        // returns true or false
668        function SelectDB($dbName)
669        {
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
673               
674            if ($this->_connectionID) {
675                $result = @mysqli_select_db($this->_connectionID, $dbName);
676                        if (!$result) {
677                        ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->ErrorMsg());
678                        }
679                        return $result;         
680                }
681            return false;       
682        }
683       
684        // parameters use PostgreSQL convention, not MySQL
685        function SelectLimit($sql,
686                              $nrows = -1,
687                              $offset = -1,
688                              $inputarr = false,
689                              $secs = 0)
690        {
691                $offsetStr = ($offset >= 0) ? "$offset," : '';
692                if ($nrows < 0) $nrows = '18446744073709551615';
693               
694                if ($secs)
695                        $rs = $this->CacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr );
696                else
697                        $rs = $this->Execute($sql . " LIMIT $offsetStr$nrows" , $inputarr );
698                       
699                return $rs;
700        }
701       
702       
703        function Prepare($sql)
704        {
705                return $sql;
706                $stmt = $this->_connectionID->prepare($sql);
707                if (!$stmt) {
708                        echo $this->ErrorMsg();
709                        return $sql;
710                }
711                return array($sql,$stmt);
712        }
713       
714       
715        // returns queryID or false
716        function _query($sql, $inputarr)
717        {
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;
725       
726                if (is_array($sql)) {
727               
728                        // Prepare() not supported because mysqli_stmt_execute does not return a recordset, but
729                        // returns as bound variables.
730               
731                        $stmt = $sql[1];
732                        $a = '';
733                        foreach($inputarr as $k => $v) {
734                                if (is_string($v)) $a .= 's';
735                                else if (is_integer($v)) $a .= 'i';
736                                else $a .= 'd';
737                        }
738                       
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);
742                        return $ret;
743                }
744               
745                /*
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());
748                    return false;
749                }
750               
751                return $mysql_res;
752                */
753               
754                if ($this->multiQuery) {
755                        $rs = mysqli_multi_query($this->_connectionID, $sql.';');
756                        if ($rs) {
757                                $rs = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->_connectionID ) : @mysqli_use_result( $this->_connectionID );
758                                return $rs ? $rs : true; // mysqli_more_results( $this->_connectionID )
759                        }
760                } else {
761                        $rs = mysqli_query($this->_connectionID, $sql, $ADODB_COUNTRECS ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT);
762               
763                        if ($rs) return $rs;
764                }
765
766                if($this->debug)
767                        ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());
768               
769                return false;
770               
771        }
772
773        /*      Returns: the last error message from previous database operation        */     
774        function ErrorMsg()
775          {
776            if (empty($this->_connectionID))
777              $this->_errorMsg = @mysqli_connect_error();
778            else
779              $this->_errorMsg = @mysqli_error($this->_connectionID);
780            return $this->_errorMsg;
781          }
782       
783        /*      Returns: the last error number from previous database operation */     
784        function ErrorNo()
785          {
786            if (empty($this->_connectionID)) 
787              return @mysqli_connect_errno();
788            else
789              return @mysqli_errno($this->_connectionID);
790          }
791       
792        // returns true or false
793        function _close()
794          {
795            @mysqli_close($this->_connectionID);
796            $this->_connectionID = false;
797          }
798
799        /*
800        * Maximum size of C field
801        */
802        function CharMax()
803        {
804                return 255;
805        }
806       
807        /*
808        * Maximum size of X field
809        */
810        function TextMax()
811        {
812          return 4294967295;
813        }
814
815
816
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
823
824  function GetCharSet()
825  {
826    //we will use ADO's builtin property charSet
827    if (!method_exists($this->_connectionID,'character_set_name'))
828        return false;
829       
830    $this->charSet = @$this->_connectionID->character_set_name();
831    if (!$this->charSet) {
832      return false;
833    } else {
834      return $this->charSet;
835    }
836  }
837
838  // SetCharSet - switch the client encoding
839  function SetCharSet($charset_name)
840  {
841    if (!method_exists($this->_connectionID,'set_charset'))
842        return false;
843
844    if ($this->charSet !== $charset_name) {
845      $if = @$this->_connectionID->set_charset($charset_name);
846      if ($if === true & $this->GetCharSet() == $charset_name) {
847        return true;
848      } else return false;
849    } else return true;
850  }
851
852
853
854
855}
856 
857/*--------------------------------------------------------------------------------------
858         Class Name: Recordset
859--------------------------------------------------------------------------------------*/
860
861class ADORecordSet_mysqli extends ADORecordSet{
862       
863        var $databaseType = "mysqli";
864        var $canSeek = true;
865       
866        function ADORecordSet_mysqli($queryID, $mode = false)
867        {
868          if ($mode === false)
869           {
870              global $ADODB_FETCH_MODE;
871              $mode = $ADODB_FETCH_MODE;
872           }
873           
874          switch ($mode)
875            {
876            case ADODB_FETCH_NUM:
877              $this->fetchMode = MYSQLI_NUM;
878              break;
879            case ADODB_FETCH_ASSOC:
880              $this->fetchMode = MYSQLI_ASSOC;
881              break;
882            case ADODB_FETCH_DEFAULT:
883            case ADODB_FETCH_BOTH:
884            default:
885              $this->fetchMode = MYSQLI_BOTH;
886              break;
887            }
888          $this->adodbFetchMode = $mode;
889          $this->ADORecordSet($queryID);       
890        }
891       
892        function _initrs()
893        {
894        global $ADODB_COUNTRECS;
895       
896                $this->_numOfRows = $ADODB_COUNTRECS ? @mysqli_num_rows($this->_queryID) : -1;
897                $this->_numOfFields = @mysqli_num_fields($this->_queryID);
898        }
899       
900/*
9011      = MYSQLI_NOT_NULL_FLAG
9022      = MYSQLI_PRI_KEY_FLAG
9034      = MYSQLI_UNIQUE_KEY_FLAG
9048      = MYSQLI_MULTIPLE_KEY_FLAG
90516     = MYSQLI_BLOB_FLAG
90632     = MYSQLI_UNSIGNED_FLAG
90764     = MYSQLI_ZEROFILL_FLAG
908128    = MYSQLI_BINARY_FLAG
909256    = MYSQLI_ENUM_FLAG
910512    = MYSQLI_AUTO_INCREMENT_FLAG
9111024   = MYSQLI_TIMESTAMP_FLAG
9122048   = MYSQLI_SET_FLAG
91332768  = MYSQLI_NUM_FLAG
91416384  = MYSQLI_PART_KEY_FLAG
91532768  = MYSQLI_GROUP_FLAG
91665536  = MYSQLI_UNIQUE_FLAG
917131072 = MYSQLI_BINCMP_FLAG
918*/
919
920        function FetchField($fieldOffset = -1)
921        {       
922                $fieldnr = $fieldOffset;
923                if ($fieldOffset != -1) {
924                  $fieldOffset = @mysqli_field_seek($this->_queryID, $fieldnr);
925                }
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;
935
936                return $o;
937        }
938
939        function GetRowAssoc($upper = true)
940        {
941                if ($this->fetchMode == MYSQLI_ASSOC && !$upper)
942                  return $this->fields;
943                $row = ADORecordSet::GetRowAssoc($upper);
944                return $row;
945        }
946       
947        /* Use associative array to get fields array */
948        function Fields($colname)
949        {       
950          if ($this->fetchMode != MYSQLI_NUM)
951            return @$this->fields[$colname];
952               
953          if (!$this->bind) {
954            $this->bind = array();
955            for ($i = 0; $i < $this->_numOfFields; $i++) {
956              $o = $this->FetchField($i);
957              $this->bind[strtoupper($o->name)] = $i;
958            }
959          }
960          return $this->fields[$this->bind[strtoupper($colname)]];
961        }
962       
963        function _seek($row)
964        {
965          if ($this->_numOfRows == 0)
966            return false;
967
968          if ($row < 0)
969            return false;
970
971          mysqli_data_seek($this->_queryID, $row);
972          $this->EOF = false;
973          return true;
974        }
975               
976               
977        function NextRecordSet()
978        {
979        global $ADODB_COUNTRECS;
980       
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)) {
988                return false;
989                }
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) {
994                        return false;
995                }
996                $this->_inited = false;
997                $this->bind = false;
998                $this->_currentRow = -1;
999                $this->Init();
1000                return true;
1001        }
1002
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.
1006        function MoveNext()
1007        {
1008                if ($this->EOF) return false;
1009                $this->_currentRow++;
1010                $this->fields = @mysqli_fetch_array($this->_queryID,$this->fetchMode);
1011               
1012                if (is_array($this->fields)) return true;
1013                $this->EOF = true;
1014                return false;
1015        }       
1016       
1017        function _fetch()
1018        {
1019                $this->fields = mysqli_fetch_array($this->_queryID,$this->fetchMode); 
1020                return is_array($this->fields);
1021        }
1022       
1023        function _close()
1024        {
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
1027
1028        while(mysqli_more_results($this->connection->_connectionID)){
1029           @mysqli_next_result($this->connection->_connectionID);
1030        }
1031
1032                mysqli_free_result($this->_queryID);
1033                $this->_queryID = false;       
1034        }
1035       
1036/*
1037
10380 = MYSQLI_TYPE_DECIMAL
10391 = MYSQLI_TYPE_CHAR
10401 = MYSQLI_TYPE_TINY
10412 = MYSQLI_TYPE_SHORT
10423 = MYSQLI_TYPE_LONG
10434 = MYSQLI_TYPE_FLOAT
10445 = MYSQLI_TYPE_DOUBLE
10456 = MYSQLI_TYPE_NULL
10467 = MYSQLI_TYPE_TIMESTAMP
10478 = MYSQLI_TYPE_LONGLONG
10489 = MYSQLI_TYPE_INT24
104910 = MYSQLI_TYPE_DATE
105011 = MYSQLI_TYPE_TIME
105112 = MYSQLI_TYPE_DATETIME
105213 = MYSQLI_TYPE_YEAR
105314 = MYSQLI_TYPE_NEWDATE
1054247 = MYSQLI_TYPE_ENUM
1055248 = MYSQLI_TYPE_SET
1056249 = MYSQLI_TYPE_TINY_BLOB
1057250 = MYSQLI_TYPE_MEDIUM_BLOB
1058251 = MYSQLI_TYPE_LONG_BLOB
1059252 = MYSQLI_TYPE_BLOB
1060253 = MYSQLI_TYPE_VAR_STRING
1061254 = MYSQLI_TYPE_STRING
1062255 = MYSQLI_TYPE_GEOMETRY
1063*/
1064
1065        function MetaType($t, $len = -1, $fieldobj = false)
1066        {
1067                if (is_object($t)) {
1068                    $fieldobj = $t;
1069                    $t = $fieldobj->type;
1070                    $len = $fieldobj->max_length;
1071                }
1072               
1073               
1074                 $len = -1; // mysql max_length is not accurate
1075                 switch (strtoupper($t)) {
1076                 case 'STRING':
1077                 case 'CHAR':
1078                 case 'VARCHAR':
1079                 case 'TINYBLOB':
1080                 case 'TINYTEXT':
1081                 case 'ENUM':
1082                 case 'SET':
1083               
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 :
1089                case 253 :
1090                   if ($len <= $this->blobSize) return 'C';
1091                   
1092                case 'TEXT':
1093                case 'LONGTEXT':
1094                case 'MEDIUMTEXT':
1095                   return 'X';
1096               
1097               
1098                   // php_mysql extension always returns 'blob' even if 'text'
1099                   // so we have to check whether binary...
1100                case 'IMAGE':
1101                case 'LONGBLOB':
1102                case 'BLOB':
1103                case 'MEDIUMBLOB':
1104               
1105                case MYSQLI_TYPE_BLOB :
1106                case MYSQLI_TYPE_LONG_BLOB :
1107                case MYSQLI_TYPE_MEDIUM_BLOB :
1108               
1109                   return !empty($fieldobj->binary) ? 'B' : 'X';
1110                case 'YEAR':
1111                case 'DATE':
1112                case MYSQLI_TYPE_DATE :
1113                case MYSQLI_TYPE_YEAR :
1114               
1115                   return 'D';
1116               
1117                case 'TIME':
1118                case 'DATETIME':
1119                case 'TIMESTAMP':
1120               
1121                case MYSQLI_TYPE_DATETIME :
1122                case MYSQLI_TYPE_NEWDATE :
1123                case MYSQLI_TYPE_TIME :
1124                case MYSQLI_TYPE_TIMESTAMP :
1125               
1126                        return 'T';
1127               
1128                case 'INT':
1129                case 'INTEGER':
1130                case 'BIGINT':
1131                case 'TINYINT':
1132                case 'MEDIUMINT':
1133                case 'SMALLINT':
1134               
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 :
1140               
1141                   if (!empty($fieldobj->primary_key)) return 'R';
1142                   
1143                   return 'I';
1144               
1145               
1146                   // Added floating-point types
1147                   // Maybe not necessery.
1148                 case 'FLOAT':
1149                 case 'DOUBLE':
1150                   //           case 'DOUBLE PRECISION':
1151                 case 'DECIMAL':
1152                 case 'DEC':
1153                 case 'FIXED':
1154                 default:
1155                        //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>";
1156                        return 'N';
1157                }
1158        } // function
1159       
1160
1161} // rs class
1162 
1163}
1164
1165class ADORecordSet_array_mysqli extends ADORecordSet_array {
1166 
1167  function ADORecordSet_array_mysqli($id=-1,$mode=false)
1168  {
1169    $this->ADORecordSet_array($id,$mode);
1170  }
1171 
1172        function MetaType($t, $len = -1, $fieldobj = false)
1173        {
1174                if (is_object($t)) {
1175                    $fieldobj = $t;
1176                    $t = $fieldobj->type;
1177                    $len = $fieldobj->max_length;
1178                }
1179               
1180               
1181                 $len = -1; // mysql max_length is not accurate
1182                 switch (strtoupper($t)) {
1183                 case 'STRING':
1184                 case 'CHAR':
1185                 case 'VARCHAR':
1186                 case 'TINYBLOB':
1187                 case 'TINYTEXT':
1188                 case 'ENUM':
1189                 case 'SET':
1190               
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 :
1196                case 253 :
1197                   if ($len <= $this->blobSize) return 'C';
1198                   
1199                case 'TEXT':
1200                case 'LONGTEXT':
1201                case 'MEDIUMTEXT':
1202                   return 'X';
1203               
1204               
1205                   // php_mysql extension always returns 'blob' even if 'text'
1206                   // so we have to check whether binary...
1207                case 'IMAGE':
1208                case 'LONGBLOB':
1209                case 'BLOB':
1210                case 'MEDIUMBLOB':
1211               
1212                case MYSQLI_TYPE_BLOB :
1213                case MYSQLI_TYPE_LONG_BLOB :
1214                case MYSQLI_TYPE_MEDIUM_BLOB :
1215               
1216                   return !empty($fieldobj->binary) ? 'B' : 'X';
1217                case 'YEAR':
1218                case 'DATE':
1219                case MYSQLI_TYPE_DATE :
1220                case MYSQLI_TYPE_YEAR :
1221               
1222                   return 'D';
1223               
1224                case 'TIME':
1225                case 'DATETIME':
1226                case 'TIMESTAMP':
1227               
1228                case MYSQLI_TYPE_DATETIME :
1229                case MYSQLI_TYPE_NEWDATE :
1230                case MYSQLI_TYPE_TIME :
1231                case MYSQLI_TYPE_TIMESTAMP :
1232               
1233                        return 'T';
1234               
1235                case 'INT':
1236                case 'INTEGER':
1237                case 'BIGINT':
1238                case 'TINYINT':
1239                case 'MEDIUMINT':
1240                case 'SMALLINT':
1241               
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 :
1247               
1248                   if (!empty($fieldobj->primary_key)) return 'R';
1249                   
1250                   return 'I';
1251               
1252               
1253                   // Added floating-point types
1254                   // Maybe not necessery.
1255                 case 'FLOAT':
1256                 case 'DOUBLE':
1257                   //           case 'DOUBLE PRECISION':
1258                 case 'DECIMAL':
1259                 case 'DEC':
1260                 case 'FIXED':
1261                 default:
1262                        //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>";
1263                        return 'N';
1264                }
1265        } // function
1266 
1267}
1268
1269?>
Note: See TracBrowser for help on using the repository browser.