adodb-odbtp.inc.php 23 KB

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