[TASK] Update ADOdb to 5.18
[Packages/TYPO3.CMS.git] / typo3 / sysext / adodb / adodb / drivers / adodb-mysql.inc.php
1 <?php
2 /*
3 V5.18 3 Sep 2012 (c) 2000-2012 John Lim (jlim#natsoft.com). All rights reserved.
4 Released under both BSD license and Lesser GPL library license.
5 Whenever there is any discrepancy between the two licenses,
6 the BSD license will take precedence.
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 28 Feb 2001: MetaColumns bug fix - suggested by Freek Dijkstra (phpeverywhere@macfreek.com)
13 */
14
15 // security - hide paths
16 if (!defined('ADODB_DIR')) die();
17
18 if (! defined("_ADODB_MYSQL_LAYER")) {
19 define("_ADODB_MYSQL_LAYER", 1 );
20
21 class ADODB_mysql extends ADOConnection {
22 var $databaseType = 'mysql';
23 var $dataProvider = 'mysql';
24 var $hasInsertID = true;
25 var $hasAffectedRows = true;
26 var $metaTablesSQL = "SELECT TABLE_NAME, CASE WHEN TABLE_TYPE = 'VIEW' THEN 'V' ELSE 'T' END FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=SCHEMA()";
27 var $metaColumnsSQL = "SHOW COLUMNS FROM `%s`";
28 var $fmtTimeStamp = "'Y-m-d H:i:s'";
29 var $hasLimit = true;
30 var $hasMoveFirst = true;
31 var $hasGenID = true;
32 var $isoDates = true; // accepts dates in ISO format
33 var $sysDate = 'CURDATE()';
34 var $sysTimeStamp = 'NOW()';
35 var $hasTransactions = false;
36 var $forceNewConnect = false;
37 var $poorAffectedRows = true;
38 var $clientFlags = 0;
39 var $charSet = '';
40 var $substr = "substring";
41 var $nameQuote = '`'; /// string to use to quote identifiers and names
42 var $compat323 = false; // true if compat with mysql 3.23
43
44 function ADODB_mysql()
45 {
46 if (defined('ADODB_EXTENSION')) $this->rsPrefix .= 'ext_';
47 }
48
49
50 // SetCharSet - switch the client encoding
51 function SetCharSet($charset_name)
52 {
53 if (!function_exists('mysql_set_charset'))
54 return false;
55
56 if ($this->charSet !== $charset_name) {
57 $ok = @mysql_set_charset($charset_name,$this->_connectionID);
58 if ($ok) {
59 $this->charSet = $charset_name;
60 return true;
61 }
62 return false;
63 }
64 return true;
65 }
66
67 function ServerInfo()
68 {
69 $arr['description'] = ADOConnection::GetOne("select version()");
70 $arr['version'] = ADOConnection::_findvers($arr['description']);
71 return $arr;
72 }
73
74 function IfNull( $field, $ifNull )
75 {
76 return " IFNULL($field, $ifNull) "; // if MySQL
77 }
78
79 function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null)
80 {
81 // save old fetch mode
82 global $ADODB_FETCH_MODE;
83
84 $false = false;
85 $save = $ADODB_FETCH_MODE;
86 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
87
88 if ($this->fetchMode !== FALSE) {
89 $savem = $this->SetFetchMode(FALSE);
90 }
91
92 $procedures = array ();
93
94 // get index details
95
96 $likepattern = '';
97 if ($NamePattern) {
98 $likepattern = " LIKE '".$NamePattern."'";
99 }
100 $rs = $this->Execute('SHOW PROCEDURE STATUS'.$likepattern);
101 if (is_object($rs)) {
102
103 // parse index data into array
104 while ($row = $rs->FetchRow()) {
105 $procedures[$row[1]] = array(
106 'type' => 'PROCEDURE',
107 'catalog' => '',
108
109 'schema' => '',
110 'remarks' => $row[7],
111 );
112 }
113 }
114
115 $rs = $this->Execute('SHOW FUNCTION STATUS'.$likepattern);
116 if (is_object($rs)) {
117 // parse index data into array
118 while ($row = $rs->FetchRow()) {
119 $procedures[$row[1]] = array(
120 'type' => 'FUNCTION',
121 'catalog' => '',
122 'schema' => '',
123 'remarks' => $row[7]
124 );
125 }
126 }
127
128 // restore fetchmode
129 if (isset($savem)) {
130 $this->SetFetchMode($savem);
131
132 }
133 $ADODB_FETCH_MODE = $save;
134
135
136 return $procedures;
137 }
138
139 function MetaTables($ttype=false,$showSchema=false,$mask=false)
140 {
141 $save = $this->metaTablesSQL;
142 if ($showSchema && is_string($showSchema)) {
143 $this->metaTablesSQL .= " from $showSchema";
144 }
145
146 if ($mask) {
147 $mask = $this->qstr($mask);
148 $this->metaTablesSQL .= " like $mask";
149 }
150 $ret = ADOConnection::MetaTables($ttype,$showSchema);
151
152 $this->metaTablesSQL = $save;
153 return $ret;
154 }
155
156
157 function MetaIndexes ($table, $primary = FALSE, $owner=false)
158 {
159 // save old fetch mode
160 global $ADODB_FETCH_MODE;
161
162 $false = false;
163 $save = $ADODB_FETCH_MODE;
164 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
165 if ($this->fetchMode !== FALSE) {
166 $savem = $this->SetFetchMode(FALSE);
167 }
168
169 // get index details
170 $rs = $this->Execute(sprintf('SHOW INDEX FROM %s',$table));
171
172 // restore fetchmode
173 if (isset($savem)) {
174 $this->SetFetchMode($savem);
175 }
176 $ADODB_FETCH_MODE = $save;
177
178 if (!is_object($rs)) {
179 return $false;
180 }
181
182 $indexes = array ();
183
184 // parse index data into array
185 while ($row = $rs->FetchRow()) {
186 if ($primary == FALSE AND $row[2] == 'PRIMARY') {
187 continue;
188 }
189
190 if (!isset($indexes[$row[2]])) {
191 $indexes[$row[2]] = array(
192 'unique' => ($row[1] == 0),
193 'columns' => array()
194 );
195 }
196
197 $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];
198 }
199
200 // sort columns by order in the index
201 foreach ( array_keys ($indexes) as $index )
202 {
203 ksort ($indexes[$index]['columns']);
204 }
205
206 return $indexes;
207 }
208
209
210 // if magic quotes disabled, use mysql_real_escape_string()
211 function qstr($s,$magic_quotes=false)
212 {
213 if (is_null($s)) return 'NULL';
214 if (!$magic_quotes) {
215
216 if (ADODB_PHPVER >= 0x4300) {
217 if (is_resource($this->_connectionID))
218 return "'".mysql_real_escape_string($s,$this->_connectionID)."'";
219 }
220 if ($this->replaceQuote[0] == '\\'){
221 $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
222 }
223 return "'".str_replace("'",$this->replaceQuote,$s)."'";
224 }
225
226 // undo magic quotes for "
227 $s = str_replace('\\"','"',$s);
228 return "'$s'";
229 }
230
231 function _insertid()
232 {
233 return ADOConnection::GetOne('SELECT LAST_INSERT_ID()');
234 //return mysql_insert_id($this->_connectionID);
235 }
236
237 function GetOne($sql,$inputarr=false)
238 {
239 global $ADODB_GETONE_EOF;
240 if ($this->compat323 == false && strncasecmp($sql,'sele',4) == 0) {
241 $rs = $this->SelectLimit($sql,1,-1,$inputarr);
242 if ($rs) {
243 $rs->Close();
244 if ($rs->EOF) return $ADODB_GETONE_EOF;
245 return reset($rs->fields);
246 }
247 } else {
248 return ADOConnection::GetOne($sql,$inputarr);
249 }
250 return false;
251 }
252
253 function BeginTrans()
254 {
255 if ($this->debug) ADOConnection::outp("Transactions not supported in 'mysql' driver. Use 'mysqlt' or 'mysqli' driver");
256 }
257
258 function _affectedrows()
259 {
260 return mysql_affected_rows($this->_connectionID);
261 }
262
263 // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html
264 // Reference on Last_Insert_ID on the recommended way to simulate sequences
265 var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
266 var $_genSeqSQL = "create table %s (id int not null)";
267 var $_genSeqCountSQL = "select count(*) from %s";
268 var $_genSeq2SQL = "insert into %s values (%s)";
269 var $_dropSeqSQL = "drop table %s";
270
271 function CreateSequence($seqname='adodbseq',$startID=1)
272 {
273 if (empty($this->_genSeqSQL)) return false;
274 $u = strtoupper($seqname);
275
276 $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
277 if (!$ok) return false;
278 return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
279 }
280
281
282 function GenID($seqname='adodbseq',$startID=1)
283 {
284 // post-nuke sets hasGenID to false
285 if (!$this->hasGenID) return false;
286
287 $savelog = $this->_logsql;
288 $this->_logsql = false;
289 $getnext = sprintf($this->_genIDSQL,$seqname);
290 $holdtransOK = $this->_transOK; // save the current status
291 $rs = @$this->Execute($getnext);
292 if (!$rs) {
293 if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset
294 $u = strtoupper($seqname);
295 $this->Execute(sprintf($this->_genSeqSQL,$seqname));
296 $cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seqname));
297 if (!$cnt) $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
298 $rs = $this->Execute($getnext);
299 }
300
301 if ($rs) {
302 $this->genID = mysql_insert_id($this->_connectionID);
303 $rs->Close();
304 } else
305 $this->genID = 0;
306
307 $this->_logsql = $savelog;
308 return $this->genID;
309 }
310
311 function MetaDatabases()
312 {
313 $qid = mysql_list_dbs($this->_connectionID);
314 $arr = array();
315 $i = 0;
316 $max = mysql_num_rows($qid);
317 while ($i < $max) {
318 $db = mysql_tablename($qid,$i);
319 if ($db != 'mysql') $arr[] = $db;
320 $i += 1;
321 }
322 return $arr;
323 }
324
325
326 // Format date column in sql string given an input format that understands Y M D
327 function SQLDate($fmt, $col=false)
328 {
329 if (!$col) $col = $this->sysTimeStamp;
330 $s = 'DATE_FORMAT('.$col.",'";
331 $concat = false;
332 $len = strlen($fmt);
333 for ($i=0; $i < $len; $i++) {
334 $ch = $fmt[$i];
335 switch($ch) {
336
337 default:
338 if ($ch == '\\') {
339 $i++;
340 $ch = substr($fmt,$i,1);
341 }
342 /** FALL THROUGH */
343 case '-':
344 case '/':
345 $s .= $ch;
346 break;
347
348 case 'Y':
349 case 'y':
350 $s .= '%Y';
351 break;
352 case 'M':
353 $s .= '%b';
354 break;
355
356 case 'm':
357 $s .= '%m';
358 break;
359 case 'D':
360 case 'd':
361 $s .= '%d';
362 break;
363
364 case 'Q':
365 case 'q':
366 $s .= "'),Quarter($col)";
367
368 if ($len > $i+1) $s .= ",DATE_FORMAT($col,'";
369 else $s .= ",('";
370 $concat = true;
371 break;
372
373 case 'H':
374 $s .= '%H';
375 break;
376
377 case 'h':
378 $s .= '%I';
379 break;
380
381 case 'i':
382 $s .= '%i';
383 break;
384
385 case 's':
386 $s .= '%s';
387 break;
388
389 case 'a':
390 case 'A':
391 $s .= '%p';
392 break;
393
394 case 'w':
395 $s .= '%w';
396 break;
397
398 case 'W':
399 $s .= '%U';
400 break;
401
402 case 'l':
403 $s .= '%W';
404 break;
405 }
406 }
407 $s.="')";
408 if ($concat) $s = "CONCAT($s)";
409 return $s;
410 }
411
412
413 // returns concatenated string
414 // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator
415 function Concat()
416 {
417 $s = "";
418 $arr = func_get_args();
419
420 // suggestion by andrew005@mnogo.ru
421 $s = implode(',',$arr);
422 if (strlen($s) > 0) return "CONCAT($s)";
423 else return '';
424 }
425
426 function OffsetDate($dayFraction,$date=false)
427 {
428 if (!$date) $date = $this->sysDate;
429
430 $fraction = $dayFraction * 24 * 3600;
431 return '('. $date . ' + INTERVAL ' . $fraction.' SECOND)';
432
433 // return "from_unixtime(unix_timestamp($date)+$fraction)";
434 }
435
436 // returns true or false
437 function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
438 {
439 if (!empty($this->port)) $argHostname .= ":".$this->port;
440
441 if (ADODB_PHPVER >= 0x4300)
442 $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword,
443 $this->forceNewConnect,$this->clientFlags);
444 else if (ADODB_PHPVER >= 0x4200)
445 $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword,
446 $this->forceNewConnect);
447 else
448 $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword);
449
450 if ($this->_connectionID === false) return false;
451 if ($argDatabasename) return $this->SelectDB($argDatabasename);
452 return true;
453 }
454
455 // returns true or false
456 function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
457 {
458 if (!empty($this->port)) $argHostname .= ":".$this->port;
459
460 if (ADODB_PHPVER >= 0x4300)
461 $this->_connectionID = mysql_pconnect($argHostname,$argUsername,$argPassword,$this->clientFlags);
462 else
463 $this->_connectionID = mysql_pconnect($argHostname,$argUsername,$argPassword);
464 if ($this->_connectionID === false) return false;
465 if ($this->autoRollback) $this->RollbackTrans();
466 if ($argDatabasename) return $this->SelectDB($argDatabasename);
467 return true;
468 }
469
470 function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
471 {
472 $this->forceNewConnect = true;
473 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
474 }
475
476 function MetaColumns($table, $normalize=true)
477 {
478 $this->_findschema($table,$schema);
479 if ($schema) {
480 $dbName = $this->database;
481 $this->SelectDB($schema);
482 }
483 global $ADODB_FETCH_MODE;
484 $save = $ADODB_FETCH_MODE;
485 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
486
487 if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
488 $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
489
490 if ($schema) {
491 $this->SelectDB($dbName);
492 }
493
494 if (isset($savem)) $this->SetFetchMode($savem);
495 $ADODB_FETCH_MODE = $save;
496 if (!is_object($rs)) {
497 $false = false;
498 return $false;
499 }
500
501 $retarr = array();
502 while (!$rs->EOF){
503 $fld = new ADOFieldObject();
504 $fld->name = $rs->fields[0];
505 $type = $rs->fields[1];
506
507 // split type into type(length):
508 $fld->scale = null;
509 if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {
510 $fld->type = $query_array[1];
511 $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
512 $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;
513 } elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {
514 $fld->type = $query_array[1];
515 $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
516 } elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) {
517 $fld->type = $query_array[1];
518 $arr = explode(",",$query_array[2]);
519 $fld->enums = $arr;
520 $zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6
521 $fld->max_length = ($zlen > 0) ? $zlen : 1;
522 } else {
523 $fld->type = $type;
524 $fld->max_length = -1;
525 }
526 $fld->not_null = ($rs->fields[2] != 'YES');
527 $fld->primary_key = ($rs->fields[3] == 'PRI');
528 $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
529 $fld->binary = (strpos($type,'blob') !== false || strpos($type,'binary') !== false);
530 $fld->unsigned = (strpos($type,'unsigned') !== false);
531 $fld->zerofill = (strpos($type,'zerofill') !== false);
532
533 if (!$fld->binary) {
534 $d = $rs->fields[4];
535 if ($d != '' && $d != 'NULL') {
536 $fld->has_default = true;
537 $fld->default_value = $d;
538 } else {
539 $fld->has_default = false;
540 }
541 }
542
543 if ($save == ADODB_FETCH_NUM) {
544 $retarr[] = $fld;
545 } else {
546 $retarr[strtoupper($fld->name)] = $fld;
547 }
548 $rs->MoveNext();
549 }
550
551 $rs->Close();
552 return $retarr;
553 }
554
555 // returns true or false
556 function SelectDB($dbName)
557 {
558 $this->database = $dbName;
559 $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
560 if ($this->_connectionID) {
561 return @mysql_select_db($dbName,$this->_connectionID);
562 }
563 else return false;
564 }
565
566 // parameters use PostgreSQL convention, not MySQL
567 function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs=0)
568 {
569 $offsetStr =($offset>=0) ? ((integer)$offset)."," : '';
570 // jason judge, see http://phplens.com/lens/lensforum/msgs.php?id=9220
571 if ($nrows < 0) $nrows = '18446744073709551615';
572
573 if ($secs)
574 $rs = $this->CacheExecute($secs,$sql." LIMIT $offsetStr".((integer)$nrows),$inputarr);
575 else
576 $rs = $this->Execute($sql." LIMIT $offsetStr".((integer)$nrows),$inputarr);
577 return $rs;
578 }
579
580 // returns queryID or false
581 function _query($sql,$inputarr=false)
582 {
583 //global $ADODB_COUNTRECS;
584 //if($ADODB_COUNTRECS)
585 return mysql_query($sql,$this->_connectionID);
586 //else return @mysql_unbuffered_query($sql,$this->_connectionID); // requires PHP >= 4.0.6
587 }
588
589 /* Returns: the last error message from previous database operation */
590 function ErrorMsg()
591 {
592
593 if ($this->_logsql) return $this->_errorMsg;
594 if (empty($this->_connectionID)) $this->_errorMsg = @mysql_error();
595 else $this->_errorMsg = @mysql_error($this->_connectionID);
596 return $this->_errorMsg;
597 }
598
599 /* Returns: the last error number from previous database operation */
600 function ErrorNo()
601 {
602 if ($this->_logsql) return $this->_errorCode;
603 if (empty($this->_connectionID)) return @mysql_errno();
604 else return @mysql_errno($this->_connectionID);
605 }
606
607 // returns true or false
608 function _close()
609 {
610 @mysql_close($this->_connectionID);
611
612 $this->charSet = '';
613 $this->_connectionID = false;
614 }
615
616
617 /*
618 * Maximum size of C field
619 */
620 function CharMax()
621 {
622 return 255;
623 }
624
625 /*
626 * Maximum size of X field
627 */
628 function TextMax()
629 {
630 return 4294967295;
631 }
632
633 // "Innox - Juan Carlos Gonzalez" <jgonzalez#innox.com.mx>
634 function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
635 {
636 global $ADODB_FETCH_MODE;
637 if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true;
638
639 if ( !empty($owner) ) {
640 $table = "$owner.$table";
641 }
642 $a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
643 if ($associative) {
644 $create_sql = isset($a_create_table["Create Table"]) ? $a_create_table["Create Table"] : $a_create_table["Create View"];
645 } else $create_sql = $a_create_table[1];
646
647 $matches = array();
648
649 if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false;
650 $foreign_keys = array();
651 $num_keys = count($matches[0]);
652 for ( $i = 0; $i < $num_keys; $i ++ ) {
653 $my_field = explode('`, `', $matches[1][$i]);
654 $ref_table = $matches[2][$i];
655 $ref_field = explode('`, `', $matches[3][$i]);
656
657 if ( $upper ) {
658 $ref_table = strtoupper($ref_table);
659 }
660
661 // see https://sourceforge.net/tracker/index.php?func=detail&aid=2287278&group_id=42718&atid=433976
662 if (!isset($foreign_keys[$ref_table])) {
663 $foreign_keys[$ref_table] = array();
664 }
665 $num_fields = count($my_field);
666 for ( $j = 0; $j < $num_fields; $j ++ ) {
667 if ( $associative ) {
668 $foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j];
669 } else {
670 $foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}";
671 }
672 }
673 }
674
675 return $foreign_keys;
676 }
677
678
679 }
680
681 /*--------------------------------------------------------------------------------------
682 Class Name: Recordset
683 --------------------------------------------------------------------------------------*/
684
685
686 class ADORecordSet_mysql extends ADORecordSet{
687
688 var $databaseType = "mysql";
689 var $canSeek = true;
690
691 function ADORecordSet_mysql($queryID,$mode=false)
692 {
693 if ($mode === false) {
694 global $ADODB_FETCH_MODE;
695 $mode = $ADODB_FETCH_MODE;
696 }
697 switch ($mode)
698 {
699 case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break;
700 case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break;
701 case ADODB_FETCH_DEFAULT:
702 case ADODB_FETCH_BOTH:
703 default:
704 $this->fetchMode = MYSQL_BOTH; break;
705 }
706 $this->adodbFetchMode = $mode;
707 $this->ADORecordSet($queryID);
708 }
709
710 function _initrs()
711 {
712 //GLOBAL $ADODB_COUNTRECS;
713 // $this->_numOfRows = ($ADODB_COUNTRECS) ? @mysql_num_rows($this->_queryID):-1;
714 $this->_numOfRows = @mysql_num_rows($this->_queryID);
715 $this->_numOfFields = @mysql_num_fields($this->_queryID);
716 }
717
718 function FetchField($fieldOffset = -1)
719 {
720 if ($fieldOffset != -1) {
721 $o = @mysql_fetch_field($this->_queryID, $fieldOffset);
722 $f = @mysql_field_flags($this->_queryID,$fieldOffset);
723 if ($o) $o->max_length = @mysql_field_len($this->_queryID,$fieldOffset); // suggested by: Jim Nicholson (jnich#att.com)
724 //$o->max_length = -1; // mysql returns the max length less spaces -- so it is unrealiable
725 if ($o) $o->binary = (strpos($f,'binary')!== false);
726 }
727 else { /* The $fieldOffset argument is not provided thus its -1 */
728 $o = @mysql_fetch_field($this->_queryID);
729 //if ($o) $o->max_length = @mysql_field_len($this->_queryID); // suggested by: Jim Nicholson (jnich#att.com)
730 $o->max_length = -1; // mysql returns the max length less spaces -- so it is unrealiable
731 }
732
733 return $o;
734 }
735
736 function GetRowAssoc($upper=true)
737 {
738 if ($this->fetchMode == MYSQL_ASSOC && !$upper) $row = $this->fields;
739 else $row = ADORecordSet::GetRowAssoc($upper);
740 return $row;
741 }
742
743 /* Use associative array to get fields array */
744 function Fields($colname)
745 {
746 // added @ by "Michael William Miller" <mille562@pilot.msu.edu>
747 if ($this->fetchMode != MYSQL_NUM) return @$this->fields[$colname];
748
749 if (!$this->bind) {
750 $this->bind = array();
751 for ($i=0; $i < $this->_numOfFields; $i++) {
752 $o = $this->FetchField($i);
753 $this->bind[strtoupper($o->name)] = $i;
754 }
755 }
756 return $this->fields[$this->bind[strtoupper($colname)]];
757 }
758
759 function _seek($row)
760 {
761 if ($this->_numOfRows == 0) return false;
762 return @mysql_data_seek($this->_queryID,$row);
763 }
764
765 function MoveNext()
766 {
767 //return adodb_movenext($this);
768 //if (defined('ADODB_EXTENSION')) return adodb_movenext($this);
769 if (@$this->fields = mysql_fetch_array($this->_queryID,$this->fetchMode)) {
770 $this->_currentRow += 1;
771 return true;
772 }
773 if (!$this->EOF) {
774 $this->_currentRow += 1;
775 $this->EOF = true;
776 }
777 return false;
778 }
779
780 function _fetch()
781 {
782 $this->fields = @mysql_fetch_array($this->_queryID,$this->fetchMode);
783 return is_array($this->fields);
784 }
785
786 function _close() {
787 @mysql_free_result($this->_queryID);
788 $this->_queryID = false;
789 }
790
791 function MetaType($t,$len=-1,$fieldobj=false)
792 {
793 if (is_object($t)) {
794 $fieldobj = $t;
795 $t = $fieldobj->type;
796 $len = $fieldobj->max_length;
797 }
798
799 $len = -1; // mysql max_length is not accurate
800 switch (strtoupper($t)) {
801 case 'STRING':
802 case 'CHAR':
803 case 'VARCHAR':
804 case 'TINYBLOB':
805 case 'TINYTEXT':
806 case 'ENUM':
807 case 'SET':
808 if ($len <= $this->blobSize) return 'C';
809
810 case 'TEXT':
811 case 'LONGTEXT':
812 case 'MEDIUMTEXT':
813 return 'X';
814
815 // php_mysql extension always returns 'blob' even if 'text'
816 // so we have to check whether binary...
817 case 'IMAGE':
818 case 'LONGBLOB':
819 case 'BLOB':
820 case 'MEDIUMBLOB':
821 case 'BINARY':
822 return !empty($fieldobj->binary) ? 'B' : 'X';
823
824 case 'YEAR':
825 case 'DATE': return 'D';
826
827 case 'TIME':
828 case 'DATETIME':
829 case 'TIMESTAMP': return 'T';
830
831 case 'INT':
832 case 'INTEGER':
833 case 'BIGINT':
834 case 'TINYINT':
835 case 'MEDIUMINT':
836 case 'SMALLINT':
837
838 if (!empty($fieldobj->primary_key)) return 'R';
839 else return 'I';
840
841 default: return 'N';
842 }
843 }
844
845 }
846
847 class ADORecordSet_ext_mysql extends ADORecordSet_mysql {
848 function ADORecordSet_ext_mysql($queryID,$mode=false)
849 {
850 if ($mode === false) {
851 global $ADODB_FETCH_MODE;
852 $mode = $ADODB_FETCH_MODE;
853 }
854 switch ($mode)
855 {
856 case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break;
857 case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break;
858 case ADODB_FETCH_DEFAULT:
859 case ADODB_FETCH_BOTH:
860 default:
861 $this->fetchMode = MYSQL_BOTH; break;
862 }
863 $this->adodbFetchMode = $mode;
864 $this->ADORecordSet($queryID);
865 }
866
867 function MoveNext()
868 {
869 return @adodb_movenext($this);
870 }
871 }
872
873
874 }
875 ?>