* @author leo.petr+mediawiki@gmail.com
*/
-/**
- * Utility class for generating blank objects
- * Intended as an equivalent to {} in Javascript
- * @ingroup Database
- */
-class BlankObject {
-}
-
-
/**
* This represents a column in a DB2 database
* @ingroup Database
if( $this->lastErrno() ) {
throw new DBUnexpectedError( $this, 'Error in fetchObject(): ' . htmlspecialchars( $this->lastError() ) );
}
- // Make field names lowercase for compatibility with MySQL
- if ($row)
- {
- $row2 = new BlankObject();
- foreach ($row as $key => $value)
- {
- $keyu = strtolower($key);
- $row2->$keyu = $value;
- }
- $row = $row2;
- }
return $row;
}
* LIST_NAMES - comma separated field names
*/
public function makeList( $a, $mode = LIST_COMMA ) {
- $this->installPrint("DB2::makeList()\n");
if ( !is_array( $a ) ) {
throw new DBUnexpectedError( $this, 'Database::makeList called with incorrect parameters' );
}
return $this->mInsertId;
}
+ /**
+ * Updates the mInsertId property with the value of the last insert into a generated column
+ * @param string $table Sanitized table name
+ * @param mixed $primaryKey String name of the primary key or a bool if this call is a do-nothing
+ * @param resource $stmt Prepared statement resource
+ * of the SELECT primary_key FROM FINAL TABLE ( INSERT ... ) form
+ */
+ private function calcInsertId($table, $primaryKey, $stmt) {
+ if ($primaryKey) {
+ $id_row = $this->fetchRow($stmt);
+ $this->mInsertId = $id_row[0];
+ }
+ }
+
/**
* INSERT wrapper, inserts an array into a table
*
* @return bool Success of insert operation. IGNORE always returns true.
*/
public function insert( $table, $args, $fname = 'DatabaseIbm_db2::insert', $options = array() ) {
- $this->installPrint("DB2::insert($table)\n");
if ( !count( $args ) ) {
return true;
}
$args = array($args);
}
// prevent insertion of NULL into primary key columns
- $args = $this->removeNullPrimaryKeys($table, $args);
+ list($args, $primaryKeys) = $this->removeNullPrimaryKeys($table, $args);
+ // if there's only one primary key
+ // we'll be able to read its value after insertion
+ $primaryKey = false;
+ if (count($primaryKeys) == 1) {
+ $primaryKey = $primaryKeys[0];
+ }
// get column names
$keys = array_keys( $args[0] );
// If IGNORE is set, we use savepoints to emulate mysql's behavior
$ignore = in_array( 'IGNORE', $options ) ? 'mw' : '';
+ // assume success
+ $res = true;
// If we are not in a transaction, we need to be for savepoint trickery
$didbegin = 0;
if (! $this->mTrxLevel) {
$this->begin();
$didbegin = 1;
}
- if ( $ignore ) {
- $olde = error_reporting( 0 );
- // For future use, we may want to track the number of actual inserts
- // Right now, insert (all writes) simply return true/false
- $numrowsinserted = 0;
- }
$sql = "INSERT INTO $table (" . implode( ',', $keys ) . ') VALUES ';
switch($key_count) {
default:
$sql .= '(?' . str_repeat(',?', $key_count-1) . ')';
}
+ // add logic to read back the new primary key value
+ if ($primaryKey) {
+ $sql = "SELECT $primaryKey FROM FINAL TABLE($sql)";
+ }
$stmt = $this->prepare($sql);
+
+ // start a transaction/enter transaction mode
+ $this->begin();
if ( !$ignore ) {
$first = true;
foreach ( $args as $row ) {
// insert each row into the database
- $this->execute($stmt, $row);
+ $res = $res & $this->execute($stmt, $row);
+ // get the last inserted value into a generated column
+ $this->calcInsertId($table, $primaryKey, $stmt);
}
}
else {
- // we must have autocommit turned off -- transaction mode on
- $this->begin();
+ $olde = error_reporting( 0 );
+ // For future use, we may want to track the number of actual inserts
+ // Right now, insert (all writes) simply return true/false
+ $numrowsinserted = 0;
+ // always return true
$res = true;
+
foreach ( $args as $row ) {
- if ( $ignore ) {
- $overhead = "SAVEPOINT $ignore ON ROLLBACK RETAIN CURSORS";
- db2_exec($this->mConn, $overhead, $this->mStmtOptions);
- }
+ $overhead = "SAVEPOINT $ignore ON ROLLBACK RETAIN CURSORS";
+ db2_exec($this->mConn, $overhead, $this->mStmtOptions);
- $this->execute($sql, $row);
- if ( $ignore ) {
- $bar = $this->lastError();
- if (!$bar) {
- db2_exec( $this->mConn, "ROLLBACK TO SAVEPOINT $ignore", $this->mStmtOptions );
- }
- else {
- db2_exec( $this->mConn, "RELEASE SAVEPOINT $ignore", $this->mStmtOptions );
- $numrowsinserted++;
- }
+ $res2 = $this->execute($stmt, $row);
+ // get the last inserted value into a generated column
+ $this->calcInsertId($table, $primaryKey, $stmt);
+
+ $errNum = $this->lastErrno();
+ if ($errNum) {
+ db2_exec( $this->mConn, "ROLLBACK TO SAVEPOINT $ignore", $this->mStmtOptions );
+ }
+ else {
+ db2_exec( $this->mConn, "RELEASE SAVEPOINT $ignore", $this->mStmtOptions );
+ $numrowsinserted++;
}
}
- }
-
- // commit either way
- $this->commit();
-
- if ( $ignore ) {
+
$olde = error_reporting( $olde );
// Set the affected row count for the whole operation
$this->mAffectedRows = $numrowsinserted;
-
- // IGNORE always returns true
- return true;
}
+ // commit either way
+ $this->commit();
return $res;
}
*
* @param string $table Name of the table
* @param array $args Array of hashes of column names with values
- * @return array Filtered array of hashes
+ * @return array Tuple containing filtered array of columns, array of primary keys
*/
private function removeNullPrimaryKeys($table, $args) {
$schema = $this->mSchema;
$args[$ai] = $row;
}
// return modified hash
- return $args;
+ return array($args, $keys);
}
/**
$obj = $this->fetchObject($res2);
$this->mNumRows = $obj->num_rows;
- $this->installPrint("DatabaseIbm_db2::select: There are $this->mNumRows rows.\n");
return $res;
}
CREATE INDEX rev_user_text_idx ON revision (rev_user_text);
--- CREATE SEQUENCE text_old_id_val;
+
CREATE TABLE text ( -- replaces reserved word 'text'
--old_id INTEGER NOT NULL,
old_id INTEGER PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 0),
old_flags VARCHAR(1024)
);
---CREATE SEQUENCE pr_id_val;
+
CREATE TABLE page_restrictions (
--pr_id INTEGER NOT NULL UNIQUE, --DEFAULT nextval('pr_id_val'),
--pr_id INTEGER PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 0),
CREATE INDEX oi_sha1 ON oldimage (oi_sha1);
-CREATE SEQUENCE filearchive_fa_id_seq;
+
CREATE TABLE filearchive (
fa_id INTEGER NOT NULL PRIMARY KEY,
--PRIMARY KEY DEFAULT nextval('filearchive_fa_id_seq'),
CREATE INDEX fa_notime ON filearchive (fa_deleted_timestamp);
CREATE INDEX fa_nouser ON filearchive (fa_deleted_user);
-CREATE SEQUENCE rc_rc_id_seq;
+
CREATE TABLE recentchanges (
rc_id INTEGER NOT NULL PRIMARY KEY,
--PRIMARY KEY DEFAULT nextval('rc_rc_id_seq'),
tc_time TIMESTAMP(3) NOT NULL
);
-CREATE SEQUENCE log_log_id_seq;
+
CREATE TABLE logging (
log_id INTEGER NOT NULL PRIMARY KEY,
--PRIMARY KEY DEFAULT nextval('log_log_id_seq'),
CREATE INDEX log_page_id_time ON logging (log_page,log_timestamp);
-CREATE SEQUENCE trackbacks_tb_id_seq;
+
CREATE TABLE trackbacks (
tb_id INTEGER NOT NULL PRIMARY KEY,
--PRIMARY KEY DEFAULT nextval('trackbacks_tb_id_seq'),
CREATE INDEX trackback_page ON trackbacks (tb_page);
-CREATE SEQUENCE job_job_id_seq;
+
CREATE TABLE job (
job_id INTEGER NOT NULL PRIMARY KEY,
--PRIMARY KEY DEFAULT nextval('job_job_id_seq'),
ul_key VARCHAR(255) NOT NULL PRIMARY KEY
);
---CREATE SEQUENCE category_id_seq;
+
CREATE TABLE category (
cat_id INTEGER NOT NULL PRIMARY KEY,
--PRIMARY KEY DEFAULT nextval('category_id_seq'),