source: moodle/trunk/fuentes/lib/adodb/drivers/adodb-ado.inc.php @ 1331

Last change on this file since 1331 was 1331, checked in by jrpelegrina, 3 years ago

Updated to moodle 3.0.3

File size: 15.9 KB
Line 
1<?php
2/*
3@version   v5.20.1  06-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.
9Set 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.
14*/
15
16// security - hide paths
17if (!defined('ADODB_DIR')) die();
18
19define("_ADODB_ADO_LAYER", 1 );
20/*--------------------------------------------------------------------------------------
21--------------------------------------------------------------------------------------*/
22
23
24class 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;
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, $argProvider= 'MSDASQL')
64        {
65                $u = 'UID';
66                $p = 'PWD';
67
68                if (!empty($this->charPage))
69                        $dbc = new COM('ADODB.Connection',null,$this->charPage);
70                else
71                        $dbc = new COM('ADODB.Connection');
72
73                if (! $dbc) return false;
74
75                /* special support if provider is mssql or access */
76                if ($argProvider=='mssql') {
77                        $u = 'User Id';  //User parameter name for OLEDB
78                        $p = 'Password';
79                        $argProvider = "SQLOLEDB"; // SQL Server Provider
80
81                        // not yet
82                        //if ($argDatabasename) $argHostname .= ";Initial Catalog=$argDatabasename";
83
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
88
89                if ($argProvider) $dbc->Provider = $argProvider;
90
91                if ($argUsername) $argHostname .= ";$u=$argUsername";
92                if ($argPassword)$argHostname .= ";$p=$argPassword";
93
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);
97
98                $this->_connectionID = $dbc;
99
100                $dbc->CursorLocation = $this->_cursor_location;
101                return  $dbc->State > 0;
102        }
103
104        // returns true or false
105        function _pconnect($argHostname, $argUsername, $argPassword, $argProvider='MSDASQL')
106        {
107                return $this->_connect($argHostname,$argUsername,$argPassword,$argProvider);
108        }
109
110/*
111        adSchemaCatalogs        = 1,
112        adSchemaCharacterSets   = 2,
113        adSchemaCollations      = 3,
114        adSchemaColumns = 4,
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,
130        adSchemaTables  = 20,
131        adSchemaTranslations    = 21,
132        adSchemaProviderTypes   = 22,
133        adSchemaViews   = 23,
134        adSchemaViewColumnUsage = 24,
135        adSchemaViewTableUsage  = 25,
136        adSchemaProcedureParameters     = 26,
137        adSchemaForeignKeys     = 27,
138        adSchemaPrimaryKeys     = 28,
139        adSchemaProcedureColumns        = 29,
140        adSchemaDBInfoKeywords  = 30,
141        adSchemaDBInfoLiterals  = 31,
142        adSchemaCubes   = 32,
143        adSchemaDimensions      = 33,
144        adSchemaHierarchies     = 34,
145        adSchemaLevels  = 35,
146        adSchemaMeasures        = 36,
147        adSchemaProperties      = 37,
148        adSchemaMembers = 38
149
150*/
151
152        function MetaTables($ttype = false, $showSchema = false, $mask = false)
153        {
154                $arr= array();
155                $dbc = $this->_connectionID;
156
157                $adors=@$dbc->OpenSchema(20);//tables
158                if ($adors){
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')
164                                        $arr[]=$f->value;
165                                //print $f->value . ' ' . $t->value.'<br>';
166                                $adors->MoveNext();
167                        }
168                        $adors->Close();
169                }
170
171                return $arr;
172        }
173
174        function MetaColumns($table, $normalize=true)
175        {
176                $table = strtoupper($table);
177                $arr = array();
178                $dbc = $this->_connectionID;
179
180                $adors=@$dbc->OpenSchema(4);//tables
181
182                if ($adors){
183                        $t = $adors->Fields(2);//table/view name
184                        while (!$adors->EOF){
185
186
187                                if (strtoupper($t->Value) == $table) {
188
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;
195                                }
196
197                                $adors->MoveNext();
198                        }
199                        $adors->Close();
200                }
201                $false = false;
202                return empty($arr) ? $false : $arr;
203        }
204
205
206
207
208        /* returns queryID or false */
209        function _query($sql,$inputarr=false)
210        {
211
212                $dbc = $this->_connectionID;
213                $false = false;
214
215        //      return rs
216                if ($inputarr) {
217
218                        if (!empty($this->charPage))
219                                $oCmd = new COM('ADODB.Command',null,$this->charPage);
220                        else
221                                $oCmd = new COM('ADODB.Command');
222                        $oCmd->ActiveConnection = $dbc;
223                        $oCmd->CommandText = $sql;
224                        $oCmd->CommandType = 1;
225
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);
230                                $len=strlen($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)))
240                                        $len=1;
241                                else
242                                        $this->adoParameterType = 130;
243
244                                // name, type, direction 1 = input, len,
245                        $p = $oCmd->CreateParameter('name',$this->adoParameterType,1,$len,$val);
246
247                                $oCmd->Parameters->Append($p);
248                        }
249                        $p = false;
250                        $rs = $oCmd->Execute();
251                        $e = $dbc->Errors;
252                        if ($dbc->Errors->Count > 0) return $false;
253                        return $rs;
254                }
255
256                $rs = @$dbc->Execute($sql,$this->_affectedRows, $this->_execute_option);
257
258                if ($dbc->Errors->Count > 0) return $false;
259                if (! $rs) return $false;
260
261                if ($rs->State == 0) {
262                        $true = true;
263                        return $true; // 0 = adStateClosed means no records returned
264                }
265                return $rs;
266        }
267
268
269        function BeginTrans()
270        {
271                if ($this->transOff) return true;
272
273                if (isset($this->_thisTransactions))
274                        if (!$this->_thisTransactions) return false;
275                else {
276                        $o = $this->_connectionID->Properties("Transaction DDL");
277                        $this->_thisTransactions = $o ? true : false;
278                        if (!$o) return false;
279                }
280                @$this->_connectionID->BeginTrans();
281                $this->transCnt += 1;
282                return true;
283        }
284
285        function CommitTrans($ok=true)
286        {
287                if (!$ok) return $this->RollbackTrans();
288                if ($this->transOff) return true;
289
290                @$this->_connectionID->CommitTrans();
291                if ($this->transCnt) @$this->transCnt -= 1;
292                return true;
293        }
294        function RollbackTrans() {
295                if ($this->transOff) return true;
296                @$this->_connectionID->RollbackTrans();
297                if ($this->transCnt) @$this->transCnt -= 1;
298                return true;
299        }
300
301        /*      Returns: the last error message from previous database operation        */
302
303        function ErrorMsg()
304        {
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;
311        }
312
313        function ErrorNo()
314        {
315                $errc = $this->_connectionID->Errors;
316                if ($errc->Count == 0) return 0;
317                $err = $errc->Item($errc->Count-1);
318                return $err->NativeError;
319        }
320
321        // returns true or false
322        function _close()
323        {
324                if ($this->_connectionID) $this->_connectionID->Close();
325                $this->_connectionID = false;
326                return true;
327        }
328
329
330}
331
332/*--------------------------------------------------------------------------------------
333         Class Name: Recordset
334--------------------------------------------------------------------------------------*/
335
336class ADORecordSet_ado extends ADORecordSet {
337
338        var $bind = false;
339        var $databaseType = "ado";
340        var $dataProvider = "ado";
341        var $_tarr = false; // caches the types
342        var $_flds; // and field objects
343        var $canSeek = true;
344        var $hideErrors = true;
345
346        function __construct($id,$mode=false)
347        {
348                if ($mode === false) {
349                        global $ADODB_FETCH_MODE;
350                        $mode = $ADODB_FETCH_MODE;
351                }
352                $this->fetchMode = $mode;
353                return parent::__construct($id,$mode);
354        }
355
356
357        // returns the field object
358        function FetchField($fieldOffset = -1) {
359                $off=$fieldOffset+1; // offsets begin at 1
360
361                $o= new ADOFieldObject();
362                $rs = $this->_queryID;
363                $f = $rs->Fields($fieldOffset);
364                $o->name = $f->Name;
365                $t = $f->Type;
366                $o->type = $this->MetaType($t);
367                $o->max_length = $f->DefinedSize;
368                $o->ado_type = $t;
369
370                //print "off=$off name=$o->name type=$o->type len=$o->max_length<br>";
371                return $o;
372        }
373
374        /* Use associative array to get fields array */
375        function Fields($colname)
376        {
377                if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
378                if (!$this->bind) {
379                        $this->bind = array();
380                        for ($i=0; $i < $this->_numOfFields; $i++) {
381                                $o = $this->FetchField($i);
382                                $this->bind[strtoupper($o->name)] = $i;
383                        }
384                }
385
386                 return $this->fields[$this->bind[strtoupper($colname)]];
387        }
388
389
390        function _initrs()
391        {
392                $rs = $this->_queryID;
393                $this->_numOfRows = $rs->RecordCount;
394
395                $f = $rs->Fields;
396                $this->_numOfFields = $f->Count;
397        }
398
399
400         // should only be used to move forward as we normally use forward-only cursors
401        function _seek($row)
402        {
403           $rs = $this->_queryID;
404                // absoluteposition doesn't work -- my maths is wrong ?
405                //      $rs->AbsolutePosition->$row-2;
406                //      return true;
407                if ($this->_currentRow > $row) return false;
408                @$rs->Move((integer)$row - $this->_currentRow-1); //adBookmarkFirst
409                return true;
410        }
411
412/*
413        OLEDB types
414
415         enum DBTYPEENUM
416        {       DBTYPE_EMPTY    = 0,
417        DBTYPE_NULL     = 1,
418        DBTYPE_I2       = 2,
419        DBTYPE_I4       = 3,
420        DBTYPE_R4       = 4,
421        DBTYPE_R8       = 5,
422        DBTYPE_CY       = 6,
423        DBTYPE_DATE     = 7,
424        DBTYPE_BSTR     = 8,
425        DBTYPE_IDISPATCH        = 9,
426        DBTYPE_ERROR    = 10,
427        DBTYPE_BOOL     = 11,
428        DBTYPE_VARIANT  = 12,
429        DBTYPE_IUNKNOWN = 13,
430        DBTYPE_DECIMAL  = 14,
431        DBTYPE_UI1      = 17,
432        DBTYPE_ARRAY    = 0x2000,
433        DBTYPE_BYREF    = 0x4000,
434        DBTYPE_I1       = 16,
435        DBTYPE_UI2      = 18,
436        DBTYPE_UI4      = 19,
437        DBTYPE_I8       = 20,
438        DBTYPE_UI8      = 21,
439        DBTYPE_GUID     = 72,
440        DBTYPE_VECTOR   = 0x1000,
441        DBTYPE_RESERVED = 0x8000,
442        DBTYPE_BYTES    = 128,
443        DBTYPE_STR      = 129,
444        DBTYPE_WSTR     = 130,
445        DBTYPE_NUMERIC  = 131,
446        DBTYPE_UDT      = 132,
447        DBTYPE_DBDATE   = 133,
448        DBTYPE_DBTIME   = 134,
449        DBTYPE_DBTIMESTAMP      = 135
450
451        ADO Types
452
453        adEmpty = 0,
454        adTinyInt       = 16,
455        adSmallInt      = 2,
456        adInteger       = 3,
457        adBigInt        = 20,
458        adUnsignedTinyInt       = 17,
459        adUnsignedSmallInt      = 18,
460        adUnsignedInt   = 19,
461        adUnsignedBigInt        = 21,
462        adSingle        = 4,
463        adDouble        = 5,
464        adCurrency      = 6,
465        adDecimal       = 14,
466        adNumeric       = 131,
467        adBoolean       = 11,
468        adError = 10,
469        adUserDefined   = 132,
470        adVariant       = 12,
471        adIDispatch     = 9,
472        adIUnknown      = 13,
473        adGUID  = 72,
474        adDate  = 7,
475        adDBDate        = 133,
476        adDBTime        = 134,
477        adDBTimeStamp   = 135,
478        adBSTR  = 8,
479        adChar  = 129,
480        adVarChar       = 200,
481        adLongVarChar   = 201,
482        adWChar = 130,
483        adVarWChar      = 202,
484        adLongVarWChar  = 203,
485        adBinary        = 128,
486        adVarBinary     = 204,
487        adLongVarBinary = 205,
488        adChapter       = 136,
489        adFileTime      = 64,
490        adDBFileTime    = 137,
491        adPropVariant   = 138,
492        adVarNumeric    = 139
493*/
494        function MetaType($t,$len=-1,$fieldobj=false)
495        {
496                if (is_object($t)) {
497                        $fieldobj = $t;
498                        $t = $fieldobj->type;
499                        $len = $fieldobj->max_length;
500                }
501
502                if (!is_numeric($t)) return $t;
503
504                switch ($t) {
505                case 0:
506                case 12: // variant
507                case 8: // bstr
508                case 129: //char
509                case 130: //wc
510                case 200: // varc
511                case 202:// varWC
512                case 128: // bin
513                case 204: // varBin
514                case 72: // guid
515                        if ($len <= $this->blobSize) return 'C';
516
517                case 201:
518                case 203:
519                        return 'X';
520                case 128:
521                case 204:
522                case 205:
523                         return 'B';
524                case 7:
525                case 133: return 'D';
526
527                case 134:
528                case 135: return 'T';
529
530                case 11: return 'L';
531
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,
540                        return 'I';
541                default: return 'N';
542                }
543        }
544
545        // time stamp not supported yet
546        function _fetch()
547        {
548                $rs = $this->_queryID;
549                if (!$rs or $rs->EOF) {
550                        $this->fields = false;
551                        return false;
552                }
553                $this->fields = array();
554
555                if (!$this->_tarr) {
556                        $tarr = array();
557                        $flds = array();
558                        for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) {
559                                $f = $rs->Fields($i);
560                                $flds[] = $f;
561                                $tarr[] = $f->Type;
562                        }
563                        // bind types and flds only once
564                        $this->_tarr = $tarr;
565                        $this->_flds = $flds;
566                }
567                $t = reset($this->_tarr);
568                $f = reset($this->_flds);
569
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>';
573                        switch($t) {
574                        case 135: // timestamp
575                                if (!strlen((string)$f->value)) $this->fields[] = false;
576                                else {
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;
580                                        else
581                                                $val = $f->value;
582                                        $this->fields[] = adodb_date('Y-m-d H:i:s',$val);
583                                }
584                                break;
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);
588                                } else
589                                        $this->fields[] = false;
590                                break;
591                        case 7: // adDate
592                                if (!strlen((string)$f->value)) $this->fields[] = false;
593                                else {
594                                        if (!is_numeric($f->value)) $val = variant_date_to_timestamp($f->value);
595                                        else $val = $f->value;
596
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);
599                                }
600                                break;
601                        case 1: // null
602                                $this->fields[] = false;
603                                break;
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;
607                                break;
608                        case 11: //BIT;
609                                $val = "";
610                                if(is_bool($f->value))  {
611                                        if($f->value==true) $val = 1;
612                                        else $val = 0;
613                                }
614                                if(is_null($f->value)) $val = null;
615
616                                $this->fields[] = $val;
617                                break;
618                        default:
619                                $this->fields[] = $f->value;
620                                break;
621                        }
622                        //print " $f->value $t, ";
623                        $f = next($this->_flds);
624                        $t = next($this->_tarr);
625                } // for
626                if ($this->hideErrors) error_reporting($olde);
627                @$rs->MoveNext(); // @ needed for some versions of PHP!
628
629                if ($this->fetchMode & ADODB_FETCH_ASSOC) {
630                        $this->fields = $this->GetRowAssoc();
631                }
632                return true;
633        }
634
635                function NextRecordSet()
636                {
637                        $rs = $this->_queryID;
638                        $this->_queryID = $rs->NextRecordSet();
639                        //$this->_queryID = $this->_QueryId->NextRecordSet();
640                        if ($this->_queryID == null) return false;
641
642                        $this->_currentRow = -1;
643                        $this->_currentPage = -1;
644                        $this->bind = false;
645                        $this->fields = false;
646                        $this->_flds = false;
647                        $this->_tarr = false;
648
649                        $this->_inited = false;
650                        $this->Init();
651                        return true;
652                }
653
654        function _close() {
655                $this->_flds = false;
656                @$this->_queryID->Close();// by Pete Dishman (peterd@telephonetics.co.uk)
657                $this->_queryID = false;
658        }
659
660}
Note: See TracBrowser for help on using the repository browser.