Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

Rev Author Line No. Line
36 kaklik 1
<?php
2
/*
3
V4.80 8 Mar 2006  (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved.
4
  Released under both BSD license and Lesser GPL library license. 
5
  Whenever there is any discrepancy between the two licenses, 
6
  the BSD license will take precedence.
7
  Set tabs to 8.
8
 
9
  MySQL code that does not support transactions. Use mysqlt if you need transactions.
10
  Requires mysql client. Works on Windows and Unix.
11
 
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 (!is_callable($this->_connectionID,'character_set_name'))
684
    	return false;
685
 
686
    $this->charSet = @$this->_connectionID->character_set_name();
687
    if (!$this->charSet) {
688
      return false;
689
    } else {
690
      return $this->charSet;
691
    }
692
  }
693
 
694
  // SetCharSet - switch the client encoding
695
  function SetCharSet($charset_name)
696
  {
697
    if (!is_callable($this->_connectionID,'set_charset'))
698
    	return false;
699
 
700
    if ($this->charSet !== $charset_name) {
701
      $if = @$this->_connectionID->set_charset($charset_name);
702
      if ($if == "0" & $this->GetCharSet() == $charset_name) {
703
        return true;
704
      } else return false;
705
    } else return true;
706
  }
707
 
708
 
709
 
710
 
711
}
712
 
713
/*--------------------------------------------------------------------------------------
714
	 Class Name: Recordset
715
--------------------------------------------------------------------------------------*/
716
 
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
 
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
?>