1<?php 2/* 3 V5.06 16 Oct 2008 (c) 2006 John Lim (jlim#natsoft.com). All rights reserved. 4 5 This is a version of the ADODB driver for DB2. It uses the 'ibm_db2' PECL extension 6 for PHP (http://pecl.php.net/package/ibm_db2), which in turn requires DB2 V8.2.2 or 7 higher. 8 9 Originally tested with PHP 5.1.1 and Apache 2.0.55 on Windows XP SP2. 10 More recently tested with PHP 5.1.2 and Apache 2.0.55 on Windows XP SP2. 11 12 This file was ported from "adodb-odbc.inc.php" by Larry Menard, "larry.menard#rogers.com". 13 I ripped out what I believed to be a lot of redundant or obsolete code, but there are 14 probably still some remnants of the ODBC support in this file; I'm relying on reviewers 15 of this code to point out any other things that can be removed. 16*/ 17 18// security - hide paths 19if (!defined('ADODB_DIR')) die(); 20 21 define("_ADODB_DB2_LAYER", 2 ); 22 23/*-------------------------------------------------------------------------------------- 24--------------------------------------------------------------------------------------*/ 25 26 27 28 29 30class ADODB_db2 extends ADOConnection { 31 var $databaseType = "db2"; 32 var $fmtDate = "'Y-m-d'"; 33 var $concat_operator = '||'; 34 35 var $sysTime = 'CURRENT TIME'; 36 var $sysDate = 'CURRENT DATE'; 37 var $sysTimeStamp = 'CURRENT TIMESTAMP'; 38 39 var $fmtTimeStamp = "'Y-m-d H:i:s'"; 40 var $replaceQuote = "''"; // string to use to replace quotes 41 var $dataProvider = "db2"; 42 var $hasAffectedRows = true; 43 44 var $binmode = DB2_BINARY; 45 46 var $useFetchArray = false; // setting this to true will make array elements in FETCH_ASSOC mode case-sensitive 47 // breaking backward-compat 48 var $_bindInputArray = false; 49 var $_genIDSQL = "VALUES NEXTVAL FOR %s"; 50 var $_genSeqSQL = "CREATE SEQUENCE %s START WITH %s NO MAXVALUE NO CYCLE"; 51 var $_dropSeqSQL = "DROP SEQUENCE %s"; 52 var $_autocommit = true; 53 var $_haserrorfunctions = true; 54 var $_lastAffectedRows = 0; 55 var $uCaseTables = true; // for meta* functions, uppercase table names 56 var $hasInsertID = true; 57 58 59 function _insertid() 60 { 61 return ADOConnection::GetOne('VALUES IDENTITY_VAL_LOCAL()'); 62 } 63 64 function ADODB_db2() 65 { 66 $this->_haserrorfunctions = ADODB_PHPVER >= 0x4050; 67 } 68 69 // returns true or false 70 function _connect($argDSN, $argUsername, $argPassword, $argDatabasename) 71 { 72 global $php_errormsg; 73 74 if (!function_exists('db2_connect')) { 75 ADOConnection::outp("Warning: The old ODBC based DB2 driver has been renamed 'odbc_db2'. This ADOdb driver calls PHP's native db2 extension which is not installed."); 76 return null; 77 } 78 // This needs to be set before the connect(). 79 // Replaces the odbc_binmode() call that was in Execute() 80 ini_set('ibm_db2.binmode', $this->binmode); 81 82 if ($argDatabasename && empty($argDSN)) { 83 84 if (stripos($argDatabasename,'UID=') && stripos($argDatabasename,'PWD=')) $this->_connectionID = db2_connect($argDatabasename,null,null); 85 else $this->_connectionID = db2_connect($argDatabasename,$argUsername,$argPassword); 86 } else { 87 if ($argDatabasename) $schema = $argDatabasename; 88 if (stripos($argDSN,'UID=') && stripos($argDSN,'PWD=')) $this->_connectionID = db2_connect($argDSN,null,null); 89 else $this->_connectionID = db2_connect($argDSN,$argUsername,$argPassword); 90 } 91 if (isset($php_errormsg)) $php_errormsg = ''; 92 93 // For db2_connect(), there is an optional 4th arg. If present, it must be 94 // an array of valid options. So far, we don't use them. 95 96 $this->_errorMsg = @db2_conn_errormsg(); 97 if (isset($this->connectStmt)) $this->Execute($this->connectStmt); 98 99 if ($this->_connectionID && isset($schema)) $this->Execute("SET SCHEMA=$schema"); 100 return $this->_connectionID != false; 101 } 102 103 // returns true or false 104 function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename) 105 { 106 global $php_errormsg; 107 108 if (!function_exists('db2_connect')) return null; 109 110 // This needs to be set before the connect(). 111 // Replaces the odbc_binmode() call that was in Execute() 112 ini_set('ibm_db2.binmode', $this->binmode); 113 114 if (isset($php_errormsg)) $php_errormsg = ''; 115 $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; 116 117 if ($argDatabasename && empty($argDSN)) { 118 119 if (stripos($argDatabasename,'UID=') && stripos($argDatabasename,'PWD=')) $this->_connectionID = db2_pconnect($argDatabasename,null,null); 120 else $this->_connectionID = db2_pconnect($argDatabasename,$argUsername,$argPassword); 121 } else { 122 if ($argDatabasename) $schema = $argDatabasename; 123 if (stripos($argDSN,'UID=') && stripos($argDSN,'PWD=')) $this->_connectionID = db2_pconnect($argDSN,null,null); 124 else $this->_connectionID = db2_pconnect($argDSN,$argUsername,$argPassword); 125 } 126 if (isset($php_errormsg)) $php_errormsg = ''; 127 128 $this->_errorMsg = @db2_conn_errormsg(); 129 if ($this->_connectionID && $this->autoRollback) @db2_rollback($this->_connectionID); 130 if (isset($this->connectStmt)) $this->Execute($this->connectStmt); 131 132 if ($this->_connectionID && isset($schema)) $this->Execute("SET SCHEMA=$schema"); 133 return $this->_connectionID != false; 134 } 135 136 // format and return date string in database timestamp format 137 function DBTimeStamp($ts) 138 { 139 if (empty($ts) && $ts !== 0) return 'null'; 140 if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts); 141 return 'TO_DATE('.adodb_date($this->fmtTimeStamp,$ts).",'YYYY-MM-DD HH24:MI:SS')"; 142 } 143 144 // Format date column in sql string given an input format that understands Y M D 145 function SQLDate($fmt, $col=false) 146 { 147 // use right() and replace() ? 148 if (!$col) $col = $this->sysDate; 149 150 /* use TO_CHAR() if $fmt is TO_CHAR() allowed fmt */ 151 if ($fmt== 'Y-m-d H:i:s') 152 return 'TO_CHAR('.$col.", 'YYYY-MM-DD HH24:MI:SS')"; 153 154 $s = ''; 155 156 $len = strlen($fmt); 157 for ($i=0; $i < $len; $i++) { 158 if ($s) $s .= $this->concat_operator; 159 $ch = $fmt[$i]; 160 switch($ch) { 161 case 'Y': 162 case 'y': 163 if ($len==1) return "year($col)"; 164 $s .= "char(year($col))"; 165 break; 166 case 'M': 167 if ($len==1) return "monthname($col)"; 168 $s .= "substr(monthname($col),1,3)"; 169 break; 170 case 'm': 171 if ($len==1) return "month($col)"; 172 $s .= "right(digits(month($col)),2)"; 173 break; 174 case 'D': 175 case 'd': 176 if ($len==1) return "day($col)"; 177 $s .= "right(digits(day($col)),2)"; 178 break; 179 case 'H': 180 case 'h': 181 if ($len==1) return "hour($col)"; 182 if ($col != $this->sysDate) $s .= "right(digits(hour($col)),2)"; 183 else $s .= "''"; 184 break; 185 case 'i': 186 case 'I': 187 if ($len==1) return "minute($col)"; 188 if ($col != $this->sysDate) 189 $s .= "right(digits(minute($col)),2)"; 190 else $s .= "''"; 191 break; 192 case 'S': 193 case 's': 194 if ($len==1) return "second($col)"; 195 if ($col != $this->sysDate) 196 $s .= "right(digits(second($col)),2)"; 197 else $s .= "''"; 198 break; 199 default: 200 if ($ch == '\\') { 201 $i++; 202 $ch = substr($fmt,$i,1); 203 } 204 $s .= $this->qstr($ch); 205 } 206 } 207 return $s; 208 } 209 210 211 function ServerInfo() 212 { 213 214 if (!empty($this->host) && ADODB_PHPVER >= 0x4300) { 215 $dsn = strtoupper($this->host); 216 $first = true; 217 $found = false; 218 219 if (!function_exists('db2_data_source')) return false; 220 221 while(true) { 222 223 $rez = @db2_data_source($this->_connectionID, 224 $first ? SQL_FETCH_FIRST : SQL_FETCH_NEXT); 225 $first = false; 226 if (!is_array($rez)) break; 227 if (strtoupper($rez['server']) == $dsn) { 228 $found = true; 229 break; 230 } 231 } 232 if (!$found) return ADOConnection::ServerInfo(); 233 if (!isset($rez['version'])) $rez['version'] = ''; 234 return $rez; 235 } else { 236 return ADOConnection::ServerInfo(); 237 } 238 } 239 240 function CreateSequence($seqname='adodbseq',$start=1) 241 { 242 if (empty($this->_genSeqSQL)) return false; 243 $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname,$start)); 244 if (!$ok) return false; 245 return true; 246 } 247 248 function DropSequence($seqname) 249 { 250 if (empty($this->_dropSeqSQL)) return false; 251 return $this->Execute(sprintf($this->_dropSeqSQL,$seqname)); 252 } 253 254 function SelectLimit($sql,$nrows=-1,$offset=-1,$inputArr=false) 255 { 256 $nrows = (integer) $nrows; 257 if ($offset <= 0) { 258 // could also use " OPTIMIZE FOR $nrows ROWS " 259 if ($nrows >= 0) $sql .= " FETCH FIRST $nrows ROWS ONLY "; 260 $rs = $this->Execute($sql,$inputArr); 261 } else { 262 if ($offset > 0 && $nrows < 0); 263 else { 264 $nrows += $offset; 265 $sql .= " FETCH FIRST $nrows ROWS ONLY "; 266 } 267 $rs = ADOConnection::SelectLimit($sql,-1,$offset,$inputArr); 268 } 269 270 return $rs; 271 } 272 273 /* 274 This algorithm is not very efficient, but works even if table locking 275 is not available. 276 277 Will return false if unable to generate an ID after $MAXLOOPS attempts. 278 */ 279 function GenID($seq='adodbseq',$start=1) 280 { 281 // if you have to modify the parameter below, your database is overloaded, 282 // or you need to implement generation of id's yourself! 283 $num = $this->GetOne("VALUES NEXTVAL FOR $seq"); 284 return $num; 285 } 286 287 288 function ErrorMsg() 289 { 290 if ($this->_haserrorfunctions) { 291 if ($this->_errorMsg !== false) return $this->_errorMsg; 292 if (empty($this->_connectionID)) return @db2_conn_errormsg(); 293 return @db2_conn_errormsg($this->_connectionID); 294 } else return ADOConnection::ErrorMsg(); 295 } 296 297 function ErrorNo() 298 { 299 300 if ($this->_haserrorfunctions) { 301 if ($this->_errorCode !== false) { 302 // bug in 4.0.6, error number can be corrupted string (should be 6 digits) 303 return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode; 304 } 305 306 if (empty($this->_connectionID)) $e = @db2_conn_error(); 307 else $e = @db2_conn_error($this->_connectionID); 308 309 // bug in 4.0.6, error number can be corrupted string (should be 6 digits) 310 // so we check and patch 311 if (strlen($e)<=2) return 0; 312 return $e; 313 } else return ADOConnection::ErrorNo(); 314 } 315 316 317 318 function BeginTrans() 319 { 320 if (!$this->hasTransactions) return false; 321 if ($this->transOff) return true; 322 $this->transCnt += 1; 323 $this->_autocommit = false; 324 return db2_autocommit($this->_connectionID,false); 325 } 326 327 function CommitTrans($ok=true) 328 { 329 if ($this->transOff) return true; 330 if (!$ok) return $this->RollbackTrans(); 331 if ($this->transCnt) $this->transCnt -= 1; 332 $this->_autocommit = true; 333 $ret = db2_commit($this->_connectionID); 334 db2_autocommit($this->_connectionID,true); 335 return $ret; 336 } 337 338 function RollbackTrans() 339 { 340 if ($this->transOff) return true; 341 if ($this->transCnt) $this->transCnt -= 1; 342 $this->_autocommit = true; 343 $ret = db2_rollback($this->_connectionID); 344 db2_autocommit($this->_connectionID,true); 345 return $ret; 346 } 347 348 function MetaPrimaryKeys($table) 349 { 350 global $ADODB_FETCH_MODE; 351 352 if ($this->uCaseTables) $table = strtoupper($table); 353 $schema = ''; 354 $this->_findschema($table,$schema); 355 356 $savem = $ADODB_FETCH_MODE; 357 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 358 $qid = @db2_primarykeys($this->_connectionID,'',$schema,$table); 359 360 if (!$qid) { 361 $ADODB_FETCH_MODE = $savem; 362 return false; 363 } 364 $rs = new ADORecordSet_db2($qid); 365 $ADODB_FETCH_MODE = $savem; 366 367 if (!$rs) return false; 368 369 $arr = $rs->GetArray(); 370 $rs->Close(); 371 $arr2 = array(); 372 for ($i=0; $i < sizeof($arr); $i++) { 373 if ($arr[$i][3]) $arr2[] = $arr[$i][3]; 374 } 375 return $arr2; 376 } 377 378 function MetaForeignKeys($table, $owner = FALSE, $upper = FALSE, $asociative = FALSE ) 379 { 380 global $ADODB_FETCH_MODE; 381 382 if ($this->uCaseTables) $table = strtoupper($table); 383 $schema = ''; 384 $this->_findschema($table,$schema); 385 386 $savem = $ADODB_FETCH_MODE; 387 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 388 $qid = @db2_foreign_keys($this->_connectionID,'',$schema,$table); 389 if (!$qid) { 390 $ADODB_FETCH_MODE = $savem; 391 return false; 392 } 393 $rs = new ADORecordSet_db2($qid); 394 395 $ADODB_FETCH_MODE = $savem; 396 /* 397 $rs->fields indices 398 0 PKTABLE_CAT 399 1 PKTABLE_SCHEM 400 2 PKTABLE_NAME 401 3 PKCOLUMN_NAME 402 4 FKTABLE_CAT 403 5 FKTABLE_SCHEM 404 6 FKTABLE_NAME 405 7 FKCOLUMN_NAME 406 */ 407 if (!$rs) return false; 408 409 $foreign_keys = array(); 410 while (!$rs->EOF) { 411 if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) { 412 if (!is_array($foreign_keys[$rs->fields[5].'.'.$rs->fields[6]])) 413 $foreign_keys[$rs->fields[5].'.'.$rs->fields[6]] = array(); 414 $foreign_keys[$rs->fields[5].'.'.$rs->fields[6]][$rs->fields[7]] = $rs->fields[3]; 415 } 416 $rs->MoveNext(); 417 } 418 419 $rs->Close(); 420 return $foreign_key; 421 } 422 423 424 function MetaTables($ttype=false,$schema=false) 425 { 426 global $ADODB_FETCH_MODE; 427 428 $savem = $ADODB_FETCH_MODE; 429 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 430 $qid = db2_tables($this->_connectionID); 431 432 $rs = new ADORecordSet_db2($qid); 433 434 $ADODB_FETCH_MODE = $savem; 435 if (!$rs) { 436 $false = false; 437 return $false; 438 } 439 440 $arr = $rs->GetArray(); 441 $rs->Close(); 442 $arr2 = array(); 443 444 if ($ttype) { 445 $isview = strncmp($ttype,'V',1) === 0; 446 } 447 for ($i=0; $i < sizeof($arr); $i++) { 448 if (!$arr[$i][2]) continue; 449 $type = $arr[$i][3]; 450 $owner = $arr[$i][1]; 451 $schemaval = ($schema) ? $arr[$i][1].'.' : ''; 452 if ($ttype) { 453 if ($isview) { 454 if (strncmp($type,'V',1) === 0) $arr2[] = $schemaval.$arr[$i][2]; 455 } else if (strncmp($owner,'SYS',3) !== 0) $arr2[] = $schemaval.$arr[$i][2]; 456 } else if (strncmp($owner,'SYS',3) !== 0) $arr2[] = $schemaval.$arr[$i][2]; 457 } 458 return $arr2; 459 } 460 461/* 462See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2datetime_data_type_changes.asp 463/ SQL data type codes / 464#define SQL_UNKNOWN_TYPE 0 465#define SQL_CHAR 1 466#define SQL_NUMERIC 2 467#define SQL_DECIMAL 3 468#define SQL_INTEGER 4 469#define SQL_SMALLINT 5 470#define SQL_FLOAT 6 471#define SQL_REAL 7 472#define SQL_DOUBLE 8 473#if (DB2VER >= 0x0300) 474#define SQL_DATETIME 9 475#endif 476#define SQL_VARCHAR 12 477 478 479/ One-parameter shortcuts for date/time data types / 480#if (DB2VER >= 0x0300) 481#define SQL_TYPE_DATE 91 482#define SQL_TYPE_TIME 92 483#define SQL_TYPE_TIMESTAMP 93 484 485#define SQL_UNICODE (-95) 486#define SQL_UNICODE_VARCHAR (-96) 487#define SQL_UNICODE_LONGVARCHAR (-97) 488*/ 489 function DB2Types($t) 490 { 491 switch ((integer)$t) { 492 case 1: 493 case 12: 494 case 0: 495 case -95: 496 case -96: 497 return 'C'; 498 case -97: 499 case -1: //text 500 return 'X'; 501 case -4: //image 502 return 'B'; 503 504 case 9: 505 case 91: 506 return 'D'; 507 508 case 10: 509 case 11: 510 case 92: 511 case 93: 512 return 'T'; 513 514 case 4: 515 case 5: 516 case -6: 517 return 'I'; 518 519 case -11: // uniqidentifier 520 return 'R'; 521 case -7: //bit 522 return 'L'; 523 524 default: 525 return 'N'; 526 } 527 } 528 529 function MetaColumns($table, $normalize=true) 530 { 531 global $ADODB_FETCH_MODE; 532 533 $false = false; 534 if ($this->uCaseTables) $table = strtoupper($table); 535 $schema = ''; 536 $this->_findschema($table,$schema); 537 538 $savem = $ADODB_FETCH_MODE; 539 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 540 541 $colname = "%"; 542 $qid = db2_columns($this->_connectionID, "", $schema, $table, $colname); 543 if (empty($qid)) return $false; 544 545 $rs = new ADORecordSet_db2($qid); 546 $ADODB_FETCH_MODE = $savem; 547 548 if (!$rs) return $false; 549 $rs->_fetch(); 550 551 $retarr = array(); 552 553 /* 554 $rs->fields indices 555 0 TABLE_QUALIFIER 556 1 TABLE_SCHEM 557 2 TABLE_NAME 558 3 COLUMN_NAME 559 4 DATA_TYPE 560 5 TYPE_NAME 561 6 PRECISION 562 7 LENGTH 563 8 SCALE 564 9 RADIX 565 10 NULLABLE 566 11 REMARKS 567 */ 568 while (!$rs->EOF) { 569 if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) { 570 $fld = new ADOFieldObject(); 571 $fld->name = $rs->fields[3]; 572 $fld->type = $this->DB2Types($rs->fields[4]); 573 574 // ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp 575 // access uses precision to store length for char/varchar 576 if ($fld->type == 'C' or $fld->type == 'X') { 577 if ($rs->fields[4] <= -95) // UNICODE 578 $fld->max_length = $rs->fields[7]/2; 579 else 580 $fld->max_length = $rs->fields[7]; 581 } else 582 $fld->max_length = $rs->fields[7]; 583 $fld->not_null = !empty($rs->fields[10]); 584 $fld->scale = $rs->fields[8]; 585 $fld->primary_key = false; 586 $retarr[strtoupper($fld->name)] = $fld; 587 } else if (sizeof($retarr)>0) 588 break; 589 $rs->MoveNext(); 590 } 591 $rs->Close(); 592 if (empty($retarr)) $retarr = false; 593 594 $qid = db2_primary_keys($this->_connectionID, "", $schema, $table); 595 if (empty($qid)) return $false; 596 597 $rs = new ADORecordSet_db2($qid); 598 $ADODB_FETCH_MODE = $savem; 599 600 if (!$rs) return $retarr; 601 $rs->_fetch(); 602 603 /* 604 $rs->fields indices 605 0 TABLE_CAT 606 1 TABLE_SCHEM 607 2 TABLE_NAME 608 3 COLUMN_NAME 609 4 KEY_SEQ 610 5 PK_NAME 611 */ 612 while (!$rs->EOF) { 613 if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) { 614 $retarr[strtoupper($rs->fields[3])]->primary_key = true; 615 } else if (sizeof($retarr)>0) 616 break; 617 $rs->MoveNext(); 618 } 619 $rs->Close(); 620 621 if (empty($retarr)) $retarr = false; 622 return $retarr; 623 } 624 625 626 function Prepare($sql) 627 { 628 if (! $this->_bindInputArray) return $sql; // no binding 629 $stmt = db2_prepare($this->_connectionID,$sql); 630 if (!$stmt) { 631 // we don't know whether db2 driver is parsing prepared stmts, so just return sql 632 return $sql; 633 } 634 return array($sql,$stmt,false); 635 } 636 637 /* returns queryID or false */ 638 function _query($sql,$inputarr=false) 639 { 640 GLOBAL $php_errormsg; 641 if (isset($php_errormsg)) $php_errormsg = ''; 642 $this->_error = ''; 643 644 if ($inputarr) { 645 if (is_array($sql)) { 646 $stmtid = $sql[1]; 647 } else { 648 $stmtid = db2_prepare($this->_connectionID,$sql); 649 650 if ($stmtid == false) { 651 $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; 652 return false; 653 } 654 } 655 656 if (! db2_execute($stmtid,$inputarr)) { 657 if ($this->_haserrorfunctions) { 658 $this->_errorMsg = db2_stmt_errormsg(); 659 $this->_errorCode = db2_stmt_error(); 660 } 661 return false; 662 } 663 664 } else if (is_array($sql)) { 665 $stmtid = $sql[1]; 666 if (!db2_execute($stmtid)) { 667 if ($this->_haserrorfunctions) { 668 $this->_errorMsg = db2_stmt_errormsg(); 669 $this->_errorCode = db2_stmt_error(); 670 } 671 return false; 672 } 673 } else 674 $stmtid = @db2_exec($this->_connectionID,$sql); 675 676 $this->_lastAffectedRows = 0; 677 if ($stmtid) { 678 if (@db2_num_fields($stmtid) == 0) { 679 $this->_lastAffectedRows = db2_num_rows($stmtid); 680 $stmtid = true; 681 } else { 682 $this->_lastAffectedRows = 0; 683 } 684 685 if ($this->_haserrorfunctions) { 686 $this->_errorMsg = ''; 687 $this->_errorCode = 0; 688 } else 689 $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; 690 } else { 691 if ($this->_haserrorfunctions) { 692 $this->_errorMsg = db2_stmt_errormsg(); 693 $this->_errorCode = db2_stmt_error(); 694 } else 695 $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; 696 697 } 698 return $stmtid; 699 } 700 701 /* 702 Insert a null into the blob field of the table first. 703 Then use UpdateBlob to store the blob. 704 705 Usage: 706 707 $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)'); 708 $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1'); 709 */ 710 function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB') 711 { 712 return $this->Execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false; 713 } 714 715 // returns true or false 716 function _close() 717 { 718 $ret = @db2_close($this->_connectionID); 719 $this->_connectionID = false; 720 return $ret; 721 } 722 723 function _affectedrows() 724 { 725 return $this->_lastAffectedRows; 726 } 727 728} 729 730/*-------------------------------------------------------------------------------------- 731 Class Name: Recordset 732--------------------------------------------------------------------------------------*/ 733 734class ADORecordSet_db2 extends ADORecordSet { 735 736 var $bind = false; 737 var $databaseType = "db2"; 738 var $dataProvider = "db2"; 739 var $useFetchArray; 740 741 function ADORecordSet_db2($id,$mode=false) 742 { 743 if ($mode === false) { 744 global $ADODB_FETCH_MODE; 745 $mode = $ADODB_FETCH_MODE; 746 } 747 $this->fetchMode = $mode; 748 749 $this->_queryID = $id; 750 } 751 752 753 // returns the field object 754 function FetchField($offset = -1) 755 { 756 $o= new ADOFieldObject(); 757 $o->name = @db2_field_name($this->_queryID,$offset); 758 $o->type = @db2_field_type($this->_queryID,$offset); 759 $o->max_length = db2_field_width($this->_queryID,$offset); 760 if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name); 761 else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name); 762 return $o; 763 } 764 765 /* Use associative array to get fields array */ 766 function Fields($colname) 767 { 768 if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname]; 769 if (!$this->bind) { 770 $this->bind = array(); 771 for ($i=0; $i < $this->_numOfFields; $i++) { 772 $o = $this->FetchField($i); 773 $this->bind[strtoupper($o->name)] = $i; 774 } 775 } 776 777 return $this->fields[$this->bind[strtoupper($colname)]]; 778 } 779 780 781 function _initrs() 782 { 783 global $ADODB_COUNTRECS; 784 $this->_numOfRows = ($ADODB_COUNTRECS) ? @db2_num_rows($this->_queryID) : -1; 785 $this->_numOfFields = @db2_num_fields($this->_queryID); 786 // some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0 787 if ($this->_numOfRows == 0) $this->_numOfRows = -1; 788 } 789 790 function _seek($row) 791 { 792 return false; 793 } 794 795 // speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated 796 function GetArrayLimit($nrows,$offset=-1) 797 { 798 if ($offset <= 0) { 799 $rs = $this->GetArray($nrows); 800 return $rs; 801 } 802 $savem = $this->fetchMode; 803 $this->fetchMode = ADODB_FETCH_NUM; 804 $this->Move($offset); 805 $this->fetchMode = $savem; 806 807 if ($this->fetchMode & ADODB_FETCH_ASSOC) { 808 $this->fields = $this->GetRowAssoc(ADODB_ASSOC_CASE); 809 } 810 811 $results = array(); 812 $cnt = 0; 813 while (!$this->EOF && $nrows != $cnt) { 814 $results[$cnt++] = $this->fields; 815 $this->MoveNext(); 816 } 817 818 return $results; 819 } 820 821 822 function MoveNext() 823 { 824 if ($this->_numOfRows != 0 && !$this->EOF) { 825 $this->_currentRow++; 826 827 $this->fields = @db2_fetch_array($this->_queryID); 828 if ($this->fields) { 829 if ($this->fetchMode & ADODB_FETCH_ASSOC) { 830 $this->fields = $this->GetRowAssoc(ADODB_ASSOC_CASE); 831 } 832 return true; 833 } 834 } 835 $this->fields = false; 836 $this->EOF = true; 837 return false; 838 } 839 840 function _fetch() 841 { 842 843 $this->fields = db2_fetch_array($this->_queryID); 844 if ($this->fields) { 845 if ($this->fetchMode & ADODB_FETCH_ASSOC) { 846 $this->fields = $this->GetRowAssoc(ADODB_ASSOC_CASE); 847 } 848 return true; 849 } 850 $this->fields = false; 851 return false; 852 } 853 854 function _close() 855 { 856 return @db2_free_result($this->_queryID); 857 } 858 859} 860?>