Difference between revisions of "Extension:MediaWikiLite.php"
(setup_database method done - uses MySQL's SQL template and regexes it to SQLite's liking) |
(Use DatabasePostgres's code to populate interwiki from MySQL template) |
||
Line 7: | Line 7: | ||
if (!defined('PDO::ATTR_SERVER_VERSION')) die('PDO::SQLite3 is not installed!'); | if (!defined('PDO::ATTR_SERVER_VERSION')) die('PDO::SQLite3 is not installed!'); | ||
− | define('MWLITE_VERSION','0.0.0, 2008-01- | + | define('MWLITE_VERSION','0.0.0, 2008-01-09'); |
$wgDBtype = 'sqlite'; | $wgDBtype = 'sqlite'; | ||
Line 92: | Line 92: | ||
function fetchObject($res) { | function fetchObject($res) { | ||
if ($res instanceof ResultWrapper) $res = $res->result; | if ($res instanceof ResultWrapper) $res = $res->result; | ||
− | + | $row = $res->fetch(PDO::FETCH_OBJ); | |
− | if ($ | + | if ($row === false) throw new DBUnexpectedError($this,'Error in fetchObject(): '.htmlspecialchars($this->lastError())); |
return $row; | return $row; | ||
} | } | ||
Line 99: | Line 99: | ||
function fetchRow($res) { | function fetchRow($res) { | ||
if ($res instanceof ResultWrapper) $res = $res->result; | if ($res instanceof ResultWrapper) $res = $res->result; | ||
− | + | $row = $res->fetch(PDO::FETCH_BOTH); | |
− | if ($ | + | if ($row === false) throw new DBUnexpectedError($this,'Error in fetchRow(): '.htmlspecialchars($this->lastError())); |
return $row; | return $row; | ||
} | } | ||
Line 106: | Line 106: | ||
function numRows($res) { | function numRows($res) { | ||
if ($res instanceof ResultWrapper) $res = $res->result; | if ($res instanceof ResultWrapper) $res = $res->result; | ||
− | + | $n = $res->rowCount(); | |
− | |||
return $n; | return $n; | ||
} | } | ||
Line 113: | Line 112: | ||
function numFields($res) { | function numFields($res) { | ||
if ($res instanceof ResultWrapper) $res = $res->result; | if ($res instanceof ResultWrapper) $res = $res->result; | ||
− | + | $n = $res->columnCount(); | |
− | |||
return $n; | return $n; | ||
} | } | ||
Line 275: | Line 273: | ||
$wgDBTableOptions = ''; | $wgDBTableOptions = ''; | ||
$mysql_tmpl = "$IP/maintenance/tables.sql"; | $mysql_tmpl = "$IP/maintenance/tables.sql"; | ||
+ | $mysql_iw = "$IP/maintenance/interwiki.sql"; | ||
$sqlite_tmpl = "$wgSQLiteDataDir/tables.sql"; | $sqlite_tmpl = "$wgSQLiteDataDir/tables.sql"; | ||
Line 294: | Line 293: | ||
} | } | ||
− | # Parse the | + | # Parse the SQLite template replacing inline variables such as /*$wgDBprefix*/ |
$err = $this->sourceFile($sqlite_tmpl); | $err = $this->sourceFile($sqlite_tmpl); | ||
if ($err !== true) $this->reportQueryError($err,0,$sql,__FUNCTION__); | if ($err !== true) $this->reportQueryError($err,0,$sql,__FUNCTION__); | ||
+ | |||
+ | # Use DatabasePostgres's code to populate interwiki from MySQL template | ||
+ | $f = fopen($mysql_iw,'r' ); | ||
+ | if ($f == false ) dieout( "<li>Could not find the interwiki.sql file"); | ||
+ | $SQL = "INSERT INTO interwiki(iw_prefix,iw_url,iw_local) VALUES "; | ||
+ | while (!feof($f)) { | ||
+ | $line = fgets($f,1024); | ||
+ | $matches = array(); | ||
+ | if (!preg_match('/^\s*(\(.+?),(\d)\)/', $line, $matches)) continue; | ||
+ | $this->query("$SQL $matches[1],$matches[2])"); | ||
+ | } | ||
} | } | ||
} | } |
Revision as of 19:34, 8 January 2008
<?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('PDO::ATTR_SERVER_VERSION')) die('PDO::SQLite3 is not installed!');
define('MWLITE_VERSION','0.0.0, 2008-01-09');
$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; $this->mConn->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_SILENT); # set error codes only, dont raise exceptions } return $this->mConn; }
# Close an SQLite database function close() { $this->mOpened = false; if (is_object($this->mConn)) { if ($this->trxLevel()) $this->immediateCommit(); $this->mConn = null; } return true; }
# todo: handle buffered/unbuffered from $this->bufferResults() function doQuery($sql) { $ret = $this->mConn->query($sql); if ($ret === false) $this->reportQueryError($this->lastError(),$this->lastErrno(),$sql,__FUNCTION__); return $ret; }
function queryIgnore($sql, $fname = ) { return $this->query($sql, $fname, true); }
function freeResult($res) { if ($res instanceof ResultWrapper) $res = $res->result; $res->closeCursor(); return; }
function fetchObject($res) { if ($res instanceof ResultWrapper) $res = $res->result; $row = $res->fetch(PDO::FETCH_OBJ); if ($row === false) throw new DBUnexpectedError($this,'Error in fetchObject(): '.htmlspecialchars($this->lastError())); return $row; }
function fetchRow($res) { if ($res instanceof ResultWrapper) $res = $res->result; $row = $res->fetch(PDO::FETCH_BOTH); if ($row === false) throw new DBUnexpectedError($this,'Error in fetchRow(): '.htmlspecialchars($this->lastError())); return $row; }
function numRows($res) { if ($res instanceof ResultWrapper) $res = $res->result; $n = $res->rowCount(); return $n; }
function numFields($res) { if ($res instanceof ResultWrapper) $res = $res->result; $n = $res->columnCount(); return $n; }
function fieldName($res,$n) { return $res->fieldName($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 (!is_object($this->mConn)) return "Cannot return last error, no db connection"; $e = $this->mConn->errorInfo(); return $e[2]; }
function lastErrno() { if (!is_object($this->mConn)) return "Cannot return last error, no db connection"; return $this->mConn->errorCode(); }
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 $this->mConn->getAttribute(PDO::ATTR_SERVER_VERSION); }
# 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) { return '"'.$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,$wgDBTableOptions; $wgDBTableOptions = ; $mysql_tmpl = "$IP/maintenance/tables.sql"; $mysql_iw = "$IP/maintenance/interwiki.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 (1 || !file_exists($sqlite_tmpl)) { $sql = file_get_contents($mysql_tmpl); $sql = preg_replace('/^\\s*--.*?$/m',,$sql); # strip comments $sql = preg_replace('/^\\s*(UNIQUE)?\\s*(PRIMARY)?\\s*KEY.+?$/m',,$sql); $sql = preg_replace('/^\\s*(UNIQUE )?INDEX.+?$/m',,$sql); # These indexes should be created with a CREATE INDEX query $sql = preg_replace('/^\\s*FULLTEXT.+?$/m',,$sql); # Full text indexes $sql = preg_replace('/ENUM\\(.+?\\)/','TEXT',$sql); # Make ENUM's into TEXT's $sql = preg_replace('/ENUM\\(.+?\\)/','TEXT',$sql); # Make ENUM's into TEXT's $sql = preg_replace('/binary\\(\\d+\\)/','BLOB',$sql); $sql = preg_replace('/(TYPE|MAX_ROWS|AVG_ROW_LENGTH)=\\w+/',,$sql); $sql = preg_replace('/,\\s*\\)/s',')',$sql); # removing previous items may leave a trailing comma $sql = str_replace('binary',,$sql); $sql = str_replace('auto_increment','PRIMARY KEY',$sql); file_put_contents($sqlite_tmpl,$sql); }
# Parse the SQLite template replacing inline variables such as /*$wgDBprefix*/ $err = $this->sourceFile($sqlite_tmpl); if ($err !== true) $this->reportQueryError($err,0,$sql,__FUNCTION__);
# Use DatabasePostgres's code to populate interwiki from MySQL template $f = fopen($mysql_iw,'r' );
if ($f == false ) dieout( "