示例#1
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;
 }
示例#2
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__);
 }
示例#3
0
 /**
  * SQL clause to skip forbidden log types for this user
  *
  * @param IDatabase $db
  * @param string $audience Public/user
  * @param User $user User to check, or null to use $wgUser
  * @return string|bool String on success, false on failure.
  */
 public static function getExcludeClause($db, $audience = 'public', User $user = null)
 {
     global $wgLogRestrictions;
     if ($audience != 'public' && $user === null) {
         global $wgUser;
         $user = $wgUser;
     }
     // Reset the array, clears extra "where" clauses when $par is used
     $hiddenLogs = array();
     // Don't show private logs to unprivileged users
     foreach ($wgLogRestrictions as $logType => $right) {
         if ($audience == 'public' || !$user->isAllowed($right)) {
             $hiddenLogs[] = $logType;
         }
     }
     if (count($hiddenLogs) == 1) {
         return 'log_type != ' . $db->addQuotes($hiddenLogs[0]);
     } elseif ($hiddenLogs) {
         return 'log_type NOT IN (' . $db->makeList($hiddenLogs) . ')';
     }
     return false;
 }
示例#4
0
 /**
  * Build a SQL expression for a closed interval (i.e. BETWEEN).
  *
  * By specifying a null $start or $end, it is also possible to create
  * half-bounded or unbounded intervals using this function.
  *
  * @param IDatabase $db Database connection
  * @param string $var Field name
  * @param mixed $start First value to include or null
  * @param mixed $end Last value to include or null
  */
 private static function intervalCond(IDatabase $db, $var, $start, $end)
 {
     if ($start === null && $end === null) {
         return "{$var} IS NOT NULL";
     } elseif ($end === null) {
         return "{$var} >= {$db->addQuotes($start)}";
     } elseif ($start === null) {
         return "{$var} <= {$db->addQuotes($end)}";
     } else {
         return "{$var} BETWEEN {$db->addQuotes($start)} AND {$db->addQuotes($end)}";
     }
 }
示例#5
0
 /**
  * Generates condition for the query used in a batch count visiting watchers.
  *
  * @param IDatabase $db
  * @param array $targetsWithVisitThresholds array of pairs (LinkTarget, last visit threshold)
  * @return string
  */
 private function getVisitingWatchersCondition(IDatabase $db, array $targetsWithVisitThresholds)
 {
     $missingTargets = [];
     $namespaceConds = [];
     foreach ($targetsWithVisitThresholds as list($target, $threshold)) {
         if ($threshold === null) {
             $missingTargets[] = $target;
             continue;
         }
         /* @var LinkTarget $target */
         $namespaceConds[$target->getNamespace()][] = $db->makeList(['wl_title = ' . $db->addQuotes($target->getDBkey()), $db->makeList(['wl_notificationtimestamp >= ' . $db->addQuotes($db->timestamp($threshold)), 'wl_notificationtimestamp IS NULL'], LIST_OR)], LIST_AND);
     }
     $conds = [];
     foreach ($namespaceConds as $namespace => $pageConds) {
         $conds[] = $db->makeList(['wl_namespace = ' . $namespace, '(' . $db->makeList($pageConds, LIST_OR) . ')'], LIST_AND);
     }
     if ($missingTargets) {
         $lb = new LinkBatch($missingTargets);
         $conds[] = $lb->constructSet('wl', $db);
     }
     return $db->makeList($conds, LIST_OR);
 }
 /**
  * Creates a query condition part for getting only items before or after the given link target
  * (while ordering using $sort mode)
  *
  * @param IDatabase $db
  * @param LinkTarget $target
  * @param string $op comparison operator to use in the conditions
  * @return string
  */
 private function getFromUntilTargetConds(IDatabase $db, LinkTarget $target, $op)
 {
     return $db->makeList(["wl_namespace {$op} " . $target->getNamespace(), $db->makeList(['wl_namespace = ' . $target->getNamespace(), "wl_title {$op}= " . $db->addQuotes($target->getDBkey())], LIST_AND)], LIST_OR);
 }