/** * (MySQL only) Adds back fulltext index after populating the table. */ private function createMysqlTextIndex() { $searchindex = $this->db->tableName('searchindex'); $this->output("\nRebuild the index...\n"); $sql = "ALTER TABLE {$searchindex} ADD FULLTEXT si_title (si_title), " . "ADD FULLTEXT si_text (si_text)"; $this->db->query($sql, __METHOD__); }
/** * Empty all tables so they can be repopulated for tests */ private function resetDB() { if ($this->db) { if ($this->db->getType() == 'oracle') { if (self::$useTemporaryTables) { wfGetLB()->closeAll(); $this->db = wfGetDB(DB_MASTER); } else { foreach ($this->tablesUsed as $tbl) { if ($tbl == 'interwiki') { continue; } $this->db->query('TRUNCATE TABLE ' . $this->db->tableName($tbl), __METHOD__); } } } else { foreach ($this->tablesUsed as $tbl) { if ($tbl == 'interwiki' || $tbl == 'user') { continue; } $this->db->delete($tbl, '*', __METHOD__); } } } }
/** * Find pages in mainspace that have a prefix of the new namespace * so we know titles that will need migrating * @param $ns int Namespace id (id for new namespace?) * @param $name String Prefix that is being made a namespace */ private function getConflicts( $ns, $name ) { $page = 'page'; $table = $this->db->tableName( $page ); $prefix = $this->db->strencode( $name ); $encNamespace = $this->db->addQuotes( $ns ); $titleSql = "TRIM(LEADING '$prefix:' FROM {$page}_title)"; if( $ns == 0 ) { // An interwiki; try an alternate encoding with '-' for ':' $titleSql = $this->db->buildConcat( array( "'$prefix-'", $titleSql ) ); } $sql = "SELECT {$page}_id AS id, {$page}_title AS oldtitle, $encNamespace + {$page}_namespace AS namespace, $titleSql AS title, {$page}_namespace AS oldnamespace FROM {$table} WHERE ( {$page}_namespace=0 OR {$page}_namespace=1 ) AND {$page}_title " . $this->db->buildLike( $name . ':', $this->db->anyString() ); $result = $this->db->query( $sql, __METHOD__ ); $set = array(); foreach( $result as $row ) { $set[] = $row; } return $set; }
private static function __getCategories($aParamValues, &$parser) { wfProfileIn(__METHOD__); self::$aCategoryNames = $aParamValues; $aPages = array(); if (!empty($aParamValues)) { # RT 26917 $aParamValues = array_map("strip_tags", array_map(array("self", "__parseCategories"), $aParamValues, array($parser))); // set timestamp option, if set $timestampLimit = BLOGS_TIMESTAMP; if (!empty(self::$aOptions['timestamp'])) { $timestampLimit = self::$aOptions['timestamp']; } /* set max length of group concat query */ self::$dbr->query('SET group_concat_max_len = ' . GROUP_CONCAT, __METHOD__); /* run query */ $res = self::$dbr->select(array(self::$dbr->tableName('page'), self::$dbr->tableName('categorylinks')), array("cl_to", "GROUP_CONCAT(DISTINCT cl_from SEPARATOR ',') AS cl_page"), array("page_namespace" => NS_BLOG_ARTICLE, "page_id = cl_from", "cl_to in (" . self::$dbr->makeList($aParamValues) . ")", "page_touched >= " . self::$dbr->addQuotes($timestampLimit)), __METHOD__, array('GROUP BY' => 'cl_to')); while ($oRow = self::$dbr->fetchObject($res)) { // BugId:49408 // Since GROUP_CONCAT respects group_concat_max_len arbitrarily, // sometimes we end up with a comma or a truncated item, which // we don't want. if (GROUP_CONCAT == strlen($oRow->cl_page)) { $aPages[] = preg_replace('/,\\d+,?$/', '', $oRow->cl_page); } else { $aPages[] = $oRow->cl_page; } } self::$dbr->freeResult($res); } wfProfileOut(__METHOD__); return $aPages; }
/** * @param DatabaseBase $dbw * @param string $table * @param string $column * @param string $wiki */ function doDeletes($dbw, $table, $column, $wiki) { if (!$dbw->tableExists($table)) { $this->error("Maintenance script cannot be run on this wiki as there is no {$table} table", 1); } $this->output("{$table}:\n"); $count = 0; do { $wikiQuoted = $dbw->addQuotes($wiki); $dbw->query("DELETE FROM {$table} WHERE {$column}={$wikiQuoted} LIMIT 500", __METHOD__); $affected = $dbw->affectedRows(); $count += $affected; $this->output("{$count}\n"); wfWaitForSlaves(); } while ($affected === 500); $this->output("{$count} {$table} rows deleted\n"); }
/** * @param DatabaseBase $db * @param string $table * @param string $field * @return null|PostgresField */ static function fromText($db, $table, $field) { $q = <<<SQL SELECT attnotnull, attlen, conname AS conname, atthasdef, adsrc, COALESCE(condeferred, 'f') AS deferred, COALESCE(condeferrable, 'f') AS deferrable, CASE WHEN typname = 'int2' THEN 'smallint' WHEN typname = 'int4' THEN 'integer' WHEN typname = 'int8' THEN 'bigint' WHEN typname = 'bpchar' THEN 'char' ELSE typname END AS typname FROM pg_class c JOIN pg_namespace n ON (n.oid = c.relnamespace) JOIN pg_attribute a ON (a.attrelid = c.oid) JOIN pg_type t ON (t.oid = a.atttypid) LEFT JOIN pg_constraint o ON (o.conrelid = c.oid AND a.attnum = ANY(o.conkey) AND o.contype = 'f') LEFT JOIN pg_attrdef d on c.oid=d.adrelid and a.attnum=d.adnum WHERE relkind = 'r' AND nspname=%s AND relname=%s AND attname=%s; SQL; $table = $db->tableName($table, 'raw'); $res = $db->query(sprintf($q, $db->addQuotes($db->getCoreSchema()), $db->addQuotes($table), $db->addQuotes($field))); $row = $db->fetchObject($res); if (!$row) { return null; } $n = new PostgresField(); $n->type = $row->typname; $n->nullable = $row->attnotnull == 'f'; $n->name = $field; $n->tablename = $table; $n->max_length = $row->attlen; $n->deferrable = $row->deferrable == 't'; $n->deferred = $row->deferred == 't'; $n->conname = $row->conname; $n->has_default = $row->atthasdef === 't'; $n->default = $row->adsrc; return $n; }
/** * @param int $limit limit number of results. * @param array $namespaces list of namespaces to filter by. No filter applied if null * @return ResultWrapper */ public function getLatestRevisionsQuery($limit, $namespaces) { $namespaces = $this->sqlSanitizeArray($namespaces); $tables = ['recentchanges']; $joinConditions = []; $conditions = []; $options = ['LIMIT' => $limit, 'ORDER BY' => 'rc_id DESC']; // clear out the bots $conditions[] = "rc_bot=0"; // filter by namespaces if provided if ($namespaces != null) { $conditions[] = "page_namespace in (" . implode(",", $namespaces) . ")"; $tables[] = 'page'; $joinConditions['page'] = ["JOIN", "rc_cur_id=page_id"]; } $query = $this->databaseConnection->selectSQLText($tables, 'rc_id as id, page_id as pageId, rc_timestamp as timestamp, rc_user as userId', $conditions, __METHOD__, $options, $joinConditions); $result = $this->databaseConnection->query($query); return $result; }
protected function destroyDB() { if ($this->useTemporaryTables || is_null($this->db)) { # Don't need to do anything return; } $tables = $this->db->listTables($this->dbPrefix(), __METHOD__); foreach ($tables as $table) { try { $sql = $this->db->getType() == 'oracle' ? "DROP TABLE {$table} CASCADE CONSTRAINTS PURGE" : "DROP TABLE `{$table}`"; $this->db->query($sql, __METHOD__); } catch (MWException $mwe) { } } if ($this->db->getType() == 'oracle') { $this->db->query('BEGIN FILL_WIKI_INFO; END;', __METHOD__); } CloneDatabase::changePrefix($this->oldTablePrefix); }
/** * @param DatabaseBase $dbw * @param string $table * @param string $column * @param string $wiki */ function doDeletes($dbw, $table, $column, $wiki) { if (!$dbw->tableExists($table)) { $this->error("Maintenance script cannot be run on this wiki as there is no {$table} table", 1); } $this->output("{$table}:\n"); $count = 0; do { // https://bugzilla.wikimedia.org/show_bug.cgi?id=52868 //$dbw->delete( // $table, // array( $column => $wiki ), // __METHOD__, // array( 'LIMIT' => 500 ), //); $wikiQuoted = $dbw->addQuotes($wiki); $dbw->query("DELETE FROM {$table} WHERE {$column}={$wikiQuoted} LIMIT 500", __METHOD__); $affected = $dbw->affectedRows(); $count += $affected; $this->output("{$count}\n"); wfWaitForSlaves(); } while ($affected === 500); $this->output("{$count} {$table} rows deleted\n"); }
/** * Create some initial DB entries for important built-in properties. Having the DB contents predefined * allows us to safe DB calls when certain data is needed. At the same time, the entries in the DB * make sure that DB-based functions work as with all other properties. */ protected function setupPredefinedProperties($verbose, DatabaseBase $db) { global $wgDBtype; $this->reportProgress("Setting up internal property indices ...\n", $verbose); // Check if we already have this structure $borderiw = $db->selectField(SMWSQLStore3::ID_TABLE, 'smw_iw', 'smw_id=' . $db->addQuotes(\SMWSql3SmwIds::FXD_PROP_BORDER_ID)); if ($borderiw != SMW_SQL3_SMWBORDERIW) { $this->reportProgress(" ... allocating space for internal properties ...\n", $verbose); $this->store->smwIds->moveSMWPageID(\SMWSql3SmwIds::FXD_PROP_BORDER_ID); // make sure position 50 is empty $db->insert(SMWSQLStore3::ID_TABLE, array('smw_id' => \SMWSql3SmwIds::FXD_PROP_BORDER_ID, 'smw_title' => '', 'smw_namespace' => 0, 'smw_iw' => SMW_SQL3_SMWBORDERIW, 'smw_subobject' => '', 'smw_sortkey' => ''), 'SMW::setup'); // put dummy "border element" on index 50 $this->reportProgress(' ', $verbose); for ($i = 0; $i < \SMWSql3SmwIds::FXD_PROP_BORDER_ID; $i++) { // make way for built-in ids $this->store->smwIds->moveSMWPageID($i); $this->reportProgress('.', $verbose); } $this->reportProgress(" done.\n", $verbose); } else { $this->reportProgress(" ... space for internal properties already allocated.\n", $verbose); } // now write actual properties; do that each time, it is cheap enough and we can update sortkeys by current language $this->reportProgress(" ... writing entries for internal properties ...", $verbose); foreach (SMWSql3SmwIds::$special_ids as $prop => $id) { $p = new SMWDIProperty($prop); $db->replace(SMWSQLStore3::ID_TABLE, array('smw_id'), array('smw_id' => $id, 'smw_title' => $p->getKey(), 'smw_namespace' => SMW_NS_PROPERTY, 'smw_iw' => $this->store->smwIds->getPropertyInterwiki($p), 'smw_subobject' => '', 'smw_sortkey' => $p->getLabel()), 'SMW::setup'); } $this->reportProgress(" done.\n", $verbose); if ($wgDBtype == 'postgres') { $sequenceIndex = SMWSQLStore3::ID_TABLE . '_smw_id_seq'; $this->reportProgress(" ... updating {$sequenceIndex} sequence accordingly.\n", $verbose); $max = $db->selectField(SMWSQLStore3::ID_TABLE, 'max(smw_id)', array(), __METHOD__); $max += 1; $db->query("ALTER SEQUENCE {$sequenceIndex} RESTART WITH {$max}", __METHOD__); } $this->reportProgress("Internal properties initialized successfully.\n", $verbose); }
function execute() { $this->dbw = wfGetDB(DB_MASTER); $logging = $this->dbw->tableName('logging'); $logging_1_10 = $this->dbw->tableName('logging_1_10'); $logging_pre_1_10 = $this->dbw->tableName('logging_pre_1_10'); if ($this->dbw->tableExists('logging_pre_1_10') && !$this->dbw->tableExists('logging')) { # Fix previous aborted run echo "Cleaning up from previous aborted run\n"; $this->dbw->query("RENAME TABLE {$logging_pre_1_10} TO {$logging}", __METHOD__); } if ($this->dbw->tableExists('logging_pre_1_10')) { echo "This script has already been run to completion\n"; return; } # Create the target table if (!$this->dbw->tableExists('logging_1_10')) { global $wgDBTableOptions; $sql = <<<EOT CREATE TABLE {$logging_1_10} ( -- Log ID, for referring to this specific log entry, probably for deletion and such. log_id int unsigned NOT NULL auto_increment, -- Symbolic keys for the general log type and the action type -- within the log. The output format will be controlled by the -- action field, but only the type controls categorization. log_type varbinary(10) NOT NULL default '', log_action varbinary(10) NOT NULL default '', -- Timestamp. Duh. log_timestamp binary(14) NOT NULL default '19700101000000', -- The user who performed this action; key to user_id log_user int unsigned NOT NULL default 0, -- Key to the page affected. Where a user is the target, -- this will point to the user page. log_namespace int NOT NULL default 0, log_title varchar(255) binary NOT NULL default '', -- Freeform text. Interpreted as edit history comments. log_comment varchar(255) NOT NULL default '', -- LF separated list of miscellaneous parameters log_params blob NOT NULL, -- rev_deleted for logs log_deleted tinyint unsigned NOT NULL default '0', PRIMARY KEY log_id (log_id), KEY type_time (log_type, log_timestamp), KEY user_time (log_user, log_timestamp), KEY page_time (log_namespace, log_title, log_timestamp), KEY times (log_timestamp) ) {$wgDBTableOptions} EOT; echo "Creating table logging_1_10\n"; $this->dbw->query($sql, __METHOD__); } # Synchronise the tables echo "Doing initial sync...\n"; $this->sync('logging', 'logging_1_10'); echo "Sync done\n\n"; # Rename the old table away echo "Renaming the old table to {$logging_pre_1_10}\n"; $this->dbw->query("RENAME TABLE {$logging} TO {$logging_pre_1_10}", __METHOD__); # Copy remaining old rows # Done before the new table is active so that $copyPos is accurate echo "Doing final sync...\n"; $this->sync('logging_pre_1_10', 'logging_1_10'); # Move the new table in echo "Moving the new table in...\n"; $this->dbw->query("RENAME TABLE {$logging_1_10} TO {$logging}", __METHOD__); echo "Finished.\n"; }
/** * Truncate a table. * @param string $table The table name to be truncated */ function clearTable($table) { print "Clearing {$table}...\n"; $tableName = $this->db->tableName($table); $this->db->query("TRUNCATE {$tableName}"); }
private function dropFunctions() { $this->db->query('DROP FUNCTION IF EXISTS mw_test_function' . ($this->db->getType() == 'postgres' ? '()' : '')); }
/** * Create an index using the suitable SQL for various RDBMS. * * @since 1.8 * @param DatabaseBase|Database $db Database handler * @param string $type "INDEX", "UNIQUE" or similar * @param string $indexName name fo the index as in DB * @param string $tableName name of the table * @param array $columns list of column names to index, comma separated * @param object $reportTo object to report messages to */ private static function createIndex($db, $type, $indexName, $tableName, $columns, $reportTo = null) { global $wgDBtype; self::reportProgress(" ... creating new index {$columns} ...", $reportTo); if ($wgDBtype == 'postgres') { // postgresql if ($db->indexInfo($tableName, $indexName) === false) { $db->query("CREATE {$type} {$indexName} ON {$tableName} ({$columns})", __METHOD__); } } elseif ($wgDBtype == 'sqlite') { // SQLite $db->query("CREATE {$type} {$indexName} ON {$tableName} ({$columns})", __METHOD__); } else { // MySQL and default $db->query("ALTER TABLE {$tableName} ADD {$type} ({$columns})", __METHOD__); } self::reportProgress("done.\n", $reportTo); }
public function query($sql, $fname = '', $tempIgnore = false) { $this->checkFunctionName($fname); $this->addSql($sql); return parent::query($sql, $fname, $tempIgnore); }
/** * @param DatabaseMysql $db * @return array - databases which are available on this cluster * use the writable devbox server instead of the production slaves. */ function getDevBoxOverrideDatabases(DatabaseBase $db) { $IGNORE_DBS = array('information_schema', 'mysql', '#mysql50#lost+found', 'wikicities_c2'); $retval = array(); $res = $db->query('SHOW DATABASES', __METHOD__); while ($row = $res->fetchObject()) { $retval[] = $row->Database; } $retval = array_diff($retval, $IGNORE_DBS); sort($retval); return $retval; }
/** * @param DatabaseBase $dbw * @return void */ private function truncate($dbw) { $test = $dbw->tableName('test'); $dbw->query("TRUNCATE TABLE {$test}"); }
/** * @param $lockDb string * @param $db DatabaseBase */ protected function initConnection( $lockDb, DatabaseBase $db ) { # Let this transaction see lock rows from other transactions $db->query( "SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;" ); }