adodb-ado5.inc.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. <?php
  2. /*
  3. V4.60 24 Jan 2005 (c) 2000-2005 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. Latest version is available at http://adodb.sourceforge.net
  9. Microsoft ADO data driver. Requires ADO. Works only on MS Windows. PHP5 compat version.
  10. */
  11. // security - hide paths
  12. if (!defined('ADODB_DIR')) die();
  13. define("_ADODB_ADO_LAYER", 1 );
  14. /*--------------------------------------------------------------------------------------
  15. --------------------------------------------------------------------------------------*/
  16. class ADODB_ado extends ADOConnection {
  17. var $databaseType = "ado";
  18. var $_bindInputArray = false;
  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 $dataProvider = "ado";
  23. var $hasAffectedRows = true;
  24. var $adoParameterType = 201; // 201 = long varchar, 203=long wide varchar, 205 = long varbinary
  25. var $_affectedRows = false;
  26. var $_thisTransactions;
  27. var $_cursor_type = 3; // 3=adOpenStatic,0=adOpenForwardOnly,1=adOpenKeyset,2=adOpenDynamic
  28. var $_cursor_location = 3; // 2=adUseServer, 3 = adUseClient;
  29. var $_lock_type = -1;
  30. var $_execute_option = -1;
  31. var $poorAffectedRows = true;
  32. var $charPage;
  33. function ADODB_ado()
  34. {
  35. $this->_affectedRows = new VARIANT;
  36. }
  37. function ServerInfo()
  38. {
  39. if (!empty($this->_connectionID)) $desc = $this->_connectionID->provider;
  40. return array('description' => $desc, 'version' => '');
  41. }
  42. function _affectedrows()
  43. {
  44. if (PHP_VERSION >= 5) return $this->_affectedRows;
  45. return $this->_affectedRows->value;
  46. }
  47. // you can also pass a connection string like this:
  48. //
  49. // $DB->Connect('USER ID=sa;PASSWORD=pwd;SERVER=mangrove;DATABASE=ai',false,false,'SQLOLEDB');
  50. function _connect($argHostname, $argUsername, $argPassword, $argProvider= 'MSDASQL')
  51. {
  52. try {
  53. $u = 'UID';
  54. $p = 'PWD';
  55. if (!empty($this->charPage))
  56. $dbc = new COM('ADODB.Connection',null,$this->charPage);
  57. else
  58. $dbc = new COM('ADODB.Connection');
  59. if (! $dbc) return false;
  60. /* special support if provider is mssql or access */
  61. if ($argProvider=='mssql') {
  62. $u = 'User Id'; //User parameter name for OLEDB
  63. $p = 'Password';
  64. $argProvider = "SQLOLEDB"; // SQL Server Provider
  65. // not yet
  66. //if ($argDatabasename) $argHostname .= ";Initial Catalog=$argDatabasename";
  67. //use trusted conection for SQL if username not specified
  68. if (!$argUsername) $argHostname .= ";Trusted_Connection=Yes";
  69. } else if ($argProvider=='access')
  70. $argProvider = "Microsoft.Jet.OLEDB.4.0"; // Microsoft Jet Provider
  71. if ($argProvider) $dbc->Provider = $argProvider;
  72. if ($argUsername) $argHostname .= ";$u=$argUsername";
  73. if ($argPassword)$argHostname .= ";$p=$argPassword";
  74. if ($this->debug) ADOConnection::outp( "Host=".$argHostname."<BR>\n version=$dbc->version");
  75. // @ added below for php 4.0.1 and earlier
  76. @$dbc->Open((string) $argHostname);
  77. $this->_connectionID = $dbc;
  78. $dbc->CursorLocation = $this->_cursor_location;
  79. return $dbc->State > 0;
  80. } catch (exception $e) {
  81. }
  82. return false;
  83. }
  84. // returns true or false
  85. function _pconnect($argHostname, $argUsername, $argPassword, $argProvider='MSDASQL')
  86. {
  87. return $this->_connect($argHostname,$argUsername,$argPassword,$argProvider);
  88. }
  89. /*
  90. adSchemaCatalogs = 1,
  91. adSchemaCharacterSets = 2,
  92. adSchemaCollations = 3,
  93. adSchemaColumns = 4,
  94. adSchemaCheckConstraints = 5,
  95. adSchemaConstraintColumnUsage = 6,
  96. adSchemaConstraintTableUsage = 7,
  97. adSchemaKeyColumnUsage = 8,
  98. adSchemaReferentialContraints = 9,
  99. adSchemaTableConstraints = 10,
  100. adSchemaColumnsDomainUsage = 11,
  101. adSchemaIndexes = 12,
  102. adSchemaColumnPrivileges = 13,
  103. adSchemaTablePrivileges = 14,
  104. adSchemaUsagePrivileges = 15,
  105. adSchemaProcedures = 16,
  106. adSchemaSchemata = 17,
  107. adSchemaSQLLanguages = 18,
  108. adSchemaStatistics = 19,
  109. adSchemaTables = 20,
  110. adSchemaTranslations = 21,
  111. adSchemaProviderTypes = 22,
  112. adSchemaViews = 23,
  113. adSchemaViewColumnUsage = 24,
  114. adSchemaViewTableUsage = 25,
  115. adSchemaProcedureParameters = 26,
  116. adSchemaForeignKeys = 27,
  117. adSchemaPrimaryKeys = 28,
  118. adSchemaProcedureColumns = 29,
  119. adSchemaDBInfoKeywords = 30,
  120. adSchemaDBInfoLiterals = 31,
  121. adSchemaCubes = 32,
  122. adSchemaDimensions = 33,
  123. adSchemaHierarchies = 34,
  124. adSchemaLevels = 35,
  125. adSchemaMeasures = 36,
  126. adSchemaProperties = 37,
  127. adSchemaMembers = 38
  128. */
  129. function &MetaTables()
  130. {
  131. $arr= array();
  132. $dbc = $this->_connectionID;
  133. $adors=@$dbc->OpenSchema(20);//tables
  134. if ($adors){
  135. $f = $adors->Fields(2);//table/view name
  136. $t = $adors->Fields(3);//table type
  137. while (!$adors->EOF){
  138. $tt=substr($t->value,0,6);
  139. if ($tt!='SYSTEM' && $tt !='ACCESS')
  140. $arr[]=$f->value;
  141. //print $f->value . ' ' . $t->value.'<br>';
  142. $adors->MoveNext();
  143. }
  144. $adors->Close();
  145. }
  146. return $arr;
  147. }
  148. function &MetaColumns($table)
  149. {
  150. $table = strtoupper($table);
  151. $arr= array();
  152. $dbc = $this->_connectionID;
  153. $adors=@$dbc->OpenSchema(4);//tables
  154. if ($adors){
  155. $t = $adors->Fields(2);//table/view name
  156. while (!$adors->EOF){
  157. if (strtoupper($t->Value) == $table) {
  158. $fld = new ADOFieldObject();
  159. $c = $adors->Fields(3);
  160. $fld->name = $c->Value;
  161. $fld->type = 'CHAR'; // cannot discover type in ADO!
  162. $fld->max_length = -1;
  163. $arr[strtoupper($fld->name)]=$fld;
  164. }
  165. $adors->MoveNext();
  166. }
  167. $adors->Close();
  168. }
  169. return $arr;
  170. }
  171. /* returns queryID or false */
  172. function &_query($sql,$inputarr=false)
  173. {
  174. try { // In PHP5, all COM errors are exceptions, so to maintain old behaviour...
  175. $dbc = $this->_connectionID;
  176. // return rs
  177. if ($inputarr) {
  178. if (!empty($this->charPage))
  179. $oCmd = new COM('ADODB.Command',null,$this->charPage);
  180. else
  181. $oCmd = new COM('ADODB.Command');
  182. $oCmd->ActiveConnection = $dbc;
  183. $oCmd->CommandText = $sql;
  184. $oCmd->CommandType = 1;
  185. foreach($inputarr as $val) {
  186. // name, type, direction 1 = input, len,
  187. $this->adoParameterType = 130;
  188. $p = $oCmd->CreateParameter('name',$this->adoParameterType,1,strlen($val),$val);
  189. //print $p->Type.' '.$p->value;
  190. $oCmd->Parameters->Append($p);
  191. }
  192. $p = false;
  193. $rs = $oCmd->Execute();
  194. $e = $dbc->Errors;
  195. if ($dbc->Errors->Count > 0) return false;
  196. return $rs;
  197. }
  198. $rs = @$dbc->Execute($sql,$this->_affectedRows, $this->_execute_option);
  199. if ($dbc->Errors->Count > 0) return false;
  200. if (! $rs) return false;
  201. if ($rs->State == 0) return true; // 0 = adStateClosed means no records returned
  202. return $rs;
  203. } catch (exception $e) {
  204. }
  205. return false;
  206. }
  207. function BeginTrans()
  208. {
  209. if ($this->transOff) return true;
  210. if (isset($this->_thisTransactions))
  211. if (!$this->_thisTransactions) return false;
  212. else {
  213. $o = $this->_connectionID->Properties("Transaction DDL");
  214. $this->_thisTransactions = $o ? true : false;
  215. if (!$o) return false;
  216. }
  217. @$this->_connectionID->BeginTrans();
  218. $this->transCnt += 1;
  219. return true;
  220. }
  221. function CommitTrans($ok=true)
  222. {
  223. if (!$ok) return $this->RollbackTrans();
  224. if ($this->transOff) return true;
  225. @$this->_connectionID->CommitTrans();
  226. if ($this->transCnt) @$this->transCnt -= 1;
  227. return true;
  228. }
  229. function RollbackTrans() {
  230. if ($this->transOff) return true;
  231. @$this->_connectionID->RollbackTrans();
  232. if ($this->transCnt) @$this->transCnt -= 1;
  233. return true;
  234. }
  235. /* Returns: the last error message from previous database operation */
  236. function ErrorMsg()
  237. {
  238. $errc = $this->_connectionID->Errors;
  239. if ($errc->Count == 0) return '';
  240. $err = $errc->Item($errc->Count-1);
  241. return $err->Description;
  242. }
  243. function ErrorNo()
  244. {
  245. $errc = $this->_connectionID->Errors;
  246. if ($errc->Count == 0) return 0;
  247. $err = $errc->Item($errc->Count-1);
  248. return $err->NativeError;
  249. }
  250. // returns true or false
  251. function _close()
  252. {
  253. if ($this->_connectionID) $this->_connectionID->Close();
  254. $this->_connectionID = false;
  255. return true;
  256. }
  257. }
  258. /*--------------------------------------------------------------------------------------
  259. Class Name: Recordset
  260. --------------------------------------------------------------------------------------*/
  261. class ADORecordSet_ado extends ADORecordSet {
  262. var $bind = false;
  263. var $databaseType = "ado";
  264. var $dataProvider = "ado";
  265. var $_tarr = false; // caches the types
  266. var $_flds; // and field objects
  267. var $canSeek = true;
  268. var $hideErrors = true;
  269. function ADORecordSet_ado($id,$mode=false)
  270. {
  271. if ($mode === false) {
  272. global $ADODB_FETCH_MODE;
  273. $mode = $ADODB_FETCH_MODE;
  274. }
  275. $this->fetchMode = $mode;
  276. return $this->ADORecordSet($id,$mode);
  277. }
  278. // returns the field object
  279. function FetchField($fieldOffset = -1) {
  280. $off=$fieldOffset+1; // offsets begin at 1
  281. $o= new ADOFieldObject();
  282. $rs = $this->_queryID;
  283. $f = $rs->Fields($fieldOffset);
  284. $o->name = $f->Name;
  285. $t = $f->Type;
  286. $o->type = $this->MetaType($t);
  287. $o->max_length = $f->DefinedSize;
  288. $o->ado_type = $t;
  289. //print "off=$off name=$o->name type=$o->type len=$o->max_length<br>";
  290. return $o;
  291. }
  292. /* Use associative array to get fields array */
  293. function Fields($colname)
  294. {
  295. if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
  296. if (!$this->bind) {
  297. $this->bind = array();
  298. for ($i=0; $i < $this->_numOfFields; $i++) {
  299. $o = $this->FetchField($i);
  300. $this->bind[strtoupper($o->name)] = $i;
  301. }
  302. }
  303. return $this->fields[$this->bind[strtoupper($colname)]];
  304. }
  305. function _initrs()
  306. {
  307. $rs = $this->_queryID;
  308. $this->_numOfRows = $rs->RecordCount;
  309. $f = $rs->Fields;
  310. $this->_numOfFields = $f->Count;
  311. }
  312. // should only be used to move forward as we normally use forward-only cursors
  313. function _seek($row)
  314. {
  315. $rs = $this->_queryID;
  316. // absoluteposition doesn't work -- my maths is wrong ?
  317. // $rs->AbsolutePosition->$row-2;
  318. // return true;
  319. if ($this->_currentRow > $row) return false;
  320. @$rs->Move((integer)$row - $this->_currentRow-1); //adBookmarkFirst
  321. return true;
  322. }
  323. /*
  324. OLEDB types
  325. enum DBTYPEENUM
  326. { DBTYPE_EMPTY = 0,
  327. DBTYPE_NULL = 1,
  328. DBTYPE_I2 = 2,
  329. DBTYPE_I4 = 3,
  330. DBTYPE_R4 = 4,
  331. DBTYPE_R8 = 5,
  332. DBTYPE_CY = 6,
  333. DBTYPE_DATE = 7,
  334. DBTYPE_BSTR = 8,
  335. DBTYPE_IDISPATCH = 9,
  336. DBTYPE_ERROR = 10,
  337. DBTYPE_BOOL = 11,
  338. DBTYPE_VARIANT = 12,
  339. DBTYPE_IUNKNOWN = 13,
  340. DBTYPE_DECIMAL = 14,
  341. DBTYPE_UI1 = 17,
  342. DBTYPE_ARRAY = 0x2000,
  343. DBTYPE_BYREF = 0x4000,
  344. DBTYPE_I1 = 16,
  345. DBTYPE_UI2 = 18,
  346. DBTYPE_UI4 = 19,
  347. DBTYPE_I8 = 20,
  348. DBTYPE_UI8 = 21,
  349. DBTYPE_GUID = 72,
  350. DBTYPE_VECTOR = 0x1000,
  351. DBTYPE_RESERVED = 0x8000,
  352. DBTYPE_BYTES = 128,
  353. DBTYPE_STR = 129,
  354. DBTYPE_WSTR = 130,
  355. DBTYPE_NUMERIC = 131,
  356. DBTYPE_UDT = 132,
  357. DBTYPE_DBDATE = 133,
  358. DBTYPE_DBTIME = 134,
  359. DBTYPE_DBTIMESTAMP = 135
  360. ADO Types
  361. adEmpty = 0,
  362. adTinyInt = 16,
  363. adSmallInt = 2,
  364. adInteger = 3,
  365. adBigInt = 20,
  366. adUnsignedTinyInt = 17,
  367. adUnsignedSmallInt = 18,
  368. adUnsignedInt = 19,
  369. adUnsignedBigInt = 21,
  370. adSingle = 4,
  371. adDouble = 5,
  372. adCurrency = 6,
  373. adDecimal = 14,
  374. adNumeric = 131,
  375. adBoolean = 11,
  376. adError = 10,
  377. adUserDefined = 132,
  378. adVariant = 12,
  379. adIDispatch = 9,
  380. adIUnknown = 13,
  381. adGUID = 72,
  382. adDate = 7,
  383. adDBDate = 133,
  384. adDBTime = 134,
  385. adDBTimeStamp = 135,
  386. adBSTR = 8,
  387. adChar = 129,
  388. adVarChar = 200,
  389. adLongVarChar = 201,
  390. adWChar = 130,
  391. adVarWChar = 202,
  392. adLongVarWChar = 203,
  393. adBinary = 128,
  394. adVarBinary = 204,
  395. adLongVarBinary = 205,
  396. adChapter = 136,
  397. adFileTime = 64,
  398. adDBFileTime = 137,
  399. adPropVariant = 138,
  400. adVarNumeric = 139
  401. */
  402. function MetaType($t,$len=-1,$fieldobj=false)
  403. {
  404. if (is_object($t)) {
  405. $fieldobj = $t;
  406. $t = $fieldobj->type;
  407. $len = $fieldobj->max_length;
  408. }
  409. if (!is_numeric($t)) return $t;
  410. switch ($t) {
  411. case 0:
  412. case 12: // variant
  413. case 8: // bstr
  414. case 129: //char
  415. case 130: //wc
  416. case 200: // varc
  417. case 202:// varWC
  418. case 128: // bin
  419. case 204: // varBin
  420. case 72: // guid
  421. if ($len <= $this->blobSize) return 'C';
  422. case 201:
  423. case 203:
  424. return 'X';
  425. case 128:
  426. case 204:
  427. case 205:
  428. return 'B';
  429. case 7:
  430. case 133: return 'D';
  431. case 134:
  432. case 135: return 'T';
  433. case 11: return 'L';
  434. case 16:// adTinyInt = 16,
  435. case 2://adSmallInt = 2,
  436. case 3://adInteger = 3,
  437. case 4://adBigInt = 20,
  438. case 17://adUnsignedTinyInt = 17,
  439. case 18://adUnsignedSmallInt = 18,
  440. case 19://adUnsignedInt = 19,
  441. case 20://adUnsignedBigInt = 21,
  442. return 'I';
  443. default: return 'N';
  444. }
  445. }
  446. // time stamp not supported yet
  447. function _fetch()
  448. {
  449. $rs = $this->_queryID;
  450. if (!$rs or $rs->EOF) {
  451. $this->fields = false;
  452. return false;
  453. }
  454. $this->fields = array();
  455. if (!$this->_tarr) {
  456. $tarr = array();
  457. $flds = array();
  458. for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) {
  459. $f = $rs->Fields($i);
  460. $flds[] = $f;
  461. $tarr[] = $f->Type;
  462. }
  463. // bind types and flds only once
  464. $this->_tarr = $tarr;
  465. $this->_flds = $flds;
  466. }
  467. $t = reset($this->_tarr);
  468. $f = reset($this->_flds);
  469. if ($this->hideErrors) $olde = error_reporting(E_ERROR|E_CORE_ERROR);// sometimes $f->value be null
  470. for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) {
  471. //echo "<p>",$t,' ';var_dump($f->value); echo '</p>';
  472. switch($t) {
  473. case 135: // timestamp
  474. if (!strlen((string)$f->value)) $this->fields[] = false;
  475. else {
  476. if (!is_numeric($f->value)) $val = variant_date_to_timestamp($f->value);
  477. else $val = $f->value;
  478. $this->fields[] = adodb_date('Y-m-d H:i:s',$val);
  479. }
  480. break;
  481. case 133:// A date value (yyyymmdd)
  482. if ($val = $f->value) {
  483. $this->fields[] = substr($val,0,4).'-'.substr($val,4,2).'-'.substr($val,6,2);
  484. } else
  485. $this->fields[] = false;
  486. break;
  487. case 7: // adDate
  488. if (!strlen((string)$f->value)) $this->fields[] = false;
  489. else {
  490. if (!is_numeric($f->value)) $val = variant_date_to_timestamp($f->value);
  491. else $val = $f->value;
  492. if (($val % 86400) == 0) $this->fields[] = adodb_date('Y-m-d',$val);
  493. else $this->fields[] = adodb_date('Y-m-d H:i:s',$val);
  494. }
  495. break;
  496. case 1: // null
  497. $this->fields[] = false;
  498. break;
  499. case 6: // currency is not supported properly;
  500. ADOConnection::outp( '<b>'.$f->Name.': currency type not supported by PHP</b>');
  501. $this->fields[] = (float) $f->value;
  502. break;
  503. default:
  504. $this->fields[] = $f->value;
  505. break;
  506. }
  507. //print " $f->value $t, ";
  508. $f = next($this->_flds);
  509. $t = next($this->_tarr);
  510. } // for
  511. if ($this->hideErrors) error_reporting($olde);
  512. @$rs->MoveNext(); // @ needed for some versions of PHP!
  513. if ($this->fetchMode & ADODB_FETCH_ASSOC) {
  514. $this->fields = &$this->GetRowAssoc(ADODB_ASSOC_CASE);
  515. }
  516. return true;
  517. }
  518. function NextRecordSet()
  519. {
  520. $rs = $this->_queryID;
  521. $this->_queryID = $rs->NextRecordSet();
  522. //$this->_queryID = $this->_QueryId->NextRecordSet();
  523. if ($this->_queryID == null) return false;
  524. $this->_currentRow = -1;
  525. $this->_currentPage = -1;
  526. $this->bind = false;
  527. $this->fields = false;
  528. $this->_flds = false;
  529. $this->_tarr = false;
  530. $this->_inited = false;
  531. $this->Init();
  532. return true;
  533. }
  534. function _close() {
  535. $this->_flds = false;
  536. @$this->_queryID->Close();// by Pete Dishman (peterd@telephonetics.co.uk)
  537. $this->_queryID = false;
  538. }
  539. }
  540. ?>