You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							361 lines
						
					
					
						
							9.1 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							361 lines
						
					
					
						
							9.1 KiB
						
					
					
				
								<?php
							 | 
						|
								/* 
							 | 
						|
								V4.55 3 Jan 2005  (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
							 | 
						|
								  Released under both BSD license and Lesser GPL library license. 
							 | 
						|
								  Whenever there is any discrepancy between the two licenses, 
							 | 
						|
								  the BSD license will take precedence. 
							 | 
						|
								Set tabs to 4 for best viewing.
							 | 
						|
								  
							 | 
						|
								  Latest version is available at http://adodb.sourceforge.net
							 | 
						|
								  
							 | 
						|
								  DB2 data driver. Requires ODBC.
							 | 
						|
								 
							 | 
						|
								From phpdb list:
							 | 
						|
								
							 | 
						|
								Hi Andrew,
							 | 
						|
								
							 | 
						|
								thanks a lot for your help. Today we discovered what
							 | 
						|
								our real problem was:
							 | 
						|
								
							 | 
						|
								After "playing" a little bit with the php-scripts that try
							 | 
						|
								to connect to the IBM DB2, we set the optional parameter
							 | 
						|
								Cursortype when calling odbc_pconnect(....).
							 | 
						|
								
							 | 
						|
								And the exciting thing: When we set the cursor type
							 | 
						|
								to SQL_CUR_USE_ODBC Cursor Type, then
							 | 
						|
								the whole query speed up from 1 till 10 seconds
							 | 
						|
								to 0.2 till 0.3 seconds for 100 records. Amazing!!!
							 | 
						|
								
							 | 
						|
								Therfore, PHP is just almost fast as calling the DB2
							 | 
						|
								from Servlets using JDBC (don't take too much care
							 | 
						|
								about the speed at whole: the database was on a
							 | 
						|
								completely other location, so the whole connection
							 | 
						|
								was made over a slow network connection).
							 | 
						|
								
							 | 
						|
								I hope this helps when other encounter the same
							 | 
						|
								problem when trying to connect to DB2 from
							 | 
						|
								PHP.
							 | 
						|
								
							 | 
						|
								Kind regards,
							 | 
						|
								Christian Szardenings
							 | 
						|
								
							 | 
						|
								2 Oct 2001
							 | 
						|
								Mark Newnham has discovered that the SQL_CUR_USE_ODBC is not supported by 
							 | 
						|
								IBM's DB2 ODBC driver, so this must be a 3rd party ODBC driver.
							 | 
						|
								
							 | 
						|
								From the IBM CLI Reference:
							 | 
						|
								
							 | 
						|
								SQL_ATTR_ODBC_CURSORS (DB2 CLI v5) 
							 | 
						|
								This connection attribute is defined by ODBC, but is not supported by DB2
							 | 
						|
								CLI. Any attempt to set or get this attribute will result in an SQLSTATE of
							 | 
						|
								HYC00 (Driver not capable). 
							 | 
						|
								
							 | 
						|
								A 32-bit option specifying how the Driver Manager uses the ODBC cursor
							 | 
						|
								library. 
							 | 
						|
								
							 | 
						|
								So I guess this means the message [above] was related to using a 3rd party
							 | 
						|
								odbc driver.
							 | 
						|
								
							 | 
						|
								Setting SQL_CUR_USE_ODBC
							 | 
						|
								========================
							 | 
						|
								To set SQL_CUR_USE_ODBC for drivers that require it, do this:
							 | 
						|
								
							 | 
						|
								$db = NewADOConnection('db2');
							 | 
						|
								$db->curMode = SQL_CUR_USE_ODBC;
							 | 
						|
								$db->Connect($dsn, $userid, $pwd);
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								USING CLI INTERFACE
							 | 
						|
								===================
							 | 
						|
								
							 | 
						|
								I have had reports that the $host and $database params have to be reversed in 
							 | 
						|
								Connect() when using the CLI interface. From Halmai Csongor csongor.halmai#nexum.hu:
							 | 
						|
								
							 | 
						|
								> The symptom is that if I change the database engine from postgres or any other to DB2 then the following
							 | 
						|
								> connection command becomes wrong despite being described this version to be correct in the docs. 
							 | 
						|
								>
							 | 
						|
								> $connection_object->Connect( $DATABASE_HOST, $DATABASE_AUTH_USER_NAME, $DATABASE_AUTH_PASSWORD, $DATABASE_NAME )
							 | 
						|
								>
							 | 
						|
								> In case of DB2 I had to swap the first and last arguments in order to connect properly. 
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								*/
							 | 
						|
								
							 | 
						|
								// security - hide paths
							 | 
						|
								if (!defined('ADODB_DIR')) die();
							 | 
						|
								
							 | 
						|
								if (!defined('_ADODB_ODBC_LAYER')) {
							 | 
						|
									include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
							 | 
						|
								}
							 | 
						|
								if (!defined('ADODB_DB2')){
							 | 
						|
								define('ADODB_DB2',1);
							 | 
						|
								
							 | 
						|
								class ADODB_DB2 extends ADODB_odbc {
							 | 
						|
									var $databaseType = "db2";	
							 | 
						|
									var $concat_operator = '||';
							 | 
						|
									var $sysDate = 'CURRENT_DATE';
							 | 
						|
									var $sysTimeStamp = 'CURRENT TIMESTAMP';
							 | 
						|
									// The complete string representation of a timestamp has the form 
							 | 
						|
									// yyyy-mm-dd-hh.mm.ss.nnnnnn.
							 | 
						|
									var $fmtTimeStamp = "'Y-m-d-H.i.s'";
							 | 
						|
									var $ansiOuter = true;
							 | 
						|
									var $identitySQL = 'values IDENTITY_VAL_LOCAL()';
							 | 
						|
									var $_bindInputArray = true;
							 | 
						|
									 var $hasInsertID = true;
							 | 
						|
									
							 | 
						|
									function ADODB_DB2()
							 | 
						|
									{
							 | 
						|
										if (strncmp(PHP_OS,'WIN',3) === 0) $this->curmode = SQL_CUR_USE_ODBC;
							 | 
						|
										$this->ADODB_odbc();
							 | 
						|
									}
							 | 
						|
									
							 | 
						|
									function IfNull( $field, $ifNull ) 
							 | 
						|
									{
							 | 
						|
										return " COALESCE($field, $ifNull) "; // if DB2 UDB
							 | 
						|
									}
							 | 
						|
									
							 | 
						|
									function ServerInfo()
							 | 
						|
									{
							 | 
						|
										//odbc_setoption($this->_connectionID,1,101 /*SQL_ATTR_ACCESS_MODE*/, 1 /*SQL_MODE_READ_ONLY*/);
							 | 
						|
										$vers = $this->GetOne('select versionnumber from sysibm.sysversions');
							 | 
						|
										//odbc_setoption($this->_connectionID,1,101, 0 /*SQL_MODE_READ_WRITE*/);
							 | 
						|
										return array('description'=>'DB2 ODBC driver', 'version'=>$vers);
							 | 
						|
									}
							 | 
						|
									
							 | 
						|
									function _insertid()
							 | 
						|
									{
							 | 
						|
										return $this->GetOne($this->identitySQL);
							 | 
						|
									}
							 | 
						|
									
							 | 
						|
									function RowLock($tables,$where)
							 | 
						|
									{
							 | 
						|
										if ($this->_autocommit) $this->BeginTrans();
							 | 
						|
										return $this->GetOne("select 1 as ignore from $tables where $where for update");
							 | 
						|
									}
							 | 
						|
									
							 | 
						|
									function &MetaTables($ttype=false,$showSchema=false, $qtable="%", $qschema="%")
							 | 
						|
									{
							 | 
						|
									global $ADODB_FETCH_MODE;
							 | 
						|
									
							 | 
						|
										$savem = $ADODB_FETCH_MODE;
							 | 
						|
										$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
							 | 
						|
										$qid = odbc_tables($this->_connectionID, "", $qschema, $qtable, "");
							 | 
						|
										
							 | 
						|
										$rs = new ADORecordSet_odbc($qid);
							 | 
						|
										
							 | 
						|
										$ADODB_FETCH_MODE = $savem;
							 | 
						|
										if (!$rs) {
							 | 
						|
											$false = false;
							 | 
						|
											return $false;
							 | 
						|
										}
							 | 
						|
										$rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
							 | 
						|
										
							 | 
						|
										$arr =& $rs->GetArray();
							 | 
						|
										//print_r($arr);
							 | 
						|
										
							 | 
						|
										$rs->Close();
							 | 
						|
										$arr2 = array();
							 | 
						|
										
							 | 
						|
										if ($ttype) {
							 | 
						|
											$isview = strncmp($ttype,'V',1) === 0;
							 | 
						|
										}
							 | 
						|
										for ($i=0; $i < sizeof($arr); $i++) {
							 | 
						|
										
							 | 
						|
											if (!$arr[$i][2]) continue;
							 | 
						|
											if (strncmp($arr[$i][1],'SYS',3) === 0) continue;
							 | 
						|
											
							 | 
						|
											$type = $arr[$i][3];
							 | 
						|
											
							 | 
						|
											if ($showSchema) $arr[$i][2] = $arr[$i][1].'.'.$arr[$i][2];
							 | 
						|
											
							 | 
						|
											if ($ttype) { 
							 | 
						|
												if ($isview) {
							 | 
						|
													if (strncmp($type,'V',1) === 0) $arr2[] = $arr[$i][2];
							 | 
						|
												} else if (strncmp($type,'T',1) === 0) $arr2[] = $arr[$i][2];
							 | 
						|
											} else if (strncmp($type,'S',1) !== 0) $arr2[] = $arr[$i][2];
							 | 
						|
										}
							 | 
						|
										return $arr2;
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									function &MetaIndexes ($table, $primary = FALSE, $owner=false)
							 | 
						|
									{
							 | 
						|
								        // save old fetch mode
							 | 
						|
								        global $ADODB_FETCH_MODE;
							 | 
						|
								        $save = $ADODB_FETCH_MODE;
							 | 
						|
								        $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
							 | 
						|
								        if ($this->fetchMode !== FALSE) {
							 | 
						|
								               $savem = $this->SetFetchMode(FALSE);
							 | 
						|
								        }
							 | 
						|
										$false = false;
							 | 
						|
										// get index details
							 | 
						|
										$table = strtoupper($table);
							 | 
						|
										$SQL="SELECT NAME, UNIQUERULE, COLNAMES FROM SYSIBM.SYSINDEXES WHERE TBNAME='$table'";
							 | 
						|
								        if ($primary) 
							 | 
						|
											$SQL.= " AND UNIQUERULE='P'";
							 | 
						|
										$rs = $this->Execute($SQL);
							 | 
						|
								        if (!is_object($rs)) {
							 | 
						|
											if (isset($savem)) 
							 | 
						|
												$this->SetFetchMode($savem);
							 | 
						|
											$ADODB_FETCH_MODE = $save;
							 | 
						|
								            return $false;
							 | 
						|
								        }
							 | 
						|
										$indexes = array ();
							 | 
						|
								        // parse index data into array
							 | 
						|
								        while ($row = $rs->FetchRow()) {
							 | 
						|
											$indexes[$row[0]] = array(
							 | 
						|
											   'unique' => ($row[1] == 'U' || $row[1] == 'P'),
							 | 
						|
											   'columns' => array()
							 | 
						|
											);
							 | 
						|
											$cols = ltrim($row[2],'+');
							 | 
						|
											$indexes[$row[0]]['columns'] = explode('+', $cols);
							 | 
						|
								        }
							 | 
						|
										if (isset($savem)) { 
							 | 
						|
								            $this->SetFetchMode($savem);
							 | 
						|
											$ADODB_FETCH_MODE = $save;
							 | 
						|
										}
							 | 
						|
								        return $indexes;
							 | 
						|
									}
							 | 
						|
									
							 | 
						|
									// Format date column in sql string given an input format that understands Y M D
							 | 
						|
									function SQLDate($fmt, $col=false)
							 | 
						|
									{	
							 | 
						|
									// use right() and replace() ?
							 | 
						|
										if (!$col) $col = $this->sysDate;
							 | 
						|
										$s = '';
							 | 
						|
										
							 | 
						|
										$len = strlen($fmt);
							 | 
						|
										for ($i=0; $i < $len; $i++) {
							 | 
						|
											if ($s) $s .= '||';
							 | 
						|
											$ch = $fmt[$i];
							 | 
						|
											switch($ch) {
							 | 
						|
											case 'Y':
							 | 
						|
											case 'y':
							 | 
						|
												$s .= "char(year($col))";
							 | 
						|
												break;
							 | 
						|
											case 'M':
							 | 
						|
												$s .= "substr(monthname($col),1,3)";
							 | 
						|
												break;
							 | 
						|
											case 'm':
							 | 
						|
												$s .= "right(digits(month($col)),2)";
							 | 
						|
												break;
							 | 
						|
											case 'D':
							 | 
						|
											case 'd':
							 | 
						|
												$s .= "right(digits(day($col)),2)";
							 | 
						|
												break;
							 | 
						|
											case 'H':
							 | 
						|
											case 'h':
							 | 
						|
												if ($col != $this->sysDate) $s .= "right(digits(hour($col)),2)";	
							 | 
						|
												else $s .= "''";
							 | 
						|
												break;
							 | 
						|
											case 'i':
							 | 
						|
											case 'I':
							 | 
						|
												if ($col != $this->sysDate)
							 | 
						|
													$s .= "right(digits(minute($col)),2)";
							 | 
						|
													else $s .= "''";
							 | 
						|
												break;
							 | 
						|
											case 'S':
							 | 
						|
											case 's':
							 | 
						|
												if ($col != $this->sysDate)
							 | 
						|
													$s .= "right(digits(second($col)),2)";
							 | 
						|
												else $s .= "''";
							 | 
						|
												break;
							 | 
						|
											default:
							 | 
						|
												if ($ch == '\\') {
							 | 
						|
													$i++;
							 | 
						|
													$ch = substr($fmt,$i,1);
							 | 
						|
												}
							 | 
						|
												$s .= $this->qstr($ch);
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
										return $s;
							 | 
						|
									} 
							 | 
						|
								 
							 | 
						|
									
							 | 
						|
									function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputArr=false)
							 | 
						|
									{
							 | 
						|
										if ($offset <= 0) {
							 | 
						|
										// could also use " OPTIMIZE FOR $nrows ROWS "
							 | 
						|
											if ($nrows >= 0) $sql .=  " FETCH FIRST $nrows ROWS ONLY ";
							 | 
						|
											$rs =& $this->Execute($sql,$inputArr);
							 | 
						|
										} else {
							 | 
						|
											if ($offset > 0 && $nrows < 0);
							 | 
						|
											else {
							 | 
						|
												$nrows += $offset;
							 | 
						|
												$sql .=  " FETCH FIRST $nrows ROWS ONLY ";
							 | 
						|
											}
							 | 
						|
											$rs =& ADOConnection::SelectLimit($sql,-1,$offset,$inputArr);
							 | 
						|
										}
							 | 
						|
										
							 | 
						|
										return $rs;
							 | 
						|
									}
							 | 
						|
									
							 | 
						|
								};
							 | 
						|
								 
							 | 
						|
								
							 | 
						|
								class  ADORecordSet_db2 extends ADORecordSet_odbc {	
							 | 
						|
									
							 | 
						|
									var $databaseType = "db2";		
							 | 
						|
									
							 | 
						|
									function ADORecordSet_db2($id,$mode=false)
							 | 
						|
									{
							 | 
						|
										$this->ADORecordSet_odbc($id,$mode);
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									function MetaType($t,$len=-1,$fieldobj=false)
							 | 
						|
									{
							 | 
						|
										if (is_object($t)) {
							 | 
						|
											$fieldobj = $t;
							 | 
						|
											$t = $fieldobj->type;
							 | 
						|
											$len = $fieldobj->max_length;
							 | 
						|
										}
							 | 
						|
										
							 | 
						|
										switch (strtoupper($t)) {
							 | 
						|
										case 'VARCHAR':
							 | 
						|
										case 'CHAR':
							 | 
						|
										case 'CHARACTER':
							 | 
						|
										case 'C':
							 | 
						|
											if ($len <= $this->blobSize) return 'C';
							 | 
						|
										
							 | 
						|
										case 'LONGCHAR':
							 | 
						|
										case 'TEXT':
							 | 
						|
										case 'CLOB':
							 | 
						|
										case 'DBCLOB': // double-byte
							 | 
						|
										case 'X':
							 | 
						|
											return 'X';
							 | 
						|
										
							 | 
						|
										case 'BLOB':
							 | 
						|
										case 'GRAPHIC':
							 | 
						|
										case 'VARGRAPHIC':
							 | 
						|
											return 'B';
							 | 
						|
											
							 | 
						|
										case 'DATE':
							 | 
						|
										case 'D':
							 | 
						|
											return 'D';
							 | 
						|
										
							 | 
						|
										case 'TIME':
							 | 
						|
										case 'TIMESTAMP':
							 | 
						|
										case 'T':
							 | 
						|
											return 'T';
							 | 
						|
										
							 | 
						|
										//case 'BOOLEAN': 
							 | 
						|
										//case 'BIT':
							 | 
						|
										//	return 'L';
							 | 
						|
											
							 | 
						|
										//case 'COUNTER':
							 | 
						|
										//	return 'R';
							 | 
						|
											
							 | 
						|
										case 'INT':
							 | 
						|
										case 'INTEGER':
							 | 
						|
										case 'BIGINT':
							 | 
						|
										case 'SMALLINT':
							 | 
						|
										case 'I':
							 | 
						|
											return 'I';
							 | 
						|
											
							 | 
						|
										default: return 'N';
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								} //define
							 | 
						|
								?>
							 |