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