Extension:MediaWikiLite.php
<?php
- Extension:SQLite
Template:PhpCategory:Extensions in progress
- - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html)
- - Author: User:NadCategory:Extensions created with Template:Extension
if (!defined('MEDIAWIKI')) die('Not an entry point.'); if (!defined('SQLITE_OK')) die('SQLite is not installed!');
define('MWLITE_VERSION','0.0.0, 2008-01-08');
$wgDBtype = 'sqlite'; $wgSQLiteDataDir = dirname(__FILE__); $wgShowSQLErrors = true;
$wgExtensionCredits['other'][] = array( 'name' => 'MediaWikiLite', 'author' => 'User:Nad', 'description' => 'Allow MediaWiki installations to store content in an SQLite database instead of MySQL, and to run as a daemon independently of a web-server.', 'url' => 'http://www.organicdesign.co.nz/Extension:SQLite.php', 'version' => MWLITE_VERSION );
class DatabaseSqlite extends Database {
var $mAffectedRows;
function DatabaseSqlite($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; } function functionalIndexes() { return true; }
static function newFromParams($server, $user, $password, $dbName, $failFunction = false, $flags = 0) { return new DatabaseSqlite($server, $user, $password, $dbName, $failFunction, $flags); }
# Open an SQLite database and return a resource handle to it # NOTE: only $dbName is used, the other parameters are irrelevant for SQLite databases function open($server,$user,$password,$dbName) { global $wgSQLiteDataDir; $this->mConn = false; if ($dbName) { if ($this->mFlags & DBO_PERSISTENT) @$this->mConn = new PDO("sqlite:$wgSQLiteDataDir/$dbName",$user,$pass,array(PDO::ATTR_PERSISTENT => true)); else @$this->mConn = @$this->mConn = new PDO("sqlite:$wgSQLiteDataDir/$dbName",$user,$pass); if ($this->mConn === false) wfDebug("DB connection error: $err\n");; $this->mOpened = $this->mConn; } return $this->mConn; }
# Close an SQLite database function close() { $this->mOpened = false; if ($this->mConn) { if ($this->trxLevel()) $this->immediateCommit(); $this->mConn = null; } return true; }
function doQuery($sql) { if ($this->bufferResults()) @$ret = sqlite_query($this->mConn, $sql, SQLITE_BOTH, $err); else @$ret = sqlite_unbuffered_query($this->mConn, $sql, SQLITE_BOTH, $err); if ($err) $this->reportQueryError($err, 0, $sql, __FUNCTION__); return $ret; }
function queryIgnore($sql, $fname = ) { return $this->query($sql, $fname, true); }
function freeResult($res) { return; }
function fetchObject($res) { if ($res instanceof ResultWrapper) $res = $res->result; @$row = sqlite_fetch_object($res); if ($this->lastErrno()) throw new DBUnexpectedError($this,'Error in fetchObject(): '.htmlspecialchars($this->lastError())); return $row; }
function fetchRow($res) { if ($res instanceof ResultWrapper) $res = $res->result; @$row = sqlite_fetch_array($res); if ($this->lastErrno()) throw new DBUnexpectedError($this,'Error in fetchRow(): '.htmlspecialchars($this->lastError())); return $row; }
function numRows($res) { if ($res instanceof ResultWrapper) $res = $res->result; @$n = sqlite_num_rows($res); if ($this->lastErrno()) throw new DBUnexpectedError($this,'Error in numRows(): '.htmlspecialchars($this->lastError())); return $n; }
function numFields($res) { if ($res instanceof ResultWrapper) $res = $res->result; @$n = sqlite_num_fields($res); if ($this->lastErrno()) throw new DBUnexpectedError($this,'Error in numFields(): '.htmlspecialchars($this->lastError())); return $n; }
function fieldName($res,$n) { return sqlite_field_name($res,$n); }
# SQLite doesn't like the back-tick for strings function tableName($name) { return ereg_replace('`','"',parent::tableName($name)); }
# This must be called after nextSequenceVal function insertId() { # todo: return $this->mInsertId; ? }
function dataSeek($res, $row) { $res->seek($row); }
function lastError() { if ($this->mConn === false) return "Cannot return last error, no db connection"; return sqlite_error_string(sqlite_last_error($this->mConn)); }
function lastErrno() { if ($this->mConn === false) return "Cannot return last error, no db connection"; return sqlite_last_error($this->mConn); }
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') { # todo }
function indexUnique($table, $index, $fname = 'Database::indexUnique') { # todo }
function insert($table, $a, $fname = 'Database::insert', $options = array()) { # todo }
function insertOneRow($table, $row, $fname) { # todo }
# SQLite does not have a "USE INDEX" clause, so return an empty string function useIndexClause($index) { return ; }
# REPLACE query wrapper function replace($table, $uniqueIndexes, $rows, $fname = 'Database::replace') { # todo }
# DELETE where the condition is a join function deleteJoin($delTable, $joinTable, $delVar, $joinVar, $conds, $fname = "Database::deleteJoin") { # todo }
# Returns the size of a text field, or -1 for "unlimited" function textFieldSize($table, $field) { # todo }
# No low priority option in SQLite function lowPriorityOption() { return ; }
# Returns an SQL expression for a simple conditional. # - uses CASE on SQLite function conditional($cond, $trueVal, $falseVal) { return " (CASE WHEN $cond THEN $trueVal ELSE $falseVal END) "; }
function wasDeadlock() { return $this->lastErrno() == SQLITE_BUSY; }
# @return string wikitext of a link to the server software's web site function getSoftwareLink() { return "SQLite"; }
# @return string Version information from the database function getServerVersion() { return sqlite_libversion(); }
# Query whether a given column exists in the mediawiki schema function fieldExists($table, $field) { return true; }
function fieldInfo($table, $field) { return false; }
function begin($fname = 'DatabasePostgres::begin') { $this->query('BEGIN', $fname); $this->mTrxLevel = 1; }
function immediateCommit($fname = 'DatabaseSqlite::immediateCommit') { return true; }
function commit($fname = 'DatabaseSqlite::commit') { $this->query('COMMIT', $fname); $this->mTrxLevel = 0; }
function limitResultForUpdate($sql, $num) { return $sql; }
function strencode($s) { return sqlite_escape_string($s); }
function encodeBlob($b) { return new SQLiteBlob($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; }
# not done public function setTimeout($timeout) { return; }
function ping() { wfDebug("Function ping() not written for SQLite yet"); return true; }
# How lagged is this slave? public function getLag() { return 0; }
# Called by the installer script (when modified according to the MediaWikiLite installation instructions) # - this is the same way PostgreSQL works, MySQL reads in tables.sql and interwiki.sql using dbsource (which calls db->sourceFile) public function setup_database() { global $IP,$wgSQLiteDataDir; $mysql_tmpl = "$IP/maintenance/tables.sql"; $sqlite_tmpl = "$wgSQLiteDataDir/tables.sql";
# Make an SQLite template file if it doesn't exist (based on the same one MySQL uses to create a new wiki db) if (!file_exists($sqlite_tmpl)) { $sql = file_get_contents($mysql_tmpl); # todo: do a regexp to make the SQL compatible with SQLite3 file_put_contents($sqlite_tmpl,$sql); }
# Parse the SQL template replacing inline variables such as /*$wgDBprefix*/ $this->sourceFile($sqlite_tmpl); }
}