]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiDB/adodb/drivers/adodb-odbc.inc.php
trailing_spaces
[SourceForge/phpwiki.git] / lib / WikiDB / adodb / drivers / adodb-odbc.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 Set tabs to 4 for best viewing.
8
9   Latest version is available at http://php.weblogs.com/
10
11   Requires ODBC. Works on Windows and Unix.
12 */
13   define("_ADODB_ODBC_LAYER", 2 );
14
15 /*--------------------------------------------------------------------------------------
16 --------------------------------------------------------------------------------------*/
17
18
19 class ADODB_odbc extends ADOConnection {
20         var $databaseType = "odbc";
21         var $fmtDate = "'Y-m-d'";
22         var $fmtTimeStamp = "'Y-m-d, h:i:sA'";
23         var $replaceQuote = "''"; // string to use to replace quotes
24         var $dataProvider = "odbc";
25         var $hasAffectedRows = true;
26         var $binmode = ODBC_BINMODE_RETURN;
27         var $useFetchArray = false; // setting this to true will make array elements in FETCH_ASSOC mode case-sensitive
28                                                                 // breaking backward-compat
29         //var $longreadlen = 8000; // default number of chars to return for a Blob/Long field
30         var $_bindInputArray = false;
31         var $curmode = SQL_CUR_USE_DRIVER; // See sqlext.h, SQL_CUR_DEFAULT == SQL_CUR_USE_DRIVER == 2L
32         var $_genSeqSQL = "create table %s (id integer)";
33         var $_autocommit = true;
34         var $_haserrorfunctions = true;
35         var $_has_stupid_odbc_fetch_api_change = true;
36         var $_lastAffectedRows = 0;
37
38         function ADODB_odbc()
39         {
40                 $this->_haserrorfunctions = ADODB_PHPVER >= 0x4050;
41                 $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
42         }
43
44         function ServerInfo()
45         {
46
47                 if (!empty($this->host) && ADODB_PHPVER >= 0x4300) {
48                         $dsn = strtoupper($this->host);
49                         $first = true;
50                         $found = false;
51
52                         if (!function_exists('odbc_data_source')) return false;
53
54                         while(true) {
55
56                                 $rez = odbc_data_source($this->_connectionID,
57                                         $first ? SQL_FETCH_FIRST : SQL_FETCH_NEXT);
58                                 $first = false;
59                                 if (!is_array($rez)) break;
60                                 if (strtoupper($rez['server']) == $dsn) {
61                                         $found = true;
62                                         break;
63                                 }
64                         }
65                         if (!$found) return ADOConnection::ServerInfo();
66                         if (!isset($rez['version'])) $rez['version'] = '';
67                         return $rez;
68                 } else {
69                         return ADOConnection::ServerInfo();
70                 }
71         }
72
73
74         function CreateSequence($seqname='adodbseq',$start=1)
75         {
76                 if (empty($this->_genSeqSQL)) return false;
77                 $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
78                 if (!$ok) return false;
79                 $start -= 1;
80                 return $this->Execute("insert into $seqname values($start)");
81         }
82
83         var $_dropSeqSQL = 'drop table %s';
84         function DropSequence($seqname)
85         {
86                 if (empty($this->_dropSeqSQL)) return false;
87                 return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
88         }
89
90         /*
91                 This algorithm is not very efficient, but works even if table locking
92                 is not available.
93
94                 Will return false if unable to generate an ID after $MAXLOOPS attempts.
95         */
96         function GenID($seq='adodbseq',$start=1)
97         {
98                 // if you have to modify the parameter below, your database is overloaded,
99                 // or you need to implement generation of id's yourself!
100                 $MAXLOOPS = 100;
101                 //$this->debug=1;
102                 while (--$MAXLOOPS>=0) {
103                         $num = $this->GetOne("select id from $seq");
104                         if ($num === false) {
105                                 $this->Execute(sprintf($this->_genSeqSQL ,$seq));
106                                 $start -= 1;
107                                 $num = '0';
108                                 $ok = $this->Execute("insert into $seq values($start)");
109                                 if (!$ok) return false;
110                         }
111                         $this->Execute("update $seq set id=id+1 where id=$num");
112
113                         if ($this->affected_rows() > 0) {
114                                 $num += 1;
115                                 $this->genID = $num;
116                                 return $num;
117                         }
118                 }
119                 if ($fn = $this->raiseErrorFn) {
120                         $fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);
121                 }
122                 return false;
123         }
124
125
126         function ErrorMsg()
127         {
128                 if ($this->_haserrorfunctions) {
129                         if ($this->_errorMsg !== false) return $this->_errorMsg;
130                         if (empty($this->_connectionID)) return @odbc_errormsg();
131                         return @odbc_errormsg($this->_connectionID);
132                 } else return ADOConnection::ErrorMsg();
133         }
134
135         function ErrorNo()
136         {
137
138                 if ($this->_haserrorfunctions) {
139                         if ($this->_errorCode !== false) {
140                                 // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
141                                 return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode;
142                         }
143
144                         if (empty($this->_connectionID)) $e = @odbc_error();
145                         else $e = @odbc_error($this->_connectionID);
146
147                          // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
148                          // so we check and patch
149                         if (strlen($e)<=2) return 0;
150                         return $e;
151                 } else return ADOConnection::ErrorNo();
152         }
153
154
155         // returns true or false
156         function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)
157         {
158         global $php_errormsg;
159
160                 if (!function_exists('odbc_connect')) return false;
161
162                 if ($this->debug && $argDatabasename && $this->databaseType != 'vfp') {
163                         ADOConnection::outp("For odbc Connect(), $argDatabasename is not used. Place dsn in 1st parameter.");
164                 }
165                 $php_errormsg = '';
166                 if ($this->curmode === false) $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword);
167                 else $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword,$this->curmode);
168                 $this->_errorMsg = $php_errormsg;
169                 if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
170
171                 //if ($this->_connectionID) odbc_autocommit($this->_connectionID,true);
172                 return $this->_connectionID != false;
173         }
174
175         // returns true or false
176         function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
177         {
178         global $php_errormsg;
179
180                 if (!function_exists('odbc_connect')) return false;
181
182                 $php_errormsg = '';
183                 if ($this->debug && $argDatabasename) {
184                         ADOConnection::outp("For odbc PConnect(), $argDatabasename is not used. Place dsn in 1st parameter.");
185                 }
186         //      print "dsn=$argDSN u=$argUsername p=$argPassword<br>"; flush();
187                 if ($this->curmode === false) $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword);
188                 else $this->_connectionID = odbc_pconnect($argDSN,$argUsername,$argPassword,$this->curmode);
189
190                 $this->_errorMsg = $php_errormsg;
191                 if ($this->_connectionID && $this->autoRollback) @odbc_rollback($this->_connectionID);
192                 if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
193
194                 return $this->_connectionID != false;
195         }
196
197         function BeginTrans()
198         {
199                 if (!$this->hasTransactions) return false;
200                 if ($this->transOff) return true;
201                 $this->transCnt += 1;
202                 $this->_autocommit = false;
203                 return odbc_autocommit($this->_connectionID,false);
204         }
205
206         function CommitTrans($ok=true)
207         {
208                 if ($this->transOff) return true;
209                 if (!$ok) return $this->RollbackTrans();
210                 if ($this->transCnt) $this->transCnt -= 1;
211                 $this->_autocommit = true;
212                 $ret = odbc_commit($this->_connectionID);
213                 odbc_autocommit($this->_connectionID,true);
214                 return $ret;
215         }
216
217         function RollbackTrans()
218         {
219                 if ($this->transOff) return true;
220                 if ($this->transCnt) $this->transCnt -= 1;
221                 $this->_autocommit = true;
222                 $ret = odbc_rollback($this->_connectionID);
223                 odbc_autocommit($this->_connectionID,true);
224                 return $ret;
225         }
226
227         function MetaPrimaryKeys($table)
228         {
229         global $ADODB_FETCH_MODE;
230
231                 $savem = $ADODB_FETCH_MODE;
232                 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
233                 $qid = @odbc_primarykeys($this->_connectionID,'','',$table);
234
235                 if (!$qid) {
236                         $ADODB_FETCH_MODE = $savem;
237                         return false;
238                 }
239                 $rs = new ADORecordSet_odbc($qid);
240                 $ADODB_FETCH_MODE = $savem;
241
242                 if (!$rs) return false;
243                 $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
244
245                 $arr =& $rs->GetArray();
246                 $rs->Close();
247                 //print_r($arr);
248                 $arr2 = array();
249                 for ($i=0; $i < sizeof($arr); $i++) {
250                         if ($arr[$i][3]) $arr2[] = $arr[$i][3];
251                 }
252                 return $arr2;
253         }
254
255
256
257         function &MetaTables($ttype=false)
258         {
259         global $ADODB_FETCH_MODE;
260
261                 $savem = $ADODB_FETCH_MODE;
262                 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
263                 $qid = odbc_tables($this->_connectionID);
264
265                 $rs = new ADORecordSet_odbc($qid);
266
267                 $ADODB_FETCH_MODE = $savem;
268                 if (!$rs) return false;
269
270                 $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
271
272                 $arr =& $rs->GetArray();
273                 //print_r($arr);
274
275                 $rs->Close();
276                 $arr2 = array();
277
278                 if ($ttype) {
279                         $isview = strncmp($ttype,'V',1) === 0;
280                 }
281                 for ($i=0; $i < sizeof($arr); $i++) {
282                         if (!$arr[$i][2]) continue;
283                         $type = $arr[$i][3];
284                         if ($ttype) {
285                                 if ($isview) {
286                                         if (strncmp($type,'V',1) === 0) $arr2[] = $arr[$i][2];
287                                 } else if (strncmp($type,'SYS',3) !== 0) $arr2[] = $arr[$i][2];
288                         } else if (strncmp($type,'SYS',3) !== 0) $arr2[] = $arr[$i][2];
289                 }
290                 return $arr2;
291         }
292
293 /*
294 / SQL data type codes /
295 #define SQL_UNKNOWN_TYPE        0
296 #define SQL_CHAR                        1
297 #define SQL_NUMERIC              2
298 #define SQL_DECIMAL              3
299 #define SQL_INTEGER              4
300 #define SQL_SMALLINT            5
301 #define SQL_FLOAT                  6
302 #define SQL_REAL                        7
303 #define SQL_DOUBLE                8
304 #if (ODBCVER >= 0x0300)
305 #define SQL_DATETIME            9
306 #endif
307 #define SQL_VARCHAR             12
308
309 / One-parameter shortcuts for date/time data types /
310 #if (ODBCVER >= 0x0300)
311 #define SQL_TYPE_DATE     91
312 #define SQL_TYPE_TIME     92
313 #define SQL_TYPE_TIMESTAMP 93
314
315 #define SQL_UNICODE                             (-95)
316 #define SQL_UNICODE_VARCHAR                     (-96)
317 #define SQL_UNICODE_LONGVARCHAR                 (-97)
318 */
319         function ODBCTypes($t)
320         {
321                 switch ((integer)$t) {
322                 case 1:
323                 case 12:
324                 case 0:
325                 case -95:
326                 case -96:
327                         return 'C';
328                 case -97:
329                 case -1: //text
330                         return 'X';
331                 case -4: //image
332                         return 'B';
333
334                 case 91:
335                 case 11:
336                         return 'D';
337
338                 case 92:
339                 case 93:
340                 case 9: return 'T';
341                 case 4:
342                 case 5:
343                 case -6:
344                         return 'I';
345
346                 case -11: // uniqidentifier
347                         return 'R';
348                 case -7: //bit
349                         return 'L';
350
351                 default:
352                         return 'N';
353                 }
354         }
355
356         function &MetaColumns($table)
357         {
358         global $ADODB_FETCH_MODE;
359
360                 $table = strtoupper($table);
361                 $schema = false;
362                 $this->_findschema($table,$schema);
363
364                 $savem = $ADODB_FETCH_MODE;
365                 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
366
367                 if (false) { // after testing, confirmed that the following does not work becoz of a bug
368                         $qid2 = odbc_tables($this->_connectionID);
369                         $rs = new ADORecordSet_odbc($qid2);
370                         $ADODB_FETCH_MODE = $savem;
371                         if (!$rs) return false;
372                         $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
373                         $rs->_fetch();
374
375                         while (!$rs->EOF) {
376                                 if ($table == strtoupper($rs->fields[2])) {
377                                         $q = $rs->fields[0];
378                                         $o = $rs->fields[1];
379                                         break;
380                                 }
381                                 $rs->MoveNext();
382                         }
383                         $rs->Close();
384
385                         $qid = odbc_columns($this->_connectionID,$q,$o,strtoupper($table),'%');
386                 } else switch ($this->databaseType) {
387                 case 'access':
388                 case 'vfp':
389                 case 'db2':
390                         $qid = odbc_columns($this->_connectionID);
391                         break;
392
393                 default:
394                         $qid = @odbc_columns($this->_connectionID,'%','%',strtoupper($table),'%');
395                         if (empty($qid)) $qid = odbc_columns($this->_connectionID);
396                         break;
397                 }
398                 if (empty($qid)) return false;
399
400                 $rs = new ADORecordSet_odbc($qid);
401                 $ADODB_FETCH_MODE = $savem;
402
403                 if (!$rs) return false;
404
405                 $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
406                 $rs->_fetch();
407                 $retarr = array();
408
409                 /*
410                 $rs->fields indices
411                 0 TABLE_QUALIFIER
412                 1 TABLE_SCHEM
413                 2 TABLE_NAME
414                 3 COLUMN_NAME
415                 4 DATA_TYPE
416                 5 TYPE_NAME
417                 6 PRECISION
418                 7 LENGTH
419                 8 SCALE
420                 9 RADIX
421                 10 NULLABLE
422                 11 REMARKS
423                 */
424                 while (!$rs->EOF) {
425                         //adodb_pr($rs->fields);
426                         if (strtoupper($rs->fields[2]) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
427                                 $fld = new ADOFieldObject();
428                                 $fld->name = $rs->fields[3];
429                                 $fld->type = $this->ODBCTypes($rs->fields[4]);
430
431                                 // ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp
432                                 // access uses precision to store length for char/varchar
433                                 if ($fld->type == 'C' or $fld->type == 'X') {
434                                         if ($this->databaseType == 'access')
435                                                 $fld->max_length = $rs->fields[6];
436                                         else if ($rs->fields[4] <= -95) // UNICODE
437                                                 $fld->max_length = $rs->fields[7]/2;
438                                         else
439                                                 $fld->max_length = $rs->fields[7];
440                                 } else
441                                         $fld->max_length = $rs->fields[7];
442                                 $fld->not_null = !empty($rs->fields[10]);
443                                 $fld->scale = $rs->fields[8];
444                                 $retarr[strtoupper($fld->name)] = $fld;
445                         } else if (sizeof($retarr)>0)
446                                 break;
447                         $rs->MoveNext();
448                 }
449                 $rs->Close(); //-- crashes 4.03pl1 -- why?
450
451                 return $retarr;
452         }
453
454         function Prepare($sql)
455         {
456                 if (! $this->_bindInputArray) return $sql; // no binding
457                 $stmt = odbc_prepare($this->_connectionID,$sql);
458                 if (!$stmt) {
459                         // we don't know whether odbc driver is parsing prepared stmts, so just return sql
460                         return $sql;
461                 }
462                 return array($sql,$stmt,false);
463         }
464
465         /* returns queryID or false */
466         function _query($sql,$inputarr=false)
467         {
468         GLOBAL $php_errormsg;
469                 $php_errormsg = '';
470                 $this->_error = '';
471
472                 if ($inputarr) {
473                         if (is_array($sql)) {
474                                 $stmtid = $sql[1];
475                         } else {
476                                 $stmtid = odbc_prepare($this->_connectionID,$sql);
477
478                                 if ($stmtid == false) {
479                                         $this->_errorMsg = $php_errormsg;
480                                         return false;
481                                 }
482                         }
483
484                         if (! odbc_execute($stmtid,$inputarr)) {
485                                 //@odbc_free_result($stmtid);
486                                 if ($this->_haserrorfunctions) {
487                                         $this->_errorMsg = odbc_errormsg();
488                                         $this->_errorCode = odbc_error();
489                                 }
490                                 return false;
491                         }
492
493                 } else if (is_array($sql)) {
494                         $stmtid = $sql[1];
495                         if (!odbc_execute($stmtid)) {
496                                 //@odbc_free_result($stmtid);
497                                 if ($this->_haserrorfunctions) {
498                                         $this->_errorMsg = odbc_errormsg();
499                                         $this->_errorCode = odbc_error();
500                                 }
501                                 return false;
502                         }
503                 } else
504                         $stmtid = odbc_exec($this->_connectionID,$sql);
505
506                 $this->_lastAffectedRows = 0;
507                 if ($stmtid) {
508                         if (@odbc_num_fields($stmtid) == 0) {
509                                 $this->_lastAffectedRows = odbc_num_rows($stmtid);
510                                 $stmtid = true;
511                         } else {
512                                 $this->_lastAffectedRows = 0;
513                                 odbc_binmode($stmtid,$this->binmode);
514                                 odbc_longreadlen($stmtid,$this->maxblobsize);
515                         }
516
517                         if ($this->_haserrorfunctions) {
518                                 $this->_errorMsg = '';
519                                 $this->_errorCode = 0;
520                         } else
521                                 $this->_errorMsg = $php_errormsg;
522                 } else {
523                         if ($this->_haserrorfunctions) {
524                                 $this->_errorMsg = odbc_errormsg();
525                                 $this->_errorCode = odbc_error();
526                         } else
527                                 $this->_errorMsg = $php_errormsg;
528                 }
529                 return $stmtid;
530         }
531
532         /*
533                 Insert a null into the blob field of the table first.
534                 Then use UpdateBlob to store the blob.
535
536                 Usage:
537
538                 $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
539                 $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
540         */
541         function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
542         {
543                 return $this->Execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false;
544         }
545
546         // returns true or false
547         function _close()
548         {
549                 $ret = @odbc_close($this->_connectionID);
550                 $this->_connectionID = false;
551                 return $ret;
552         }
553
554         function _affectedrows()
555         {
556                 return $this->_lastAffectedRows;
557         }
558
559 }
560
561 /*--------------------------------------------------------------------------------------
562          Class Name: Recordset
563 --------------------------------------------------------------------------------------*/
564
565 class ADORecordSet_odbc extends ADORecordSet {
566
567         var $bind = false;
568         var $databaseType = "odbc";
569         var $dataProvider = "odbc";
570         var $useFetchArray;
571         var $_has_stupid_odbc_fetch_api_change;
572
573         function ADORecordSet_odbc($id,$mode=false)
574         {
575                 if ($mode === false) {
576                         global $ADODB_FETCH_MODE;
577                         $mode = $ADODB_FETCH_MODE;
578                 }
579                 $this->fetchMode = $mode;
580
581                 $this->_queryID = $id;
582
583                 // the following is required for mysql odbc driver in 4.3.1 -- why?
584                 $this->EOF = false;
585                 $this->_currentRow = -1;
586                 //$this->ADORecordSet($id);
587         }
588
589
590         // returns the field object
591         function &FetchField($fieldOffset = -1)
592         {
593
594                 $off=$fieldOffset+1; // offsets begin at 1
595
596                 $o= new ADOFieldObject();
597                 $o->name = @odbc_field_name($this->_queryID,$off);
598                 $o->type = @odbc_field_type($this->_queryID,$off);
599                 $o->max_length = @odbc_field_len($this->_queryID,$off);
600                 if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name);
601                 else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name);
602                 return $o;
603         }
604
605         /* Use associative array to get fields array */
606         function Fields($colname)
607         {
608                 if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
609                 if (!$this->bind) {
610                         $this->bind = array();
611                         for ($i=0; $i < $this->_numOfFields; $i++) {
612                                 $o = $this->FetchField($i);
613                                 $this->bind[strtoupper($o->name)] = $i;
614                         }
615                 }
616
617                  return $this->fields[$this->bind[strtoupper($colname)]];
618         }
619
620
621         function _initrs()
622         {
623         global $ADODB_COUNTRECS;
624                 $this->_numOfRows = ($ADODB_COUNTRECS) ? @odbc_num_rows($this->_queryID) : -1;
625                 $this->_numOfFields = @odbc_num_fields($this->_queryID);
626                 // some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0
627                 if ($this->_numOfRows == 0) $this->_numOfRows = -1;
628                 //$this->useFetchArray = $this->connection->useFetchArray;
629                 $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
630         }
631
632         function _seek($row)
633         {
634                 return false;
635         }
636
637         // speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated
638         function &GetArrayLimit($nrows,$offset=-1)
639         {
640                 if ($offset <= 0) {
641                         $rs =& $this->GetArray($nrows);
642                         return $rs;
643                 }
644                 $savem = $this->fetchMode;
645                 $this->fetchMode = ADODB_FETCH_NUM;
646                 $this->Move($offset);
647                 $this->fetchMode = $savem;
648
649                 if ($this->fetchMode & ADODB_FETCH_ASSOC) {
650                         $this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE);
651                 }
652
653                 $results = array();
654                 $cnt = 0;
655                 while (!$this->EOF && $nrows != $cnt) {
656                         $results[$cnt++] = $this->fields;
657                         $this->MoveNext();
658                 }
659
660                 return $results;
661         }
662
663
664         function MoveNext()
665         {
666                 if ($this->_numOfRows != 0 && !$this->EOF) {
667                         $this->_currentRow++;
668                         $row = 0;
669                         if ($this->_has_stupid_odbc_fetch_api_change)
670                                 $rez = @odbc_fetch_into($this->_queryID,$this->fields);
671                         else
672                                 $rez = @odbc_fetch_into($this->_queryID,$row,$this->fields);
673                         if ($rez) {
674                                 if ($this->fetchMode & ADODB_FETCH_ASSOC) {
675                                         $this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE);
676                                 }
677                                 return true;
678                         }
679                 }
680                 $this->fields = false;
681                 $this->EOF = true;
682                 return false;
683         }
684
685         function _fetch()
686         {
687                 $row = 0;
688                 if ($this->_has_stupid_odbc_fetch_api_change)
689                         $rez = @odbc_fetch_into($this->_queryID,$this->fields,$row);
690                 else
691                         $rez = @odbc_fetch_into($this->_queryID,$row,$this->fields);
692
693                 if ($rez) {
694                         if ($this->fetchMode & ADODB_FETCH_ASSOC) {
695                                 $this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE);
696                         }
697                         return true;
698                 }
699                 $this->fields = false;
700                 return false;
701         }
702
703         function _close()
704         {
705                 return @odbc_free_result($this->_queryID);
706         }
707
708 }
709
710 ?>