X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=includes%2Fdb%2FDatabaseIbm_db2.php;h=ed37939747797fa28e9dbd14001cb6c56f7f3122;hb=f675c6bf054aea9c14b329366b23d2ae5e78fdb3;hp=5fbf81c7ae86dbc0e90fdda021ca60299b54d14c;hpb=16cded8b32fc671125d89af1827f49665715c0ea;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/db/DatabaseIbm_db2.php b/includes/db/DatabaseIbm_db2.php index 5fbf81c7ae..ed37939747 100644 --- a/includes/db/DatabaseIbm_db2.php +++ b/includes/db/DatabaseIbm_db2.php @@ -13,7 +13,7 @@ * This represents a column in a DB2 database * @ingroup Database */ -class IBM_DB2Field { +class IBM_DB2Field implements Field { private $name = ''; private $tablename = ''; private $type = ''; @@ -75,7 +75,7 @@ SQL; * Can column be null? * @return bool true or false */ - function nullable() { return $this->nullable; } + function isNullable() { return $this->nullable; } /** * How much can you fit in the column per row? * @return int length @@ -114,9 +114,8 @@ class DatabaseIbm_db2 extends DatabaseBase { protected $mPHPError = false; protected $mServer, $mUser, $mPassword, $mConn = null, $mDBname; - protected $mOut, $mOpened = false; + protected $mOpened = false; - protected $mFailFunction; protected $mTablePrefix; protected $mFlags; protected $mTrxLevel = 0; @@ -145,7 +144,7 @@ class DatabaseIbm_db2 extends DatabaseBase { public $mStmtOptions = array(); /** Default schema */ - const USE_GLOBAL = 'mediawiki'; + const USE_GLOBAL = 'get from global'; /** Option that applies to nothing */ const NONE_OPTION = 0x00; @@ -246,34 +245,21 @@ class DatabaseIbm_db2 extends DatabaseBase { return 'ibm_db2'; } - ###################################### - # Setup - ###################################### - - /** * * @param $server String: hostname of database server * @param $user String: username * @param $password String: password * @param $dbName String: database name on the server - * @param $failFunction Callback (optional) * @param $flags Integer: database behaviour flags (optional, unused) * @param $schema String */ - public function DatabaseIbm_db2( $server = false, $user = false, + public function __construct( $server = false, $user = false, $password = false, - $dbName = false, $failFunction = false, $flags = 0, + $dbName = false, $flags = 0, $schema = self::USE_GLOBAL ) { - - global $wgOut, $wgDBmwschema; - # Can't get a reference if it hasn't been set yet - if ( !isset( $wgOut ) ) { - $wgOut = null; - } - $this->mOut =& $wgOut; - $this->mFlags = DBO_TRX | $flags; + global $wgDBmwschema; if ( $schema == self::USE_GLOBAL ) { $this->mSchema = $wgDBmwschema; @@ -282,6 +268,10 @@ class DatabaseIbm_db2 extends DatabaseBase { } // configure the connection and statement objects + /* + $this->setDB2Option( 'cursor', 'DB2_SCROLLABLE', + self::CONN_OPTION | self::STMT_OPTION ); + */ $this->setDB2Option( 'db2_attr_case', 'DB2_CASE_LOWER', self::CONN_OPTION | self::STMT_OPTION ); $this->setDB2Option( 'deferred_prepare', 'DB2_DEFERRED_PREPARE_ON', @@ -289,7 +279,7 @@ class DatabaseIbm_db2 extends DatabaseBase { $this->setDB2Option( 'rowcount', 'DB2_ROWCOUNT_PREFETCH_ON', self::STMT_OPTION ); - $this->open( $server, $user, $password, $dbName ); + parent::__construct( $server, $user, $password, $dbName, DBO_TRX | $flags ); } /** @@ -335,26 +325,17 @@ class DatabaseIbm_db2 extends DatabaseBase { * @return a fresh connection */ public function open( $server, $user, $password, $dbName ) { - // Load the port number - global $wgDBport; wfProfileIn( __METHOD__ ); - // Load IBM DB2 driver if missing + # Load IBM DB2 driver if missing wfDl( 'ibm_db2' ); - // Test for IBM DB2 support, to avoid suppressed fatal error + # Test for IBM DB2 support, to avoid suppressed fatal error if ( !function_exists( 'db2_connect' ) ) { - $error = <<installPrint( $error ); - $this->reportConnectionError( $error ); + throw new DBConnectionError( $this, "DB2 functions missing, have you enabled the ibm_db2 extension for PHP?" ); } - if ( strlen( $user ) < 1 ) { - return null; - } + global $wgDBport; // Close existing connection $this->close(); @@ -367,22 +348,26 @@ ERROR; $this->openUncataloged( $dbName, $user, $password, $server, $port ); - // Apply connection config - db2_set_option( $this->mConn, $this->mConnOptions, 1 ); - // Some MediaWiki code is still transaction-less (?). - // The strategy is to keep AutoCommit on for that code - // but switch it off whenever a transaction is begun. - db2_autocommit( $this->mConn, DB2_AUTOCOMMIT_ON ); - if ( !$this->mConn ) { $this->installPrint( "DB connection error\n" ); $this->installPrint( "Server: $server, Database: $dbName, User: $user, Password: " . substr( $password, 0, 3 ) . "...\n" ); $this->installPrint( $this->lastError() . "\n" ); - return null; + wfProfileOut( __METHOD__ ); + wfDebug( "DB connection error\n" ); + wfDebug( "Server: $server, Database: $dbName, User: $user, Password: " . substr( $password, 0, 3 ) . "...\n" ); + wfDebug( $this->lastError() . "\n" ); + throw new DBConnectionError( $this, $this->lastError() ); } + // Apply connection config + db2_set_option( $this->mConn, $this->mConnOptions, 1 ); + // Some MediaWiki code is still transaction-less (?). + // The strategy is to keep AutoCommit on for that code + // but switch it off whenever a transaction is begun. + db2_autocommit( $this->mConn, DB2_AUTOCOMMIT_ON ); + $this->mOpened = true; $this->applySchema(); @@ -402,16 +387,8 @@ ERROR; */ protected function openUncataloged( $dbName, $user, $password, $server, $port ) { - $str = "DRIVER={IBM DB2 ODBC DRIVER};"; - $str .= "DATABASE=$dbName;"; - $str .= "HOSTNAME=$server;"; - // port was formerly validated to not be 0 - $str .= "PORT=$port;"; - $str .= "PROTOCOL=TCPIP;"; - $str .= "UID=$user;"; - $str .= "PWD=$password;"; - - @$this->mConn = db2_pconnect( $str, $user, $password ); + $dsn = "DRIVER={IBM DB2 ODBC DRIVER};DATABASE=$dbName;CHARSET=UTF-8;HOSTNAME=$server;PORT=$port;PROTOCOL=TCPIP;UID=$user;PWD=$password;"; + @$this->mConn = db2_pconnect($dsn, "", "", array()); } /** @@ -430,24 +407,6 @@ ERROR; } } - /** - * Returns a fresh instance of this class - * - * @param $server String: hostname of database server - * @param $user String: username - * @param $password String - * @param $dbName String: database name on the server - * @param $failFunction Callback (optional) - * @param $flags Integer: database behaviour flags (optional, unused) - * @return DatabaseIbm_db2 object - */ - static function newFromParams( $server, $user, $password, $dbName, - $failFunction = false, $flags = 0 ) - { - return new DatabaseIbm_db2( $server, $user, $password, $dbName, - $failFunction, $flags ); - } - /** * Retrieves the most current database error * Forces a database rollback @@ -499,10 +458,16 @@ ERROR; /*private*/ public function doQuery( $sql ) { $this->applySchema(); - + + // Needed to handle any UTF-8 encoding issues in the raw sql + // Note that we fully support prepared statements for DB2 + // prepare() and execute() should be used instead of doQuery() whenever possible + $sql = utf8_decode($sql); + $ret = db2_exec( $this->mConn, $sql, $this->mStmtOptions ); if( $ret == false ) { $error = db2_stmt_errormsg(); + $this->installPrint( "
$sql
" ); $this->installPrint( $error ); throw new DBUnexpectedError( $this, 'SQL error: ' @@ -527,10 +492,11 @@ ERROR; */ public function tableExists( $table ) { $schema = $this->mSchema; - $sql = <<< EOF -SELECT COUNT( * ) FROM SYSIBM.SYSTABLES ST -WHERE ST.NAME = '$table' AND ST.CREATOR = '$schema' -EOF; + + $sql = "SELECT COUNT( * ) FROM SYSIBM.SYSTABLES ST WHERE ST.NAME = '" . + strtoupper( $table ) . + "' AND ST.CREATOR = '" . + strtoupper( $schema ) . "'"; $res = $this->query( $sql ); if ( !$res ) { return false; @@ -579,12 +545,15 @@ EOF; if ( $res instanceof ResultWrapper ) { $res = $res->result; } - @$row = db2_fetch_array( $res ); - if ( $this->lastErrno() ) { - throw new DBUnexpectedError( $this, 'Error in fetchRow(): ' - . htmlspecialchars( $this->lastError() ) ); + if ( db2_num_rows( $res ) > 0) { + @$row = db2_fetch_array( $res ); + if ( $this->lastErrno() ) { + throw new DBUnexpectedError( $this, 'Error in fetchRow(): ' + . htmlspecialchars( $this->lastError() ) ); + } + return $row; } - return $row; + return false; } /** @@ -610,7 +579,6 @@ EOF; } else { print '
  • Foreign keys done
  • '; } - $res = null; // TODO: populate interwiki links @@ -757,7 +725,7 @@ EOF; function makeList( $a, $mode = LIST_COMMA ) { if ( !is_array( $a ) ) { throw new DBUnexpectedError( $this, - 'DatabaseBase::makeList called with incorrect parameters' ); + 'DatabaseIbm_db2::makeList called with incorrect parameters' ); } // if this is for a prepared UPDATE statement @@ -810,9 +778,10 @@ EOF; * Handle reserved keyword replacement in table names * * @param $name Object + * @param $name Boolean * @return String */ - public function tableName( $name ) { + public function tableName( $name, $quoted = true ) { // we want maximum compatibility with MySQL schema return $name; } @@ -928,9 +897,9 @@ EOF; } else { $sql .= '( ?' . str_repeat( ',?', $key_count-1 ) . ' )'; } - //$this->installPrint( "Preparing the following SQL:" ); - //$this->installPrint( "$sql" ); - //$this->installPrint( print_r( $args, true )); + $this->installPrint( "Preparing the following SQL:" ); + $this->installPrint( "$sql" ); + $this->installPrint( print_r( $args, true )); $stmt = $this->prepare( $sql ); // start a transaction/enter transaction mode @@ -962,7 +931,7 @@ EOF; $overhead = "SAVEPOINT $ignore ON ROLLBACK RETAIN CURSORS"; db2_exec( $this->mConn, $overhead, $this->mStmtOptions ); - $this->execute( $stmt, $row ); + $res2 = $this->execute( $stmt, $row ); if ( !$res2 ) { $this->installPrint( 'Last error:' ); @@ -1003,18 +972,22 @@ EOF; */ private function removeNullPrimaryKeys( $table, $args ) { $schema = $this->mSchema; + // find out the primary keys - $keyres = db2_primary_keys( $this->mConn, null, strtoupper( $schema ), - strtoupper( $table ) - ); + $keyres = $this->doQuery( "SELECT NAME FROM SYSIBM.SYSCOLUMNS WHERE TBNAME = '" + . strtoupper( $table ) + . "' AND TBCREATOR = '" + . strtoupper( $schema ) + . "' AND KEYSEQ > 0" ); + $keys = array(); for ( - $row = $this->fetchObject( $keyres ); + $row = $this->fetchRow( $keyres ); $row != null; - $row = $this->fetchObject( $keyres ) + $row = $this->fetchRow( $keyres ) ) { - $keys[] = strtolower( $row->column_name ); + $keys[] = strtolower( $row[0] ); } // remove primary keys foreach ( $args as $ai => $row ) { @@ -1041,7 +1014,7 @@ EOF; * more of IGNORE, LOW_PRIORITY * @return Boolean */ - public function update( $table, $values, $conds, $fname = 'Database::update', + public function update( $table, $values, $conds, $fname = 'DatabaseIbm_db2::update', $options = array() ) { $table = $this->tableName( $table ); @@ -1066,10 +1039,10 @@ EOF; * * Use $conds == "*" to delete all rows */ - public function delete( $table, $conds, $fname = 'Database::delete' ) { + public function delete( $table, $conds, $fname = 'DatabaseIbm_db2::delete' ) { if ( !$conds ) { throw new DBUnexpectedError( $this, - 'Database::delete() called with no conditions' ); + 'DatabaseIbm_db2::delete() called with no conditions' ); } $table = $this->tableName( $table ); $sql = "DELETE FROM $table"; @@ -1149,10 +1122,7 @@ EOF; } # Now insert the row - $sql = "INSERT INTO $table ( " - . $this->makeList( array_keys( $row ), LIST_NAMES ) - .' ) VALUES ( ' . $this->makeList( $row, LIST_COMMA ) . ' )'; - $this->query( $sql, $fname ); + $this->insert($table, $row); } } @@ -1166,6 +1136,7 @@ EOF; if ( $res instanceof ResultWrapper ) { $res = $res->result; } + if ( $this->mNumRows ) { return $this->mNumRows; } else { @@ -1253,11 +1224,9 @@ EOF; $join_conds ); // We must adjust for offset - if ( isset( $options['LIMIT'] ) ) { - if ( isset ( $options['OFFSET'] ) ) { - $limit = $options['LIMIT']; - $offset = $options['OFFSET']; - } + if ( isset( $options['LIMIT'] ) && isset ( $options['OFFSET'] ) ) { + $limit = $options['LIMIT']; + $offset = $options['OFFSET']; } // DB2 does not have a proper num_rows() function yet, so we must emulate @@ -1469,7 +1438,7 @@ SQL; * @return Bool */ public function indexUnique ( $table, $index, - $fname = 'Database::indexUnique' ) + $fname = 'DatabaseIbm_db2::indexUnique' ) { $table = $this->tableName( $table ); $sql = <<tableName( $delTable ); @@ -1532,7 +1501,7 @@ SQL; $sql = <<