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