]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiDB/adodb/drivers/adodb-ibase.inc.php
elseif
[SourceForge/phpwiki.git] / lib / WikiDB / adodb / drivers / adodb-ibase.inc.php
1 <?php
2 /*
3 V4.22 15 Apr 2004  (c) 2000-2004 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
8   Latest version is available at http://php.weblogs.com/
9
10   Interbase data driver. Requires interbase client. Works on Windows and Unix.
11
12   3 Jan 2002 -- suggestions by Hans-Peter Oeri <kampfcaspar75@oeri.ch>
13       changed transaction handling and added experimental blob stuff
14
15   Docs to interbase at the website
16    http://www.synectics.co.za/php3/tutorial/IB_PHP3_API.html
17
18   To use gen_id(), see
19    http://www.volny.cz/iprenosil/interbase/ip_ib_code.htm#_code_creategen
20
21    $rs = $conn->Execute('select gen_id(adodb,1) from rdb$database');
22    $id = $rs->fields[0];
23    $conn->Execute("insert into table (id, col1,...) values ($id, $val1,...)");
24 */
25
26 class ADODB_ibase extends ADOConnection {
27     var $databaseType = "ibase";
28     var $dataProvider = "ibase";
29     var $replaceQuote = "''"; // string to use to replace quotes
30     var $ibase_timefmt = '%Y-%m-%d'; // For hours,mins,secs change to '%Y-%m-%d %H:%M:%S';
31     var $fmtDate = "'Y-m-d'";
32     var $fmtTimeStamp = "'Y-m-d, H:i:s'";
33     var $concat_operator='||';
34     var $_transactionID;
35     var $metaTablesSQL = "select rdb\$relation_name from rdb\$relations where rdb\$relation_name not like 'RDB\$%'";
36     //OPN STUFF start
37     var $metaColumnsSQL = "select a.rdb\$field_name, a.rdb\$null_flag, a.rdb\$default_source, b.rdb\$field_length, b.rdb\$field_scale, b.rdb\$field_sub_type, b.rdb\$field_precision, b.rdb\$field_type from rdb\$relation_fields a, rdb\$fields b where a.rdb\$field_source = b.rdb\$field_name and a.rdb\$relation_name = '%s' order by a.rdb\$field_position asc";
38     //OPN STUFF end
39     var $ibasetrans;
40     var $hasGenID = true;
41     var $_bindInputArray = true;
42     var $buffers = 0;
43     var $dialect = 1;
44     var $sysDate = "cast('TODAY' as date)";
45     var $sysTimeStamp = "cast('NOW' as timestamp)";
46     var $ansiOuter = true;
47     var $hasAffectedRows = false;
48     var $poorAffectedRows = true;
49     var $blobEncodeType = 'C';
50
51     function ADODB_ibase()
52     {
53          if (defined('IBASE_DEFAULT')) $this->ibasetrans = IBASE_DEFAULT;
54       }
55
56     function MetaPrimaryKeys($table,$owner_notused=false,$internalKey=false)
57     {
58         if ($internalKey) return array('RDB$DB_KEY');
59
60         $table = strtoupper($table);
61
62         $sql = 'SELECT S.RDB$FIELD_NAME AFIELDNAME
63     FROM RDB$INDICES I JOIN RDB$INDEX_SEGMENTS S ON I.RDB$INDEX_NAME=S.RDB$INDEX_NAME
64     WHERE I.RDB$RELATION_NAME=\''.$table.'\' and I.RDB$INDEX_NAME like \'RDB$PRIMARY%\'
65     ORDER BY I.RDB$INDEX_NAME,S.RDB$FIELD_POSITION';
66
67         $a = $this->GetCol($sql,false,true);
68         if ($a && sizeof($a)>0) return $a;
69         return false;
70     }
71
72     function ServerInfo()
73     {
74         $arr['dialect'] = $this->dialect;
75         switch($arr['dialect']) {
76         case '':
77         case '1': $s = 'Interbase 5.5 or earlier'; break;
78         case '2': $s = 'Interbase 5.6'; break;
79         default:
80         case '3': $s = 'Interbase 6.0'; break;
81         }
82         $arr['version'] = ADOConnection::_findvers($s);
83         $arr['description'] = $s;
84         return $arr;
85     }
86
87     function BeginTrans()
88     {
89         if ($this->transOff) return true;
90         $this->transCnt += 1;
91         $this->autoCommit = false;
92          $this->_transactionID = $this->_connectionID;//ibase_trans($this->ibasetrans, $this->_connectionID);
93         return $this->_transactionID;
94     }
95
96     function CommitTrans($ok=true)
97     {
98         if (!$ok) return $this->RollbackTrans();
99         if ($this->transOff) return true;
100         if ($this->transCnt) $this->transCnt -= 1;
101         $ret = false;
102         $this->autoCommit = true;
103         if ($this->_transactionID) {
104                        //print ' commit ';
105             $ret = ibase_commit($this->_transactionID);
106         }
107         $this->_transactionID = false;
108         return $ret;
109     }
110
111     function RollbackTrans()
112     {
113         if ($this->transOff) return true;
114         if ($this->transCnt) $this->transCnt -= 1;
115         $ret = false;
116         $this->autoCommit = true;
117         if ($this->_transactionID)
118                   $ret = ibase_rollback($this->_transactionID);
119         $this->_transactionID = false;
120
121         return $ret;
122     }
123
124     function &MetaIndexes ($table, $primary = FALSE, $owner=false)
125     {
126         // save old fetch mode
127         global $ADODB_FETCH_MODE;
128
129         $save = $ADODB_FETCH_MODE;
130         $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
131         if ($this->fetchMode !== FALSE) {
132                $savem = $this->SetFetchMode(FALSE);
133         }
134         $table = strtoupper($table);
135         $sql = "SELECT * FROM RDB\$INDICES WHERE RDB\$RELATION_NAME = '".$table."'";
136         if (!$primary) {
137             $sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$%'";
138         } else {
139             $sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$FOREIGN%'";
140         }
141         // get index details
142         $rs = $this->Execute($sql);
143         if (!is_object($rs)) {
144             // restore fetchmode
145             if (isset($savem)) {
146                 $this->SetFetchMode($savem);
147             }
148             $ADODB_FETCH_MODE = $save;
149             return FALSE;
150         }
151
152         $indexes = array ();
153         while ($row = $rs->FetchRow()) {
154             $index = $row[0];
155              if (!isset($indexes[$index])) {
156                      if (is_null($row[3])) {$row[3] = 0;}
157                      $indexes[$index] = array(
158                              'unique' => ($row[3] == 1),
159                              'columns' => array()
160                      );
161              }
162             $sql = "SELECT * FROM RDB\$INDEX_SEGMENTS WHERE RDB\$INDEX_NAME = '".$name."' ORDER BY RDB\$FIELD_POSITION ASC";
163             $rs1 = $this->Execute($sql);
164             while ($row1 = $rs1->FetchRow()) {
165                  $indexes[$index]['columns'][$row1[2]] = $row1[1];
166             }
167         }
168         // restore fetchmode
169         if (isset($savem)) {
170             $this->SetFetchMode($savem);
171         }
172         $ADODB_FETCH_MODE = $save;
173
174         return $indexes;
175     }
176
177     // See http://community.borland.com/article/0,1410,25844,00.html
178     function RowLock($tables,$where,$col)
179     {
180         if ($this->autoCommit) $this->BeginTrans();
181         $this->Execute("UPDATE $table SET $col=$col WHERE $where "); // is this correct - jlim?
182         return 1;
183     }
184
185     function CreateSequence($seqname,$startID=1)
186     {
187         $ok = $this->Execute(("INSERT INTO RDB\$GENERATORS (RDB\$GENERATOR_NAME) VALUES (UPPER('$seqname'))" ));
188         if (!$ok) return false;
189         return $this->Execute("SET GENERATOR $seqname TO ".($startID-1).';');
190     }
191
192     function DropSequence($seqname)
193     {
194         $seqname = strtoupper($seqname);
195         $this->Execute("delete from RDB\$GENERATORS where RDB\$GENERATOR_NAME='$seqname'");
196     }
197
198     function GenID($seqname='adodbseq',$startID=1)
199     {
200         $getnext = ("SELECT Gen_ID($seqname,1) FROM RDB\$DATABASE");
201         $rs = @$this->Execute($getnext);
202         if (!$rs) {
203             $this->Execute(("INSERT INTO RDB\$GENERATORS (RDB\$GENERATOR_NAME) VALUES (UPPER('$seqname'))" ));
204             $this->Execute("SET GENERATOR $seqname TO ".($startID-1).';');
205             $rs = $this->Execute($getnext);
206         }
207         if ($rs && !$rs->EOF) $this->genID = (integer) reset($rs->fields);
208         else $this->genID = 0; // false
209
210         if ($rs) $rs->Close();
211
212         return $this->genID;
213     }
214
215     function SelectDB($dbName)
216     {
217            return false;
218     }
219
220     function _handleerror()
221     {
222         $this->_errorMsg = ibase_errmsg();
223     }
224
225     function ErrorNo()
226     {
227         if (preg_match('/error code = ([\-0-9]*)/i', $this->_errorMsg,$arr)) return (integer) $arr[1];
228         else return 0;
229     }
230
231     function ErrorMsg()
232     {
233             return $this->_errorMsg;
234     }
235
236        // returns true or false
237     function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
238     {
239         if (!function_exists('ibase_pconnect')) return false;
240         if ($argDatabasename) $argHostname .= ':'.$argDatabasename;
241         $this->_connectionID = ibase_connect($argHostname,$argUsername,$argPassword,$this->charSet,$this->buffers,$this->dialect);
242          if ($this->dialect != 1) { // http://www.ibphoenix.com/ibp_60_del_id_ds.html
243             $this->replaceQuote = "''";
244         }
245         if ($this->_connectionID === false) {
246             $this->_handleerror();
247             return false;
248         }
249
250         ibase_timefmt($this->ibase_timefmt);
251         return true;
252     }
253        // returns true or false
254     function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
255     {
256         if (!function_exists('ibase_pconnect')) return false;
257         if ($argDatabasename) $argHostname .= ':'.$argDatabasename;
258         $this->_connectionID = ibase_pconnect($argHostname,$argUsername,$argPassword,$this->charSet,$this->buffers,$this->dialect);
259         if ($this->dialect != 1) { // http://www.ibphoenix.com/ibp_60_del_id_ds.html
260             $this->replaceQuote = "''";
261         }
262         if ($this->_connectionID === false) {
263             $this->_handleerror();
264             return false;
265         }
266
267         ibase_timefmt($this->ibase_timefmt);
268         return true;
269     }
270
271     function Prepare($sql)
272     {
273         $stmt = ibase_prepare($this->_connectionID,$sql);
274         if (!$stmt) return false;
275         return array($sql,$stmt);
276     }
277
278        // returns query ID if successful, otherwise false
279        // there have been reports of problems with nested queries - the code is probably not re-entrant?
280     function _query($sql,$iarr=false)
281     {
282
283         if (!$this->autoCommit && $this->_transactionID) {
284             $conn = $this->_transactionID;
285             $docommit = false;
286         } else {
287             $conn = $this->_connectionID;
288             $docommit = true;
289         }
290         if (is_array($sql)) {
291             $fn = 'ibase_execute';
292             $sql = $sql[1];
293
294             if (is_array($iarr)) {
295                 if  (ADODB_PHPVER >= 0x4050) { // actually 4.0.4
296                     if ( !isset($iarr[0]) ) $iarr[0] = ''; // PHP5 compat hack
297                     $fnarr =& array_merge( array($sql) , $iarr);
298                     $ret = call_user_func_array($fn,$fnarr);
299                 } else {
300                     switch(sizeof($iarr)) {
301                     case 1: $ret = $fn($sql,$iarr[0]); break;
302                     case 2: $ret = $fn($sql,$iarr[0],$iarr[1]); break;
303                     case 3: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2]); break;
304                     case 4: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3]); break;
305                     case 5: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4]); break;
306                     case 6: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5]); break;
307                     case 7: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6]); break;
308                     default: ADOConnection::outp( "Too many parameters to ibase query $sql");
309                     case 8: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6],$iarr[7]); break;
310                     }
311                 }
312             } else $ret = $fn($sql);
313         } else {
314             $fn = 'ibase_query';
315
316             if (is_array($iarr)) {
317                 if (ADODB_PHPVER >= 0x4050) { // actually 4.0.4
318                     if ( !isset($iarr[0]) ) $iarr[0] = ''; // PHP5 compat hack
319                     $fnarr =& array_merge( array($conn,$sql) , $iarr);
320                     $ret = call_user_func_array($fn,$fnarr);
321                 } else {
322                     switch(sizeof($iarr)) {
323                     case 1: $ret = $fn($conn,$sql,$iarr[0]); break;
324                     case 2: $ret = $fn($conn,$sql,$iarr[0],$iarr[1]); break;
325                     case 3: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2]); break;
326                     case 4: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3]); break;
327                     case 5: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4]); break;
328                     case 6: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5]); break;
329                     case 7: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6]); break;
330                     default: ADOConnection::outp( "Too many parameters to ibase query $sql");
331                     case 8: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6],$iarr[7]); break;
332                     }
333                 }
334             } else $ret = $fn($conn,$sql);
335         }
336         if ($docommit && $ret === true) ibase_commit($this->_connectionID);
337
338         $this->_handleerror();
339         return $ret;
340     }
341
342      // returns true or false
343      function _close()
344      {
345         if (!$this->autoCommit) @ibase_rollback($this->_connectionID);
346         return @ibase_close($this->_connectionID);
347      }
348
349     //OPN STUFF start
350     function _ConvertFieldType(&$fld, $ftype, $flen, $fscale, $fsubtype, $fprecision, $isInterbase6)
351     {
352         $fscale = abs($fscale);
353         $fld->max_length = $flen;
354         $fld->scale = null;
355         switch($ftype){
356             case 7:
357             case 8:
358                 if ($isInterbase6) {
359                     switch($fsubtype){
360                         case 0:
361                             $fld->type = ($ftype == 7 ? 'smallint' : 'integer');
362                             break;
363                         case 1:
364                             $fld->type = 'numeric';
365                             $fld->max_length = $fprecision;
366                             $fld->scale = $fscale;
367                             break;
368                         case 2:
369                             $fld->type = 'decimal';
370                             $fld->max_length = $fprecision;
371                             $fld->scale = $fscale;
372                             break;
373                     } // switch
374                 } else {
375                     if ($fscale !=0) {
376                         $fld->type = 'decimal';
377                         $fld->scale = $fscale;
378                         $fld->max_length = ($ftype == 7 ? 4 : 9);
379                     } else {
380                         $fld->type = ($ftype == 7 ? 'smallint' : 'integer');
381                     }
382                 }
383                 break;
384             case 16:
385                 if ($isInterbase6) {
386                     switch($fsubtype){
387                         case 0:
388                             $fld->type = 'decimal';
389                             $fld->max_length = 18;
390                             $fld->scale = 0;
391                             break;
392                         case 1:
393                             $fld->type = 'numeric';
394                             $fld->max_length = $fprecision;
395                             $fld->scale = $fscale;
396                             break;
397                         case 2:
398                             $fld->type = 'decimal';
399                             $fld->max_length = $fprecision;
400                             $fld->scale = $fscale;
401                             break;
402                     } // switch
403                 }
404                 break;
405             case 10:
406                 $fld->type = 'float';
407                 break;
408             case 14:
409                 $fld->type = 'char';
410                 break;
411             case 27:
412                 if ($fscale !=0) {
413                     $fld->type = 'decimal';
414                     $fld->max_length = 15;
415                     $fld->scale = 5;
416                 } else {
417                     $fld->type = 'double';
418                 }
419                 break;
420             case 35:
421                 if ($isInterbase6) {
422                     $fld->type = 'timestamp';
423                 } else {
424                     $fld->type = 'date';
425                 }
426                 break;
427             case 12:
428             case 13:
429                 $fld->type = 'date';
430                 break;
431             case 37:
432                 $fld->type = 'varchar';
433                 break;
434             case 40:
435                 $fld->type = 'cstring';
436                 break;
437             case 261:
438                 $fld->type = 'blob';
439                 $fld->max_length = -1;
440                 break;
441         } // switch
442     }
443     //OPN STUFF end
444         // returns array of ADOFieldObjects for current table
445     function &MetaColumns($table)
446     {
447     global $ADODB_FETCH_MODE;
448
449         if ($this->metaColumnsSQL) {
450
451             $save = $ADODB_FETCH_MODE;
452             $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
453
454             $rs = $this->Execute(sprintf($this->metaColumnsSQL,strtoupper($table)));
455
456             $ADODB_FETCH_MODE = $save;
457             if ($rs === false) return false;
458
459             $retarr = array();
460             //OPN STUFF start
461             $isInterbase6 = ($this->dialect==3 ? true : false);
462             //OPN STUFF end
463             while (!$rs->EOF) { //print_r($rs->fields);
464                 $fld = new ADOFieldObject();
465                 $fld->name = trim($rs->fields[0]);
466                 //OPN STUFF start
467                 $this->_ConvertFieldType($fld, $rs->fields[7], $rs->fields[3], $rs->fields[4], $rs->fields[5], $rs->fields[6], $isInterbase6);
468                 if (isset($rs->fields[1]) && $rs->fields[1]) {
469                     $fld->not_null = true;
470                 }
471                 if (isset($rs->fields[2])) {
472
473                     $fld->has_default = true;
474                     $d = substr($rs->fields[2],strlen('default '));
475                     switch ($fld->type)
476                     {
477                     case 'smallint':
478                     case 'integer': $fld->default_value = (int) $d; break;
479                     case 'char':
480                     case 'blob':
481                     case 'text':
482                     case 'varchar': $fld->default_value = (string) substr($d,1,strlen($d)-2); break;
483                     case 'double':
484                     case 'float': $fld->default_value = (float) $d; break;
485                     default: $fld->default_value = $d; break;
486                     }
487             //  case 35:$tt = 'TIMESTAMP'; break;
488                 }
489                 if ((isset($rs->fields[5])) && ($fld->type == 'blob')) {
490                     $fld->sub_type = $rs->fields[5];
491                 } else {
492                     $fld->sub_type = null;
493                 }
494                 //OPN STUFF end
495                 if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
496                 else $retarr[strtoupper($fld->name)] = $fld;
497
498                 $rs->MoveNext();
499             }
500             $rs->Close();
501             return $retarr;
502         }
503         return false;
504     }
505
506     function BlobEncode( $blob )
507     {
508         $blobid = ibase_blob_create( $this->_connectionID);
509         ibase_blob_add( $blobid, $blob );
510         return ibase_blob_close( $blobid );
511     }
512
513     // since we auto-decode all blob's since 2.42,
514     // BlobDecode should not do any transforms
515     function BlobDecode($blob)
516     {
517         return $blob;
518     }
519
520
521
522
523     // old blobdecode function
524     // still used to auto-decode all blob's
525     function _BlobDecode( $blob )
526     {
527         $blobid = ibase_blob_open( $blob );
528         $realblob = ibase_blob_get( $blobid,$this->maxblobsize); // 2nd param is max size of blob -- Kevin Boillet <kevinboillet@yahoo.fr>
529         while($string = ibase_blob_get($blobid, 8192)){
530             $realblob .= $string;
531         }
532         ibase_blob_close( $blobid );
533
534         return( $realblob );
535     }
536
537     function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')
538     {
539         $fd = fopen($path,'rb');
540         if ($fd === false) return false;
541         $blob_id = ibase_blob_create($this->_connectionID);
542
543         /* fill with data */
544
545         while ($val = fread($fd,32768)){
546             ibase_blob_add($blob_id, $val);
547         }
548
549         /* close and get $blob_id_str for inserting into table */
550         $blob_id_str = ibase_blob_close($blob_id);
551
552         fclose($fd);
553         return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
554     }
555
556     /*
557         Insert a null into the blob field of the table first.
558         Then use UpdateBlob to store the blob.
559
560         Usage:
561
562         $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
563         $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
564     */
565     function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
566     {
567     $blob_id = ibase_blob_create($this->_connectionID);
568
569     // ibase_blob_add($blob_id, $val);
570
571     // replacement that solves the problem by which only the first modulus 64K /
572     // of $val are stored at the blob field ////////////////////////////////////
573     // Thx Abel Berenstein  aberenstein#afip.gov.ar
574     $len = strlen($val);
575     $chunk_size = 32768;
576     $tail_size = $len % $chunk_size;
577     $n_chunks = ($len - $tail_size) / $chunk_size;
578
579     for ($n = 0; $n < $n_chunks; $n++) {
580         $start = $n * $chunk_size;
581         $data = substr($val, $start, $chunk_size);
582         ibase_blob_add($blob_id, $data);
583     }
584
585     if ($tail_size) {
586         $start = $n_chunks * $chunk_size;
587         $data = substr($val, $start, $tail_size);
588         ibase_blob_add($blob_id, $data);
589     }
590     // end replacement /////////////////////////////////////////////////////////
591
592     $blob_id_str = ibase_blob_close($blob_id);
593
594     return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
595
596     }
597
598     function OldUpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
599     {
600         $blob_id = ibase_blob_create($this->_connectionID);
601         ibase_blob_add($blob_id, $val);
602         $blob_id_str = ibase_blob_close($blob_id);
603         return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
604     }
605
606     // Format date column in sql string given an input format that understands Y M D
607     // Only since Interbase 6.0 - uses EXTRACT
608     // problem - does not zero-fill the day and month yet
609     function SQLDate($fmt, $col=false)
610     {
611         if (!$col) $col = $this->sysDate;
612         $s = '';
613
614         $len = strlen($fmt);
615         for ($i=0; $i < $len; $i++) {
616             if ($s) $s .= '||';
617             $ch = $fmt[$i];
618             switch($ch) {
619             case 'Y':
620             case 'y':
621                 $s .= "extract(year from $col)";
622                 break;
623             case 'M':
624             case 'm':
625                 $s .= "extract(month from $col)";
626                 break;
627             case 'Q':
628             case 'q':
629                 $s .= "cast(((extract(month from $col)+2) / 3) as integer)";
630                 break;
631             case 'D':
632             case 'd':
633                 $s .= "(extract(day from $col))";
634                 break;
635             case 'H':
636             case 'h':
637               $s .= "(extract(hour from $col))";
638               break;
639             case 'I':
640             case 'i':
641               $s .= "(extract(minute from $col))";
642               break;
643             case 'S':
644             case 's':
645               $s .= "CAST((extract(second from $col)) AS INTEGER)";
646               break;
647
648             default:
649                 if ($ch == '\\') {
650                     $i++;
651                     $ch = substr($fmt,$i,1);
652                 }
653                 $s .= $this->qstr($ch);
654                 break;
655             }
656         }
657         return $s;
658     }
659 }
660
661 /*--------------------------------------------------------------------------------------
662          Class Name: Recordset
663 --------------------------------------------------------------------------------------*/
664
665 class ADORecordset_ibase extends ADORecordSet
666 {
667
668     var $databaseType = "ibase";
669     var $bind=false;
670     var $_cacheType;
671
672     function ADORecordset_ibase($id,$mode=false)
673     {
674     global $ADODB_FETCH_MODE;
675
676             $this->fetchMode = ($mode === false) ? $ADODB_FETCH_MODE : $mode;
677             return $this->ADORecordSet($id);
678     }
679
680     /*          Returns: an object containing field information.
681             Get column information in the Recordset object. fetchField() can be used in order to obtain information about
682             fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
683             fetchField() is retrieved.          */
684
685     function &FetchField($fieldOffset = -1)
686     {
687              $fld = new ADOFieldObject;
688              $ibf = ibase_field_info($this->_queryID,$fieldOffset);
689              $fld->name = strtolower($ibf['alias']);
690              if (empty($fld->name)) $fld->name = strtolower($ibf['name']);
691              $fld->type = $ibf['type'];
692              $fld->max_length = $ibf['length'];
693              return $fld;
694     }
695
696     function _initrs()
697     {
698             $this->_numOfRows = -1;
699             $this->_numOfFields = @ibase_num_fields($this->_queryID);
700
701             // cache types for blob decode check
702             for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
703                 $f1 = $this->FetchField($i);
704                 $this->_cacheType[] = $f1->type;
705             }
706     }
707
708     function _seek($row)
709     {
710         return false;
711     }
712
713     function _fetch()
714     {
715         $f = @ibase_fetch_row($this->_queryID);
716         if ($f === false) {
717             $this->fields = false;
718             return false;
719         }
720         // OPN stuff start - optimized
721         // fix missing nulls and decode blobs automatically
722
723         global $ADODB_ANSI_PADDING_OFF;
724         //$ADODB_ANSI_PADDING_OFF=1;
725         $rtrim = !empty($ADODB_ANSI_PADDING_OFF);
726
727         for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
728             if ($this->_cacheType[$i]=="BLOB") {
729                 if (isset($f[$i])) {
730                     $f[$i] = $this->connection->_BlobDecode($f[$i]);
731                 } else {
732                     $f[$i] = null;
733                 }
734             } else {
735                 if (!isset($f[$i])) {
736                     $f[$i] = null;
737                 } elseif ($rtrim && is_string($f[$i])) {
738                     $f[$i] = rtrim($f[$i]);
739                 }
740             }
741         }
742         // OPN stuff end
743
744         $this->fields = $f;
745         if ($this->fetchMode == ADODB_FETCH_ASSOC) {
746             $this->fields = &$this->GetRowAssoc(ADODB_ASSOC_CASE);
747         } elseif ($this->fetchMode == ADODB_FETCH_BOTH) {
748             $this->fields =& array_merge($this->fields,$this->GetRowAssoc(ADODB_ASSOC_CASE));
749         }
750         return true;
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 _close()
770     {
771             return @ibase_free_result($this->_queryID);
772     }
773
774     function MetaType($t,$len=-1,$fieldobj=false)
775     {
776         if (is_object($t)) {
777             $fieldobj = $t;
778             $t = $fieldobj->type;
779             $len = $fieldobj->max_length;
780         }
781         switch (strtoupper($t)) {
782         case 'CHAR':
783             return 'C';
784
785         case 'TEXT':
786         case 'VARCHAR':
787         case 'VARYING':
788         if ($len <= $this->blobSize) return 'C';
789             return 'X';
790         case 'BLOB':
791             return 'B';
792
793         case 'TIMESTAMP':
794         case 'DATE': return 'D';
795
796                 //case 'T': return 'T';
797
798                 //case 'L': return 'L';
799         case 'INT':
800         case 'SHORT':
801         case 'INTEGER': return 'I';
802         default: return 'N';
803         }
804     }
805
806 }
807 ?>