]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiDB/adodb/drivers/adodb-odbtp.inc.php
new ADODB library 4.22 with multiple drivers (not only mysql as before), major change...
[SourceForge/phpwiki.git] / lib / WikiDB / adodb / drivers / adodb-odbtp.inc.php
1 <?php\r
2 /*\r
3 V4.22 15 Apr 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
4   Released under both BSD license and Lesser GPL library license.\r
5   Whenever there is any discrepancy between the two licenses,\r
6   the BSD license will take precedence. See License.txt.\r
7   Set tabs to 4 for best viewing.\r
8   Latest version is available at http://php.weblogs.com/\r
9 */\r
10 // Code contributed by "stefan bogdan" <sbogdan#rsb.ro>\r
11 \r
12 define("_ADODB_ODBTP_LAYER", 2 );\r
13 \r
14 class ADODB_odbtp extends ADOConnection{\r
15         var $databaseType = "odbtp";\r
16         var $dataProvider = "odbtp";\r
17         var $fmtDate = "'Y-m-d'";\r
18         var $fmtTimeStamp = "'Y-m-d, h:i:sA'";\r
19         var $replaceQuote = "''"; // string to use to replace quotes\r
20         var $odbc_driver = 0;\r
21         var $hasAffectedRows = true;\r
22         var $hasInsertID = false;\r
23         var $hasGenID = true;\r
24         var $hasMoveFirst = true;\r
25 \r
26         var $_genSeqSQL = "create table %s (seq_name char(30) not null unique , seq_value integer not null)";\r
27         var $_dropSeqSQL = "delete from adodb_seq where seq_name = '%s'";\r
28         var $_autocommit = true;\r
29         var $_bindInputArray = false;\r
30         var $_useUnicodeSQL = false;\r
31         var $_canPrepareSP = false;\r
32 \r
33         function ADODB_odbtp()\r
34         {\r
35         }\r
36 \r
37         function ServerInfo()\r
38         {\r
39                 return array('description' => @odbtp_get_attr( ODB_ATTR_DBMSNAME, $this->_connectionID),\r
40                              'version' => @odbtp_get_attr( ODB_ATTR_DBMSVER, $this->_connectionID));\r
41         }\r
42 \r
43         function ErrorMsg()\r
44         {\r
45                 if (empty($this->_connectionID)) return @odbtp_last_error();\r
46                 return @odbtp_last_error($this->_connectionID);\r
47         }\r
48 \r
49         function ErrorNo()\r
50         {\r
51                 if (empty($this->_connectionID)) return @odbtp_last_error_state();\r
52                         return @odbtp_last_error_state($this->_connectionID);\r
53         }\r
54 \r
55         function _insertid()\r
56         {\r
57         // SCOPE_IDENTITY()\r
58         // Returns the last IDENTITY value inserted into an IDENTITY column in\r
59         // the same scope. A scope is a module -- a stored procedure, trigger,\r
60         // function, or batch. Thus, two statements are in the same scope if\r
61         // they are in the same stored procedure, function, or batch.\r
62                         return $this->GetOne($this->identitySQL);\r
63         }\r
64 \r
65         function _affectedrows()\r
66         {\r
67                 if ($this->_queryID) {\r
68                         return @odbtp_affected_rows ($this->_queryID);\r
69            } else\r
70                 return 0;\r
71         }\r
72 \r
73         function CreateSequence($seqname='adodbseq',$start=1)\r
74         {\r
75                 //verify existence\r
76                 $num = $this->GetOne("select seq_value from adodb_seq");\r
77                 $seqtab='adodb_seq';\r
78                 if( $this->odbc_driver == ODB_DRIVER_FOXPRO ) {\r
79                         $path = @odbtp_get_attr( ODB_ATTR_DATABASENAME, $this->_connectionID );\r
80                         //if using vfp dbc file\r
81                         if( !strcasecmp(strrchr($path, '.'), '.dbc') )\r
82                 $path = substr($path,0,strrpos($path,'\/'));\r
83                 $seqtab = $path . '/' . $seqtab;\r
84         }\r
85                 if($num == false) {\r
86                         if (empty($this->_genSeqSQL)) return false;\r
87                         $ok = $this->Execute(sprintf($this->_genSeqSQL ,$seqtab));\r
88                 }\r
89                 $num = $this->GetOne("select seq_value from adodb_seq where seq_name='$seqname'");\r
90                 if ($num) {\r
91                         return false;\r
92                 }\r
93                 $start -= 1;\r
94                 return $this->Execute("insert into adodb_seq values('$seqname',$start)");\r
95         }\r
96 \r
97         function DropSequence($seqname)\r
98         {\r
99                 if (empty($this->_dropSeqSQL)) return false;\r
100                 return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));\r
101         }\r
102 \r
103         function GenID($seq='adodbseq',$start=1)\r
104         {\r
105                 $seqtab='adodb_seq';\r
106                 if( $this->odbc_driver == ODB_DRIVER_FOXPRO ) {\r
107                         $path = @odbtp_get_attr( ODB_ATTR_DATABASENAME, $this->_connectionID );\r
108                         //if using vfp dbc file\r
109                         if( !strcasecmp(strrchr($path, '.'), '.dbc') )\r
110                 $path = substr($path,0,strrpos($path,'\/'));\r
111                 $seqtab = $path . '/' . $seqtab;\r
112         }\r
113                 $MAXLOOPS = 100;\r
114                 while (--$MAXLOOPS>=0) {\r
115                         $num = $this->GetOne("select seq_value from adodb_seq where seq_name='$seq'");\r
116                         if ($num === false) {\r
117                                 //verify if abodb_seq table exist\r
118                                 $ok = $this->GetOne("select seq_value from adodb_seq ");\r
119                                 if(!$ok) {\r
120                                         //creating the sequence table adodb_seq\r
121                                         $this->Execute(sprintf($this->_genSeqSQL ,$seqtab));\r
122                                 }\r
123                                 $start -= 1;\r
124                                 $num = '0';\r
125                                 $ok = $this->Execute("insert into adodb_seq values('$seq',$start)");\r
126                                 if (!$ok) return false;\r
127                         }\r
128                         $ok = $this->Execute("update adodb_seq set seq_value=seq_value+1 where seq_name='$seq'");\r
129                         if($ok) {\r
130                                 $num += 1;\r
131                                 $this->genID = $num;\r
132                                 return $num;\r
133                         }\r
134                 }\r
135         if ($fn = $this->raiseErrorFn) {\r
136                 $fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);\r
137         }\r
138                 return false;\r
139         }\r
140 \r
141         //example for $UserOrDSN\r
142         //for visual fox : DRIVER={Microsoft Visual FoxPro Driver};SOURCETYPE=DBF;SOURCEDB=c:\YourDbfFileDir;EXCLUSIVE=NO;\r
143         //for visual fox dbc: DRIVER={Microsoft Visual FoxPro Driver};SOURCETYPE=DBC;SOURCEDB=c:\YourDbcFileDir\mydb.dbc;EXCLUSIVE=NO;\r
144         //for access : DRIVER={Microsoft Access Driver (*.mdb)};DBQ=c:\path_to_access_db\base_test.mdb;UID=root;PWD=;\r
145         //for mssql : DRIVER={SQL Server};SERVER=myserver;UID=myuid;PWD=mypwd;DATABASE=OdbtpTest;\r
146         //if uid & pwd can be separate\r
147     function _connect($HostOrInterface, $UserOrDSN='', $argPassword='', $argDatabase='')\r
148         {\r
149                 $this->_connectionID = @odbtp_connect($HostOrInterface,$UserOrDSN,$argPassword,$argDatabase);\r
150                 if ($this->_connectionID === false)\r
151                 {\r
152                         $this->_errorMsg = $this->ErrorMsg() ;\r
153                         return false;\r
154                 }\r
155                 $this->odbc_driver = @odbtp_get_attr(ODB_ATTR_DRIVER, $this->_connectionID);\r
156 \r
157                 // Set driver specific attributes\r
158                 switch( $this->odbc_driver ) {\r
159                         case ODB_DRIVER_MSSQL:\r
160                                 $this->fmtDate = "'Y-m-d'";\r
161                                 $this->fmtTimeStamp = "'Y-m-d h:i:sA'";\r
162                                 $this->sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';\r
163                                 $this->sysTimeStamp = 'GetDate()';\r
164                                 $this->ansiOuter = true;\r
165                                 $this->leftOuter = '*=';\r
166                                 $this->rightOuter = '=*';\r
167                 $this->hasTop = 'top';\r
168                                 $this->hasInsertID = true;\r
169                                 $this->hasTransactions = true;\r
170                                 $this->_bindInputArray = true;\r
171                                 $this->_canSelectDb = true;\r
172                                 $this->substr = "substring";\r
173                                 $this->length = 'len';\r
174                                 $this->upperCase = 'upper';\r
175                                 $this->identitySQL = 'select @@IDENTITY';\r
176                                 $this->metaDatabasesSQL = "select name from master..sysdatabases where name <> 'master'";\r
177                                 break;\r
178                         case ODB_DRIVER_JET:\r
179                                 $this->fmtDate = "#Y-m-d#";\r
180                                 $this->fmtTimeStamp = "#Y-m-d h:i:sA#";\r
181                                 $this->sysDate = "FORMAT(NOW,'yyyy-mm-dd')";\r
182                                 $this->sysTimeStamp = 'NOW';\r
183                 $this->hasTop = 'top';\r
184                                 $this->hasTransactions = false;\r
185                                 $this->_canPrepareSP = true;  // For MS Access only.\r
186 \r
187                                 // Can't rebind ODB_CHAR to ODB_WCHAR if row cache enabled.\r
188                                 if ($this->_useUnicodeSQL)\r
189                                         odbtp_use_row_cache($this->_connectionID, FALSE, 0);\r
190                                 break;\r
191                         case ODB_DRIVER_FOXPRO:\r
192                                 $this->fmtDate = "{^Y-m-d}";\r
193                                 $this->fmtTimeStamp = "{^Y-m-d, h:i:sA}";\r
194                                 $this->sysDate = 'date()';\r
195                                 $this->sysTimeStamp = 'datetime()';\r
196                                 $this->ansiOuter = true;\r
197                 $this->hasTop = 'top';\r
198                         $this->hasTransactions = false;\r
199                                 $this->replaceQuote = "'+chr(39)+'";\r
200                                 $this->true = '.T.';\r
201                                 $this->false = '.F.';\r
202                                 $this->upperCase = 'upper';\r
203                                 break;\r
204                         case ODB_DRIVER_ORACLE:\r
205                                 $this->fmtDate = "'Y-m-d 00:00:00'";\r
206                                 $this->fmtTimeStamp = "'Y-m-d h:i:sA'";\r
207                                 $this->sysDate = 'TRUNC(SYSDATE)';\r
208                                 $this->sysTimeStamp = 'SYSDATE';\r
209                                 $this->hasTransactions = true;\r
210                                 $this->_bindInputArray = true;\r
211                                 $this->concat_operator = '||';\r
212                                 break;\r
213                         case ODB_DRIVER_SYBASE:\r
214                                 $this->fmtDate = "'Y-m-d'";\r
215                                 $this->fmtTimeStamp = "'Y-m-d H:i:s'";\r
216                                 $this->sysDate = 'GetDate()';\r
217                                 $this->sysTimeStamp = 'GetDate()';\r
218                                 $this->leftOuter = '*=';\r
219                                 $this->rightOuter = '=*';\r
220                                 $this->hasInsertID = true;\r
221                                 $this->hasTransactions = true;\r
222                                 $this->upperCase = 'upper';\r
223                                 $this->identitySQL = 'select @@IDENTITY';\r
224                                 break;\r
225                         default:\r
226                                 if( @odbtp_get_attr(ODB_ATTR_TXNCAPABLE, $this->_connectionID) )\r
227                         $this->hasTransactions = true;\r
228                                 else\r
229                                         $this->hasTransactions = false;\r
230                 }\r
231         @odbtp_set_attr(ODB_ATTR_FULLCOLINFO, TRUE, $this->_connectionID );\r
232                 if ($this->_useUnicodeSQL )\r
233                         @odbtp_set_attr(ODB_ATTR_UNICODESQL, TRUE, $this->_connectionID);\r
234         return true;\r
235         }\r
236         \r
237         function _pconnect($HostOrInterface, $UserOrDSN='', $argPassword='', $argDatabase='')\r
238         {\r
239                 return $this->_connect($HostOrInterface, $UserOrDSN, $argPassword, $argDatabase);\r
240         }\r
241         \r
242         function SelectDB($dbName)\r
243         {\r
244                 if (!@odbtp_select_db($dbName, $this->_connectionID)) {\r
245                         return false;\r
246                 }\r
247                 $this->databaseName = $dbName;\r
248                 return true;\r
249         }\r
250         \r
251         function &MetaTables($ttype='',$showSchema=false,$mask=false)\r
252         {\r
253         global $ADODB_FETCH_MODE;\r
254 \r
255                 $savem = $ADODB_FETCH_MODE;\r
256                 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
257                 $arr =& $this->GetArray("||SQLTables||||$ttype");\r
258                 $ADODB_FETCH_MODE = $savem;\r
259 \r
260                 $arr2 = array();\r
261                 for ($i=0; $i < sizeof($arr); $i++) {\r
262                         if ($arr[$i][3] == 'SYSTEM TABLE' )     continue;\r
263                         if ($arr[$i][2])\r
264                                 $arr2[] = $showSchema ? $arr[$i][1].'.'.$arr[$i][2] : $arr[$i][2];\r
265                 }\r
266                 return $arr2;\r
267         }\r
268         \r
269         function &MetaColumns($table,$upper=true)\r
270         {\r
271         global $ADODB_FETCH_MODE;\r
272 \r
273                 $schema = false;\r
274                 $this->_findschema($table,$schema);\r
275                 if ($upper) $table = strtoupper($table);\r
276 \r
277                 $savem = $ADODB_FETCH_MODE;\r
278                 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
279                 $rs = $this->Execute( "||SQLColumns||$schema|$table" );\r
280                 $ADODB_FETCH_MODE = $savem;\r
281 \r
282                 if (!$rs) return false;\r
283                 \r
284                 while (!$rs->EOF) {\r
285                         //print_r($rs->fields);\r
286                         if (strtoupper($rs->fields[2]) == $table) {\r
287                                 $fld = new ADOFieldObject();\r
288                                 $fld->name = $rs->fields[3];\r
289                                 $fld->type = $rs->fields[5];\r
290                                 $fld->max_length = $rs->fields[6];\r
291                         $fld->not_null = !empty($rs->fields[9]);\r
292                                 $fld->scale = $rs->fields[7];\r
293                                 if (!is_null($rs->fields[12])) {\r
294                                         $fld->has_default = true;\r
295                                         $fld->default_value = $rs->fields[12];\r
296                                 }\r
297                                 $retarr[strtoupper($fld->name)] = $fld;\r
298                         } else if (sizeof($retarr)>0)\r
299                                 break;\r
300                         $rs->MoveNext();\r
301                 }\r
302                 $rs->Close(); \r
303 \r
304                 return $retarr;\r
305         }\r
306 \r
307         function &MetaPrimaryKeys($table, $owner='')\r
308         {\r
309         global $ADODB_FETCH_MODE;\r
310 \r
311                 $savem = $ADODB_FETCH_MODE;\r
312                 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
313                 $arr =& $this->GetArray("||SQLPrimaryKeys||$owner|$table");\r
314                 $ADODB_FETCH_MODE = $savem;\r
315 \r
316                 //print_r($arr);\r
317                 $arr2 = array();\r
318                 for ($i=0; $i < sizeof($arr); $i++) {\r
319                         if ($arr[$i][3]) $arr2[] = $arr[$i][3];\r
320                 }\r
321                 return $arr2;\r
322         }\r
323 \r
324         function &MetaForeignKeys($table, $owner='', $upper=false)\r
325         {\r
326         global $ADODB_FETCH_MODE;\r
327 \r
328                 $savem = $ADODB_FETCH_MODE;\r
329                 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
330                 $constraints =& $this->GetArray("||SQLForeignKeys|||||$owner|$table");\r
331                 $ADODB_FETCH_MODE = $savem;\r
332 \r
333                 $arr = false;\r
334                 foreach($constraints as $constr) {\r
335                         //print_r($constr);\r
336                         $arr[$constr[11]][$constr[2]][] = $constr[7].'='.$constr[3];\r
337                 }\r
338                 if (!$arr) return false;\r
339 \r
340                 $arr2 = array();\r
341 \r
342                 foreach($arr as $k => $v) {\r
343                         foreach($v as $a => $b) {\r
344                                 if ($upper) $a = strtoupper($a);\r
345                                 $arr2[$a] = $b;\r
346                         }\r
347                 }\r
348                 return $arr2;\r
349         }\r
350 \r
351         function BeginTrans()\r
352         {\r
353                 if (!$this->hasTransactions) return false;\r
354                 if ($this->transOff) return true;\r
355                 $this->transCnt += 1;\r
356                 $this->_autocommit = false;\r
357                 $rs = @odbtp_set_attr(ODB_ATTR_TRANSACTIONS,ODB_TXN_READUNCOMMITTED,$this->_connectionID);\r
358                 if(!$rs) return false;\r
359                 else return true;\r
360         }\r
361 \r
362         function CommitTrans($ok=true)\r
363         {\r
364                 if ($this->transOff) return true;\r
365                 if (!$ok) return $this->RollbackTrans();\r
366                 if ($this->transCnt) $this->transCnt -= 1;\r
367                 $this->_autocommit = true;\r
368                 if( ($ret = odbtp_commit($this->_connectionID)) )\r
369                         $ret = @odbtp_set_attr(ODB_ATTR_TRANSACTIONS, ODB_TXN_NONE, $this->_connectionID);//set transaction off\r
370                 return $ret;\r
371         }\r
372 \r
373         function RollbackTrans()\r
374         {\r
375                 if ($this->transOff) return true;\r
376                 if ($this->transCnt) $this->transCnt -= 1;\r
377                 $this->_autocommit = true;\r
378                 if( ($ret = odbtp_rollback($this->_connectionID)) )\r
379                         $ret = @odbtp_set_attr(ODB_ATTR_TRANSACTIONS, ODB_TXN_NONE, $this->_connectionID);//set transaction off\r
380                 return $ret;\r
381         }\r
382 \r
383         function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)\r
384         {\r
385                 // TOP requires ORDER BY for Visual FoxPro\r
386                 if( $this->odbc_driver == ODB_DRIVER_FOXPRO ) {\r
387                         if (!preg_match('/ORDER[ \t\r\n]+BY/is',$sql)) $sql .= ' ORDER BY 1';\r
388                 }\r
389                 return ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);\r
390         }\r
391 \r
392         function Prepare($sql)\r
393         {\r
394                 if (! $this->_bindInputArray) return $sql; // no binding\r
395                 $stmt = odbtp_prepare($sql,$this->_connectionID);\r
396                 if (!$stmt) {\r
397                 //      print "Prepare Error for ($sql) ".$this->ErrorMsg()."<br>";\r
398                         return $sql;\r
399                 }\r
400                 return array($sql,$stmt,false);\r
401         }\r
402 \r
403         function PrepareSP($sql)\r
404         {\r
405                 if (!$this->_canPrepareSP) return $sql; // Can't prepare procedures\r
406 \r
407                 $stmt = odbtp_prepare_proc($sql,$this->_connectionID);\r
408                 if (!$stmt) return false;\r
409                 return array($sql,$stmt);\r
410         }\r
411 \r
412         /*\r
413         Usage:\r
414                 $stmt = $db->PrepareSP('SP_RUNSOMETHING'); -- takes 2 params, @myid and @group\r
415 \r
416                 # note that the parameter does not have @ in front!\r
417                 $db->Parameter($stmt,$id,'myid');\r
418                 $db->Parameter($stmt,$group,'group',false,64);\r
419                 $db->Parameter($stmt,$group,'photo',false,100000,ODB_BINARY);\r
420                 $db->Execute($stmt);\r
421 \r
422                 @param $stmt Statement returned by Prepare() or PrepareSP().\r
423                 @param $var PHP variable to bind to. Can set to null (for isNull support).\r
424                 @param $name Name of stored procedure variable name to bind to.\r
425                 @param [$isOutput] Indicates direction of parameter 0/false=IN  1=OUT  2= IN/OUT. This is ignored in odbtp.\r
426                 @param [$maxLen] Holds an maximum length of the variable.\r
427                 @param [$type] The data type of $var. Legal values depend on driver.\r
428 \r
429                 See odbtp_attach_param documentation at http://odbtp.sourceforge.net.\r
430         */\r
431         function Parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=0, $type=0)\r
432         {\r
433                 if ( $this->odbc_driver == ODB_DRIVER_JET ) {\r
434                         $name = '['.$name.']';\r
435                         if( !$type && $this->_useUnicodeSQL\r
436                                 && @odbtp_param_bindtype($stmt[1], $name) == ODB_CHAR )\r
437                         {\r
438                                 $type = ODB_WCHAR;\r
439                         }\r
440                 }\r
441                 else {\r
442                         $name = '@'.$name;\r
443                 }\r
444                 return odbtp_attach_param($stmt[1], $name, $var, $type, $maxLen);\r
445         }\r
446 \r
447         /*\r
448                 Insert a null into the blob field of the table first.\r
449                 Then use UpdateBlob to store the blob.\r
450 \r
451                 Usage:\r
452 \r
453                 $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');\r
454                 $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');\r
455         */\r
456 \r
457         function UpdateBlob($table,$column,$val,$where,$blobtype='image')\r
458         {\r
459                 $sql = "UPDATE $table SET $column = ? WHERE $where";\r
460                 if( !($stmt = odbtp_prepare($sql, $this->_connectionID)) )\r
461                         return false;\r
462                 if( !odbtp_input( $stmt, 1, ODB_BINARY, 1000000, $blobtype ) )\r
463                         return false;\r
464                 if( !odbtp_set( $stmt, 1, $val ) )\r
465                         return false;\r
466                 return odbtp_execute( $stmt ) != false;\r
467         }\r
468 \r
469         function IfNull( $field, $ifNull )\r
470         {\r
471                 switch( $this->odbc_driver ) {\r
472                         case ODB_DRIVER_MSSQL:\r
473                                 return " ISNULL($field, $ifNull) ";\r
474                         case ODB_DRIVER_JET:\r
475                                 return " IIF(IsNull($field), $ifNull, $field) ";\r
476                 }\r
477                 return " CASE WHEN $field is null THEN $ifNull ELSE $field END ";\r
478         }\r
479 \r
480         function _query($sql,$inputarr=false)\r
481         {\r
482                 if ($inputarr) {\r
483                         if (is_array($sql)) {\r
484                                 $stmtid = $sql[1];\r
485                         } else {\r
486                                 $stmtid = odbtp_prepare($sql,$this->_connectionID);\r
487                                 if ($stmtid == false) {\r
488                                         $this->_errorMsg = $php_errormsg;\r
489                                         return false;\r
490                                 }\r
491                         }\r
492                         $num_params = odbtp_num_params( $stmtid );\r
493                         for( $param = 1; $param <= $num_params; $param++ ) {\r
494                                 @odbtp_input( $stmtid, $param );\r
495                                 @odbtp_set( $stmtid, $param, $inputarr[$param-1] );\r
496                         }\r
497                         if (! odbtp_execute($stmtid) ) {\r
498                                 return false;\r
499                         }\r
500                 } else if (is_array($sql)) {\r
501                         $stmtid = $sql[1];\r
502                         if (!odbtp_execute($stmtid)) {\r
503                                 return false;\r
504                         }\r
505                 } else {\r
506                         $stmtid = @odbtp_query($sql,$this->_connectionID);\r
507                 }\r
508                 $this->_lastAffectedRows = 0;\r
509                 if ($stmtid) {\r
510                                 $this->_lastAffectedRows = @odbtp_affected_rows($stmtid);\r
511                 }\r
512         return $stmtid;\r
513         }\r
514 \r
515         function _close()\r
516         {\r
517                 $ret = @odbtp_close($this->_connectionID);\r
518                 $this->_connectionID = false;\r
519                 return $ret;\r
520         }\r
521 }\r
522 \r
523 class ADORecordSet_odbtp extends ADORecordSet {\r
524 \r
525         var $databaseType = 'odbtp';\r
526         var $canSeek = true;\r
527 \r
528         function ADORecordSet_odbtp($queryID,$mode=false)\r
529         {\r
530                 if ($mode === false) {\r
531                         global $ADODB_FETCH_MODE;\r
532                         $mode = $ADODB_FETCH_MODE;\r
533                 }\r
534                 $this->fetchMode = $mode;\r
535                 $this->ADORecordSet($queryID);\r
536         }\r
537 \r
538         function _initrs()\r
539         {\r
540                 $this->_numOfFields = @odbtp_num_fields($this->_queryID);\r
541                 if (!($this->_numOfRows = @odbtp_num_rows($this->_queryID)))\r
542                         $this->_numOfRows = -1;\r
543         }\r
544 \r
545         function &FetchField($fieldOffset = 0)\r
546         {\r
547                 $off=$fieldOffset; // offsets begin at 0\r
548                 $o= new ADOFieldObject();\r
549                 $o->name = @odbtp_field_name($this->_queryID,$off);\r
550                 $o->type = @odbtp_field_type($this->_queryID,$off);\r
551         $o->max_length = @odbtp_field_length($this->_queryID,$off);\r
552                 if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name);\r
553                 else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name);\r
554                 return $o;\r
555         }\r
556 \r
557         function _seek($row)\r
558         {\r
559                 return @odbtp_data_seek($this->_queryID, $row);\r
560         }\r
561 \r
562         function fields($colname)\r
563         {\r
564                 if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];\r
565 \r
566                 if (!$this->bind) {\r
567                         $this->bind = array();\r
568                         for ($i=0; $i < $this->_numOfFields; $i++) {\r
569                                 $name = @odbtp_field_name( $this->_queryID, $i );\r
570                                 $this->bind[strtoupper($name)] = $i;\r
571                         }\r
572                 }\r
573                  return $this->fields[$this->bind[strtoupper($colname)]];\r
574         }\r
575 \r
576         function _fetch_odbtp($type=0)\r
577         {\r
578                 switch ($this->fetchMode) {\r
579                         case ADODB_FETCH_NUM:\r
580                                 $this->fields = @odbtp_fetch_row($this->_queryID, $type);\r
581                                 break;\r
582                         case ADODB_FETCH_ASSOC:\r
583                                 $this->fields = @odbtp_fetch_assoc($this->_queryID, $type);\r
584                                 break;\r
585             default:\r
586                                 $this->fields = @odbtp_fetch_array($this->_queryID, $type);\r
587                 }\r
588                 return is_array($this->fields);\r
589         }\r
590 \r
591         function _fetch()\r
592         {\r
593                 return $this->_fetch_odbtp();\r
594         }\r
595 \r
596         function MoveFirst()\r
597         {\r
598                 if (!$this->_fetch_odbtp(ODB_FETCH_FIRST)) return false;\r
599                 $this->EOF = false;\r
600           $this->_currentRow = 0;\r
601           return true;\r
602     }\r
603 \r
604     function MoveLast()\r
605    {\r
606                 if (!$this->_fetch_odbtp(ODB_FETCH_LAST)) return false;\r
607                 $this->EOF = false;\r
608                 $this->_currentRow = $this->_numOfRows - 1;\r
609           return true;\r
610     }\r
611     \r
612         function NextRecordSet()\r
613         {\r
614                 if (!@odbtp_next_result($this->_queryID)) return false;\r
615                 $this->_inited = false;\r
616                 $this->bind = false;\r
617                 $this->_currentRow = -1;\r
618                 $this->Init();\r
619                 return true;\r
620         }\r
621 \r
622         function _close()\r
623         {\r
624                 return @odbtp_free_query($this->_queryID);\r
625         }\r
626 }\r
627 \r
628 ?>\r
629 \r
630 \r