Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]

   1  <?php
   2  /**
   3   * Microsoft ADO driver (PHP5 compat version).
   4   *
   5   * Requires ADO. Works only on MS Windows.
   6   *
   7   * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
   8   *
   9   * @package ADOdb
  10   * @link https://adodb.org Project's web site and documentation
  11   * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
  12   *
  13   * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
  14   * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
  15   * any later version. This means you can use it in proprietary products.
  16   * See the LICENSE.md file distributed with this source code for details.
  17   * @license BSD-3-Clause
  18   * @license LGPL-2.1-or-later
  19   *
  20   * @copyright 2000-2013 John Lim
  21   * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
  22   */
  23  
  24  // security - hide paths
  25  if (!defined('ADODB_DIR')) die();
  26  
  27  define("_ADODB_ADO_LAYER", 1 );
  28  /*--------------------------------------------------------------------------------------
  29  --------------------------------------------------------------------------------------*/
  30  
  31  
  32  class ADODB_ado extends ADOConnection {
  33  	 var $databaseType = "ado";
  34  	 var $_bindInputArray = false;
  35  	 var $fmtDate = "'Y-m-d'";
  36  	 var $fmtTimeStamp = "'Y-m-d, h:i:sA'";
  37  	 var $replaceQuote = "''"; // string to use to replace quotes
  38  	 var $dataProvider = "ado";
  39  	 var $hasAffectedRows = true;
  40  	 var $adoParameterType = 201; // 201 = long varchar, 203=long wide varchar, 205 = long varbinary
  41  	 var $_affectedRows = false;
  42  	 var $_thisTransactions;
  43  	 var $_cursor_type = 3; // 3=adOpenStatic,0=adOpenForwardOnly,1=adOpenKeyset,2=adOpenDynamic
  44  	 var $_cursor_location = 3; // 2=adUseServer, 3 = adUseClient;
  45  	 var $_lock_type = -1;
  46  	 var $_execute_option = -1;
  47  	 var $poorAffectedRows = true;
  48  	 var $charPage;
  49  
  50  	function __construct()
  51  	 {
  52  	 	 $this->_affectedRows = new VARIANT;
  53  	 }
  54  
  55  	function ServerInfo()
  56  	 {
  57  	 	 if (!empty($this->_connectionID)) $desc = $this->_connectionID->provider;
  58  	 	 return array('description' => $desc, 'version' => '');
  59  	 }
  60  
  61  	function _affectedrows()
  62  	 {
  63  	 	 return $this->_affectedRows;
  64  	 }
  65  
  66  	 // you can also pass a connection string like this:
  67  	 //
  68  	 // $DB->Connect('USER ID=sa;PASSWORD=pwd;SERVER=mangrove;DATABASE=ai',false,false,'SQLOLEDB');
  69  	function _connect($argHostname, $argUsername, $argPassword,$argDBorProvider, $argProvider= '')
  70  	 {
  71  	 // two modes
  72  	 //	 -	 if $argProvider is empty, we assume that $argDBorProvider holds provider -- this is for backward compat
  73  	 //	 - 	 if $argProvider is not empty, then $argDBorProvider holds db
  74  
  75  
  76  	 	  if ($argProvider) {
  77  	 	  	 $argDatabasename = $argDBorProvider;
  78  	 	  } else {
  79  	 	  	 $argDatabasename = '';
  80  	 	  	 if ($argDBorProvider) $argProvider = $argDBorProvider;
  81  	 	 	 else if (stripos($argHostname,'PROVIDER') === false) /* full conn string is not in $argHostname */
  82  	 	 	 	 $argProvider = 'MSDASQL';
  83  	 	 }
  84  
  85  
  86  	 	 try {
  87  	 	 $u = 'UID';
  88  	 	 $p = 'PWD';
  89  
  90  	 	 if (!empty($this->charPage))
  91  	 	 	 $dbc = new COM('ADODB.Connection',null,$this->charPage);
  92  	 	 else
  93  	 	 	 $dbc = new COM('ADODB.Connection');
  94  
  95  	 	 if (! $dbc) return false;
  96  
  97  	 	 /* special support if provider is mssql or access */
  98  	 	 if ($argProvider=='mssql') {
  99  	 	 	 $u = 'User Id';  //User parameter name for OLEDB
 100  	 	 	 $p = 'Password';
 101  	 	 	 $argProvider = "SQLOLEDB"; // SQL Server Provider
 102  
 103  	 	 	 // not yet
 104  	 	 	 //if ($argDatabasename) $argHostname .= ";Initial Catalog=$argDatabasename";
 105  
 106  	 	 	 //use trusted connection for SQL if username not specified
 107  	 	 	 if (!$argUsername) $argHostname .= ";Trusted_Connection=Yes";
 108  	 	 } else if ($argProvider=='access')
 109  	 	 	 $argProvider = "Microsoft.Jet.OLEDB.4.0"; // Microsoft Jet Provider
 110  
 111  	 	 if ($argProvider) $dbc->Provider = $argProvider;
 112  
 113  	 	 if ($argProvider) $argHostname = "PROVIDER=$argProvider;DRIVER={SQL Server};SERVER=$argHostname";
 114  
 115  
 116  	 	 if ($argDatabasename) $argHostname .= ";DATABASE=$argDatabasename";
 117  	 	 if ($argUsername) $argHostname .= ";$u=$argUsername";
 118  	 	 if ($argPassword)$argHostname .= ";$p=$argPassword";
 119  
 120  	 	 if ($this->debug) ADOConnection::outp( "Host=".$argHostname."<BR>\n version=$dbc->version");
 121  	 	 // @ added below for php 4.0.1 and earlier
 122  	 	 @$dbc->Open((string) $argHostname);
 123  
 124  	 	 $this->_connectionID = $dbc;
 125  
 126  	 	 $dbc->CursorLocation = $this->_cursor_location;
 127  	 	 return  $dbc->State > 0;
 128  	 	 } catch (exception $e) {
 129  	 	 	 if ($this->debug) echo "<pre>",$argHostname,"\n",$e,"</pre>\n";
 130  	 	 }
 131  
 132  	 	 return false;
 133  	 }
 134  
 135  	 // returns true or false
 136  	function _pconnect($argHostname, $argUsername, $argPassword, $argProvider='MSDASQL')
 137  	 {
 138  	 	 return $this->_connect($argHostname,$argUsername,$argPassword,$argProvider);
 139  	 }
 140  
 141  /*
 142  	 adSchemaCatalogs	 = 1,
 143  	 adSchemaCharacterSets	 = 2,
 144  	 adSchemaCollations	 = 3,
 145  	 adSchemaColumns	 = 4,
 146  	 adSchemaCheckConstraints	 = 5,
 147  	 adSchemaConstraintColumnUsage	 = 6,
 148  	 adSchemaConstraintTableUsage	 = 7,
 149  	 adSchemaKeyColumnUsage	 = 8,
 150  	 adSchemaReferentialContraints	 = 9,
 151  	 adSchemaTableConstraints	 = 10,
 152  	 adSchemaColumnsDomainUsage	 = 11,
 153  	 adSchemaIndexes	 = 12,
 154  	 adSchemaColumnPrivileges	 = 13,
 155  	 adSchemaTablePrivileges	 = 14,
 156  	 adSchemaUsagePrivileges	 = 15,
 157  	 adSchemaProcedures	 = 16,
 158  	 adSchemaSchemata	 = 17,
 159  	 adSchemaSQLLanguages	 = 18,
 160  	 adSchemaStatistics	 = 19,
 161  	 adSchemaTables	 = 20,
 162  	 adSchemaTranslations	 = 21,
 163  	 adSchemaProviderTypes	 = 22,
 164  	 adSchemaViews	 = 23,
 165  	 adSchemaViewColumnUsage	 = 24,
 166  	 adSchemaViewTableUsage	 = 25,
 167  	 adSchemaProcedureParameters	 = 26,
 168  	 adSchemaForeignKeys	 = 27,
 169  	 adSchemaPrimaryKeys	 = 28,
 170  	 adSchemaProcedureColumns	 = 29,
 171  	 adSchemaDBInfoKeywords	 = 30,
 172  	 adSchemaDBInfoLiterals	 = 31,
 173  	 adSchemaCubes	 = 32,
 174  	 adSchemaDimensions	 = 33,
 175  	 adSchemaHierarchies	 = 34,
 176  	 adSchemaLevels	 = 35,
 177  	 adSchemaMeasures	 = 36,
 178  	 adSchemaProperties	 = 37,
 179  	 adSchemaMembers	 = 38
 180  
 181  */
 182  
 183  	function MetaTables($ttype = false, $showSchema = false, $mask = false)
 184  	 {
 185  	 	 $arr= array();
 186  	 	 $dbc = $this->_connectionID;
 187  
 188  	 	 $adors=@$dbc->OpenSchema(20);//tables
 189  	 	 if ($adors){
 190  	 	 	 $f = $adors->Fields(2);//table/view name
 191  	 	 	 $t = $adors->Fields(3);//table type
 192  	 	 	 while (!$adors->EOF){
 193  	 	 	 	 $tt=substr($t->value,0,6);
 194  	 	 	 	 if ($tt!='SYSTEM' && $tt !='ACCESS')
 195  	 	 	 	 	 $arr[]=$f->value;
 196  	 	 	 	 //print $f->value . ' ' . $t->value.'<br>';
 197  	 	 	 	 $adors->MoveNext();
 198  	 	 	 }
 199  	 	 	 $adors->Close();
 200  	 	 }
 201  
 202  	 	 return $arr;
 203  	 }
 204  
 205  	function MetaColumns($table, $normalize=true)
 206  	 {
 207  	 	 $table = strtoupper($table);
 208  	 	 $arr= array();
 209  	 	 $dbc = $this->_connectionID;
 210  
 211  	 	 $adors=@$dbc->OpenSchema(4);//tables
 212  
 213  	 	 if ($adors){
 214  	 	 	 $t = $adors->Fields(2);//table/view name
 215  	 	 	 while (!$adors->EOF){
 216  
 217  
 218  	 	 	 	 if (strtoupper($t->Value) == $table) {
 219  
 220  	 	 	 	 	 $fld = new ADOFieldObject();
 221  	 	 	 	 	 $c = $adors->Fields(3);
 222  	 	 	 	 	 $fld->name = $c->Value;
 223  	 	 	 	 	 $fld->type = 'CHAR'; // cannot discover type in ADO!
 224  	 	 	 	 	 $fld->max_length = -1;
 225  	 	 	 	 	 $arr[strtoupper($fld->name)]=$fld;
 226  	 	 	 	 }
 227  
 228  	 	 	 	 $adors->MoveNext();
 229  	 	 	 }
 230  	 	 	 $adors->Close();
 231  	 	 }
 232  
 233  	 	 return $arr;
 234  	 }
 235  
 236  	 /* returns queryID or false */
 237  	function _query($sql,$inputarr=false)
 238  	 {
 239  	 	 try { // In PHP5, all COM errors are exceptions, so to maintain old behaviour...
 240  
 241  	 	 $dbc = $this->_connectionID;
 242  
 243  	 //	 return rs
 244  
 245  	 	 $false = false;
 246  
 247  	 	 if ($inputarr) {
 248  
 249  	 	 	 if (!empty($this->charPage))
 250  	 	 	 	 $oCmd = new COM('ADODB.Command',null,$this->charPage);
 251  	 	 	 else
 252  	 	 	 	 $oCmd = new COM('ADODB.Command');
 253  	 	 	 $oCmd->ActiveConnection = $dbc;
 254  	 	 	 $oCmd->CommandText = $sql;
 255  	 	 	 $oCmd->CommandType = 1;
 256  
 257  	 	 	 foreach ($inputarr as $val) {
 258  	 	 	 	 $type = gettype($val);
 259  	 	 	 	 $len=strlen($val);
 260  	 	 	 	 if ($type == 'boolean')
 261  	 	 	 	 	 $this->adoParameterType = 11;
 262  	 	 	 	 else if ($type == 'integer')
 263  	 	 	 	 	 $this->adoParameterType = 3;
 264  	 	 	 	 else if ($type == 'double')
 265  	 	 	 	 	 $this->adoParameterType = 5;
 266  	 	 	 	 elseif ($type == 'string')
 267  	 	 	 	 	 $this->adoParameterType = 202;
 268  	 	 	 	 else if (($val === null) || (!defined($val)))
 269  	 	 	 	 	 $len=1;
 270  	 	 	 	 else
 271  	 	 	 	 	 $this->adoParameterType = 130;
 272  
 273  	 	 	 	 // name, type, direction 1 = input, len,
 274          	 	 $p = $oCmd->CreateParameter('name',$this->adoParameterType,1,$len,$val);
 275  
 276  	 	 	 	 $oCmd->Parameters->Append($p);
 277  	 	 	 }
 278  
 279  	 	 	 $p = false;
 280  	 	 	 $rs = $oCmd->Execute();
 281  	 	 	 $e = $dbc->Errors;
 282  	 	 	 if ($dbc->Errors->Count > 0) return $false;
 283  	 	 	 return $rs;
 284  	 	 }
 285  
 286  	 	 $rs = @$dbc->Execute($sql,$this->_affectedRows, $this->_execute_option);
 287  
 288  	 	 if ($dbc->Errors->Count > 0) return $false;
 289  	 	 if (! $rs) return $false;
 290  
 291  	 	 if ($rs->State == 0) {
 292  	 	 	 $true = true;
 293  	 	 	 return $true; // 0 = adStateClosed means no records returned
 294  	 	 }
 295  	 	 return $rs;
 296  
 297  	 	 } catch (exception $e) {
 298  
 299  	 	 }
 300  	 	 return $false;
 301  	 }
 302  
 303  
 304  	function BeginTrans()
 305  	 {
 306  	 	 if ($this->transOff) return true;
 307  
 308  	 	 if (isset($this->_thisTransactions))
 309  	 	 	 if (!$this->_thisTransactions) return false;
 310  	 	 else {
 311  	 	 	 $o = $this->_connectionID->Properties("Transaction DDL");
 312  	 	 	 $this->_thisTransactions = $o ? true : false;
 313  	 	 	 if (!$o) return false;
 314  	 	 }
 315  	 	 @$this->_connectionID->BeginTrans();
 316  	 	 $this->transCnt += 1;
 317  	 	 return true;
 318  	 }
 319  	function CommitTrans($ok=true)
 320  	 {
 321  	 	 if (!$ok) return $this->RollbackTrans();
 322  	 	 if ($this->transOff) return true;
 323  
 324  	 	 @$this->_connectionID->CommitTrans();
 325  	 	 if ($this->transCnt) @$this->transCnt -= 1;
 326  	 	 return true;
 327  	 }
 328  	function RollbackTrans() {
 329  	 	 if ($this->transOff) return true;
 330  	 	 @$this->_connectionID->RollbackTrans();
 331  	 	 if ($this->transCnt) @$this->transCnt -= 1;
 332  	 	 return true;
 333  	 }
 334  
 335  	 /*	 Returns: the last error message from previous database operation	 */
 336  
 337  	function ErrorMsg()
 338  	 {
 339  	 	 if (!$this->_connectionID) return "No connection established";
 340  	 	 $errmsg = '';
 341  
 342  	 	 try {
 343  	 	 	 $errc = $this->_connectionID->Errors;
 344  	 	 	 if (!$errc) return "No Errors object found";
 345  	 	 	 if ($errc->Count == 0) return '';
 346  	 	 	 $err = $errc->Item($errc->Count-1);
 347  	 	 	 $errmsg = $err->Description;
 348  	 	 }catch(exception $e) {
 349  	 	 }
 350  	 	 return $errmsg;
 351  	 }
 352  
 353  	function ErrorNo()
 354  	 {
 355  	 	 $errc = $this->_connectionID->Errors;
 356  	 	 if ($errc->Count == 0) return 0;
 357  	 	 $err = $errc->Item($errc->Count-1);
 358  	 	 return $err->NativeError;
 359  	 }
 360  
 361  	 // returns true or false
 362  	function _close()
 363  	 {
 364  	 	 if ($this->_connectionID) $this->_connectionID->Close();
 365  	 	 $this->_connectionID = false;
 366  	 	 return true;
 367  	 }
 368  
 369  
 370  }
 371  
 372  /*--------------------------------------------------------------------------------------
 373  	  Class Name: Recordset
 374  --------------------------------------------------------------------------------------*/
 375  
 376  class ADORecordSet_ado extends ADORecordSet {
 377  
 378  	 var $bind = false;
 379  	 var $databaseType = "ado";
 380  	 var $dataProvider = "ado";
 381  	 var $_tarr = false; // caches the types
 382  	 var $_flds; // and field objects
 383  	 var $canSeek = true;
 384    	 var $hideErrors = true;
 385  
 386  	function __construct($id,$mode=false)
 387  	 {
 388  	 	 if ($mode === false) {
 389  	 	 	 global $ADODB_FETCH_MODE;
 390  	 	 	 $mode = $ADODB_FETCH_MODE;
 391  	 	 }
 392  	 	 $this->fetchMode = $mode;
 393  	 	 parent::__construct($id);
 394  	 }
 395  
 396  
 397  	 // returns the field object
 398  	function FetchField($fieldOffset = -1) {
 399  	 	 $off=$fieldOffset+1; // offsets begin at 1
 400  
 401  	 	 $o= new ADOFieldObject();
 402  	 	 $rs = $this->_queryID;
 403  	 	 if (!$rs) return false;
 404  
 405  	 	 $f = $rs->Fields($fieldOffset);
 406  	 	 $o->name = $f->Name;
 407  	 	 $t = $f->Type;
 408  	 	 $o->type = $this->MetaType($t);
 409  	 	 $o->max_length = $f->DefinedSize;
 410  	 	 $o->ado_type = $t;
 411  
 412  
 413  	 	 //print "off=$off name=$o->name type=$o->type len=$o->max_length<br>";
 414  	 	 return $o;
 415  	 }
 416  
 417  	 /* Use associative array to get fields array */
 418  	function Fields($colname)
 419  	 {
 420  	 	 if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
 421  	 	 if (!$this->bind) {
 422  	 	 	 $this->bind = array();
 423  	 	 	 for ($i=0; $i < $this->_numOfFields; $i++) {
 424  	 	 	 	 $o = $this->FetchField($i);
 425  	 	 	 	 $this->bind[strtoupper($o->name)] = $i;
 426  	 	 	 }
 427  	 	 }
 428  
 429  	 	  return $this->fields[$this->bind[strtoupper($colname)]];
 430  	 }
 431  
 432  
 433  	function _initrs()
 434  	 {
 435  	 	 $rs = $this->_queryID;
 436  
 437  	 	 try {
 438  	 	 	 $this->_numOfRows = $rs->RecordCount;
 439  	 	 } catch (Exception $e) {
 440  	 	 	 $this->_numOfRows = -1;
 441  	 	 }
 442  	 	 $f = $rs->Fields;
 443  	 	 $this->_numOfFields = $f->Count;
 444  	 }
 445  
 446  
 447  	  // should only be used to move forward as we normally use forward-only cursors
 448  	function _seek($row)
 449  	 {
 450  	    $rs = $this->_queryID;
 451  	 	 // absoluteposition doesn't work -- my maths is wrong ?
 452  	 	 //	 $rs->AbsolutePosition->$row-2;
 453  	 	 //	 return true;
 454  	 	 if ($this->_currentRow > $row) return false;
 455  	 	 @$rs->Move((integer)$row - $this->_currentRow-1); //adBookmarkFirst
 456  	 	 return true;
 457  	 }
 458  
 459  /*
 460  	 OLEDB types
 461  
 462  	  enum DBTYPEENUM
 463  	 {	 DBTYPE_EMPTY	 = 0,
 464  	 DBTYPE_NULL	 = 1,
 465  	 DBTYPE_I2	 = 2,
 466  	 DBTYPE_I4	 = 3,
 467  	 DBTYPE_R4	 = 4,
 468  	 DBTYPE_R8	 = 5,
 469  	 DBTYPE_CY	 = 6,
 470  	 DBTYPE_DATE	 = 7,
 471  	 DBTYPE_BSTR	 = 8,
 472  	 DBTYPE_IDISPATCH	 = 9,
 473  	 DBTYPE_ERROR	 = 10,
 474  	 DBTYPE_BOOL	 = 11,
 475  	 DBTYPE_VARIANT	 = 12,
 476  	 DBTYPE_IUNKNOWN	 = 13,
 477  	 DBTYPE_DECIMAL	 = 14,
 478  	 DBTYPE_UI1	 = 17,
 479  	 DBTYPE_ARRAY	 = 0x2000,
 480  	 DBTYPE_BYREF	 = 0x4000,
 481  	 DBTYPE_I1	 = 16,
 482  	 DBTYPE_UI2	 = 18,
 483  	 DBTYPE_UI4	 = 19,
 484  	 DBTYPE_I8	 = 20,
 485  	 DBTYPE_UI8	 = 21,
 486  	 DBTYPE_GUID	 = 72,
 487  	 DBTYPE_VECTOR	 = 0x1000,
 488  	 DBTYPE_RESERVED	 = 0x8000,
 489  	 DBTYPE_BYTES	 = 128,
 490  	 DBTYPE_STR	 = 129,
 491  	 DBTYPE_WSTR	 = 130,
 492  	 DBTYPE_NUMERIC	 = 131,
 493  	 DBTYPE_UDT	 = 132,
 494  	 DBTYPE_DBDATE	 = 133,
 495  	 DBTYPE_DBTIME	 = 134,
 496  	 DBTYPE_DBTIMESTAMP	 = 135
 497  
 498  	 ADO Types
 499  
 500     	 adEmpty	 = 0,
 501  	 adTinyInt	 = 16,
 502  	 adSmallInt	 = 2,
 503  	 adInteger	 = 3,
 504  	 adBigInt	 = 20,
 505  	 adUnsignedTinyInt	 = 17,
 506  	 adUnsignedSmallInt	 = 18,
 507  	 adUnsignedInt	 = 19,
 508  	 adUnsignedBigInt	 = 21,
 509  	 adSingle	 = 4,
 510  	 adDouble	 = 5,
 511  	 adCurrency	 = 6,
 512  	 adDecimal	 = 14,
 513  	 adNumeric	 = 131,
 514  	 adBoolean	 = 11,
 515  	 adError	 = 10,
 516  	 adUserDefined	 = 132,
 517  	 adVariant	 = 12,
 518  	 adIDispatch	 = 9,
 519  	 adIUnknown	 = 13,
 520  	 adGUID	 = 72,
 521  	 adDate	 = 7,
 522  	 adDBDate	 = 133,
 523  	 adDBTime	 = 134,
 524  	 adDBTimeStamp	 = 135,
 525  	 adBSTR	 = 8,
 526  	 adChar	 = 129,
 527  	 adVarChar	 = 200,
 528  	 adLongVarChar	 = 201,
 529  	 adWChar	 = 130,
 530  	 adVarWChar	 = 202,
 531  	 adLongVarWChar	 = 203,
 532  	 adBinary	 = 128,
 533  	 adVarBinary	 = 204,
 534  	 adLongVarBinary	 = 205,
 535  	 adChapter	 = 136,
 536  	 adFileTime	 = 64,
 537  	 adDBFileTime	 = 137,
 538  	 adPropVariant	 = 138,
 539  	 adVarNumeric	 = 139
 540  */
 541  	function MetaType($t,$len=-1,$fieldobj=false)
 542  	 {
 543  	 	 if (is_object($t)) {
 544  	 	 	 $fieldobj = $t;
 545  	 	 	 $t = $fieldobj->type;
 546  	 	 	 $len = $fieldobj->max_length;
 547  	 	 }
 548  	 	 
 549  	 	 $t = strtoupper($t);
 550  	 	 
 551  	 	 if (array_key_exists($t,$this->connection->customActualTypes))
 552  	 	 	 return  $this->connection->customActualTypes[$t];
 553  
 554  	 	 if (!is_numeric($t)) 
 555  	 	 	 return $t;
 556  
 557  	 	 switch ($t) {
 558  	 	 case 0:
 559  	 	 case 12: // variant
 560  	 	 case 8: // bstr
 561  	 	 case 129: //char
 562  	 	 case 130: //wc
 563  	 	 case 200: // varc
 564  	 	 case 202:// varWC
 565  	 	 case 128: // bin
 566  	 	 case 204: // varBin
 567  	 	 case 72: // guid
 568  	 	 	 if ($len <= $this->blobSize) return 'C';
 569  
 570  	 	 case 201:
 571  	 	 case 203:
 572  	 	 	 return 'X';
 573  	 	 case 128:
 574  	 	 case 204:
 575  	 	 case 205:
 576  	 	 	  return 'B';
 577  	 	 case 7:
 578  	 	 case 133: return 'D';
 579  
 580  	 	 case 134:
 581  	 	 case 135: return 'T';
 582  
 583  	 	 case 11: return 'L';
 584  
 585  	 	 case 16://	 adTinyInt	 = 16,
 586  	 	 case 2://adSmallInt	 = 2,
 587  	 	 case 3://adInteger	 = 3,
 588  	 	 case 4://adBigInt	 = 20,
 589  	 	 case 17://adUnsignedTinyInt	 = 17,
 590  	 	 case 18://adUnsignedSmallInt	 = 18,
 591  	 	 case 19://adUnsignedInt	 = 19,
 592  	 	 case 20://adUnsignedBigInt	 = 21,
 593  	 	 	 return 'I';
 594  	 	 default: return ADODB_DEFAULT_METATYPE;
 595  	 	 }
 596  	 }
 597  
 598  	 // time stamp not supported yet
 599  	function _fetch()
 600  	 {
 601  	 	 $rs = $this->_queryID;
 602  	 	 if (!$rs or $rs->EOF) {
 603  	 	 	 $this->fields = false;
 604  	 	 	 return false;
 605  	 	 }
 606  	 	 $this->fields = array();
 607  
 608  	 	 if (!$this->_tarr) {
 609  	 	 	 $tarr = array();
 610  	 	 	 $flds = array();
 611  	 	 	 for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) {
 612  	 	 	 	 $f = $rs->Fields($i);
 613  	 	 	 	 $flds[] = $f;
 614  	 	 	 	 $tarr[] = $f->Type;
 615  	 	 	 }
 616  	 	 	 // bind types and flds only once
 617  	 	 	 $this->_tarr = $tarr;
 618  	 	 	 $this->_flds = $flds;
 619  	 	 }
 620  	 	 $t = reset($this->_tarr);
 621  	 	 $f = reset($this->_flds);
 622  
 623  	 	 if ($this->hideErrors)  $olde = error_reporting(E_ERROR|E_CORE_ERROR);// sometimes $f->value be null
 624  	 	 for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) {
 625  	 	 	 //echo "<p>",$t,' ';var_dump($f->value); echo '</p>';
 626  	 	 	 switch($t) {
 627  	 	 	 case 135: // timestamp
 628  	 	 	 	 if (!strlen((string)$f->value)) $this->fields[] = false;
 629  	 	 	 	 else {
 630  	 	 	 	 	 if (!is_numeric($f->value)) # $val = variant_date_to_timestamp($f->value);
 631  	 	 	 	 	 	 // VT_DATE stores dates as (float) fractional days since 1899/12/30 00:00:00
 632  	 	 	 	 	 	 $val= (float) variant_cast($f->value,VT_R8)*3600*24-2209161600;
 633  	 	 	 	 	 else
 634  	 	 	 	 	 	 $val = $f->value;
 635  	 	 	 	 	 $this->fields[] = adodb_date('Y-m-d H:i:s',$val);
 636  	 	 	 	 }
 637  	 	 	 	 break;
 638  	 	 	 case 133:// A date value (yyyymmdd)
 639  	 	 	 	 if ($val = $f->value) {
 640  	 	 	 	 	 $this->fields[] = substr($val,0,4).'-'.substr($val,4,2).'-'.substr($val,6,2);
 641  	 	 	 	 } else
 642  	 	 	 	 	 $this->fields[] = false;
 643  	 	 	 	 break;
 644  	 	 	 case 7: // adDate
 645  	 	 	 	 if (!strlen((string)$f->value)) $this->fields[] = false;
 646  	 	 	 	 else {
 647  	 	 	 	 	 if (!is_numeric($f->value)) $val = variant_date_to_timestamp($f->value);
 648  	 	 	 	 	 else $val = $f->value;
 649  
 650  	 	 	 	 	 if (($val % 86400) == 0) $this->fields[] = adodb_date('Y-m-d',$val);
 651  	 	 	 	 	 else $this->fields[] = adodb_date('Y-m-d H:i:s',$val);
 652  	 	 	 	 }
 653  	 	 	 	 break;
 654  	 	 	 case 1: // null
 655  	 	 	 	 $this->fields[] = false;
 656  	 	 	 	 break;
 657  	 	 	 case 20:
 658  	 	 	 case 21: // bigint (64 bit)
 659      	 	 	 $this->fields[] = (float) $f->value; // if 64 bit PHP, could use (int)
 660      	 	 	 break;
 661  	 	 	 case 6: // currency is not supported properly;
 662  	 	 	 	 ADOConnection::outp( '<b>'.$f->Name.': currency type not supported by PHP</b>');
 663  	 	 	 	 $this->fields[] = (float) $f->value;
 664  	 	 	 	 break;
 665  	 	 	 case 11: //BIT;
 666  	 	 	 	 $val = "";
 667  	 	 	 	 if(is_bool($f->value))	 {
 668  	 	 	 	 	 if($f->value==true) $val = 1;
 669  	 	 	 	 	 else $val = 0;
 670  	 	 	 	 }
 671  	 	 	 	 if(is_null($f->value)) $val = null;
 672  
 673  	 	 	 	 $this->fields[] = $val;
 674  	 	 	 	 break;
 675  	 	 	 default:
 676  	 	 	 	 $this->fields[] = $f->value;
 677  	 	 	 	 break;
 678  	 	 	 }
 679  	 	 	 //print " $f->value $t, ";
 680  	 	 	 $f = next($this->_flds);
 681  	 	 	 $t = next($this->_tarr);
 682  	 	 } // for
 683  	 	 if ($this->hideErrors) error_reporting($olde);
 684  	 	 @$rs->MoveNext(); // @ needed for some versions of PHP!
 685  
 686  	 	 if ($this->fetchMode & ADODB_FETCH_ASSOC) {
 687  	 	 	 $this->fields = $this->GetRowAssoc();
 688  	 	 }
 689  	 	 return true;
 690  	 }
 691  
 692  		function NextRecordSet()
 693  	 	 {
 694  	 	 	 $rs = $this->_queryID;
 695  	 	 	 $this->_queryID = $rs->NextRecordSet();
 696  	 	 	 //$this->_queryID = $this->_QueryId->NextRecordSet();
 697  	 	 	 if ($this->_queryID == null) return false;
 698  
 699  	 	 	 $this->_currentRow = -1;
 700  	 	 	 $this->_currentPage = -1;
 701  	 	 	 $this->bind = false;
 702  	 	 	 $this->fields = false;
 703  	 	 	 $this->_flds = false;
 704  	 	 	 $this->_tarr = false;
 705  
 706  	 	 	 $this->_inited = false;
 707  	 	 	 $this->Init();
 708  	 	 	 return true;
 709  	 	 }
 710  
 711  	function _close() {
 712  	 	 $this->_flds = false;
 713  	 	 try {
 714  	 	 @$this->_queryID->Close();// by Pete Dishman (peterd@telephonetics.co.uk)
 715  	 	 } catch (Exception $e) {
 716  	 	 }
 717  	 	 $this->_queryID = false;
 718  	 }
 719  
 720  }