EOL standardization fixes
[openemr.git] / library / adodb / drivers / adodb-ado.inc.php
blob68ea5056abd7e59b9afe4c1237b2e723da941adb
1 <?php
2 /*
3 V4.20 22 Feb 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.
7 Set tabs to 4 for best viewing.
9 Latest version is available at http://php.weblogs.com/
11 Microsoft ADO data driver. Requires ADO. Works only on MS Windows.
13 define("_ADODB_ADO_LAYER", 1 );
14 /*--------------------------------------------------------------------------------------
15 --------------------------------------------------------------------------------------*/
17 class ADODB_ado extends ADOConnection {
18 var $databaseType = "ado";
19 var $_bindInputArray = false;
20 var $fmtDate = "'Y-m-d'";
21 var $fmtTimeStamp = "'Y-m-d, h:i:sA'";
22 var $replaceQuote = "''"; // string to use to replace quotes
23 var $dataProvider = "ado";
24 var $hasAffectedRows = true;
25 var $adoParameterType = 201; // 201 = long varchar, 203=long wide varchar, 205 = long varbinary
26 var $_affectedRows = false;
27 var $_thisTransactions;
28 var $_cursor_type = 3; // 3=adOpenStatic,0=adOpenForwardOnly,1=adOpenKeyset,2=adOpenDynamic
29 var $_cursor_location = 3; // 2=adUseServer, 3 = adUseClient;
30 var $_lock_type = -1;
31 var $_execute_option = -1;
32 var $poorAffectedRows = true;
33 var $charPage;
35 function ADODB_ado()
37 $this->_affectedRows = new VARIANT;
40 function ServerInfo()
42 if (!empty($this->_connectionID)) $desc = $this->_connectionID->provider;
43 return array('description' => $desc, 'version' => '');
46 function _affectedrows()
48 return $this->_affectedRows->value;
51 // you can also pass a connection string like this:
53 // $DB->Connect('USER ID=sa;PASSWORD=pwd;SERVER=mangrove;DATABASE=ai',false,false,'SQLOLEDB');
54 function _connect($argHostname, $argUsername, $argPassword, $argProvider= 'MSDASQL')
56 $u = 'UID';
57 $p = 'PWD';
59 if (!empty($this->charPage))
60 $dbc = new COM('ADODB.Connection',null,$this->charPage);
61 else
62 $dbc = new COM('ADODB.Connection');
64 if (! $dbc) return false;
66 /* special support if provider is mssql or access */
67 if ($argProvider=='mssql') {
68 $u = 'User Id'; //User parameter name for OLEDB
69 $p = 'Password';
70 $argProvider = "SQLOLEDB"; // SQL Server Provider
72 // not yet
73 //if ($argDatabasename) $argHostname .= ";Initial Catalog=$argDatabasename";
75 //use trusted conection for SQL if username not specified
76 if (!$argUsername) $argHostname .= ";Trusted_Connection=Yes";
77 } else if ($argProvider=='access')
78 $argProvider = "Microsoft.Jet.OLEDB.4.0"; // Microsoft Jet Provider
80 if ($argProvider) $dbc->Provider = $argProvider;
82 if ($argUsername) $argHostname .= ";$u=$argUsername";
83 if ($argPassword)$argHostname .= ";$p=$argPassword";
85 if ($this->debug) ADOConnection::outp( "Host=".$argHostname."<BR>\n version=$dbc->version");
86 // @ added below for php 4.0.1 and earlier
87 @$dbc->Open((string) $argHostname);
89 $this->_connectionID = $dbc;
91 $dbc->CursorLocation = $this->_cursor_location;
92 return $dbc->State > 0;
95 // returns true or false
96 function _pconnect($argHostname, $argUsername, $argPassword, $argProvider='MSDASQL')
98 return $this->_connect($argHostname,$argUsername,$argPassword,$argProvider);
102 adSchemaCatalogs = 1,
103 adSchemaCharacterSets = 2,
104 adSchemaCollations = 3,
105 adSchemaColumns = 4,
106 adSchemaCheckConstraints = 5,
107 adSchemaConstraintColumnUsage = 6,
108 adSchemaConstraintTableUsage = 7,
109 adSchemaKeyColumnUsage = 8,
110 adSchemaReferentialContraints = 9,
111 adSchemaTableConstraints = 10,
112 adSchemaColumnsDomainUsage = 11,
113 adSchemaIndexes = 12,
114 adSchemaColumnPrivileges = 13,
115 adSchemaTablePrivileges = 14,
116 adSchemaUsagePrivileges = 15,
117 adSchemaProcedures = 16,
118 adSchemaSchemata = 17,
119 adSchemaSQLLanguages = 18,
120 adSchemaStatistics = 19,
121 adSchemaTables = 20,
122 adSchemaTranslations = 21,
123 adSchemaProviderTypes = 22,
124 adSchemaViews = 23,
125 adSchemaViewColumnUsage = 24,
126 adSchemaViewTableUsage = 25,
127 adSchemaProcedureParameters = 26,
128 adSchemaForeignKeys = 27,
129 adSchemaPrimaryKeys = 28,
130 adSchemaProcedureColumns = 29,
131 adSchemaDBInfoKeywords = 30,
132 adSchemaDBInfoLiterals = 31,
133 adSchemaCubes = 32,
134 adSchemaDimensions = 33,
135 adSchemaHierarchies = 34,
136 adSchemaLevels = 35,
137 adSchemaMeasures = 36,
138 adSchemaProperties = 37,
139 adSchemaMembers = 38
143 function &MetaTables()
145 $arr= array();
146 $dbc = $this->_connectionID;
148 $adors=@$dbc->OpenSchema(20);//tables
149 if ($adors){
150 $f = $adors->Fields(2);//table/view name
151 $t = $adors->Fields(3);//table type
152 while (!$adors->EOF){
153 $tt=substr($t->value,0,6);
154 if ($tt!='SYSTEM' && $tt !='ACCESS')
155 $arr[]=$f->value;
156 //print $f->value . ' ' . $t->value.'<br>';
157 $adors->MoveNext();
159 $adors->Close();
162 return $arr;
165 function &MetaColumns($table)
167 $table = strtoupper($table);
168 $arr= array();
169 $dbc = $this->_connectionID;
171 $adors=@$dbc->OpenSchema(4);//tables
173 if ($adors){
174 $t = $adors->Fields(2);//table/view name
175 while (!$adors->EOF){
178 if (strtoupper($t->Value) == $table) {
180 $fld = new ADOFieldObject();
181 $c = $adors->Fields(3);
182 $fld->name = $c->Value;
183 $fld->type = 'CHAR'; // cannot discover type in ADO!
184 $fld->max_length = -1;
185 $arr[strtoupper($fld->name)]=$fld;
188 $adors->MoveNext();
190 $adors->Close();
193 return $arr;
199 /* returns queryID or false */
200 function &_query($sql,$inputarr=false)
203 $dbc = $this->_connectionID;
205 // return rs
206 if ($inputarr) {
208 if (!empty($this->charPage))
209 $oCmd = new COM('ADODB.Command',null,$this->charPage);
210 else
211 $oCmd = new COM('ADODB.Command');
212 $oCmd->ActiveConnection = $dbc;
213 $oCmd->CommandText = $sql;
214 $oCmd->CommandType = 1;
216 foreach($inputarr as $val) {
217 // name, type, direction 1 = input, len,
218 $this->adoParameterType = 130;
219 $p = $oCmd->CreateParameter('name',$this->adoParameterType,1,strlen($val),$val);
220 //print $p->Type.' '.$p->value;
221 $oCmd->Parameters->Append($p);
223 $p = false;
224 $rs = $oCmd->Execute();
225 $e = $dbc->Errors;
226 if ($dbc->Errors->Count > 0) return false;
227 return $rs;
230 $rs = @$dbc->Execute($sql,$this->_affectedRows, $this->_execute_option);
232 $rs = new COM('ADODB.Recordset');
233 if ($rs) {
234 $rs->Open ($sql, $dbc, $this->_cursor_type,$this->_lock_type, $this->_execute_option);
237 if ($dbc->Errors->Count > 0) return false;
238 if (! $rs) return false;
240 if ($rs->State == 0) return true; // 0 = adStateClosed means no records returned
241 return $rs;
245 function BeginTrans()
247 if ($this->transOff) return true;
249 if (isset($this->_thisTransactions))
250 if (!$this->_thisTransactions) return false;
251 else {
252 $o = $this->_connectionID->Properties("Transaction DDL");
253 $this->_thisTransactions = $o ? true : false;
254 if (!$o) return false;
256 @$this->_connectionID->BeginTrans();
257 $this->transCnt += 1;
258 return true;
260 function CommitTrans($ok=true)
262 if (!$ok) return $this->RollbackTrans();
263 if ($this->transOff) return true;
265 @$this->_connectionID->CommitTrans();
266 if ($this->transCnt) @$this->transCnt -= 1;
267 return true;
269 function RollbackTrans() {
270 if ($this->transOff) return true;
271 @$this->_connectionID->RollbackTrans();
272 if ($this->transCnt) @$this->transCnt -= 1;
273 return true;
276 /* Returns: the last error message from previous database operation */
278 function ErrorMsg()
280 $errc = $this->_connectionID->Errors;
281 if ($errc->Count == 0) return '';
282 $err = $errc->Item($errc->Count-1);
283 return $err->Description;
286 function ErrorNo()
288 $errc = $this->_connectionID->Errors;
289 if ($errc->Count == 0) return 0;
290 $err = $errc->Item($errc->Count-1);
291 return $err->NativeError;
294 // returns true or false
295 function _close()
297 if ($this->_connectionID) $this->_connectionID->Close();
298 $this->_connectionID = false;
299 return true;
305 /*--------------------------------------------------------------------------------------
306 Class Name: Recordset
307 --------------------------------------------------------------------------------------*/
309 class ADORecordSet_ado extends ADORecordSet {
311 var $bind = false;
312 var $databaseType = "ado";
313 var $dataProvider = "ado";
314 var $_tarr = false; // caches the types
315 var $_flds; // and field objects
316 var $canSeek = true;
317 var $hideErrors = true;
319 function ADORecordSet_ado($id,$mode=false)
321 if ($mode === false) {
322 global $ADODB_FETCH_MODE;
323 $mode = $ADODB_FETCH_MODE;
325 $this->fetchMode = $mode;
326 return $this->ADORecordSet($id,$mode);
330 // returns the field object
331 function FetchField($fieldOffset = -1) {
332 $off=$fieldOffset+1; // offsets begin at 1
334 $o= new ADOFieldObject();
335 $rs = $this->_queryID;
336 $f = $rs->Fields($fieldOffset);
337 $o->name = $f->Name;
338 $t = $f->Type;
339 $o->type = $this->MetaType($t);
340 $o->max_length = $f->DefinedSize;
341 $o->ado_type = $t;
344 //print "off=$off name=$o->name type=$o->type len=$o->max_length<br>";
345 return $o;
348 /* Use associative array to get fields array */
349 function Fields($colname)
351 if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
352 if (!$this->bind) {
353 $this->bind = array();
354 for ($i=0; $i < $this->_numOfFields; $i++) {
355 $o = $this->FetchField($i);
356 $this->bind[strtoupper($o->name)] = $i;
360 return $this->fields[$this->bind[strtoupper($colname)]];
364 function _initrs()
366 $rs = $this->_queryID;
367 $this->_numOfRows = $rs->RecordCount;
369 $f = $rs->Fields;
370 $this->_numOfFields = $f->Count;
374 // should only be used to move forward as we normally use forward-only cursors
375 function _seek($row)
377 $rs = $this->_queryID;
378 // absoluteposition doesn't work -- my maths is wrong ?
379 // $rs->AbsolutePosition->$row-2;
380 // return true;
381 if ($this->_currentRow > $row) return false;
382 @$rs->Move((integer)$row - $this->_currentRow-1); //adBookmarkFirst
383 return true;
387 OLEDB types
389 enum DBTYPEENUM
390 { DBTYPE_EMPTY = 0,
391 DBTYPE_NULL = 1,
392 DBTYPE_I2 = 2,
393 DBTYPE_I4 = 3,
394 DBTYPE_R4 = 4,
395 DBTYPE_R8 = 5,
396 DBTYPE_CY = 6,
397 DBTYPE_DATE = 7,
398 DBTYPE_BSTR = 8,
399 DBTYPE_IDISPATCH = 9,
400 DBTYPE_ERROR = 10,
401 DBTYPE_BOOL = 11,
402 DBTYPE_VARIANT = 12,
403 DBTYPE_IUNKNOWN = 13,
404 DBTYPE_DECIMAL = 14,
405 DBTYPE_UI1 = 17,
406 DBTYPE_ARRAY = 0x2000,
407 DBTYPE_BYREF = 0x4000,
408 DBTYPE_I1 = 16,
409 DBTYPE_UI2 = 18,
410 DBTYPE_UI4 = 19,
411 DBTYPE_I8 = 20,
412 DBTYPE_UI8 = 21,
413 DBTYPE_GUID = 72,
414 DBTYPE_VECTOR = 0x1000,
415 DBTYPE_RESERVED = 0x8000,
416 DBTYPE_BYTES = 128,
417 DBTYPE_STR = 129,
418 DBTYPE_WSTR = 130,
419 DBTYPE_NUMERIC = 131,
420 DBTYPE_UDT = 132,
421 DBTYPE_DBDATE = 133,
422 DBTYPE_DBTIME = 134,
423 DBTYPE_DBTIMESTAMP = 135
425 ADO Types
427 adEmpty = 0,
428 adTinyInt = 16,
429 adSmallInt = 2,
430 adInteger = 3,
431 adBigInt = 20,
432 adUnsignedTinyInt = 17,
433 adUnsignedSmallInt = 18,
434 adUnsignedInt = 19,
435 adUnsignedBigInt = 21,
436 adSingle = 4,
437 adDouble = 5,
438 adCurrency = 6,
439 adDecimal = 14,
440 adNumeric = 131,
441 adBoolean = 11,
442 adError = 10,
443 adUserDefined = 132,
444 adVariant = 12,
445 adIDispatch = 9,
446 adIUnknown = 13,
447 adGUID = 72,
448 adDate = 7,
449 adDBDate = 133,
450 adDBTime = 134,
451 adDBTimeStamp = 135,
452 adBSTR = 8,
453 adChar = 129,
454 adVarChar = 200,
455 adLongVarChar = 201,
456 adWChar = 130,
457 adVarWChar = 202,
458 adLongVarWChar = 203,
459 adBinary = 128,
460 adVarBinary = 204,
461 adLongVarBinary = 205,
462 adChapter = 136,
463 adFileTime = 64,
464 adDBFileTime = 137,
465 adPropVariant = 138,
466 adVarNumeric = 139
468 function MetaType($t,$len=-1,$fieldobj=false)
470 if (is_object($t)) {
471 $fieldobj = $t;
472 $t = $fieldobj->type;
473 $len = $fieldobj->max_length;
476 if (!is_numeric($t)) return $t;
478 switch ($t) {
479 case 0:
480 case 12: // variant
481 case 8: // bstr
482 case 129: //char
483 case 130: //wc
484 case 200: // varc
485 case 202:// varWC
486 case 128: // bin
487 case 204: // varBin
488 case 72: // guid
489 if ($len <= $this->blobSize) return 'C';
491 case 201:
492 case 203:
493 return 'X';
494 case 128:
495 case 204:
496 case 205:
497 return 'B';
498 case 7:
499 case 133: return 'D';
501 case 134:
502 case 135: return 'T';
504 case 11: return 'L';
506 case 16:// adTinyInt = 16,
507 case 2://adSmallInt = 2,
508 case 3://adInteger = 3,
509 case 4://adBigInt = 20,
510 case 17://adUnsignedTinyInt = 17,
511 case 18://adUnsignedSmallInt = 18,
512 case 19://adUnsignedInt = 19,
513 case 20://adUnsignedBigInt = 21,
514 return 'I';
515 default: return 'N';
519 // time stamp not supported yet
520 function _fetch()
522 $rs = $this->_queryID;
523 if (!$rs or $rs->EOF) {
524 $this->fields = false;
525 return false;
527 $this->fields = array();
529 if (!$this->_tarr) {
530 $tarr = array();
531 $flds = array();
532 for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) {
533 $f = $rs->Fields($i);
534 $flds[] = $f;
535 $tarr[] = $f->Type;
537 // bind types and flds only once
538 $this->_tarr = $tarr;
539 $this->_flds = $flds;
541 $t = reset($this->_tarr);
542 $f = reset($this->_flds);
544 if ($this->hideErrors) $olde = error_reporting(E_ERROR|E_CORE_ERROR);// sometimes $f->value be null
545 for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) {
547 switch($t) {
548 case 135: // timestamp
549 if (!strlen((string)$f->value)) $this->fields[] = false;
550 else $this->fields[] = adodb_date('Y-m-d H:i:s',(float)$f->value);
551 break;
552 case 133:// A date value (yyyymmdd)
553 if ($val = $f->value) {
554 $this->fields[] = substr($val,0,4).'-'.substr($val,4,2).'-'.substr($val,6,2);
555 } else
556 $this->fields[] = false;
557 break;
558 case 7: // adDate
559 if (!strlen((string)$f->value)) $this->fields[] = false;
560 else $this->fields[] = adodb_date('Y-m-d',(float)$f->value);
561 break;
562 case 1: // null
563 $this->fields[] = false;
564 break;
565 case 6: // currency is not supported properly;
566 ADOConnection::outp( '<b>'.$f->Name.': currency type not supported by PHP</b>');
567 $this->fields[] = (float) $f->value;
568 break;
569 default:
570 $this->fields[] = $f->value;
571 break;
573 //print " $f->value $t, ";
574 $f = next($this->_flds);
575 $t = next($this->_tarr);
576 } // for
577 if ($this->hideErrors) error_reporting($olde);
578 @$rs->MoveNext(); // @ needed for some versions of PHP!
580 if ($this->fetchMode & ADODB_FETCH_ASSOC) {
581 $this->fields = &$this->GetRowAssoc(ADODB_ASSOC_CASE);
583 return true;
586 function NextRecordSet()
588 $rs = $this->_queryID;
589 $this->_queryID = $rs->NextRecordSet();
590 //$this->_queryID = $this->_QueryId->NextRecordSet();
591 if ($this->_queryID == null) return false;
593 $this->_currentRow = -1;
594 $this->_currentPage = -1;
595 $this->bind = false;
596 $this->fields = false;
597 $this->_flds = false;
598 $this->_tarr = false;
600 $this->_inited = false;
601 $this->Init();
602 return true;
605 function _close() {
606 $this->_flds = false;
607 @$this->_queryID->Close();// by Pete Dishman (peterd@telephonetics.co.uk)
608 $this->_queryID = false;