Example #1
0
 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));
     }
 }
Example #3
0
 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']);
 }
Example #6
0
 /**
  * @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'));
 }
Example #8
0
 /**
  * @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);
     }
 }
Example #9
0
 /**
  * @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']);
 }
Example #10
0
 /**
  * @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);
 }
Example #11
0
 /**
  * @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);
 }
Example #12
0
 /**
  * @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();
 }
Example #13
0
 /**
  * @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']);
     }
 }
Example #14
0
 /**
  * @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);
 }
Example #16
0
 /**
  * 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;
 }
Example #17
0
 /**
  * 执行一条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);
 }
Example #18
0
 /**
  * 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;
 }
Example #19
0
 /**
  * @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';
     }
 }
Example #20
0
 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))];
 }
Example #21
0
 /**
  * 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;
 }
Example #22
0
 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;
     }
 }
Example #23
0
 /**
  * @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);
 }
Example #24
0
 /**
  * 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__);
 }
Example #25
0
 /**
  * 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));
 }
Example #27
0
 /**
  * @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()]);
 }
Example #28
0
 /**
  * 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;
 }
Example #29
0
 /**
  * 获取表的字段描述
  * @return array
  */
 function desc()
 {
     return $this->db->query('describe ' . $this->table)->fetchall();
 }
Example #30
0
 /**
  * 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;
 }