00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 if (!defined('ADODB_DIR')) die();
00015
00016 define("_ADODB_ODBC_LAYER", 2 );
00017
00018
00019
00020
00021
00022 class ADODB_odbc extends ADOConnection {
00023 var $databaseType = "odbc";
00024 var $fmtDate = "'Y-m-d'";
00025 var $fmtTimeStamp = "'Y-m-d, h:i:sA'";
00026 var $replaceQuote = "''";
00027 var $dataProvider = "odbc";
00028 var $hasAffectedRows = true;
00029 var $binmode = ODBC_BINMODE_RETURN;
00030 var $useFetchArray = false;
00031
00032
00033 var $_bindInputArray = false;
00034 var $curmode = SQL_CUR_USE_DRIVER;
00035 var $_genSeqSQL = "create table %s (id integer)";
00036 var $_autocommit = true;
00037 var $_haserrorfunctions = true;
00038 var $_has_stupid_odbc_fetch_api_change = true;
00039 var $_lastAffectedRows = 0;
00040 var $uCaseTables = true;
00041
00042 function ADODB_odbc()
00043 {
00044 $this->_haserrorfunctions = ADODB_PHPVER >= 0x4050;
00045 $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
00046 }
00047
00048
00049 function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)
00050 {
00051 global $php_errormsg;
00052
00053 if (!function_exists('odbc_connect')) return null;
00054
00055 if ($this->debug && $argDatabasename && $this->databaseType != 'vfp') {
00056 ADOConnection::outp("For odbc Connect(), $argDatabasename is not used. Place dsn in 1st parameter.");
00057 }
00058 if (isset($php_errormsg)) $php_errormsg = '';
00059 if ($this->curmode === false) $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword);
00060 else $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword,$this->curmode);
00061 $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
00062 if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
00063
00064 return $this->_connectionID != false;
00065 }
00066
00067
00068 function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
00069 {
00070 global $php_errormsg;
00071
00072 if (!function_exists('odbc_connect')) return null;
00073
00074 if (isset($php_errormsg)) $php_errormsg = '';
00075 $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
00076 if ($this->debug && $argDatabasename) {
00077 ADOConnection::outp("For odbc PConnect(), $argDatabasename is not used. Place dsn in 1st parameter.");
00078 }
00079
00080 if ($this->curmode === false) $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword);
00081 else $this->_connectionID = odbc_pconnect($argDSN,$argUsername,$argPassword,$this->curmode);
00082
00083 $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
00084 if ($this->_connectionID && $this->autoRollback) @odbc_rollback($this->_connectionID);
00085 if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
00086
00087 return $this->_connectionID != false;
00088 }
00089
00090
00091 function ServerInfo()
00092 {
00093
00094 if (!empty($this->host) && ADODB_PHPVER >= 0x4300) {
00095 $dsn = strtoupper($this->host);
00096 $first = true;
00097 $found = false;
00098
00099 if (!function_exists('odbc_data_source')) return false;
00100
00101 while(true) {
00102
00103 $rez = @odbc_data_source($this->_connectionID,
00104 $first ? SQL_FETCH_FIRST : SQL_FETCH_NEXT);
00105 $first = false;
00106 if (!is_array($rez)) break;
00107 if (strtoupper($rez['server']) == $dsn) {
00108 $found = true;
00109 break;
00110 }
00111 }
00112 if (!$found) return ADOConnection::ServerInfo();
00113 if (!isset($rez['version'])) $rez['version'] = '';
00114 return $rez;
00115 } else {
00116 return ADOConnection::ServerInfo();
00117 }
00118 }
00119
00120
00121 function CreateSequence($seqname='adodbseq',$start=1)
00122 {
00123 if (empty($this->_genSeqSQL)) return false;
00124 $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
00125 if (!$ok) return false;
00126 $start -= 1;
00127 return $this->Execute("insert into $seqname values($start)");
00128 }
00129
00130 var $_dropSeqSQL = 'drop table %s';
00131 function DropSequence($seqname)
00132 {
00133 if (empty($this->_dropSeqSQL)) return false;
00134 return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
00135 }
00136
00137
00138
00139
00140
00141
00142
00143 function GenID($seq='adodbseq',$start=1)
00144 {
00145
00146
00147 $MAXLOOPS = 100;
00148
00149 while (--$MAXLOOPS>=0) {
00150 $num = $this->GetOne("select id from $seq");
00151 if ($num === false) {
00152 $this->Execute(sprintf($this->_genSeqSQL ,$seq));
00153 $start -= 1;
00154 $num = '0';
00155 $ok = $this->Execute("insert into $seq values($start)");
00156 if (!$ok) return false;
00157 }
00158 $this->Execute("update $seq set id=id+1 where id=$num");
00159
00160 if ($this->affected_rows() > 0) {
00161 $num += 1;
00162 $this->genID = $num;
00163 return $num;
00164 }
00165 }
00166 if ($fn = $this->raiseErrorFn) {
00167 $fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);
00168 }
00169 return false;
00170 }
00171
00172
00173 function ErrorMsg()
00174 {
00175 if ($this->_haserrorfunctions) {
00176 if ($this->_errorMsg !== false) return $this->_errorMsg;
00177 if (empty($this->_connectionID)) return @odbc_errormsg();
00178 return @odbc_errormsg($this->_connectionID);
00179 } else return ADOConnection::ErrorMsg();
00180 }
00181
00182 function ErrorNo()
00183 {
00184
00185 if ($this->_haserrorfunctions) {
00186 if ($this->_errorCode !== false) {
00187
00188 return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode;
00189 }
00190
00191 if (empty($this->_connectionID)) $e = @odbc_error();
00192 else $e = @odbc_error($this->_connectionID);
00193
00194
00195
00196 if (strlen($e)<=2) return 0;
00197 return $e;
00198 } else return ADOConnection::ErrorNo();
00199 }
00200
00201
00202
00203 function BeginTrans()
00204 {
00205 if (!$this->hasTransactions) return false;
00206 if ($this->transOff) return true;
00207 $this->transCnt += 1;
00208 $this->_autocommit = false;
00209 return odbc_autocommit($this->_connectionID,false);
00210 }
00211
00212 function CommitTrans($ok=true)
00213 {
00214 if ($this->transOff) return true;
00215 if (!$ok) return $this->RollbackTrans();
00216 if ($this->transCnt) $this->transCnt -= 1;
00217 $this->_autocommit = true;
00218 $ret = odbc_commit($this->_connectionID);
00219 odbc_autocommit($this->_connectionID,true);
00220 return $ret;
00221 }
00222
00223 function RollbackTrans()
00224 {
00225 if ($this->transOff) return true;
00226 if ($this->transCnt) $this->transCnt -= 1;
00227 $this->_autocommit = true;
00228 $ret = odbc_rollback($this->_connectionID);
00229 odbc_autocommit($this->_connectionID,true);
00230 return $ret;
00231 }
00232
00233 function MetaPrimaryKeys($table)
00234 {
00235 global $ADODB_FETCH_MODE;
00236
00237 if ($this->uCaseTables) $table = strtoupper($table);
00238 $schema = '';
00239 $this->_findschema($table,$schema);
00240
00241 $savem = $ADODB_FETCH_MODE;
00242 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00243 $qid = @odbc_primarykeys($this->_connectionID,'',$schema,$table);
00244
00245 if (!$qid) {
00246 $ADODB_FETCH_MODE = $savem;
00247 return false;
00248 }
00249 $rs = new ADORecordSet_odbc($qid);
00250 $ADODB_FETCH_MODE = $savem;
00251
00252 if (!$rs) return false;
00253 $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
00254
00255 $arr =& $rs->GetArray();
00256 $rs->Close();
00257
00258 $arr2 = array();
00259 for ($i=0; $i < sizeof($arr); $i++) {
00260 if ($arr[$i][3]) $arr2[] = $arr[$i][3];
00261 }
00262 return $arr2;
00263 }
00264
00265
00266
00267 function &MetaTables($ttype=false)
00268 {
00269 global $ADODB_FETCH_MODE;
00270
00271 $savem = $ADODB_FETCH_MODE;
00272 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00273 $qid = odbc_tables($this->_connectionID);
00274
00275 $rs = new ADORecordSet_odbc($qid);
00276
00277 $ADODB_FETCH_MODE = $savem;
00278 if (!$rs) {
00279 $false = false;
00280 return $false;
00281 }
00282 $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
00283
00284 $arr =& $rs->GetArray();
00285
00286
00287 $rs->Close();
00288 $arr2 = array();
00289
00290 if ($ttype) {
00291 $isview = strncmp($ttype,'V',1) === 0;
00292 }
00293 for ($i=0; $i < sizeof($arr); $i++) {
00294 if (!$arr[$i][2]) continue;
00295 $type = $arr[$i][3];
00296 if ($ttype) {
00297 if ($isview) {
00298 if (strncmp($type,'V',1) === 0) $arr2[] = $arr[$i][2];
00299 } else if (strncmp($type,'SYS',3) !== 0) $arr2[] = $arr[$i][2];
00300 } else if (strncmp($type,'SYS',3) !== 0) $arr2[] = $arr[$i][2];
00301 }
00302 return $arr2;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 function ODBCTypes($t)
00334 {
00335 switch ((integer)$t) {
00336 case 1:
00337 case 12:
00338 case 0:
00339 case -95:
00340 case -96:
00341 return 'C';
00342 case -97:
00343 case -1:
00344 return 'X';
00345 case -4:
00346 return 'B';
00347
00348 case 9:
00349 case 91:
00350 return 'D';
00351
00352 case 10:
00353 case 11:
00354 case 92:
00355 case 93:
00356 return 'T';
00357
00358 case 4:
00359 case 5:
00360 case -6:
00361 return 'I';
00362
00363 case -11:
00364 return 'R';
00365 case -7:
00366 return 'L';
00367
00368 default:
00369 return 'N';
00370 }
00371 }
00372
00373 function &MetaColumns($table)
00374 {
00375 global $ADODB_FETCH_MODE;
00376
00377 $false = false;
00378 if ($this->uCaseTables) $table = strtoupper($table);
00379 $schema = '';
00380 $this->_findschema($table,$schema);
00381
00382 $savem = $ADODB_FETCH_MODE;
00383 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 switch ($this->databaseType) {
00407 case 'access':
00408 case 'vfp':
00409 $qid = odbc_columns($this->_connectionID);#,'%','',strtoupper($table),'%');
00410 break;
00411
00412
00413 case 'db2':
00414 $colname = "%";
00415 $qid = odbc_columns($this->_connectionID, "", $schema, $table, $colname);
00416 break;
00417
00418 default:
00419 $qid = @odbc_columns($this->_connectionID,'%','%',strtoupper($table),'%');
00420 if (empty($qid)) $qid = odbc_columns($this->_connectionID);
00421 break;
00422 }
00423 if (empty($qid)) return $false;
00424
00425 $rs =& new ADORecordSet_odbc($qid);
00426 $ADODB_FETCH_MODE = $savem;
00427
00428 if (!$rs) return $false;
00429 $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
00430 $rs->_fetch();
00431
00432 $retarr = array();
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 while (!$rs->EOF) {
00450
00451 if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
00452 $fld = new ADOFieldObject();
00453 $fld->name = $rs->fields[3];
00454 $fld->type = $this->ODBCTypes($rs->fields[4]);
00455
00456
00457
00458 if ($fld->type == 'C' or $fld->type == 'X') {
00459 if ($this->databaseType == 'access')
00460 $fld->max_length = $rs->fields[6];
00461 else if ($rs->fields[4] <= -95)
00462 $fld->max_length = $rs->fields[7]/2;
00463 else
00464 $fld->max_length = $rs->fields[7];
00465 } else
00466 $fld->max_length = $rs->fields[7];
00467 $fld->not_null = !empty($rs->fields[10]);
00468 $fld->scale = $rs->fields[8];
00469 $retarr[strtoupper($fld->name)] = $fld;
00470 } else if (sizeof($retarr)>0)
00471 break;
00472 $rs->MoveNext();
00473 }
00474 $rs->Close();
00475
00476 if (empty($retarr)) $retarr = false;
00477 return $retarr;
00478 }
00479
00480 function Prepare($sql)
00481 {
00482 if (! $this->_bindInputArray) return $sql;
00483 $stmt = odbc_prepare($this->_connectionID,$sql);
00484 if (!$stmt) {
00485
00486 return $sql;
00487 }
00488 return array($sql,$stmt,false);
00489 }
00490
00491
00492 function _query($sql,$inputarr=false)
00493 {
00494 GLOBAL $php_errormsg;
00495 if (isset($php_errormsg)) $php_errormsg = '';
00496 $this->_error = '';
00497
00498 if ($inputarr) {
00499 if (is_array($sql)) {
00500 $stmtid = $sql[1];
00501 } else {
00502 $stmtid = odbc_prepare($this->_connectionID,$sql);
00503
00504 if ($stmtid == false) {
00505 $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
00506 return false;
00507 }
00508 }
00509
00510 if (! odbc_execute($stmtid,$inputarr)) {
00511
00512 if ($this->_haserrorfunctions) {
00513 $this->_errorMsg = odbc_errormsg();
00514 $this->_errorCode = odbc_error();
00515 }
00516 if($this->_errorCode == '00000') {
00517 $this->_errorMsg = '';
00518 $this->_errorCode = 0;
00519 return true;
00520 }
00521 return false;
00522 }
00523
00524 } else if (is_array($sql)) {
00525 $stmtid = $sql[1];
00526 if (!odbc_execute($stmtid)) {
00527
00528 if ($this->_haserrorfunctions) {
00529 $this->_errorMsg = odbc_errormsg();
00530 $this->_errorCode = odbc_error();
00531 }
00532 if($this->_errorCode == '00000') {
00533 $this->_errorMsg = '';
00534 $this->_errorCode = 0;
00535 return true;
00536 }
00537 return false;
00538 }
00539 } else
00540 $stmtid = odbc_exec($this->_connectionID,$sql);
00541
00542 $this->_lastAffectedRows = 0;
00543 if ($stmtid) {
00544 if (@odbc_num_fields($stmtid) == 0) {
00545 $this->_lastAffectedRows = odbc_num_rows($stmtid);
00546 $stmtid = true;
00547 } else {
00548 $this->_lastAffectedRows = 0;
00549 odbc_binmode($stmtid,$this->binmode);
00550 odbc_longreadlen($stmtid,$this->maxblobsize);
00551 }
00552
00553 if ($this->_haserrorfunctions) {
00554 $this->_errorMsg = '';
00555 $this->_errorCode = 0;
00556 } else
00557 $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
00558 } else {
00559 if ($this->_haserrorfunctions) {
00560 $this->_errorMsg = odbc_errormsg();
00561 $this->_errorCode = odbc_error();
00562 } else
00563 $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
00564 }
00565 return $stmtid;
00566 }
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
00578 {
00579 return $this->Execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false;
00580 }
00581
00582
00583 function _close()
00584 {
00585 $ret = @odbc_close($this->_connectionID);
00586 $this->_connectionID = false;
00587 return $ret;
00588 }
00589
00590 function _affectedrows()
00591 {
00592 return $this->_lastAffectedRows;
00593 }
00594
00595 }
00596
00597
00598
00599
00600
00601 class ADORecordSet_odbc extends ADORecordSet {
00602
00603 var $bind = false;
00604 var $databaseType = "odbc";
00605 var $dataProvider = "odbc";
00606 var $useFetchArray;
00607 var $_has_stupid_odbc_fetch_api_change;
00608
00609 function ADORecordSet_odbc($id,$mode=false)
00610 {
00611 if ($mode === false) {
00612 global $ADODB_FETCH_MODE;
00613 $mode = $ADODB_FETCH_MODE;
00614 }
00615 $this->fetchMode = $mode;
00616
00617 $this->_queryID = $id;
00618
00619
00620 $this->EOF = false;
00621 $this->_currentRow = -1;
00622
00623 }
00624
00625
00626
00627 function &FetchField($fieldOffset = -1)
00628 {
00629
00630 $off=$fieldOffset+1;
00631
00632 $o= new ADOFieldObject();
00633 $o->name = @odbc_field_name($this->_queryID,$off);
00634 $o->type = @odbc_field_type($this->_queryID,$off);
00635 $o->max_length = @odbc_field_len($this->_queryID,$off);
00636 if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name);
00637 else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name);
00638 return $o;
00639 }
00640
00641
00642 function Fields($colname)
00643 {
00644 if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
00645 if (!$this->bind) {
00646 $this->bind = array();
00647 for ($i=0; $i < $this->_numOfFields; $i++) {
00648 $o = $this->FetchField($i);
00649 $this->bind[strtoupper($o->name)] = $i;
00650 }
00651 }
00652
00653 return $this->fields[$this->bind[strtoupper($colname)]];
00654 }
00655
00656
00657 function _initrs()
00658 {
00659 global $ADODB_COUNTRECS;
00660 $this->_numOfRows = ($ADODB_COUNTRECS) ? @odbc_num_rows($this->_queryID) : -1;
00661 $this->_numOfFields = @odbc_num_fields($this->_queryID);
00662
00663 if ($this->_numOfRows == 0) $this->_numOfRows = -1;
00664
00665 $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
00666 }
00667
00668 function _seek($row)
00669 {
00670 return false;
00671 }
00672
00673
00674 function &GetArrayLimit($nrows,$offset=-1)
00675 {
00676 if ($offset <= 0) {
00677 $rs =& $this->GetArray($nrows);
00678 return $rs;
00679 }
00680 $savem = $this->fetchMode;
00681 $this->fetchMode = ADODB_FETCH_NUM;
00682 $this->Move($offset);
00683 $this->fetchMode = $savem;
00684
00685 if ($this->fetchMode & ADODB_FETCH_ASSOC) {
00686 $this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE);
00687 }
00688
00689 $results = array();
00690 $cnt = 0;
00691 while (!$this->EOF && $nrows != $cnt) {
00692 $results[$cnt++] = $this->fields;
00693 $this->MoveNext();
00694 }
00695
00696 return $results;
00697 }
00698
00699
00700 function MoveNext()
00701 {
00702 if ($this->_numOfRows != 0 && !$this->EOF) {
00703 $this->_currentRow++;
00704
00705 if ($this->_has_stupid_odbc_fetch_api_change)
00706 $rez = @odbc_fetch_into($this->_queryID,$this->fields);
00707 else {
00708 $row = 0;
00709 $rez = @odbc_fetch_into($this->_queryID,$row,$this->fields);
00710 }
00711 if ($rez) {
00712 if ($this->fetchMode & ADODB_FETCH_ASSOC) {
00713 $this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE);
00714 }
00715 return true;
00716 }
00717 }
00718 $this->fields = false;
00719 $this->EOF = true;
00720 return false;
00721 }
00722
00723 function _fetch()
00724 {
00725
00726 if ($this->_has_stupid_odbc_fetch_api_change)
00727 $rez = @odbc_fetch_into($this->_queryID,$this->fields);
00728 else {
00729 $row = 0;
00730 $rez = @odbc_fetch_into($this->_queryID,$row,$this->fields);
00731 }
00732 if ($rez) {
00733 if ($this->fetchMode & ADODB_FETCH_ASSOC) {
00734 $this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE);
00735 }
00736 return true;
00737 }
00738 $this->fields = false;
00739 return false;
00740 }
00741
00742 function _close()
00743 {
00744 return @odbc_free_result($this->_queryID);
00745 }
00746
00747 }
00748 ?>