X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FDatabasePostgreSQL.php;h=c92a824648831c748ae55cf1dd23d67e968e6f4f;hb=8f0f91659d5db006f61ff8c3332f83928e546f5d;hp=21420a36506534c91cd76528b930f306dd8cc8ad;hpb=90155b8a9719ada6522a320a3315b4e698fdd970;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/DatabasePostgreSQL.php b/includes/DatabasePostgreSQL.php index 21420a3650..c92a824648 100644 --- a/includes/DatabasePostgreSQL.php +++ b/includes/DatabasePostgreSQL.php @@ -1,20 +1,16 @@ close(); $this->mServer = $server; $this->mUser = $user; $this->mPassword = $password; $this->mDBname = $dbName; + $this->mSchemas = array($wgDBschema,'public'); $success = false; if ( '' != $dbName ) { # start a database connection - @$this->mConn = pg_connect("host=$server dbname=$dbName user=$user password=$password"); + $hstring=""; + if ($server!=false && $server!="") { + $hstring="host=$server "; + } + @$this->mConn = pg_connect("$hstring dbname=$dbName user=$user password=$password"); 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" ); } else { + $this->setSchema(); $this->mOpened = true; } } @@ -165,6 +170,18 @@ class DatabasePgsql extends Database { return false; } + function indexUnique ($table, $index, $fname = 'Database::indexUnique' ) { + $sql = "SELECT indexname FROM pg_indexes WHERE tablename='{$table}'". + " AND indexdef LIKE 'CREATE UNIQUE%({$index})'"; + $res = $this->query( $sql, $fname ); + if ( !$res ) + return NULL; + while ($row = $this->fetchObject( $res )) + return true; + return false; + + } + function fieldInfo( $table, $field ) { wfDebugDieBacktrace( 'Database::fieldInfo() error : mysql_fetch_field() not implemented for postgre' ); /* @@ -181,7 +198,7 @@ class DatabasePgsql extends Database { return false;*/ } - function insertArray( $table, $a, $fname = 'Database::insertArray', $options = array() ) { + function insert( $table, $a, $fname = 'Database::insert', $options = array() ) { # PostgreSQL doesn't support options # We have a go at faking one of them # TODO: DELAYED, LOW_PRIORITY @@ -199,7 +216,7 @@ class DatabasePgsql extends Database { $a = array( $a ); } foreach ( $a as $row ) { - parent::insertArray( $table, $row, $fname, array() ); + parent::insert( $table, $row, $fname, array() ); } $this->ignoreErrors( $oldIgnore ); $retVal = true; @@ -222,12 +239,16 @@ class DatabasePgsql extends Database { # First run any transformations from the parent object $name = parent::tableName( $name ); + # Replace backticks into double quotes + $name = strtr($name,'`','"'); + # Now quote PG reserved keywords switch( $name ) { case 'user': - return '"user"'; case 'old': - return '"old"'; + case 'group': + return '"' . $name . '"'; + default: return $name; } @@ -241,7 +262,7 @@ class DatabasePgsql extends Database { * Return the next in a sequence, save the value for retrieval via insertId() */ function nextSequenceValue( $seqName ) { - $value = $this->getField(''," nextval('" . $seqName . "')"); + $value = $this->selectField(''," nextval('" . $seqName . "')"); $this->mInsertId = $value; return $value; } @@ -265,6 +286,10 @@ class DatabasePgsql extends Database { # 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 ) ) ) { @@ -274,17 +299,17 @@ class DatabasePgsql extends Database { foreach( $rows as $row ) { # Delete rows which collide if ( $uniqueIndexes ) { - $sql = "DELETE FROM $table WHERE ("; + $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; - $sql .= "("; foreach ( $index as $col ) { if ( $first2 ) { $first2 = false; @@ -293,16 +318,16 @@ class DatabasePgsql extends Database { } $sql .= $col.'=' . $this->addQuotes( $row[$col] ); } - } else { + } else { $sql .= $index.'=' . $this->addQuotes( $row[$index] ); - } + } } $sql .= ')'; $this->query( $sql, $fname ); } # Now insert the row - $sql = "INSERT INTO $table (" . $this->makeList( array_flip( $row ) ) .') VALUES (' . + $sql = "INSERT INTO $table (" . $this->makeList( array_keys( $row ), LIST_NAMES ) .') VALUES (' . $this->makeList( $row, LIST_COMMA ) . ')'; $this->query( $sql, $fname ); } @@ -328,8 +353,17 @@ class DatabasePgsql extends Database { # Returns the size of a text field, or -1 for "unlimited" function textFieldSize( $table, $field ) { $table = $this->tableName( $table ); - $res = $this->query( "SELECT $field FROM $table LIMIT 1", "Database::textFieldLength" ); - $size = pg_field_size( $res, 0 ); + $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; } @@ -341,28 +375,75 @@ class DatabasePgsql extends Database { function limitResult($limit,$offset) { return " LIMIT $limit ".(is_numeric($offset)?" OFFSET {$offset} ":""); } + + /** + * Returns an SQL expression for a simple conditional. + * Uses CASE on PostgreSQL. + * + * @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) "; + } # FIXME: actually detecting deadlocks might be nice function wasDeadlock() { return false; } - # Return DB-style timestamp used for MySQL schema - function timestamp( $ts=0 ) { - return wfTimestamp(TS_DB,$ts); + # Return DB-style timestamp used for MySQL schema + function timestamp( $ts=0 ) { + return wfTimestamp(TS_DB,$ts); + } + + /** + * Return aggregated value function call + */ + function aggregateValue ($valuedata,$valuename='value') { + return $valuedata; } - function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) { - $message = "A database error has occurred\n" . - "Query: $sql\n" . - "Function: $fname\n" . - "Error: $errno $error\n"; + + function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) { + $message = "A database error has occurred\n" . + "Query: $sql\n" . + "Function: $fname\n" . + "Error: $errno $error\n"; wfDebugDieBacktrace($message); } + + /** + * @return string wikitext of a link to the server software's web site + */ + function getSoftwareLink() { + return "[http://www.postgresql.org/ PostgreSQL]"; + } + + /** + * @return string Version information from the database + */ + function getServerVersion() { + $res = $this->query( "SELECT version()" ); + $row = $this->fetchRow( $res ); + $version = $row[0]; + $this->freeResult( $res ); + return $version; + } + + function setSchema($schema=false) { + $schemas=$this->mSchemas; + if ($schema) { array_unshift($schemas,$schema); } + $searchpath=$this->makeList($schemas,LIST_NAMES); + $this->query("SET search_path = $searchpath"); + } } /** * Just an alias. + * @package MediaWiki */ class DatabasePostgreSQL extends DatabasePgsql { }