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