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