Documentation TYPO3 par Ameos |
00001 <?php 00002 /* 00003 V4.93 10 Oct 2006 (c) 2000-2006 John Lim (jlim#natsoft.com.my). All rights reserved. 00004 Released under both BSD license and Lesser GPL library license. 00005 Whenever there is any discrepancy between the two licenses, 00006 the BSD license will take precedence. 00007 Set tabs to 4 for best viewing. 00008 00009 Latest version is available at http://adodb.sourceforge.net 00010 00011 Microsoft ADO data driver. Requires ADO. Works only on MS Windows. PHP5 compat version. 00012 */ 00013 00014 // security - hide paths 00015 if (!defined('ADODB_DIR')) die(); 00016 00017 define("_ADODB_ADO_LAYER", 1 ); 00018 /*-------------------------------------------------------------------------------------- 00019 --------------------------------------------------------------------------------------*/ 00020 00021 00022 class ADODB_ado extends ADOConnection { 00023 var $databaseType = "ado"; 00024 var $_bindInputArray = false; 00025 var $fmtDate = "'Y-m-d'"; 00026 var $fmtTimeStamp = "'Y-m-d, h:i:sA'"; 00027 var $replaceQuote = "''"; // string to use to replace quotes 00028 var $dataProvider = "ado"; 00029 var $hasAffectedRows = true; 00030 var $adoParameterType = 201; // 201 = long varchar, 203=long wide varchar, 205 = long varbinary 00031 var $_affectedRows = false; 00032 var $_thisTransactions; 00033 var $_cursor_type = 3; // 3=adOpenStatic,0=adOpenForwardOnly,1=adOpenKeyset,2=adOpenDynamic 00034 var $_cursor_location = 3; // 2=adUseServer, 3 = adUseClient; 00035 var $_lock_type = -1; 00036 var $_execute_option = -1; 00037 var $poorAffectedRows = true; 00038 var $charPage; 00039 00040 function ADODB_ado() 00041 { 00042 $this->_affectedRows = new VARIANT; 00043 } 00044 00045 function ServerInfo() 00046 { 00047 if (!empty($this->_connectionID)) $desc = $this->_connectionID->provider; 00048 return array('description' => $desc, 'version' => ''); 00049 } 00050 00051 function _affectedrows() 00052 { 00053 if (PHP_VERSION >= 5) return $this->_affectedRows; 00054 00055 return $this->_affectedRows->value; 00056 } 00057 00058 // you can also pass a connection string like this: 00059 // 00060 // $DB->Connect('USER ID=sa;PASSWORD=pwd;SERVER=mangrove;DATABASE=ai',false,false,'SQLOLEDB'); 00061 function _connect($argHostname, $argUsername, $argPassword,$argDBorProvider, $argProvider= '') 00062 { 00063 // two modes 00064 // - if $argProvider is empty, we assume that $argDBorProvider holds provider -- this is for backward compat 00065 // - if $argProvider is not empty, then $argDBorProvider holds db 00066 00067 00068 if ($argProvider) { 00069 $argDatabasename = $argDBorProvider; 00070 } else { 00071 $argDatabasename = ''; 00072 if ($argDBorProvider) $argProvider = $argDBorProvider; 00073 else $argProvider = 'MSDASQL'; 00074 } 00075 00076 00077 try { 00078 $u = 'UID'; 00079 $p = 'PWD'; 00080 00081 if (!empty($this->charPage)) 00082 $dbc = new COM('ADODB.Connection',null,$this->charPage); 00083 else 00084 $dbc = new COM('ADODB.Connection'); 00085 00086 if (! $dbc) return false; 00087 00088 /* special support if provider is mssql or access */ 00089 if ($argProvider=='mssql') { 00090 $u = 'User Id'; //User parameter name for OLEDB 00091 $p = 'Password'; 00092 $argProvider = "SQLOLEDB"; // SQL Server Provider 00093 00094 // not yet 00095 //if ($argDatabasename) $argHostname .= ";Initial Catalog=$argDatabasename"; 00096 00097 //use trusted conection for SQL if username not specified 00098 if (!$argUsername) $argHostname .= ";Trusted_Connection=Yes"; 00099 } else if ($argProvider=='access') 00100 $argProvider = "Microsoft.Jet.OLEDB.4.0"; // Microsoft Jet Provider 00101 00102 if ($argProvider) $dbc->Provider = $argProvider; 00103 00104 if ($argProvider) $argHostname = "PROVIDER=$argProvider;DRIVER={SQL Server};SERVER=$argHostname"; 00105 00106 00107 if ($argDatabasename) $argHostname .= ";DATABASE=$argDatabasename"; 00108 if ($argUsername) $argHostname .= ";$u=$argUsername"; 00109 if ($argPassword)$argHostname .= ";$p=$argPassword"; 00110 00111 if ($this->debug) ADOConnection::outp( "Host=".$argHostname."<BR>\n version=$dbc->version"); 00112 // @ added below for php 4.0.1 and earlier 00113 @$dbc->Open((string) $argHostname); 00114 00115 $this->_connectionID = $dbc; 00116 00117 $dbc->CursorLocation = $this->_cursor_location; 00118 return $dbc->State > 0; 00119 } catch (exception $e) { 00120 } 00121 00122 return false; 00123 } 00124 00125 // returns true or false 00126 function _pconnect($argHostname, $argUsername, $argPassword, $argProvider='MSDASQL') 00127 { 00128 return $this->_connect($argHostname,$argUsername,$argPassword,$argProvider); 00129 } 00130 00131 /* 00132 adSchemaCatalogs = 1, 00133 adSchemaCharacterSets = 2, 00134 adSchemaCollations = 3, 00135 adSchemaColumns = 4, 00136 adSchemaCheckConstraints = 5, 00137 adSchemaConstraintColumnUsage = 6, 00138 adSchemaConstraintTableUsage = 7, 00139 adSchemaKeyColumnUsage = 8, 00140 adSchemaReferentialContraints = 9, 00141 adSchemaTableConstraints = 10, 00142 adSchemaColumnsDomainUsage = 11, 00143 adSchemaIndexes = 12, 00144 adSchemaColumnPrivileges = 13, 00145 adSchemaTablePrivileges = 14, 00146 adSchemaUsagePrivileges = 15, 00147 adSchemaProcedures = 16, 00148 adSchemaSchemata = 17, 00149 adSchemaSQLLanguages = 18, 00150 adSchemaStatistics = 19, 00151 adSchemaTables = 20, 00152 adSchemaTranslations = 21, 00153 adSchemaProviderTypes = 22, 00154 adSchemaViews = 23, 00155 adSchemaViewColumnUsage = 24, 00156 adSchemaViewTableUsage = 25, 00157 adSchemaProcedureParameters = 26, 00158 adSchemaForeignKeys = 27, 00159 adSchemaPrimaryKeys = 28, 00160 adSchemaProcedureColumns = 29, 00161 adSchemaDBInfoKeywords = 30, 00162 adSchemaDBInfoLiterals = 31, 00163 adSchemaCubes = 32, 00164 adSchemaDimensions = 33, 00165 adSchemaHierarchies = 34, 00166 adSchemaLevels = 35, 00167 adSchemaMeasures = 36, 00168 adSchemaProperties = 37, 00169 adSchemaMembers = 38 00170 00171 */ 00172 00173 function &MetaTables() 00174 { 00175 $arr= array(); 00176 $dbc = $this->_connectionID; 00177 00178 $adors=@$dbc->OpenSchema(20);//tables 00179 if ($adors){ 00180 $f = $adors->Fields(2);//table/view name 00181 $t = $adors->Fields(3);//table type 00182 while (!$adors->EOF){ 00183 $tt=substr($t->value,0,6); 00184 if ($tt!='SYSTEM' && $tt !='ACCESS') 00185 $arr[]=$f->value; 00186 //print $f->value . ' ' . $t->value.'<br>'; 00187 $adors->MoveNext(); 00188 } 00189 $adors->Close(); 00190 } 00191 00192 return $arr; 00193 } 00194 00195 function &MetaColumns($table) 00196 { 00197 $table = strtoupper($table); 00198 $arr= array(); 00199 $dbc = $this->_connectionID; 00200 00201 $adors=@$dbc->OpenSchema(4);//tables 00202 00203 if ($adors){ 00204 $t = $adors->Fields(2);//table/view name 00205 while (!$adors->EOF){ 00206 00207 00208 if (strtoupper($t->Value) == $table) { 00209 00210 $fld = new ADOFieldObject(); 00211 $c = $adors->Fields(3); 00212 $fld->name = $c->Value; 00213 $fld->type = 'CHAR'; // cannot discover type in ADO! 00214 $fld->max_length = -1; 00215 $arr[strtoupper($fld->name)]=$fld; 00216 } 00217 00218 $adors->MoveNext(); 00219 } 00220 $adors->Close(); 00221 } 00222 00223 return $arr; 00224 } 00225 00226 /* returns queryID or false */ 00227 function &_query($sql,$inputarr=false) 00228 { 00229 try { // In PHP5, all COM errors are exceptions, so to maintain old behaviour... 00230 00231 $dbc = $this->_connectionID; 00232 00233 // return rs 00234 00235 $false = false; 00236 00237 if ($inputarr) { 00238 00239 if (!empty($this->charPage)) 00240 $oCmd = new COM('ADODB.Command',null,$this->charPage); 00241 else 00242 $oCmd = new COM('ADODB.Command'); 00243 $oCmd->ActiveConnection = $dbc; 00244 $oCmd->CommandText = $sql; 00245 $oCmd->CommandType = 1; 00246 00247 foreach($inputarr as $val) { 00248 // name, type, direction 1 = input, len, 00249 $this->adoParameterType = 130; 00250 $p = $oCmd->CreateParameter('name',$this->adoParameterType,1,strlen($val),$val); 00251 //print $p->Type.' '.$p->value; 00252 $oCmd->Parameters->Append($p); 00253 } 00254 $p = false; 00255 $rs = $oCmd->Execute(); 00256 $e = $dbc->Errors; 00257 if ($dbc->Errors->Count > 0) return $false; 00258 return $rs; 00259 } 00260 00261 $rs = @$dbc->Execute($sql,$this->_affectedRows, $this->_execute_option); 00262 00263 if ($dbc->Errors->Count > 0) return $false; 00264 if (! $rs) return $false; 00265 00266 if ($rs->State == 0) { 00267 $true = true; 00268 return $true; // 0 = adStateClosed means no records returned 00269 } 00270 return $rs; 00271 00272 } catch (exception $e) { 00273 00274 } 00275 return $false; 00276 } 00277 00278 00279 function BeginTrans() 00280 { 00281 if ($this->transOff) return true; 00282 00283 if (isset($this->_thisTransactions)) 00284 if (!$this->_thisTransactions) return false; 00285 else { 00286 $o = $this->_connectionID->Properties("Transaction DDL"); 00287 $this->_thisTransactions = $o ? true : false; 00288 if (!$o) return false; 00289 } 00290 @$this->_connectionID->BeginTrans(); 00291 $this->transCnt += 1; 00292 return true; 00293 } 00294 function CommitTrans($ok=true) 00295 { 00296 if (!$ok) return $this->RollbackTrans(); 00297 if ($this->transOff) return true; 00298 00299 @$this->_connectionID->CommitTrans(); 00300 if ($this->transCnt) @$this->transCnt -= 1; 00301 return true; 00302 } 00303 function RollbackTrans() { 00304 if ($this->transOff) return true; 00305 @$this->_connectionID->RollbackTrans(); 00306 if ($this->transCnt) @$this->transCnt -= 1; 00307 return true; 00308 } 00309 00310 /* Returns: the last error message from previous database operation */ 00311 00312 function ErrorMsg() 00313 { 00314 if (!$this->_connectionID) return "No connection established"; 00315 $errmsg = ''; 00316 00317 try { 00318 $errc = $this->_connectionID->Errors; 00319 if (!$errc) return "No Errors object found"; 00320 if ($errc->Count == 0) return ''; 00321 $err = $errc->Item($errc->Count-1); 00322 $errmsg = $err->Description; 00323 }catch(exception $e) { 00324 } 00325 return $errmsg; 00326 } 00327 00328 function ErrorNo() 00329 { 00330 $errc = $this->_connectionID->Errors; 00331 if ($errc->Count == 0) return 0; 00332 $err = $errc->Item($errc->Count-1); 00333 return $err->NativeError; 00334 } 00335 00336 // returns true or false 00337 function _close() 00338 { 00339 if ($this->_connectionID) $this->_connectionID->Close(); 00340 $this->_connectionID = false; 00341 return true; 00342 } 00343 00344 00345 } 00346 00347 /*-------------------------------------------------------------------------------------- 00348 Class Name: Recordset 00349 --------------------------------------------------------------------------------------*/ 00350 00351 class ADORecordSet_ado extends ADORecordSet { 00352 00353 var $bind = false; 00354 var $databaseType = "ado"; 00355 var $dataProvider = "ado"; 00356 var $_tarr = false; // caches the types 00357 var $_flds; // and field objects 00358 var $canSeek = true; 00359 var $hideErrors = true; 00360 00361 function ADORecordSet_ado($id,$mode=false) 00362 { 00363 if ($mode === false) { 00364 global $ADODB_FETCH_MODE; 00365 $mode = $ADODB_FETCH_MODE; 00366 } 00367 $this->fetchMode = $mode; 00368 return $this->ADORecordSet($id,$mode); 00369 } 00370 00371 00372 // returns the field object 00373 function &FetchField($fieldOffset = -1) { 00374 $off=$fieldOffset+1; // offsets begin at 1 00375 00376 $o= new ADOFieldObject(); 00377 $rs = $this->_queryID; 00378 $f = $rs->Fields($fieldOffset); 00379 $o->name = $f->Name; 00380 $t = $f->Type; 00381 $o->type = $this->MetaType($t); 00382 $o->max_length = $f->DefinedSize; 00383 $o->ado_type = $t; 00384 00385 00386 //print "off=$off name=$o->name type=$o->type len=$o->max_length<br>"; 00387 return $o; 00388 } 00389 00390 /* Use associative array to get fields array */ 00391 function Fields($colname) 00392 { 00393 if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname]; 00394 if (!$this->bind) { 00395 $this->bind = array(); 00396 for ($i=0; $i < $this->_numOfFields; $i++) { 00397 $o = $this->FetchField($i); 00398 $this->bind[strtoupper($o->name)] = $i; 00399 } 00400 } 00401 00402 return $this->fields[$this->bind[strtoupper($colname)]]; 00403 } 00404 00405 00406 function _initrs() 00407 { 00408 $rs = $this->_queryID; 00409 $this->_numOfRows = $rs->RecordCount; 00410 00411 $f = $rs->Fields; 00412 $this->_numOfFields = $f->Count; 00413 } 00414 00415 00416 // should only be used to move forward as we normally use forward-only cursors 00417 function _seek($row) 00418 { 00419 $rs = $this->_queryID; 00420 // absoluteposition doesn't work -- my maths is wrong ? 00421 // $rs->AbsolutePosition->$row-2; 00422 // return true; 00423 if ($this->_currentRow > $row) return false; 00424 @$rs->Move((integer)$row - $this->_currentRow-1); //adBookmarkFirst 00425 return true; 00426 } 00427 00428 /* 00429 OLEDB types 00430 00431 enum DBTYPEENUM 00432 { DBTYPE_EMPTY = 0, 00433 DBTYPE_NULL = 1, 00434 DBTYPE_I2 = 2, 00435 DBTYPE_I4 = 3, 00436 DBTYPE_R4 = 4, 00437 DBTYPE_R8 = 5, 00438 DBTYPE_CY = 6, 00439 DBTYPE_DATE = 7, 00440 DBTYPE_BSTR = 8, 00441 DBTYPE_IDISPATCH = 9, 00442 DBTYPE_ERROR = 10, 00443 DBTYPE_BOOL = 11, 00444 DBTYPE_VARIANT = 12, 00445 DBTYPE_IUNKNOWN = 13, 00446 DBTYPE_DECIMAL = 14, 00447 DBTYPE_UI1 = 17, 00448 DBTYPE_ARRAY = 0x2000, 00449 DBTYPE_BYREF = 0x4000, 00450 DBTYPE_I1 = 16, 00451 DBTYPE_UI2 = 18, 00452 DBTYPE_UI4 = 19, 00453 DBTYPE_I8 = 20, 00454 DBTYPE_UI8 = 21, 00455 DBTYPE_GUID = 72, 00456 DBTYPE_VECTOR = 0x1000, 00457 DBTYPE_RESERVED = 0x8000, 00458 DBTYPE_BYTES = 128, 00459 DBTYPE_STR = 129, 00460 DBTYPE_WSTR = 130, 00461 DBTYPE_NUMERIC = 131, 00462 DBTYPE_UDT = 132, 00463 DBTYPE_DBDATE = 133, 00464 DBTYPE_DBTIME = 134, 00465 DBTYPE_DBTIMESTAMP = 135 00466 00467 ADO Types 00468 00469 adEmpty = 0, 00470 adTinyInt = 16, 00471 adSmallInt = 2, 00472 adInteger = 3, 00473 adBigInt = 20, 00474 adUnsignedTinyInt = 17, 00475 adUnsignedSmallInt = 18, 00476 adUnsignedInt = 19, 00477 adUnsignedBigInt = 21, 00478 adSingle = 4, 00479 adDouble = 5, 00480 adCurrency = 6, 00481 adDecimal = 14, 00482 adNumeric = 131, 00483 adBoolean = 11, 00484 adError = 10, 00485 adUserDefined = 132, 00486 adVariant = 12, 00487 adIDispatch = 9, 00488 adIUnknown = 13, 00489 adGUID = 72, 00490 adDate = 7, 00491 adDBDate = 133, 00492 adDBTime = 134, 00493 adDBTimeStamp = 135, 00494 adBSTR = 8, 00495 adChar = 129, 00496 adVarChar = 200, 00497 adLongVarChar = 201, 00498 adWChar = 130, 00499 adVarWChar = 202, 00500 adLongVarWChar = 203, 00501 adBinary = 128, 00502 adVarBinary = 204, 00503 adLongVarBinary = 205, 00504 adChapter = 136, 00505 adFileTime = 64, 00506 adDBFileTime = 137, 00507 adPropVariant = 138, 00508 adVarNumeric = 139 00509 */ 00510 function MetaType($t,$len=-1,$fieldobj=false) 00511 { 00512 if (is_object($t)) { 00513 $fieldobj = $t; 00514 $t = $fieldobj->type; 00515 $len = $fieldobj->max_length; 00516 } 00517 00518 if (!is_numeric($t)) return $t; 00519 00520 switch ($t) { 00521 case 0: 00522 case 12: // variant 00523 case 8: // bstr 00524 case 129: //char 00525 case 130: //wc 00526 case 200: // varc 00527 case 202:// varWC 00528 case 128: // bin 00529 case 204: // varBin 00530 case 72: // guid 00531 if ($len <= $this->blobSize) return 'C'; 00532 00533 case 201: 00534 case 203: 00535 return 'X'; 00536 case 128: 00537 case 204: 00538 case 205: 00539 return 'B'; 00540 case 7: 00541 case 133: return 'D'; 00542 00543 case 134: 00544 case 135: return 'T'; 00545 00546 case 11: return 'L'; 00547 00548 case 16:// adTinyInt = 16, 00549 case 2://adSmallInt = 2, 00550 case 3://adInteger = 3, 00551 case 4://adBigInt = 20, 00552 case 17://adUnsignedTinyInt = 17, 00553 case 18://adUnsignedSmallInt = 18, 00554 case 19://adUnsignedInt = 19, 00555 case 20://adUnsignedBigInt = 21, 00556 return 'I'; 00557 default: return 'N'; 00558 } 00559 } 00560 00561 // time stamp not supported yet 00562 function _fetch() 00563 { 00564 $rs = $this->_queryID; 00565 if (!$rs or $rs->EOF) { 00566 $this->fields = false; 00567 return false; 00568 } 00569 $this->fields = array(); 00570 00571 if (!$this->_tarr) { 00572 $tarr = array(); 00573 $flds = array(); 00574 for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) { 00575 $f = $rs->Fields($i); 00576 $flds[] = $f; 00577 $tarr[] = $f->Type; 00578 } 00579 // bind types and flds only once 00580 $this->_tarr = $tarr; 00581 $this->_flds = $flds; 00582 } 00583 $t = reset($this->_tarr); 00584 $f = reset($this->_flds); 00585 00586 if ($this->hideErrors) $olde = error_reporting(E_ERROR|E_CORE_ERROR);// sometimes $f->value be null 00587 for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) { 00588 //echo "<p>",$t,' ';var_dump($f->value); echo '</p>'; 00589 switch($t) { 00590 case 135: // timestamp 00591 if (!strlen((string)$f->value)) $this->fields[] = false; 00592 else { 00593 if (!is_numeric($f->value)) # $val = variant_date_to_timestamp($f->value); 00594 // VT_DATE stores dates as (float) fractional days since 1899/12/30 00:00:00 00595 $val= (float) variant_cast($f->value,VT_R8)*3600*24-2209161600; 00596 else 00597 $val = $f->value; 00598 $this->fields[] = adodb_date('Y-m-d H:i:s',$val); 00599 } 00600 break; 00601 case 133:// A date value (yyyymmdd) 00602 if ($val = $f->value) { 00603 $this->fields[] = substr($val,0,4).'-'.substr($val,4,2).'-'.substr($val,6,2); 00604 } else 00605 $this->fields[] = false; 00606 break; 00607 case 7: // adDate 00608 if (!strlen((string)$f->value)) $this->fields[] = false; 00609 else { 00610 if (!is_numeric($f->value)) $val = variant_date_to_timestamp($f->value); 00611 else $val = $f->value; 00612 00613 if (($val % 86400) == 0) $this->fields[] = adodb_date('Y-m-d',$val); 00614 else $this->fields[] = adodb_date('Y-m-d H:i:s',$val); 00615 } 00616 break; 00617 case 1: // null 00618 $this->fields[] = false; 00619 break; 00620 case 6: // currency is not supported properly; 00621 ADOConnection::outp( '<b>'.$f->Name.': currency type not supported by PHP</b>'); 00622 $this->fields[] = (float) $f->value; 00623 break; 00624 default: 00625 $this->fields[] = $f->value; 00626 break; 00627 } 00628 //print " $f->value $t, "; 00629 $f = next($this->_flds); 00630 $t = next($this->_tarr); 00631 } // for 00632 if ($this->hideErrors) error_reporting($olde); 00633 @$rs->MoveNext(); // @ needed for some versions of PHP! 00634 00635 if ($this->fetchMode & ADODB_FETCH_ASSOC) { 00636 $this->fields = &$this->GetRowAssoc(ADODB_ASSOC_CASE); 00637 } 00638 return true; 00639 } 00640 00641 function NextRecordSet() 00642 { 00643 $rs = $this->_queryID; 00644 $this->_queryID = $rs->NextRecordSet(); 00645 //$this->_queryID = $this->_QueryId->NextRecordSet(); 00646 if ($this->_queryID == null) return false; 00647 00648 $this->_currentRow = -1; 00649 $this->_currentPage = -1; 00650 $this->bind = false; 00651 $this->fields = false; 00652 $this->_flds = false; 00653 $this->_tarr = false; 00654 00655 $this->_inited = false; 00656 $this->Init(); 00657 return true; 00658 } 00659 00660 function _close() { 00661 $this->_flds = false; 00662 @$this->_queryID->Close();// by Pete Dishman (peterd@telephonetics.co.uk) 00663 $this->_queryID = false; 00664 } 00665 00666 } 00667 00668 ?>