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