/** * @param array $updates Array of arrays each containing two keys, 'primaryKey' * and 'changes'. primaryKey must contain a map of column names to values * sufficient to uniquely identify the row changes must contain a map of column * names to update values to apply to the row. */ public function write(array $updates) { $this->db->begin(); foreach ($updates as $update) { $this->db->update($this->table, $update['changes'], $update['primaryKey'], __METHOD__); } $this->db->commit(); wfWaitForSlaves(false, false, $this->clusterName); }
/** * Do all the updates * * @param array $what what updates to perform */ public function doUpdates($what = array('core', 'extensions', 'stats')) { global $wgVersion, $wgLocalisationCacheConf; $this->db->begin(__METHOD__); $what = array_flip($what); $this->skipSchema = isset($what['noschema']) || $this->fileHandle !== null; if (isset($what['core'])) { $this->runUpdates($this->getCoreUpdateList(), false); } if (isset($what['extensions'])) { $this->runUpdates($this->getOldGlobalUpdates(), false); $this->runUpdates($this->getExtensionUpdates(), true); } if (isset($what['stats'])) { $this->checkStats(); } if (isset($what['purge'])) { $this->purgeCache(); if ($wgLocalisationCacheConf['manualRecache']) { $this->rebuildLocalisationCache(); } } $this->setAppliedUpdates($wgVersion, $this->updates); if ($this->fileHandle) { $this->skipSchema = false; $this->writeSchemaUpdateFile(); $this->setAppliedUpdates("{$wgVersion}-schema", $this->updatesSkipped); } $this->db->commit(__METHOD__); }
/** * Create database tables from scratch. * * @return Status */ public function createTables() { $status = $this->getConnection(); if (!$status->isOK()) { return $status; } $this->db->selectDB($this->getVar('wgDBname')); if ($this->db->tableExists('archive', __METHOD__)) { $status->warning('config-install-tables-exist'); $this->enableLB(); return $status; } $this->db->setFlag(DBO_DDLMODE); // For Oracle's handling of schema files $this->db->begin(__METHOD__); $error = $this->db->sourceFile($this->db->getSchemaPath()); if ($error !== true) { $this->db->reportQueryError($error, 0, '', __METHOD__); $this->db->rollback(__METHOD__); $status->fatal('config-install-tables-failed', $error); } else { $this->db->commit(__METHOD__); } // Resume normal operations if ($status->isOk()) { $this->enableLB(); } return $status; }
/** * Create the tables for each extension the user enabled * @return Status */ public function createExtensionTables() { $status = $this->getConnection(); if (!$status->isOK()) { return $status; } $updater = DatabaseUpdater::newForDB($this->db); $extensionUpdates = $updater->getNewExtensions(); $ourExtensions = array_map('strtolower', $this->getVar('_Extensions')); foreach ($ourExtensions as $ext) { if (isset($extensionUpdates[$ext])) { $this->db->begin(__METHOD__); $error = $this->db->sourceFile($extensionUpdates[$ext]); if ($error !== true) { $this->db->rollback(__METHOD__); $status->warning('config-install-tables-failed', $error); } else { $this->db->commit(__METHOD__); } } } // Now run updates to create tables for old extensions $updater->doUpdates(array('extensions')); return $status; }
/** * Merge page histories * * @param integer $id The page_id * @param Title $newTitle The new title */ private function mergePage($row, Title $newTitle) { $id = $row->page_id; // Construct the WikiPage object we will need later, while the // page_id still exists. Note that this cannot use makeTitleSafe(), // we are deliberately constructing an invalid title. $sourceTitle = Title::makeTitle($row->page_namespace, $row->page_title); $sourceTitle->resetArticleID($id); $wikiPage = new WikiPage($sourceTitle); $wikiPage->loadPageData('fromdbmaster'); $destId = $newTitle->getArticleId(); $this->db->begin(__METHOD__); $this->db->update('revision', array('rev_page' => $destId), array('rev_page' => $id), __METHOD__); $this->db->delete('page', array('page_id' => $id), __METHOD__); /* Call LinksDeletionUpdate to delete outgoing links from the old title, * and update category counts. * * Calling external code with a fake broken Title is a fairly dubious * idea. It's necessary because it's quite a lot of code to duplicate, * but that also makes it fragile since it would be easy for someone to * accidentally introduce an assumption of title validity to the code we * are calling. */ $update = new LinksDeletionUpdate($wikiPage); $update->doUpdate(); $this->db->commit(__METHOD__); return true; }
/** * Apply a SQL source file to the database as part of running an installation step. * * @param string $sourceFileMethod * @param string $stepName * @param string $archiveTableMustNotExist * @return Status */ private function stepApplySourceFile($sourceFileMethod, $stepName, $archiveTableMustNotExist = false) { $status = $this->getConnection(); if (!$status->isOK()) { return $status; } $this->db->selectDB($this->getVar('wgDBname')); if ($archiveTableMustNotExist && $this->db->tableExists('archive', __METHOD__)) { $status->warning("config-{$stepName}-tables-exist"); $this->enableLB(); return $status; } $this->db->setFlag(DBO_DDLMODE); // For Oracle's handling of schema files $this->db->begin(__METHOD__); $error = $this->db->sourceFile(call_user_func(array($this->db, $sourceFileMethod))); if ($error !== true) { $this->db->reportQueryError($error, 0, '', __METHOD__); $this->db->rollback(__METHOD__); $status->fatal("config-{$stepName}-tables-failed", $error); } else { $this->db->commit(__METHOD__); } // Resume normal operations if ($status->isOk()) { $this->enableLB(); } return $status; }
/** * Merge page histories * * @param integer $id The page_id * @param Title $newTitle The new title */ private function mergePage($id, Title $newTitle) { $destId = $newTitle->getArticleId(); $this->db->begin(__METHOD__); $this->db->update('revision', array('rev_page' => $destId), array('rev_page' => $id), __METHOD__); $this->db->delete('page', array('page_id' => $id), __METHOD__); // @fixme Need WikiPage::doDeleteUpdates() or similar to avoid orphan // rows in the links tables. $this->db->commit(__METHOD__); return true; }
/** * Remove a batch of users * * @param DatabaseBase $dbw * @param int[] $batch list of user IDs to remove */ private function removeBatch(DatabaseBase $dbw, array $batch) { $rows = 0; $dbw->begin(__METHOD__); // remove entries from user table $dbw->delete(self::USER_TABLE, ['user_id' => $batch], __METHOD__); $rows += $dbw->affectedRows(); // remove entries from user_properties table $dbw->delete('user_properties', ['up_user' => $batch], __METHOD__); $rows += $dbw->affectedRows(); $dbw->commit(__METHOD__); $this->info('Batch removed', ['batch' => count($batch), 'rows' => $rows]); }
/** * Perform a cleanup for a set of wikis * * @param DatabaseBase $db database handler * @param string $table name of table to clean up * @param string $wiki_id_column table column name to use when querying for wiki ID * @param Array $city_ids IDs of wikis to remove from the table */ private function doTableCleanup(DatabaseBase $db, $table, array $city_ids, $wiki_id_column = 'wiki_id') { $start = microtime(true); $db->delete($table, [$wiki_id_column => $city_ids], __METHOD__); $rows = $db->affectedRows(); // just in case MW decides to start a transaction automagically $db->commit(__METHOD__); Wikia\Logger\WikiaLogger::instance()->info(__METHOD__, ['table' => $table, 'cities' => join(', ', $city_ids), 'count' => count($city_ids), 'took' => round(microtime(true) - $start, 4), 'rows' => $rows]); $this->output(sprintf("%s: %s - removed %d rows\n", date('Y-m-d H:i:s'), $table, $rows)); // throttle delete queries if ($rows > 0) { sleep(5); } }
/** * Do all the updates * * @param $what Array: what updates to perform */ public function doUpdates($what = array('core', 'extensions', 'stats')) { global $wgVersion; $this->db->begin(__METHOD__); $what = array_flip($what); if (isset($what['core'])) { $this->runUpdates($this->getCoreUpdateList(), false); } if (isset($what['extensions'])) { $this->runUpdates($this->getOldGlobalUpdates(), false); $this->runUpdates($this->getExtensionUpdates(), true); } $this->setAppliedUpdates($wgVersion, $this->updates); if (isset($what['stats'])) { $this->checkStats(); } $this->db->commit(__METHOD__); }
/** * Do all the updates * * @param $what Array: what updates to perform */ public function doUpdates($what = array('core', 'extensions', 'purge', 'stats')) { global $wgLocalisationCacheConf, $wgVersion; $this->db->begin(__METHOD__); $what = array_flip($what); if (isset($what['core'])) { $this->runUpdates($this->getCoreUpdateList(), false); } if (isset($what['extensions'])) { $this->runUpdates($this->getOldGlobalUpdates(), false); $this->runUpdates($this->getExtensionUpdates(), true); } $this->setAppliedUpdates($wgVersion, $this->updates); if (isset($what['stats'])) { $this->checkStats(); } if (isset($what['purge'])) { $this->purgeCache(); if ($wgLocalisationCacheConf['manualRecache']) { $this->rebuildLocalisationCache(); } } $this->db->commit(__METHOD__); }
public function finishWrite() { if ($this->readOnly) { return; } if ($this->batch) { $this->dbw->insert('l10n_cache', $this->batch, __METHOD__); } $this->dbw->commit(__METHOD__); $this->currentLang = null; $this->dbw = null; $this->batch = array(); $this->writesDone = true; }
public function finishWrite() { if ($this->readOnly) { return; } elseif (is_null($this->currentLang)) { throw new MWException(__CLASS__ . ': must call startWrite() before finishWrite()'); } $this->dbw->begin(__METHOD__); try { $this->dbw->delete('l10n_cache', array('lc_lang' => $this->currentLang), __METHOD__); foreach (array_chunk($this->batch, 500) as $rows) { $this->dbw->insert('l10n_cache', $rows, __METHOD__); } $this->writesDone = true; } catch (DBQueryError $e) { if ($this->dbw->wasReadOnlyError()) { $this->readOnly = true; // just avoid site down time } else { throw $e; } } $this->dbw->commit(__METHOD__); $this->currentLang = null; $this->batch = array(); }
/** * Write (insert) the properties into the DB. * * @since 1.2 * * @param Database $dbw * * @return boolean Success indicator */ protected function writePropsToDB(DatabaseBase $dbw) { $success = true; if (array_key_exists('defaultOwnWorkLicence', $this->config) && array_key_exists('licensesOwnWork', $this->config) && !in_array($this->config['defaultOwnWorkLicence'], $this->config['licensesOwnWork'])) { $this->config['licensesOwnWork'][] = $this->config['defaultOwnWorkLicence']; } $dbw->begin(); // TODO: it'd be better to serialize() arrays foreach ($this->config as $prop => $value) { $success &= $dbw->insert('uw_campaign_conf', array('cc_campaign_id' => $this->id, 'cc_property' => $prop, 'cc_value' => is_array($value) ? implode('|', $value) : $value), __METHOD__); } $dbw->commit(); return $success; }
/** * This function should *not* be called outside of JobQueueDB * * @param DatabaseBase $dbw * @param array $jobs * @param int $flags * @param string $method * @return boolean * @throws type */ public function doBatchPushInternal(DatabaseBase $dbw, array $jobs, $flags, $method) { if (!count($jobs)) { return true; } $rowSet = array(); // (sha1 => job) map for jobs that are de-duplicated $rowList = array(); // list of jobs for jobs that are are not de-duplicated foreach ($jobs as $job) { $row = $this->insertFields($job); if ($job->ignoreDuplicates()) { $rowSet[$row['job_sha1']] = $row; } else { $rowList[] = $row; } } if ($flags & self::QOS_ATOMIC) { $dbw->begin($method); // wrap all the job additions in one transaction } try { // Strip out any duplicate jobs that are already in the queue... if (count($rowSet)) { $res = $dbw->select('job', 'job_sha1', array('job_sha1' => array_keys($rowSet), 'job_token' => ''), $method); foreach ($res as $row) { wfDebug("Job with hash '{$row->job_sha1}' is a duplicate.\n"); unset($rowSet[$row->job_sha1]); // already enqueued } } // Build the full list of job rows to insert $rows = array_merge($rowList, array_values($rowSet)); // Insert the job rows in chunks to avoid slave lag... foreach (array_chunk($rows, 50) as $rowBatch) { $dbw->insert('job', $rowBatch, $method); } JobQueue::incrStats('job-insert', $this->type, count($rows)); JobQueue::incrStats('job-insert-duplicate', $this->type, count($rowSet) + count($rowList) - count($rows)); } catch (DBError $e) { if ($flags & self::QOS_ATOMIC) { $dbw->rollback($method); } throw $e; } if ($flags & self::QOS_ATOMIC) { $dbw->commit($method); } $this->cache->set($this->getCacheKey('empty'), 'false', JobQueueDB::CACHE_TTL_LONG); return true; }
protected function acceptRequest_rollback(DatabaseBase $dbw, $user_id, $acd_id) { $dbw->begin(); # DELETE the user in case something caused a COMMIT already somewhere. if ($user_id) { $dbw->delete('user', array('user_id' => $user_id), __METHOD__); $dbw->delete('user_groups', array('ug_user' => $user_id), __METHOD__); } # DELETE the new account_credentials row likewise. if ($acd_id) { $dbw->delete('account_credentials', array('acd_id' => $acd_id), __METHOD__); } $dbw->commit(); }
/** * @param array $updates Array of arrays each containing two keys, 'primaryKey' and 'changes'. * primaryKey must contain a map of column names to values sufficient to uniquely identify the row * changes must contain a map of column names to update values to apply to the row */ public function write(array $updates) { $this->db->begin(); foreach ($updates as $id => $update) { //echo "Updating: ";var_dump( $update['primaryKey'] ); //echo "With values: ";var_dump( $update['changes'] ); $this->db->update($this->table, $update['changes'], $update['primaryKey'], __METHOD__); } $this->db->commit(); wfWaitForSlaves(false, false, $this->clusterName); }