diff options
author | Pierre Schmitz <pierre@archlinux.de> | 2008-12-15 18:02:47 +0100 |
---|---|---|
committer | Pierre Schmitz <pierre@archlinux.de> | 2008-12-15 18:02:47 +0100 |
commit | 396b28f3d881f5debd888ba9bb9b47c2d478a76f (patch) | |
tree | 10d6e1a721ee4ef69def34a57f02d7eb3fc9e31e /includes/DatabaseOracle.php | |
parent | 0be4d3ccf6c4fe98a72704f9463ecdea2ee5e615 (diff) |
update to Mediawiki 1.13.3; some cleanups
Diffstat (limited to 'includes/DatabaseOracle.php')
-rw-r--r-- | includes/DatabaseOracle.php | 697 |
1 files changed, 0 insertions, 697 deletions
diff --git a/includes/DatabaseOracle.php b/includes/DatabaseOracle.php deleted file mode 100644 index 38485481..00000000 --- a/includes/DatabaseOracle.php +++ /dev/null @@ -1,697 +0,0 @@ -<?php - -/** - * This is the Oracle database abstraction layer. - * @addtogroup Database - */ -class ORABlob { - var $mData; - - function __construct($data) { - $this->mData = $data; - } - - function getData() { - return $this->mData; - } -} - -/** - * The oci8 extension is fairly weak and doesn't support oci_num_rows, among - * other things. We use a wrapper class to handle that and other - * Oracle-specific bits, like converting column names back to lowercase. - * @addtogroup Database - */ -class ORAResult { - private $rows; - private $cursor; - private $stmt; - private $nrows; - private $db; - - function __construct(&$db, $stmt) { - $this->db =& $db; - if (($this->nrows = oci_fetch_all($stmt, $this->rows, 0, -1, OCI_FETCHSTATEMENT_BY_ROW | OCI_NUM)) === false) { - $e = oci_error($stmt); - $db->reportQueryError($e['message'], $e['code'], '', __FUNCTION__); - return; - } - - $this->cursor = 0; - $this->stmt = $stmt; - } - - function free() { - oci_free_statement($this->stmt); - } - - function seek($row) { - $this->cursor = min($row, $this->nrows); - } - - function numRows() { - return $this->nrows; - } - - function numFields() { - return oci_num_fields($this->stmt); - } - - function fetchObject() { - if ($this->cursor >= $this->nrows) - return false; - - $row = $this->rows[$this->cursor++]; - $ret = new stdClass(); - foreach ($row as $k => $v) { - $lc = strtolower(oci_field_name($this->stmt, $k + 1)); - $ret->$lc = $v; - } - - return $ret; - } - - function fetchAssoc() { - if ($this->cursor >= $this->nrows) - return false; - - $row = $this->rows[$this->cursor++]; - $ret = array(); - foreach ($row as $k => $v) { - $lc = strtolower(oci_field_name($this->stmt, $k + 1)); - $ret[$lc] = $v; - $ret[$k] = $v; - } - return $ret; - } -} - -/** - * @addtogroup Database - */ -class DatabaseOracle extends Database { - var $mInsertId = NULL; - var $mLastResult = NULL; - var $numeric_version = NULL; - var $lastResult = null; - var $cursor = 0; - var $mAffectedRows; - - function DatabaseOracle($server = false, $user = false, $password = false, $dbName = false, - $failFunction = false, $flags = 0 ) - { - - global $wgOut; - # Can't get a reference if it hasn't been set yet - if ( !isset( $wgOut ) ) { - $wgOut = NULL; - } - $this->mOut =& $wgOut; - $this->mFailFunction = $failFunction; - $this->mFlags = $flags; - $this->open( $server, $user, $password, $dbName); - - } - - function cascadingDeletes() { - return true; - } - function cleanupTriggers() { - return true; - } - function strictIPs() { - return true; - } - function realTimestamps() { - return true; - } - function implicitGroupby() { - return false; - } - function implicitOrderby() { - return false; - } - function searchableIPs() { - return true; - } - - static function newFromParams( $server = false, $user = false, $password = false, $dbName = false, - $failFunction = false, $flags = 0) - { - return new DatabaseOracle( $server, $user, $password, $dbName, $failFunction, $flags ); - } - - /** - * Usually aborts on failure - * If the failFunction is set to a non-zero integer, returns success - */ - function open( $server, $user, $password, $dbName ) { - if ( !function_exists( 'oci_connect' ) ) { - throw new DBConnectionError( $this, "Oracle functions missing, have you compiled PHP with the --with-oci8 option?\n (Note: if you recently installed PHP, you may need to restart your webserver and database)\n" ); - } - - # Needed for proper UTF-8 functionality - putenv("NLS_LANG=AMERICAN_AMERICA.AL32UTF8"); - - $this->close(); - $this->mServer = $server; - $this->mUser = $user; - $this->mPassword = $password; - $this->mDBname = $dbName; - - if (!strlen($user)) { ## e.g. the class is being loaded - return; - } - - error_reporting( E_ALL ); - $this->mConn = oci_connect($user, $password, $dbName); - - if ($this->mConn == false) { - wfDebug("DB connection error\n"); - wfDebug("Server: $server, Database: $dbName, User: $user, Password: " . substr( $password, 0, 3 ) . "...\n"); - wfDebug($this->lastError()."\n"); - return false; - } - - $this->mOpened = true; - return $this->mConn; - } - - /** - * Closes a database connection, if it is open - * Returns success, true if already closed - */ - function close() { - $this->mOpened = false; - if ( $this->mConn ) { - return oci_close( $this->mConn ); - } else { - return true; - } - } - - function execFlags() { - return $this->mTrxLevel ? OCI_DEFAULT : OCI_COMMIT_ON_SUCCESS; - } - - function doQuery($sql) { - wfDebug("SQL: [$sql]\n"); - if (!mb_check_encoding($sql)) { - throw new MWException("SQL encoding is invalid"); - } - - if (($this->mLastResult = $stmt = oci_parse($this->mConn, $sql)) === false) { - $e = oci_error($this->mConn); - $this->reportQueryError($e['message'], $e['code'], $sql, __FUNCTION__); - } - - if (oci_execute($stmt, $this->execFlags()) == false) { - $e = oci_error($stmt); - $this->reportQueryError($e['message'], $e['code'], $sql, __FUNCTION__); - } - if (oci_statement_type($stmt) == "SELECT") - return new ORAResult($this, $stmt); - else { - $this->mAffectedRows = oci_num_rows($stmt); - return true; - } - } - - function queryIgnore($sql, $fname = '') { - return $this->query($sql, $fname, true); - } - - function freeResult($res) { - $res->free(); - } - - function fetchObject($res) { - return $res->fetchObject(); - } - - function fetchRow($res) { - return $res->fetchAssoc(); - } - - function numRows($res) { - return $res->numRows(); - } - - function numFields($res) { - return $res->numFields(); - } - - function fieldName($stmt, $n) { - return pg_field_name($stmt, $n); - } - - /** - * This must be called after nextSequenceVal - */ - function insertId() { - return $this->mInsertId; - } - - function dataSeek($res, $row) { - $res->seek($row); - } - - function lastError() { - if ($this->mConn === false) - $e = oci_error(); - else - $e = oci_error($this->mConn); - return $e['message']; - } - - function lastErrno() { - if ($this->mConn === false) - $e = oci_error(); - else - $e = oci_error($this->mConn); - return $e['code']; - } - - function affectedRows() { - return $this->mAffectedRows; - } - - /** - * Returns information about an index - * If errors are explicitly ignored, returns NULL on failure - */ - function indexInfo( $table, $index, $fname = 'Database::indexExists' ) { - return false; - } - - function indexUnique ($table, $index, $fname = 'Database::indexUnique' ) { - return false; - } - - function insert( $table, $a, $fname = 'Database::insert', $options = array() ) { - if (!is_array($options)) - $options = array($options); - - #if (in_array('IGNORE', $options)) - # $oldIgnore = $this->ignoreErrors(true); - - # IGNORE is performed using single-row inserts, ignoring errors in each - # FIXME: need some way to distiguish between key collision and other types of error - //$oldIgnore = $this->ignoreErrors(true); - if (!is_array(reset($a))) { - $a = array($a); - } - foreach ($a as $row) { - $this->insertOneRow($table, $row, $fname); - } - //$this->ignoreErrors($oldIgnore); - $retVal = true; - - //if (in_array('IGNORE', $options)) - // $this->ignoreErrors($oldIgnore); - - return $retVal; - } - - function insertOneRow($table, $row, $fname) { - // "INSERT INTO tables (a, b, c)" - $sql = "INSERT INTO " . $this->tableName($table) . " (" . join(',', array_keys($row)) . ')'; - $sql .= " VALUES ("; - - // for each value, append ":key" - $first = true; - $returning = ''; - foreach ($row as $col => $val) { - if (is_object($val)) { - $what = "EMPTY_BLOB()"; - assert($returning === ''); - $returning = " RETURNING $col INTO :bval"; - $blobcol = $col; - } else - $what = ":$col"; - - if ($first) - $sql .= "$what"; - else - $sql.= ", $what"; - $first = false; - } - $sql .= ") $returning"; - - $stmt = oci_parse($this->mConn, $sql); - foreach ($row as $col => $val) { - if (!is_object($val)) { - if (oci_bind_by_name($stmt, ":$col", $row[$col]) === false) - $this->reportQueryError($this->lastErrno(), $this->lastError(), $sql, __METHOD__); - } - } - - if (($bval = oci_new_descriptor($this->mConn, OCI_D_LOB)) === false) { - $e = oci_error($stmt); - throw new DBUnexpectedError($this, "Cannot create LOB descriptor: " . $e['message']); - } - - if (strlen($returning)) - oci_bind_by_name($stmt, ":bval", $bval, -1, SQLT_BLOB); - - if (oci_execute($stmt, OCI_DEFAULT) === false) { - $e = oci_error($stmt); - $this->reportQueryError($e['message'], $e['code'], $sql, __METHOD__); - } - if (strlen($returning)) { - $bval->save($row[$blobcol]->getData()); - $bval->free(); - } - if (!$this->mTrxLevel) - oci_commit($this->mConn); - - oci_free_statement($stmt); - } - - function tableName( $name ) { - # Replace reserved words with better ones - switch( $name ) { - case 'user': - return 'mwuser'; - case 'text': - return 'pagecontent'; - default: - return $name; - } - } - - /** - * Return the next in a sequence, save the value for retrieval via insertId() - */ - function nextSequenceValue($seqName) { - $res = $this->query("SELECT $seqName.nextval FROM dual"); - $row = $this->fetchRow($res); - $this->mInsertId = $row[0]; - $this->freeResult($res); - return $this->mInsertId; - } - - /** - * Oracle does not have a "USE INDEX" clause, so return an empty string - */ - function useIndexClause($index) { - return ''; - } - - # REPLACE query wrapper - # Oracle simulates this with a DELETE followed by INSERT - # $row is the row to insert, an associative array - # $uniqueIndexes is an array of indexes. Each element may be either a - # field name or an array of field names - # - # It may be more efficient to leave off unique indexes which are unlikely to collide. - # However if you do this, you run the risk of encountering errors which wouldn't have - # occurred in MySQL - function replace( $table, $uniqueIndexes, $rows, $fname = 'Database::replace' ) { - $table = $this->tableName($table); - - if (count($rows)==0) { - return; - } - - # Single row case - if (!is_array(reset($rows))) { - $rows = array($rows); - } - - foreach( $rows as $row ) { - # Delete rows which collide - if ( $uniqueIndexes ) { - $sql = "DELETE FROM $table WHERE "; - $first = true; - foreach ( $uniqueIndexes as $index ) { - if ( $first ) { - $first = false; - $sql .= "("; - } else { - $sql .= ') OR ('; - } - if ( is_array( $index ) ) { - $first2 = true; - foreach ( $index as $col ) { - if ( $first2 ) { - $first2 = false; - } else { - $sql .= ' AND '; - } - $sql .= $col.'=' . $this->addQuotes( $row[$col] ); - } - } else { - $sql .= $index.'=' . $this->addQuotes( $row[$index] ); - } - } - $sql .= ')'; - $this->query( $sql, $fname ); - } - - # 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); - } - } - - # DELETE where the condition is a join - function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds, $fname = "Database::deleteJoin" ) { - if ( !$conds ) { - throw new DBUnexpectedError($this, 'Database::deleteJoin() called with empty $conds' ); - } - - $delTable = $this->tableName( $delTable ); - $joinTable = $this->tableName( $joinTable ); - $sql = "DELETE FROM $delTable WHERE $delVar IN (SELECT $joinVar FROM $joinTable "; - if ( $conds != '*' ) { - $sql .= 'WHERE ' . $this->makeList( $conds, LIST_AND ); - } - $sql .= ')'; - - $this->query( $sql, $fname ); - } - - # Returns the size of a text field, or -1 for "unlimited" - function textFieldSize( $table, $field ) { - $table = $this->tableName( $table ); - $sql = "SELECT t.typname as ftype,a.atttypmod as size - FROM pg_class c, pg_attribute a, pg_type t - WHERE relname='$table' AND a.attrelid=c.oid AND - a.atttypid=t.oid and a.attname='$field'"; - $res =$this->query($sql); - $row=$this->fetchObject($res); - if ($row->ftype=="varchar") { - $size=$row->size-4; - } else { - $size=$row->size; - } - $this->freeResult( $res ); - return $size; - } - - function lowPriorityOption() { - return ''; - } - - function limitResult($sql, $limit, $offset) { - if ($offset === false) - $offset = 0; - return "SELECT * FROM ($sql) WHERE rownum >= (1 + $offset) AND rownum < 1 + $limit + $offset"; - } - - /** - * Returns an SQL expression for a simple conditional. - * Uses CASE on Oracle - * - * @param string $cond SQL expression which will result in a boolean value - * @param string $trueVal SQL expression to return if true - * @param string $falseVal SQL expression to return if false - * @return string SQL fragment - */ - function conditional( $cond, $trueVal, $falseVal ) { - return " (CASE WHEN $cond THEN $trueVal ELSE $falseVal END) "; - } - - function wasDeadlock() { - return $this->lastErrno() == 'OCI-00060'; - } - - function timestamp($ts = 0) { - return wfTimestamp(TS_ORACLE, $ts); - } - - /** - * Return aggregated value function call - */ - function aggregateValue ($valuedata,$valuename='value') { - return $valuedata; - } - - function reportQueryError($error, $errno, $sql, $fname, $tempIgnore = false) { - # Ignore errors during error handling to avoid infinite - # recursion - $ignore = $this->ignoreErrors(true); - ++$this->mErrorCount; - - if ($ignore || $tempIgnore) { -echo "error ignored! query = [$sql]\n"; - wfDebug("SQL ERROR (ignored): $error\n"); - $this->ignoreErrors( $ignore ); - } - else { -echo "error!\n"; - $message = "A database error has occurred\n" . - "Query: $sql\n" . - "Function: $fname\n" . - "Error: $errno $error\n"; - throw new DBUnexpectedError($this, $message); - } - } - - /** - * @return string wikitext of a link to the server software's web site - */ - function getSoftwareLink() { - return "[http://www.oracle.com/ Oracle]"; - } - - /** - * @return string Version information from the database - */ - function getServerVersion() { - return oci_server_version($this->mConn); - } - - /** - * Query whether a given table exists (in the given schema, or the default mw one if not given) - */ - function tableExists($table) { - $etable= $this->addQuotes($table); - $SQL = "SELECT 1 FROM user_tables WHERE table_name='$etable'"; - $res = $this->query($SQL); - $count = $res ? oci_num_rows($res) : 0; - if ($res) - $this->freeResult($res); - return $count; - } - - /** - * Query whether a given column exists in the mediawiki schema - */ - function fieldExists( $table, $field ) { - return true; // XXX - } - - function fieldInfo( $table, $field ) { - return false; // XXX - } - - function begin( $fname = '' ) { - $this->mTrxLevel = 1; - } - function immediateCommit( $fname = '' ) { - return true; - } - function commit( $fname = '' ) { - oci_commit($this->mConn); - $this->mTrxLevel = 0; - } - - /* Not even sure why this is used in the main codebase... */ - function limitResultForUpdate($sql, $num) { - return $sql; - } - - function strencode($s) { - return str_replace("'", "''", $s); - } - - function encodeBlob($b) { - return new ORABlob($b); - } - function decodeBlob($b) { - return $b; //return $b->load(); - } - - function addQuotes( $s ) { - global $wgLang; - $s = $wgLang->checkTitleEncoding($s); - return "'" . $this->strencode($s) . "'"; - } - - function quote_ident( $s ) { - return $s; - } - - /* For now, does nothing */ - function selectDB( $db ) { - return true; - } - - /** - * Returns an optional USE INDEX clause to go after the table, and a - * string to go at the end of the query - * - * @private - * - * @param array $options an associative array of options to be turned into - * an SQL query, valid keys are listed in the function. - * @return array - */ - function makeSelectOptions( $options ) { - $preLimitTail = $postLimitTail = ''; - $startOpts = ''; - - $noKeyOptions = array(); - foreach ( $options as $key => $option ) { - if ( is_numeric( $key ) ) { - $noKeyOptions[$option] = true; - } - } - - if ( isset( $options['GROUP BY'] ) ) $preLimitTail .= " GROUP BY {$options['GROUP BY']}"; - if ( isset( $options['ORDER BY'] ) ) $preLimitTail .= " ORDER BY {$options['ORDER BY']}"; - - if (isset($options['LIMIT'])) { - // $tailOpts .= $this->limitResult('', $options['LIMIT'], - // isset($options['OFFSET']) ? $options['OFFSET'] - // : false); - } - - #if ( isset( $noKeyOptions['FOR UPDATE'] ) ) $tailOpts .= ' FOR UPDATE'; - #if ( isset( $noKeyOptions['LOCK IN SHARE MODE'] ) ) $tailOpts .= ' LOCK IN SHARE MODE'; - if ( isset( $noKeyOptions['DISTINCT'] ) || isset( $noKeyOptions['DISTINCTROW'] ) ) $startOpts .= 'DISTINCT'; - - if ( isset( $options['USE INDEX'] ) && ! is_array( $options['USE INDEX'] ) ) { - $useIndex = $this->useIndexClause( $options['USE INDEX'] ); - } else { - $useIndex = ''; - } - - return array( $startOpts, $useIndex, $preLimitTail, $postLimitTail ); - } - - public function setTimeout( $timeout ) { - // @todo fixme no-op - } - - function ping() { - wfDebug( "Function ping() not written for DatabaseOracle.php yet"); - return true; - } - - /** - * How lagged is this slave? - * - * @return int - */ - public function getLag() { - # Not implemented for Oracle - return 0; - } - -} // end DatabaseOracle class - - |