3 @version v5.20.2 27-Dec-2015
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.
11 Latest version is available at http://adodb.sourceforge.net
13 Microsoft ADO data driver. Requires ADO. Works only on MS Windows.
16 // security - hide paths
17 if (!defined('ADODB_DIR')) die();
19 define("_ADODB_ADO_LAYER", 1 );
20 /*--------------------------------------------------------------------------------------
21 --------------------------------------------------------------------------------------*/
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;
34 var $_thisTransactions;
35 var $_cursor_type = 3; // 3=adOpenStatic,0=adOpenForwardOnly,1=adOpenKeyset,2=adOpenDynamic
36 var $_cursor_location = 3; // 2=adUseServer, 3 = adUseClient;
38 var $_execute_option = -1;
39 var $poorAffectedRows = true;
42 function __construct()
44 $this->_affectedRows
= new VARIANT
;
49 if (!empty($this->_connectionID
)) $desc = $this->_connectionID
->provider
;
50 return array('description' => $desc, 'version' => '');
53 function _affectedrows()
55 if (PHP_VERSION
>= 5) return $this->_affectedRows
;
57 return $this->_affectedRows
->value
;
60 // you can also pass a connection string like this:
62 // $DB->Connect('USER ID=sa;PASSWORD=pwd;SERVER=mangrove;DATABASE=ai',false,false,'SQLOLEDB');
63 function _connect($argHostname, $argUsername, $argPassword, $argProvider= 'MSDASQL')
68 if (!empty($this->charPage
))
69 $dbc = new COM('ADODB.Connection',null,$this->charPage
);
71 $dbc = new COM('ADODB.Connection');
73 if (! $dbc) return false;
75 /* special support if provider is mssql or access */
76 if ($argProvider=='mssql') {
77 $u = 'User Id'; //User parameter name for OLEDB
79 $argProvider = "SQLOLEDB"; // SQL Server Provider
82 //if ($argDatabasename) $argHostname .= ";Initial Catalog=$argDatabasename";
84 //use trusted conection for SQL if username not specified
85 if (!$argUsername) $argHostname .= ";Trusted_Connection=Yes";
86 } else if ($argProvider=='access')
87 $argProvider = "Microsoft.Jet.OLEDB.4.0"; // Microsoft Jet Provider
89 if ($argProvider) $dbc->Provider
= $argProvider;
91 if ($argUsername) $argHostname .= ";$u=$argUsername";
92 if ($argPassword)$argHostname .= ";$p=$argPassword";
94 if ($this->debug
) ADOConnection
::outp( "Host=".$argHostname."<BR>\n version=$dbc->version");
95 // @ added below for php 4.0.1 and earlier
96 @$dbc->Open((string) $argHostname);
98 $this->_connectionID
= $dbc;
100 $dbc->CursorLocation
= $this->_cursor_location
;
101 return $dbc->State
> 0;
104 // returns true or false
105 function _pconnect($argHostname, $argUsername, $argPassword, $argProvider='MSDASQL')
107 return $this->_connect($argHostname,$argUsername,$argPassword,$argProvider);
111 adSchemaCatalogs = 1,
112 adSchemaCharacterSets = 2,
113 adSchemaCollations = 3,
115 adSchemaCheckConstraints = 5,
116 adSchemaConstraintColumnUsage = 6,
117 adSchemaConstraintTableUsage = 7,
118 adSchemaKeyColumnUsage = 8,
119 adSchemaReferentialContraints = 9,
120 adSchemaTableConstraints = 10,
121 adSchemaColumnsDomainUsage = 11,
122 adSchemaIndexes = 12,
123 adSchemaColumnPrivileges = 13,
124 adSchemaTablePrivileges = 14,
125 adSchemaUsagePrivileges = 15,
126 adSchemaProcedures = 16,
127 adSchemaSchemata = 17,
128 adSchemaSQLLanguages = 18,
129 adSchemaStatistics = 19,
131 adSchemaTranslations = 21,
132 adSchemaProviderTypes = 22,
134 adSchemaViewColumnUsage = 24,
135 adSchemaViewTableUsage = 25,
136 adSchemaProcedureParameters = 26,
137 adSchemaForeignKeys = 27,
138 adSchemaPrimaryKeys = 28,
139 adSchemaProcedureColumns = 29,
140 adSchemaDBInfoKeywords = 30,
141 adSchemaDBInfoLiterals = 31,
143 adSchemaDimensions = 33,
144 adSchemaHierarchies = 34,
146 adSchemaMeasures = 36,
147 adSchemaProperties = 37,
152 function MetaTables($ttype = false, $showSchema = false, $mask = false)
155 $dbc = $this->_connectionID
;
157 $adors=@$dbc->OpenSchema(20);//tables
159 $f = $adors->Fields(2);//table/view name
160 $t = $adors->Fields(3);//table type
161 while (!$adors->EOF
){
162 $tt=substr($t->value
,0,6);
163 if ($tt!='SYSTEM' && $tt !='ACCESS')
165 //print $f->value . ' ' . $t->value.'<br>';
174 function MetaColumns($table, $normalize=true)
176 $table = strtoupper($table);
178 $dbc = $this->_connectionID
;
180 $adors=@$dbc->OpenSchema(4);//tables
183 $t = $adors->Fields(2);//table/view name
184 while (!$adors->EOF
){
187 if (strtoupper($t->Value
) == $table) {
189 $fld = new ADOFieldObject();
190 $c = $adors->Fields(3);
191 $fld->name
= $c->Value
;
192 $fld->type
= 'CHAR'; // cannot discover type in ADO!
193 $fld->max_length
= -1;
194 $arr[strtoupper($fld->name
)]=$fld;
202 return empty($arr) ?
$false : $arr;
208 /* returns queryID or false */
209 function _query($sql,$inputarr=false)
212 $dbc = $this->_connectionID
;
218 if (!empty($this->charPage
))
219 $oCmd = new COM('ADODB.Command',null,$this->charPage
);
221 $oCmd = new COM('ADODB.Command');
222 $oCmd->ActiveConnection
= $dbc;
223 $oCmd->CommandText
= $sql;
224 $oCmd->CommandType
= 1;
226 // Map by http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/mdmthcreateparam.asp
227 // Check issue http://bugs.php.net/bug.php?id=40664 !!!
228 while(list(, $val) = each($inputarr)) {
229 $type = gettype($val);
231 if ($type == 'boolean')
232 $this->adoParameterType
= 11;
233 else if ($type == 'integer')
234 $this->adoParameterType
= 3;
235 else if ($type == 'double')
236 $this->adoParameterType
= 5;
237 elseif ($type == 'string')
238 $this->adoParameterType
= 202;
239 else if (($val === null) ||
(!defined($val)))
242 $this->adoParameterType
= 130;
244 // name, type, direction 1 = input, len,
245 $p = $oCmd->CreateParameter('name',$this->adoParameterType
,1,$len,$val);
247 $oCmd->Parameters
->Append($p);
250 $rs = $oCmd->Execute();
252 if ($dbc->Errors
->Count
> 0) return $false;
256 $rs = @$dbc->Execute($sql,$this->_affectedRows
, $this->_execute_option
);
258 if ($dbc->Errors
->Count
> 0) return $false;
259 if (! $rs) return $false;
261 if ($rs->State
== 0) {
263 return $true; // 0 = adStateClosed means no records returned
269 function BeginTrans()
271 if ($this->transOff
) return true;
273 if (isset($this->_thisTransactions
))
274 if (!$this->_thisTransactions
) return false;
276 $o = $this->_connectionID
->Properties("Transaction DDL");
277 $this->_thisTransactions
= $o ?
true : false;
278 if (!$o) return false;
280 @$this->_connectionID
->BeginTrans();
281 $this->transCnt +
= 1;
285 function CommitTrans($ok=true)
287 if (!$ok) return $this->RollbackTrans();
288 if ($this->transOff
) return true;
290 @$this->_connectionID
->CommitTrans();
291 if ($this->transCnt
) @$this->transCnt
-= 1;
294 function RollbackTrans() {
295 if ($this->transOff
) return true;
296 @$this->_connectionID
->RollbackTrans();
297 if ($this->transCnt
) @$this->transCnt
-= 1;
301 /* Returns: the last error message from previous database operation */
305 if (!$this->_connectionID
) return "No connection established";
306 $errc = $this->_connectionID
->Errors
;
307 if (!$errc) return "No Errors object found";
308 if ($errc->Count
== 0) return '';
309 $err = $errc->Item($errc->Count
-1);
310 return $err->Description
;
315 $errc = $this->_connectionID
->Errors
;
316 if ($errc->Count
== 0) return 0;
317 $err = $errc->Item($errc->Count
-1);
318 return $err->NativeError
;
321 // returns true or false
324 if ($this->_connectionID
) $this->_connectionID
->Close();
325 $this->_connectionID
= false;
332 /*--------------------------------------------------------------------------------------
333 Class Name: Recordset
334 --------------------------------------------------------------------------------------*/
336 class ADORecordSet_ado
extends ADORecordSet
{
339 var $databaseType = "ado";
340 var $dataProvider = "ado";
341 var $_tarr = false; // caches the types
342 var $_flds; // and field objects
344 var $hideErrors = true;
346 function __construct($id,$mode=false)
348 if ($mode === false) {
349 global $ADODB_FETCH_MODE;
350 $mode = $ADODB_FETCH_MODE;
352 $this->fetchMode
= $mode;
353 return parent
::__construct($id,$mode);
357 // returns the field object
358 function FetchField($fieldOffset = -1) {
359 $off=$fieldOffset+
1; // offsets begin at 1
361 $o= new ADOFieldObject();
362 $rs = $this->_queryID
;
363 $f = $rs->Fields($fieldOffset);
366 $o->type
= $this->MetaType($t);
367 $o->max_length
= $f->DefinedSize
;
370 //print "off=$off name=$o->name type=$o->type len=$o->max_length<br>";
374 /* Use associative array to get fields array */
375 function Fields($colname)
377 if ($this->fetchMode
& ADODB_FETCH_ASSOC
) return $this->fields
[$colname];
379 $this->bind
= array();
380 for ($i=0; $i < $this->_numOfFields
; $i++
) {
381 $o = $this->FetchField($i);
382 $this->bind
[strtoupper($o->name
)] = $i;
386 return $this->fields
[$this->bind
[strtoupper($colname)]];
392 $rs = $this->_queryID
;
393 $this->_numOfRows
= $rs->RecordCount
;
396 $this->_numOfFields
= $f->Count
;
400 // should only be used to move forward as we normally use forward-only cursors
403 $rs = $this->_queryID
;
404 // absoluteposition doesn't work -- my maths is wrong ?
405 // $rs->AbsolutePosition->$row-2;
407 if ($this->_currentRow
> $row) return false;
408 @$rs->Move((integer)$row - $this->_currentRow
-1); //adBookmarkFirst
425 DBTYPE_IDISPATCH = 9,
429 DBTYPE_IUNKNOWN = 13,
432 DBTYPE_ARRAY = 0x2000,
433 DBTYPE_BYREF = 0x4000,
440 DBTYPE_VECTOR = 0x1000,
441 DBTYPE_RESERVED = 0x8000,
445 DBTYPE_NUMERIC = 131,
449 DBTYPE_DBTIMESTAMP = 135
458 adUnsignedTinyInt = 17,
459 adUnsignedSmallInt = 18,
461 adUnsignedBigInt = 21,
484 adLongVarWChar = 203,
487 adLongVarBinary = 205,
494 function MetaType($t,$len=-1,$fieldobj=false)
498 $t = $fieldobj->type
;
499 $len = $fieldobj->max_length
;
502 if (!is_numeric($t)) return $t;
515 if ($len <= $this->blobSize
) return 'C';
525 case 133: return 'D';
528 case 135: return 'T';
532 case 16:// adTinyInt = 16,
533 case 2://adSmallInt = 2,
534 case 3://adInteger = 3,
535 case 4://adBigInt = 20,
536 case 17://adUnsignedTinyInt = 17,
537 case 18://adUnsignedSmallInt = 18,
538 case 19://adUnsignedInt = 19,
539 case 20://adUnsignedBigInt = 21,
545 // time stamp not supported yet
548 $rs = $this->_queryID
;
549 if (!$rs or $rs->EOF
) {
550 $this->fields
= false;
553 $this->fields
= array();
558 for ($i=0,$max = $this->_numOfFields
; $i < $max; $i++
) {
559 $f = $rs->Fields($i);
563 // bind types and flds only once
564 $this->_tarr
= $tarr;
565 $this->_flds
= $flds;
567 $t = reset($this->_tarr
);
568 $f = reset($this->_flds
);
570 if ($this->hideErrors
) $olde = error_reporting(E_ERROR|E_CORE_ERROR
);// sometimes $f->value be null
571 for ($i=0,$max = $this->_numOfFields
; $i < $max; $i++
) {
572 //echo "<p>",$t,' ';var_dump($f->value); echo '</p>';
574 case 135: // timestamp
575 if (!strlen((string)$f->value
)) $this->fields
[] = false;
577 if (!is_numeric($f->value
)) # $val = variant_date_to_timestamp($f->value);
578 // VT_DATE stores dates as (float) fractional days since 1899/12/30 00:00:00
579 $val=(float) variant_cast($f->value
,VT_R8
)*3600*24-2209161600;
582 $this->fields
[] = adodb_date('Y-m-d H:i:s',$val);
585 case 133:// A date value (yyyymmdd)
586 if ($val = $f->value
) {
587 $this->fields
[] = substr($val,0,4).'-'.substr($val,4,2).'-'.substr($val,6,2);
589 $this->fields
[] = false;
592 if (!strlen((string)$f->value
)) $this->fields
[] = false;
594 if (!is_numeric($f->value
)) $val = variant_date_to_timestamp($f->value
);
595 else $val = $f->value
;
597 if (($val %
86400) == 0) $this->fields
[] = adodb_date('Y-m-d',$val);
598 else $this->fields
[] = adodb_date('Y-m-d H:i:s',$val);
602 $this->fields
[] = false;
604 case 6: // currency is not supported properly;
605 ADOConnection
::outp( '<b>'.$f->Name
.': currency type not supported by PHP</b>');
606 $this->fields
[] = (float) $f->value
;
610 if(is_bool($f->value
)) {
611 if($f->value
==true) $val = 1;
614 if(is_null($f->value
)) $val = null;
616 $this->fields
[] = $val;
619 $this->fields
[] = $f->value
;
622 //print " $f->value $t, ";
623 $f = next($this->_flds
);
624 $t = next($this->_tarr
);
626 if ($this->hideErrors
) error_reporting($olde);
627 @$rs->MoveNext(); // @ needed for some versions of PHP!
629 if ($this->fetchMode
& ADODB_FETCH_ASSOC
) {
630 $this->fields
= $this->GetRowAssoc();
635 function NextRecordSet()
637 $rs = $this->_queryID
;
638 $this->_queryID
= $rs->NextRecordSet();
639 //$this->_queryID = $this->_QueryId->NextRecordSet();
640 if ($this->_queryID
== null) return false;
642 $this->_currentRow
= -1;
643 $this->_currentPage
= -1;
645 $this->fields
= false;
646 $this->_flds
= false;
647 $this->_tarr
= false;
649 $this->_inited
= false;
655 $this->_flds
= false;
656 @$this->_queryID
->Close();// by Pete Dishman (peterd@telephonetics.co.uk)
657 $this->_queryID
= false;