PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/rdfapi-php/api/util/adodb/drivers/adodb-odbtp.inc.php

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