protected function initConnection($lockDb, IDatabase $db) { # Let this transaction see lock rows from other transactions $db->query("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;"); # Do everything in a transaction as it all gets rolled back eventually $db->startAtomic(__CLASS__); }
/** * @param IDatabase $db * @return mixed */ public function doQuery($db) { $ids = array_map('intval', $this->ids); $live = $db->select(array('revision', 'page', 'user'), array_merge(Revision::selectFields(), Revision::selectUserFields()), array('rev_page' => $this->title->getArticleID(), 'rev_id' => $ids), __METHOD__, array('ORDER BY' => 'rev_id DESC'), array('page' => Revision::pageJoinCond(), 'user' => Revision::userJoinCond())); if ($live->numRows() >= count($ids)) { // All requested revisions are live, keeps things simple! return $live; } // Check if any requested revisions are available fully deleted. $archived = $db->select(array('archive'), Revision::selectArchiveFields(), array('ar_rev_id' => $ids), __METHOD__, array('ORDER BY' => 'ar_rev_id DESC')); if ($archived->numRows() == 0) { return $live; } elseif ($live->numRows() == 0) { return $archived; } else { // Combine the two! Whee $rows = array(); foreach ($live as $row) { $rows[$row->rev_id] = $row; } foreach ($archived as $row) { $rows[$row->ar_rev_id] = $row; } krsort($rows); return new FakeResultWrapper(array_values($rows)); } }
protected function getWeightScale($index, IDatabase $conn = null) { if (!$conn) { return 0.0; } $weight = 1.0; if ($this->warmCacheRatio > 0) { $res = $conn->query('SHOW STATUS', false); $s = $res ? $conn->fetchObject($res) : false; if ($s === false) { $host = $this->parent->getServerName($index); $this->replLogger->error(__METHOD__ . ": could not get status for {$host}"); } else { // http://dev.mysql.com/doc/refman/5.7/en/server-status-variables.html if ($s->Innodb_buffer_pool_pages_total > 0) { $ratio = $s->Innodb_buffer_pool_pages_data / $s->Innodb_buffer_pool_pages_total; } elseif ($s->Qcache_total_blocks > 0) { $ratio = 1.0 - $s->Qcache_free_blocks / $s->Qcache_total_blocks; } else { $ratio = 1.0; } // Stop caring once $ratio >= $this->warmCacheRatio $weight *= min($ratio / $this->warmCacheRatio, 1.0); } } return $weight; }
/** * @param IDatabase $db * @return mixed */ public function doQuery($db) { $ids = array_map('intval', $this->ids); $queryInfo = ['tables' => ['revision', 'user'], 'fields' => array_merge(Revision::selectFields(), Revision::selectUserFields()), 'conds' => ['rev_page' => $this->title->getArticleID(), 'rev_id' => $ids], 'options' => ['ORDER BY' => 'rev_id DESC'], 'join_conds' => ['page' => Revision::pageJoinCond(), 'user' => Revision::userJoinCond()]]; ChangeTags::modifyDisplayQuery($queryInfo['tables'], $queryInfo['fields'], $queryInfo['conds'], $queryInfo['join_conds'], $queryInfo['options'], ''); $live = $db->select($queryInfo['tables'], $queryInfo['fields'], $queryInfo['conds'], __METHOD__, $queryInfo['options'], $queryInfo['join_conds']); if ($live->numRows() >= count($ids)) { // All requested revisions are live, keeps things simple! return $live; } $archiveQueryInfo = ['tables' => ['archive'], 'fields' => Revision::selectArchiveFields(), 'conds' => ['ar_rev_id' => $ids], 'options' => ['ORDER BY' => 'ar_rev_id DESC'], 'join_conds' => []]; ChangeTags::modifyDisplayQuery($archiveQueryInfo['tables'], $archiveQueryInfo['fields'], $archiveQueryInfo['conds'], $archiveQueryInfo['join_conds'], $archiveQueryInfo['options'], ''); // Check if any requested revisions are available fully deleted. $archived = $db->select($archiveQueryInfo['tables'], $archiveQueryInfo['fields'], $archiveQueryInfo['conds'], __METHOD__, $archiveQueryInfo['options'], $archiveQueryInfo['join_conds']); if ($archived->numRows() == 0) { return $live; } elseif ($live->numRows() == 0) { return $archived; } else { // Combine the two! Whee $rows = []; foreach ($live as $row) { $rows[$row->rev_id] = $row; } foreach ($archived as $row) { $rows[$row->ar_rev_id] = $row; } krsort($rows); return new FakeResultWrapper(array_values($rows)); } }
/** * @param IDatabase $db * @return mixed */ public function doQuery($db) { $ids = array_map('intval', $this->ids); $queryInfo = array('tables' => array('revision', 'user'), 'fields' => array_merge(Revision::selectFields(), Revision::selectUserFields()), 'conds' => array('rev_page' => $this->title->getArticleID(), 'rev_id' => $ids), 'options' => array('ORDER BY' => 'rev_id DESC'), 'join_conds' => array('page' => Revision::pageJoinCond(), 'user' => Revision::userJoinCond())); ChangeTags::modifyDisplayQuery($queryInfo['tables'], $queryInfo['fields'], $queryInfo['conds'], $queryInfo['join_conds'], $queryInfo['options'], ''); return $db->select($queryInfo['tables'], $queryInfo['fields'], $queryInfo['conds'], __METHOD__, $queryInfo['options'], $queryInfo['join_conds']); }
/** * @param IDatabase $db * @return mixed */ public function doQuery($db) { $archiveNames = array(); foreach ($this->ids as $timestamp) { $archiveNames[] = $timestamp . '!' . $this->title->getDBkey(); } return $db->select('oldimage', OldLocalFile::selectFields(), array('oi_name' => $this->title->getDBkey(), 'oi_archive_name' => $archiveNames), __METHOD__, array('ORDER BY' => 'oi_timestamp DESC')); }
/** * @param IDatabase $db * @return mixed */ public function doQuery($db) { $timestamps = array(); foreach ($this->ids as $id) { $timestamps[] = $db->timestamp($id); } return $db->select('archive', Revision::selectArchiveFields(), array('ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), 'ar_timestamp' => $timestamps), __METHOD__, array('ORDER BY' => 'ar_timestamp DESC')); }
/** * @param callable $callback * @param string $fname Calling method * @param IDatabase|null $dbw Abort if this DB is rolled back [optional] (since 1.28) */ public function __construct(callable $callback, $fname = 'unknown', IDatabase $dbw = null) { $this->callback = $callback; $this->fname = $fname; if ($dbw && $dbw->trxLevel()) { $dbw->onTransactionResolution([$this, 'cancelOnRollback'], $fname); } }
/** * @param IDatabase $db * @return mixed */ public function doQuery($db) { $ids = array_map('intval', $this->ids); $queryInfo = DatabaseLogEntry::getSelectQueryData(); $queryInfo['conds'] += array('log_id' => $ids); $queryInfo['options'] += array('ORDER BY' => 'log_id DESC'); ChangeTags::modifyDisplayQuery($queryInfo['tables'], $queryInfo['fields'], $queryInfo['conds'], $queryInfo['join_conds'], $queryInfo['options'], ''); return $db->select($queryInfo['tables'], $queryInfo['fields'], $queryInfo['conds'], __METHOD__, $queryInfo['options'], $queryInfo['join_conds']); }
/** * @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); }
/** * @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) { $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory(); $ticket = $lbFactory->getEmptyTransactionTicket(__METHOD__); foreach ($updates as $update) { $this->db->update($this->table, $update['changes'], $update['primaryKey'], __METHOD__); } $lbFactory->commitAndWaitForReplication(__METHOD__, $ticket); }
/** * @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(); wfGetLBFactory()->waitForReplication(); }
/** * @param array $params An associative array with one member: * - connection: An IDatabase connection object */ public function __construct(array $params) { if (!isset($params['connection'])) { throw new InvalidArgumentException("Missing 'connection' argument."); } $this->db = $params['connection']; parent::__construct(['servers' => [['type' => $this->db->getType(), 'host' => $this->db->getServer(), 'dbname' => $this->db->getDBname(), 'load' => 1]], 'trxProfiler' => isset($params['trxProfiler']) ? $params['trxProfiler'] : null, 'srvCache' => isset($params['srvCache']) ? $params['srvCache'] : null, 'wanCache' => isset($params['wanCache']) ? $params['wanCache'] : null]); if (isset($params['readOnlyReason'])) { $this->db->setLBInfo('readOnlyReason', $params['readOnlyReason']); } }
/** * @param IDatabase $db * @param string $error * @param int|string $errno * @param string $sql * @param string $fname */ function __construct(IDatabase $db, $error, $errno, $sql, $fname) { if ($db instanceof Database && $db->wasConnectionError($errno)) { $message = "A connection error occured. \n" . "Query: {$sql}\n" . "Function: {$fname}\n" . "Error: {$errno} {$error}\n"; } else { $message = "A database query error has occurred. Did you forget to run " . "your application's database schema updater after upgrading? \n" . "Query: {$sql}\n" . "Function: {$fname}\n" . "Error: {$errno} {$error}\n"; } parent::__construct($db, $message); $this->error = $error; $this->errno = $errno; $this->sql = $sql; $this->fname = $fname; }
/** * @param IDatabase $db * @return mixed */ public function doQuery($db) { $timestamps = []; foreach ($this->ids as $id) { $timestamps[] = $db->timestamp($id); } $tables = ['archive']; $fields = Revision::selectArchiveFields(); $conds = ['ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), 'ar_timestamp' => $timestamps]; $join_conds = []; $options = ['ORDER BY' => 'ar_timestamp DESC']; ChangeTags::modifyDisplayQuery($tables, $fields, $conds, $join_conds, $options, ''); return $db->select($tables, $fields, $conds, __METHOD__, $options, $join_conds); }
/** * Uses the primary key list and the maximal result row from the * previous iteration to build an SQL condition sufficient for * selecting the next page of results. All except the final key use * `=` conditions while the final key uses a `>` condition * * Example output: * array( '( foo = 42 AND bar > 7 ) OR ( foo > 42 )' ) * * @return array The SQL conditions necessary to select the next set * of rows in the batched query */ protected function buildConditions() { if (!$this->current) { return $this->conditions; } $maxRow = end($this->current); $maximumValues = []; foreach ($this->primaryKey as $column) { $maximumValues[$column] = $this->db->addQuotes($maxRow->{$column}); } $pkConditions = []; // For example: If we have 3 primary keys // first run through will generate // col1 = 4 AND col2 = 7 AND col3 > 1 // second run through will generate // col1 = 4 AND col2 > 7 // and the final run through will generate // col1 > 4 while ($maximumValues) { $pkConditions[] = $this->buildGreaterThanCondition($maximumValues); array_pop($maximumValues); } $conditions = $this->conditions; $conditions[] = sprintf('( %s )', implode(' ) OR ( ', $pkConditions)); return $conditions; }
/** * 执行一条SQL语句 * @param $sql * @return \Swoole\Database\MySQLiRecord */ public function query($sql) { if ($this->debug) { echo "{$sql}<br />\n<hr />"; } $this->read_times += 1; return $this->_db->query($sql); }
/** * Free a result object * * This either saves memory in PHP (buffered queries) or on the server (unbuffered queries). * In general, queries are not large enough in result sets for this to be worth calling. */ public function free() { if ($this->db) { $this->db->freeResult($this); $this->db = null; } $this->result = null; }
/** * @param IDatabase $db * @return string SearchEngine subclass name * @since 1.28 */ public static function getSearchEngineClass(IDatabase $db) { switch ($db->getType()) { case 'sqlite': return 'SearchSqlite'; case 'mysql': return 'SearchMySQL'; case 'postgres': return 'SearchPostgres'; case 'mssql': return 'SearchMssql'; case 'oracle': return 'SearchOracle'; default: return 'SearchEngineDummy'; } }
public function set($key, $value) { if ($this->readOnly) { return; } elseif (is_null($this->currentLang)) { throw new MWException(__CLASS__ . ': must call startWrite() before set()'); } $this->batch[] = ['lc_lang' => $this->currentLang, 'lc_key' => $key, 'lc_value' => $this->dbw->encodeBlob(serialize($value))]; }
/** * Get a master connection to the logging DB * * @return IDatabase * @throws DBError */ protected function getMasterDB() { if (!$this->dbw) { // Get a separate connection in autocommit mode $lb = wfGetLBFactory()->newMainLB(); $this->dbw = $lb->getConnection(DB_MASTER, array(), $this->wiki); $this->dbw->clearFlag(DBO_TRX); } return $this->dbw; }
public function doUpdate() { if (!$this->callback) { return; } $autoTrx = $this->dbw->getFlag(DBO_TRX); $this->dbw->clearFlag(DBO_TRX); try { /** @var Exception $e */ $e = null; call_user_func_array($this->callback, [$this->dbw, $this->fname]); } catch (Exception $e) { } if ($autoTrx) { $this->dbw->setFlag(DBO_TRX); } if ($e) { throw $e; } }
/** * @param IDatabase $db * @param resource $stmt A valid OCI statement identifier * @param bool $unique */ function __construct(&$db, $stmt, $unique = false) { $this->db =& $db; $this->nrows = oci_fetch_all($stmt, $this->rows, 0, -1, OCI_FETCHSTATEMENT_BY_ROW | OCI_NUM); if ($this->nrows === false) { $e = oci_error($stmt); $db->reportQueryError($e['message'], $e['code'], '', __METHOD__); $this->free(); return; } if ($unique) { $this->rows = $this->array_unique_md($this->rows); $this->nrows = count($this->rows); } if ($this->nrows > 0) { foreach ($this->rows[0] as $k => $v) { $this->columns[$k] = strtolower(oci_field_name($stmt, $k + 1)); } } $this->cursor = 0; oci_free_statement($stmt); }
/** * Invalidate the cache of a list of pages from a single namespace. * This is intended for use by subclasses. * * @param IDatabase $dbw * @param int $namespace Namespace number * @param array $dbkeys */ public static function invalidatePages(IDatabase $dbw, $namespace, array $dbkeys) { if ($dbkeys === []) { return; } $dbw->onTransactionIdle(function () use($dbw, $namespace, $dbkeys) { $services = MediaWikiServices::getInstance(); $lbFactory = $services->getDBLoadBalancerFactory(); // Determine which pages need to be updated. // This is necessary to prevent the job queue from smashing the DB with // large numbers of concurrent invalidations of the same page. $now = $dbw->timestamp(); $ids = $dbw->selectFieldValues('page', 'page_id', ['page_namespace' => $namespace, 'page_title' => $dbkeys, 'page_touched < ' . $dbw->addQuotes($now)], __METHOD__); if (!$ids) { return; } $batchSize = $services->getMainConfig()->get('UpdateRowsPerQuery'); $ticket = $lbFactory->getEmptyTransactionTicket(__METHOD__); foreach (array_chunk($ids, $batchSize) as $idBatch) { $dbw->update('page', ['page_touched' => $now], ['page_id' => $idBatch, 'page_touched < ' . $dbw->addQuotes($now)], __METHOD__); $lbFactory->commitAndWaitForReplication(__METHOD__, $ticket); } }, __METHOD__); }
/** * Count the number of items on a user's watchlist * * @param IDatabase $dbr A database connection * @return int */ protected function countItems($dbr) { # Fetch the raw count $rows = $dbr->select('watchlist', array('count' => 'COUNT(*)'), array('wl_user' => $this->getUser()->getId()), __METHOD__); $row = $dbr->fetchObject($rows); $count = $row->count; return floor($count / 2); }
/** * @param IDatabase $dbr * @param string|array $condition * @return bool|ResultWrapper */ protected static function listPages($dbr, $condition) { return $dbr->select(array('archive'), array('ar_namespace', 'ar_title', 'count' => 'COUNT(*)'), $condition, __METHOD__, array('GROUP BY' => array('ar_namespace', 'ar_title'), 'ORDER BY' => array('ar_namespace', 'ar_title'), 'LIMIT' => 100)); }
/** * @param IDatabase $db * @return mixed */ public function doQuery($db) { $conds = ['rev_page' => $this->title->getArticleID()]; if ($this->ids !== null) { $conds['rev_id'] = array_map('intval', $this->ids); } return $db->select(['revision', 'page', 'user'], array_merge(Revision::selectFields(), Revision::selectUserFields()), $conds, __METHOD__, ['ORDER BY' => 'rev_id DESC'], ['page' => Revision::pageJoinCond(), 'user' => Revision::userJoinCond()]); }
/** * If the given revision is newer than the currently set page_latest, * update the page record. Otherwise, do nothing. * * @deprecated since 1.24, use updateRevisionOn instead * * @param IDatabase $dbw * @param Revision $revision * @return bool */ public function updateIfNewerOn($dbw, $revision) { $row = $dbw->selectRow(['revision', 'page'], ['rev_id', 'rev_timestamp', 'page_is_redirect'], ['page_id' => $this->getId(), 'page_latest=rev_id'], __METHOD__); if ($row) { if (wfTimestamp(TS_MW, $row->rev_timestamp) >= $revision->getTimestamp()) { return false; } $prev = $row->rev_id; $lastRevIsRedirect = (bool) $row->page_is_redirect; } else { // No or missing previous revision; mark the page as new $prev = 0; $lastRevIsRedirect = null; } $ret = $this->updateRevisionOn($dbw, $revision, $prev, $lastRevIsRedirect); return $ret; }
/** * 获取表的字段描述 * @return array */ function desc() { return $this->db->query('describe ' . $this->table)->fetchall(); }
/** * This function should *not* be called outside of JobQueueDB * * @param IDatabase $dbw * @param IJobSpecification[] $jobs * @param int $flags * @param string $method * @throws DBError * @return void */ public function doBatchPushInternal(IDatabase $dbw, array $jobs, $flags, $method) { if (!count($jobs)) { return; } $rowSet = array(); // (sha1 => job) map for jobs that are de-duplicated $rowList = array(); // list of jobs for jobs that 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->startAtomic($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('inserts', $this->type, count($rows)); JobQueue::incrStats('dupe_inserts', $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->endAtomic($method); } return; }