Update to upstream version 4.94
[Packages/TYPO3.CMS.git] / typo3 / sysext / adodb / adodb / drivers / adodb-db2.inc.php
1 <?php
2 /*
3 V4.94 23 Jan 2007 (c) 2006 John Lim (jlim#natsoft.com.my). All rights reserved.
4
5 This is a version of the ADODB driver for DB2. It uses the 'ibm_db2' PECL extension
6 for PHP (http://pecl.php.net/package/ibm_db2), which in turn requires DB2 V8.2.2 or
7 higher.
8
9 Originally tested with PHP 5.1.1 and Apache 2.0.55 on Windows XP SP2.
10 More recently tested with PHP 5.1.2 and Apache 2.0.55 on Windows XP SP2.
11
12 This file was ported from "adodb-odbc.inc.php" by Larry Menard, "larry.menard#rogers.com".
13 I ripped out what I believed to be a lot of redundant or obsolete code, but there are
14 probably still some remnants of the ODBC support in this file; I'm relying on reviewers
15 of this code to point out any other things that can be removed.
16 */
17
18 // security - hide paths
19 if (!defined('ADODB_DIR')) die();
20
21 define("_ADODB_DB2_LAYER", 2 );
22
23 /*--------------------------------------------------------------------------------------
24 --------------------------------------------------------------------------------------*/
25
26
27 class ADODB_db2 extends ADOConnection {
28 var $databaseType = "db2";
29 var $fmtDate = "'Y-m-d'";
30 var $concat_operator = '||';
31
32 var $sysTime = 'CURRENT TIME';
33 var $sysDate = 'CURRENT DATE';
34 var $sysTimeStamp = 'CURRENT TIMESTAMP';
35
36 var $fmtTimeStamp = "'Y-m-d-H.i.s'";
37 var $replaceQuote = "''"; // string to use to replace quotes
38 var $dataProvider = "db2";
39 var $hasAffectedRows = true;
40
41 var $binmode = DB2_BINARY;
42
43 var $useFetchArray = false; // setting this to true will make array elements in FETCH_ASSOC mode case-sensitive
44 // breaking backward-compat
45 var $_bindInputArray = false;
46 var $_genIDSQL = "VALUES NEXTVAL FOR %s";
47 var $_genSeqSQL = "CREATE SEQUENCE %s START WITH 1 NO MAXVALUE NO CYCLE";
48 var $_dropSeqSQL = "DROP SEQUENCE %s";
49 var $_autocommit = true;
50 var $_haserrorfunctions = true;
51 var $_lastAffectedRows = 0;
52 var $uCaseTables = true; // for meta* functions, uppercase table names
53 var $hasInsertID = true;
54
55 function _insertid()
56 {
57 return ADOConnection::GetOne('VALUES IDENTITY_VAL_LOCAL()');
58 }
59
60 function ADODB_db2()
61 {
62 $this->_haserrorfunctions = ADODB_PHPVER >= 0x4050;
63 }
64
65 // returns true or false
66 function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)
67 {
68 global $php_errormsg;
69
70 if (!function_exists('db2_connect')) {
71 ADOConnection::outp("Warning: The old ODBC based DB2 driver has been renamed 'odbc_db2'. This ADOdb driver calls PHP's native db2 extension.");
72 return null;
73 }
74 // This needs to be set before the connect().
75 // Replaces the odbc_binmode() call that was in Execute()
76 ini_set('ibm_db2.binmode', $this->binmode);
77
78 if ($argDatabasename) {
79 $this->_connectionID = db2_connect($argDatabasename,$argUsername,$argPassword);
80 } else {
81 $this->_connectionID = db2_connect($argDSN,$argUsername,$argPassword);
82 }
83 if (isset($php_errormsg)) $php_errormsg = '';
84
85 // For db2_connect(), there is an optional 4th arg. If present, it must be
86 // an array of valid options. So far, we don't use them.
87
88 $this->_errorMsg = @db2_conn_errormsg();
89
90 if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
91
92 return $this->_connectionID != false;
93 }
94
95 // returns true or false
96 function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
97 {
98 global $php_errormsg;
99
100 if (!function_exists('db2_connect')) return null;
101
102 // This needs to be set before the connect().
103 // Replaces the odbc_binmode() call that was in Execute()
104 ini_set('ibm_db2.binmode', $this->binmode);
105
106 if (isset($php_errormsg)) $php_errormsg = '';
107 $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
108
109 if ($argDatabasename) {
110 $this->_connectionID = db2_pconnect($argDatabasename,$argUsername,$argPassword);
111 } else {
112 $this->_connectionID = db2_pconnect($argDSN,$argUsername,$argPassword);
113 }
114 if (isset($php_errormsg)) $php_errormsg = '';
115
116 $this->_errorMsg = @db2_conn_errormsg();
117 if ($this->_connectionID && $this->autoRollback) @db2_rollback($this->_connectionID);
118 if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
119
120 return $this->_connectionID != false;
121 }
122
123 // format and return date string in database timestamp format
124 function DBTimeStamp($ts)
125 {
126 if (empty($ts) && $ts !== 0) return 'null';
127 if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts);
128 return 'TO_DATE('.adodb_date($this->fmtTimeStamp,$ts).",'YYYY-MM-DD HH24:MI:SS')";
129 }
130
131 // Format date column in sql string given an input format that understands Y M D
132 function SQLDate($fmt, $col=false)
133 {
134 // use right() and replace() ?
135 if (!$col) $col = $this->sysDate;
136
137 /* use TO_CHAR() if $fmt is TO_CHAR() allowed fmt */
138 if ($fmt== 'Y-m-d H:i:s')
139 return 'TO_CHAR('.$col.", 'YYYY-MM-DD HH24:MI:SS')";
140
141 $s = '';
142
143 $len = strlen($fmt);
144 for ($i=0; $i < $len; $i++) {
145 if ($s) $s .= $this->concat_operator;
146 $ch = $fmt[$i];
147 switch($ch) {
148 case 'Y':
149 case 'y':
150 if ($len==1) return "year($col)";
151 $s .= "char(year($col))";
152 break;
153 case 'M':
154 if ($len==1) return "monthname($col)";
155 $s .= "substr(monthname($col),1,3)";
156 break;
157 case 'm':
158 if ($len==1) return "month($col)";
159 $s .= "right(digits(month($col)),2)";
160 break;
161 case 'D':
162 case 'd':
163 if ($len==1) return "day($col)";
164 $s .= "right(digits(day($col)),2)";
165 break;
166 case 'H':
167 case 'h':
168 if ($len==1) return "hour($col)";
169 if ($col != $this->sysDate) $s .= "right(digits(hour($col)),2)";
170 else $s .= "''";
171 break;
172 case 'i':
173 case 'I':
174 if ($len==1) return "minute($col)";
175 if ($col != $this->sysDate)
176 $s .= "right(digits(minute($col)),2)";
177 else $s .= "''";
178 break;
179 case 'S':
180 case 's':
181 if ($len==1) return "second($col)";
182 if ($col != $this->sysDate)
183 $s .= "right(digits(second($col)),2)";
184 else $s .= "''";
185 break;
186 default:
187 if ($ch == '\\') {
188 $i++;
189 $ch = substr($fmt,$i,1);
190 }
191 $s .= $this->qstr($ch);
192 }
193 }
194 return $s;
195 }
196
197
198 function ServerInfo()
199 {
200
201 if (!empty($this->host) && ADODB_PHPVER >= 0x4300) {
202 $dsn = strtoupper($this->host);
203 $first = true;
204 $found = false;
205
206 if (!function_exists('db2_data_source')) return false;
207
208 while(true) {
209
210 $rez = @db2_data_source($this->_connectionID,
211 $first ? SQL_FETCH_FIRST : SQL_FETCH_NEXT);
212 $first = false;
213 if (!is_array($rez)) break;
214 if (strtoupper($rez['server']) == $dsn) {
215 $found = true;
216 break;
217 }
218 }
219 if (!$found) return ADOConnection::ServerInfo();
220 if (!isset($rez['version'])) $rez['version'] = '';
221 return $rez;
222 } else {
223 return ADOConnection::ServerInfo();
224 }
225 }
226
227
228 function CreateSequence($seqname='adodbseq',$start=1)
229 {
230 if (empty($this->_genSeqSQL)) return false;
231 $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
232 if (!$ok) return false;
233 return true;
234 }
235
236 function DropSequence($seqname)
237 {
238 if (empty($this->_dropSeqSQL)) return false;
239 return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
240 }
241
242 /*
243 This algorithm is not very efficient, but works even if table locking
244 is not available.
245
246 Will return false if unable to generate an ID after $MAXLOOPS attempts.
247 */
248 function GenID($seq='adodbseq',$start=1)
249 {
250 // if you have to modify the parameter below, your database is overloaded,
251 // or you need to implement generation of id's yourself!
252 $num = $this->GetOne("VALUES NEXTVAL FOR $seq");
253 return $num;
254 }
255
256
257 function ErrorMsg()
258 {
259 if ($this->_haserrorfunctions) {
260 if ($this->_errorMsg !== false) return $this->_errorMsg;
261 if (empty($this->_connectionID)) return @db2_conn_errormsg();
262 return @db2_conn_errormsg($this->_connectionID);
263 } else return ADOConnection::ErrorMsg();
264 }
265
266 function ErrorNo()
267 {
268
269 if ($this->_haserrorfunctions) {
270 if ($this->_errorCode !== false) {
271 // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
272 return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode;
273 }
274
275 if (empty($this->_connectionID)) $e = @db2_conn_error();
276 else $e = @db2_conn_error($this->_connectionID);
277
278 // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
279 // so we check and patch
280 if (strlen($e)<=2) return 0;
281 return $e;
282 } else return ADOConnection::ErrorNo();
283 }
284
285
286
287 function BeginTrans()
288 {
289 if (!$this->hasTransactions) return false;
290 if ($this->transOff) return true;
291 $this->transCnt += 1;
292 $this->_autocommit = false;
293 return db2_autocommit($this->_connectionID,false);
294 }
295
296 function CommitTrans($ok=true)
297 {
298 if ($this->transOff) return true;
299 if (!$ok) return $this->RollbackTrans();
300 if ($this->transCnt) $this->transCnt -= 1;
301 $this->_autocommit = true;
302 $ret = db2_commit($this->_connectionID);
303 db2_autocommit($this->_connectionID,true);
304 return $ret;
305 }
306
307 function RollbackTrans()
308 {
309 if ($this->transOff) return true;
310 if ($this->transCnt) $this->transCnt -= 1;
311 $this->_autocommit = true;
312 $ret = db2_rollback($this->_connectionID);
313 db2_autocommit($this->_connectionID,true);
314 return $ret;
315 }
316
317 function MetaPrimaryKeys($table)
318 {
319 global $ADODB_FETCH_MODE;
320
321 if ($this->uCaseTables) $table = strtoupper($table);
322 $schema = '';
323 $this->_findschema($table,$schema);
324
325 $savem = $ADODB_FETCH_MODE;
326 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
327 $qid = @db2_primarykeys($this->_connectionID,'',$schema,$table);
328
329 if (!$qid) {
330 $ADODB_FETCH_MODE = $savem;
331 return false;
332 }
333 $rs = new ADORecordSet_db2($qid);
334 $ADODB_FETCH_MODE = $savem;
335
336 if (!$rs) return false;
337
338 $arr =& $rs->GetArray();
339 $rs->Close();
340 $arr2 = array();
341 for ($i=0; $i < sizeof($arr); $i++) {
342 if ($arr[$i][3]) $arr2[] = $arr[$i][3];
343 }
344 return $arr2;
345 }
346
347 function MetaForeignKeys($table, $owner = FALSE, $upper = FALSE, $asociative = FALSE )
348 {
349 global $ADODB_FETCH_MODE;
350
351 if ($this->uCaseTables) $table = strtoupper($table);
352 $schema = '';
353 $this->_findschema($table,$schema);
354
355 $savem = $ADODB_FETCH_MODE;
356 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
357 $qid = @db2_foreign_keys($this->_connectionID,'',$schema,$table);
358 if (!$qid) {
359 $ADODB_FETCH_MODE = $savem;
360 return false;
361 }
362 $rs = new ADORecordSet_db2($qid);
363
364 $ADODB_FETCH_MODE = $savem;
365 /*
366 $rs->fields indices
367 0 PKTABLE_CAT
368 1 PKTABLE_SCHEM
369 2 PKTABLE_NAME
370 3 PKCOLUMN_NAME
371 4 FKTABLE_CAT
372 5 FKTABLE_SCHEM
373 6 FKTABLE_NAME
374 7 FKCOLUMN_NAME
375 */
376 if (!$rs) return false;
377
378 $foreign_keys = array();
379 while (!$rs->EOF) {
380 if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
381 if (!is_array($foreign_keys[$rs->fields[5].'.'.$rs->fields[6]]))
382 $foreign_keys[$rs->fields[5].'.'.$rs->fields[6]] = array();
383 $foreign_keys[$rs->fields[5].'.'.$rs->fields[6]][$rs->fields[7]] = $rs->fields[3];
384 }
385 $rs->MoveNext();
386 }
387
388 $rs->Close();
389 return $foreign_key;
390 }
391
392
393 function &MetaTables($ttype=false,$schema=false)
394 {
395 global $ADODB_FETCH_MODE;
396
397 $savem = $ADODB_FETCH_MODE;
398 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
399 $qid = db2_tables($this->_connectionID);
400
401 $rs = new ADORecordSet_db2($qid);
402
403 $ADODB_FETCH_MODE = $savem;
404 if (!$rs) {
405 $false = false;
406 return $false;
407 }
408
409 $arr =& $rs->GetArray();
410
411 $rs->Close();
412 $arr2 = array();
413
414 if ($ttype) {
415 $isview = strncmp($ttype,'V',1) === 0;
416 }
417 for ($i=0; $i < sizeof($arr); $i++) {
418 if (!$arr[$i][2]) continue;
419 $type = $arr[$i][3];
420 $schemaval = ($schema) ? $arr[$i][1].'.' : '';
421 if ($ttype) {
422 if ($isview) {
423 if (strncmp($type,'V',1) === 0) $arr2[] = $schemaval.$arr[$i][2];
424 } else if (strncmp($type,'SYS',3) !== 0) $arr2[] = $schemaval.$arr[$i][2];
425 } else if (strncmp($type,'SYS',3) !== 0) $arr2[] = $schemaval.$arr[$i][2];
426 }
427 return $arr2;
428 }
429
430 /*
431 See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2datetime_data_type_changes.asp
432 / SQL data type codes /
433 #define SQL_UNKNOWN_TYPE 0
434 #define SQL_CHAR 1
435 #define SQL_NUMERIC 2
436 #define SQL_DECIMAL 3
437 #define SQL_INTEGER 4
438 #define SQL_SMALLINT 5
439 #define SQL_FLOAT 6
440 #define SQL_REAL 7
441 #define SQL_DOUBLE 8
442 #if (DB2VER >= 0x0300)
443 #define SQL_DATETIME 9
444 #endif
445 #define SQL_VARCHAR 12
446
447
448 / One-parameter shortcuts for date/time data types /
449 #if (DB2VER >= 0x0300)
450 #define SQL_TYPE_DATE 91
451 #define SQL_TYPE_TIME 92
452 #define SQL_TYPE_TIMESTAMP 93
453
454 #define SQL_UNICODE (-95)
455 #define SQL_UNICODE_VARCHAR (-96)
456 #define SQL_UNICODE_LONGVARCHAR (-97)
457 */
458 function DB2Types($t)
459 {
460 switch ((integer)$t) {
461 case 1:
462 case 12:
463 case 0:
464 case -95:
465 case -96:
466 return 'C';
467 case -97:
468 case -1: //text
469 return 'X';
470 case -4: //image
471 return 'B';
472
473 case 9:
474 case 91:
475 return 'D';
476
477 case 10:
478 case 11:
479 case 92:
480 case 93:
481 return 'T';
482
483 case 4:
484 case 5:
485 case -6:
486 return 'I';
487
488 case -11: // uniqidentifier
489 return 'R';
490 case -7: //bit
491 return 'L';
492
493 default:
494 return 'N';
495 }
496 }
497
498 function &MetaColumns($table)
499 {
500 global $ADODB_FETCH_MODE;
501
502 $false = false;
503 if ($this->uCaseTables) $table = strtoupper($table);
504 $schema = '';
505 $this->_findschema($table,$schema);
506
507 $savem = $ADODB_FETCH_MODE;
508 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
509
510 $colname = "%";
511 $qid = db2_columns($this->_connectionID, "", $schema, $table, $colname);
512 if (empty($qid)) return $false;
513
514 $rs =& new ADORecordSet_db2($qid);
515 $ADODB_FETCH_MODE = $savem;
516
517 if (!$rs) return $false;
518 $rs->_fetch();
519
520 $retarr = array();
521
522 /*
523 $rs->fields indices
524 0 TABLE_QUALIFIER
525 1 TABLE_SCHEM
526 2 TABLE_NAME
527 3 COLUMN_NAME
528 4 DATA_TYPE
529 5 TYPE_NAME
530 6 PRECISION
531 7 LENGTH
532 8 SCALE
533 9 RADIX
534 10 NULLABLE
535 11 REMARKS
536 */
537 while (!$rs->EOF) {
538 if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
539 $fld = new ADOFieldObject();
540 $fld->name = $rs->fields[3];
541 $fld->type = $this->DB2Types($rs->fields[4]);
542
543 // ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp
544 // access uses precision to store length for char/varchar
545 if ($fld->type == 'C' or $fld->type == 'X') {
546 if ($rs->fields[4] <= -95) // UNICODE
547 $fld->max_length = $rs->fields[7]/2;
548 else
549 $fld->max_length = $rs->fields[7];
550 } else
551 $fld->max_length = $rs->fields[7];
552 $fld->not_null = !empty($rs->fields[10]);
553 $fld->scale = $rs->fields[8];
554 $fld->primary_key = false;
555 $retarr[strtoupper($fld->name)] = $fld;
556 } else if (sizeof($retarr)>0)
557 break;
558 $rs->MoveNext();
559 }
560 $rs->Close();
561 if (empty($retarr)) $retarr = false;
562
563 $qid = db2_primary_keys($this->_connectionID, "", $schema, $table);
564 if (empty($qid)) return $false;
565
566 $rs =& new ADORecordSet_db2($qid);
567 $ADODB_FETCH_MODE = $savem;
568
569 if (!$rs) return $retarr;
570 $rs->_fetch();
571
572 /*
573 $rs->fields indices
574 0 TABLE_CAT
575 1 TABLE_SCHEM
576 2 TABLE_NAME
577 3 COLUMN_NAME
578 4 KEY_SEQ
579 5 PK_NAME
580 */
581 while (!$rs->EOF) {
582 if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
583 $retarr[strtoupper($rs->fields[3])]->primary_key = true;
584 } else if (sizeof($retarr)>0)
585 break;
586 $rs->MoveNext();
587 }
588 $rs->Close();
589
590 if (empty($retarr)) $retarr = false;
591 return $retarr;
592 }
593
594 function Prepare($sql)
595 {
596 if (! $this->_bindInputArray) return $sql; // no binding
597 $stmt = db2_prepare($this->_connectionID,$sql);
598 if (!$stmt) {
599 // we don't know whether db2 driver is parsing prepared stmts, so just return sql
600 return $sql;
601 }
602 return array($sql,$stmt,false);
603 }
604
605 /* returns queryID or false */
606 function _query($sql,$inputarr=false)
607 {
608 GLOBAL $php_errormsg;
609 if (isset($php_errormsg)) $php_errormsg = '';
610 $this->_error = '';
611
612 if ($inputarr) {
613 if (is_array($sql)) {
614 $stmtid = $sql[1];
615 } else {
616 $stmtid = db2_prepare($this->_connectionID,$sql);
617
618 if ($stmtid == false) {
619 $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
620 return false;
621 }
622 }
623
624 if (! db2_execute($stmtid,$inputarr)) {
625 if ($this->_haserrorfunctions) {
626 $this->_errorMsg = db2_stmt_errormsg();
627 $this->_errorCode = db2_stmt_error();
628 }
629 return false;
630 }
631
632 } else if (is_array($sql)) {
633 $stmtid = $sql[1];
634 if (!db2_execute($stmtid)) {
635 if ($this->_haserrorfunctions) {
636 $this->_errorMsg = db2_stmt_errormsg();
637 $this->_errorCode = db2_stmt_error();
638 }
639 return false;
640 }
641 } else
642 $stmtid = @db2_exec($this->_connectionID,$sql);
643
644 $this->_lastAffectedRows = 0;
645 if ($stmtid) {
646 if (@db2_num_fields($stmtid) == 0) {
647 $this->_lastAffectedRows = db2_num_rows($stmtid);
648 $stmtid = true;
649 } else {
650 $this->_lastAffectedRows = 0;
651 }
652
653 if ($this->_haserrorfunctions) {
654 $this->_errorMsg = '';
655 $this->_errorCode = 0;
656 } else
657 $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
658 } else {
659 if ($this->_haserrorfunctions) {
660 $this->_errorMsg = db2_stmt_errormsg();
661 $this->_errorCode = db2_stmt_error();
662 } else
663 $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
664
665 }
666 return $stmtid;
667 }
668
669 /*
670 Insert a null into the blob field of the table first.
671 Then use UpdateBlob to store the blob.
672
673 Usage:
674
675 $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
676 $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
677 */
678 function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
679 {
680 return $this->Execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false;
681 }
682
683 // returns true or false
684 function _close()
685 {
686 $ret = @db2_close($this->_connectionID);
687 $this->_connectionID = false;
688 return $ret;
689 }
690
691 function _affectedrows()
692 {
693 return $this->_lastAffectedRows;
694 }
695
696 }
697
698 /*--------------------------------------------------------------------------------------
699 Class Name: Recordset
700 --------------------------------------------------------------------------------------*/
701
702 class ADORecordSet_db2 extends ADORecordSet {
703
704 var $bind = false;
705 var $databaseType = "db2";
706 var $dataProvider = "db2";
707 var $useFetchArray;
708
709 function ADORecordSet_db2($id,$mode=false)
710 {
711 if ($mode === false) {
712 global $ADODB_FETCH_MODE;
713 $mode = $ADODB_FETCH_MODE;
714 }
715 $this->fetchMode = $mode;
716
717 $this->_queryID = $id;
718 }
719
720
721 // returns the field object
722 function &FetchField($offset = -1)
723 {
724 $o= new ADOFieldObject();
725 $o->name = @db2_field_name($this->_queryID,$offset);
726 $o->type = @db2_field_type($this->_queryID,$offset);
727 $o->max_length = db2_field_width($this->_queryID,$offset);
728 if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name);
729 else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name);
730 return $o;
731 }
732
733 /* Use associative array to get fields array */
734 function Fields($colname)
735 {
736 if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
737 if (!$this->bind) {
738 $this->bind = array();
739 for ($i=0; $i < $this->_numOfFields; $i++) {
740 $o = $this->FetchField($i);
741 $this->bind[strtoupper($o->name)] = $i;
742 }
743 }
744
745 return $this->fields[$this->bind[strtoupper($colname)]];
746 }
747
748
749 function _initrs()
750 {
751 global $ADODB_COUNTRECS;
752 $this->_numOfRows = ($ADODB_COUNTRECS) ? @db2_num_rows($this->_queryID) : -1;
753 $this->_numOfFields = @db2_num_fields($this->_queryID);
754 // some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0
755 if ($this->_numOfRows == 0) $this->_numOfRows = -1;
756 }
757
758 function _seek($row)
759 {
760 return false;
761 }
762
763 // speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated
764 function &GetArrayLimit($nrows,$offset=-1)
765 {
766 if ($offset <= 0) {
767 $rs =& $this->GetArray($nrows);
768 return $rs;
769 }
770 $savem = $this->fetchMode;
771 $this->fetchMode = ADODB_FETCH_NUM;
772 $this->Move($offset);
773 $this->fetchMode = $savem;
774
775 if ($this->fetchMode & ADODB_FETCH_ASSOC) {
776 $this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE);
777 }
778
779 $results = array();
780 $cnt = 0;
781 while (!$this->EOF && $nrows != $cnt) {
782 $results[$cnt++] = $this->fields;
783 $this->MoveNext();
784 }
785
786 return $results;
787 }
788
789
790 function MoveNext()
791 {
792 if ($this->_numOfRows != 0 && !$this->EOF) {
793 $this->_currentRow++;
794
795 $this->fields = @db2_fetch_array($this->_queryID);
796 if ($this->fields) {
797 if ($this->fetchMode & ADODB_FETCH_ASSOC) {
798 $this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE);
799 }
800 return true;
801 }
802 }
803 $this->fields = false;
804 $this->EOF = true;
805 return false;
806 }
807
808 function _fetch()
809 {
810
811 $this->fields = db2_fetch_array($this->_queryID);
812 if ($this->fields) {
813 if ($this->fetchMode & ADODB_FETCH_ASSOC) {
814 $this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE);
815 }
816 return true;
817 }
818 $this->fields = false;
819 return false;
820 }
821
822 function _close()
823 {
824 return @db2_free_result($this->_queryID);
825 }
826
827 }
828 ?>