);
}
+ return $this->nonNativeInsertSelect(
+ $destTable,
+ $srcTable,
+ $varMap,
+ $conds,
+ $fname,
+ $insertOptions,
+ $selectOptions,
+ $selectJoinConds
+ );
+ }
+
+ /**
+ * Implementation of insertSelect() based on select() and insert()
+ *
+ * @see IDatabase::insertSelect()
+ * @since 1.30
+ * @param string $destTable
+ * @param string|array $srcTable
+ * @param array $varMap
+ * @param array $conds
+ * @param string $fname
+ * @param array $insertOptions
+ * @param array $selectOptions
+ * @param array $selectJoinConds
+ * @return bool
+ */
+ protected function nonNativeInsertSelect( $destTable, $srcTable, $varMap, $conds,
+ $fname = __METHOD__,
+ $insertOptions = [], $selectOptions = [], $selectJoinConds = []
+ ) {
// For web requests, do a locking SELECT and then INSERT. This puts the SELECT burden
// on only the master (without needing row-based-replication). It also makes it easy to
// know how big the INSERT is going to be.
}
// If IGNORE is set, we use savepoints to emulate mysql's behavior
+ // @todo If PostgreSQL 9.5+, we could use ON CONFLICT DO NOTHING instead
$savepoint = $olde = null;
$numrowsinserted = 0;
if ( in_array( 'IGNORE', $options ) ) {
}
/*
- * If IGNORE is set, we use savepoints to emulate mysql's behavior
- * Ignore LOW PRIORITY option, since it is MySQL-specific
+ * If IGNORE is set, use the non-native version.
+ * @todo If PostgreSQL 9.5+, we could use ON CONFLICT DO NOTHING
*/
- $savepoint = $olde = null;
- $numrowsinserted = 0;
if ( in_array( 'IGNORE', $insertOptions ) ) {
- $savepoint = new SavepointPostgres( $this, 'mw', $this->queryLogger );
- $olde = error_reporting( 0 );
- $savepoint->savepoint();
+ return $this->nonNativeInsertSelect(
+ $destTable, $srcTable, $varMap, $conds, $fname, $insertOptions, $selectOptions, $selectJoinConds
+ );
}
- $res = parent::nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname,
+ return parent::nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname,
$insertOptions, $selectOptions, $selectJoinConds );
-
- if ( $savepoint ) {
- $bar = pg_result_error( $this->mLastResult );
- if ( $bar != false ) {
- $savepoint->rollback();
- } else {
- $savepoint->release();
- $numrowsinserted++;
- }
- error_reporting( $olde );
- $savepoint->commit();
-
- // Set the affected row count for the whole operation
- $this->mAffectedRows = $numrowsinserted;
-
- // IGNORE always returns true
- return true;
- }
-
- return $res;
}
public function tableName( $name, $format = 'quoted' ) {
case 'title':
case 'title-link':
$title = Title::newFromText( $value );
- if ( $title ) {
- $value = [];
- ApiQueryBase::addTitleInfo( $value, $title, "{$name}_" );
+ if ( !$title ) {
+ // Huh? Do something halfway sane.
+ $title = SpecialPage::getTitleFor( 'Badtitle', $value );
}
+ $value = [];
+ ApiQueryBase::addTitleInfo( $value, $title, "{$name}_" );
return $value;
case 'user':
$hideLiu = $registration->getFilter( 'hideliu' );
$hideLiu->setDefault( $user->getBoolOption( 'watchlisthideliu' ) );
+ // Selecting both hideanons and hideliu on watchlist preferances
+ // gives mutually exclusive filters, so those are ignored
+ if ( $user->getBoolOption( 'watchlisthideanons' ) &&
+ !$user->getBoolOption( 'watchlisthideliu' )
+ ) {
+ $this->getFilterGroup( 'userExpLevel' )
+ ->setDefault( 'registered' );
+ }
+
+ if ( $user->getBoolOption( 'watchlisthideliu' ) &&
+ !$user->getBoolOption( 'watchlisthideanons' )
+ ) {
+ $this->getFilterGroup( 'userExpLevel' )
+ ->setDefault( 'unregistered' );
+ }
+
$reviewStatus = $this->getFilterGroup( 'reviewStatus' );
if ( $reviewStatus !== null ) {
// Conditional on feature being available and rights
$this->output( sprintf( "%.2fs\n", $seconds ) );
}
# Reopen any connections that have closed
- if ( !wfGetLB()->pingAll() ) {
- $this->output( "\n" );
- do {
- $this->error( "Connection failed, reconnecting in 10 seconds..." );
- sleep( 10 );
- } while ( !wfGetLB()->pingAll() );
- $this->output( "Reconnected\n\n" );
- }
- # Wait for the replica DB to catch up
- wfWaitForSlaves();
+ $this->reopenAndWaitFotReplicas();
} else {
$this->output( "cheap, skipped\n" );
}
}
}
+ /**
+ * Re-open any closed db connection, and wait for replicas
+ *
+ * Queries that take a really long time, might cause the
+ * mysql connection to "go away"
+ */
+ private function reopenAndWaiFotReplicas() {
+ if ( !wfGetLB()->pingAll() ) {
+ $this->output( "\n" );
+ do {
+ $this->error( "Connection failed, reconnecting in 10 seconds..." );
+ sleep( 10 );
+ } while ( !wfGetLB()->pingAll() );
+ $this->output( "Reconnected\n\n" );
+ }
+ # Wait for the replica DB to catch up
+ wfWaitForSlaves();
+ }
+
public function doSpecialPageCacheUpdates( $dbw ) {
global $wgSpecialPageCacheUpdates;
}
$this->output( sprintf( "%.2fs\n", $seconds ) );
# Wait for the replica DB to catch up
- wfWaitForSlaves();
+ $this->reopenAndWaitForReplicas();
}
}
}
'key_ns' => NS_PROJECT,
'key_title' => Title::newFromText( 'project:foo' )->getFullText(),
] ],
+ [ '4:title-link:key', '<invalid>', [
+ 'key_ns' => NS_SPECIAL,
+ 'key_title' => SpecialPage::getTitleFor( 'Badtitle', '<invalid>' )->getFullText(),
+ ] ],
[ '4:user:key', 'foo', [ 'key' => 'Foo' ] ],
[ '4:user-link:key', 'foo', [ 'key' => 'Foo' ] ],
];
// Second two overriden
'hideanons' => false,
'hideliu' => true,
+ 'userExpLevel' => 'registered'
] + $wikiDefaults,
[
'watchlisthideminor' => 1,
'hidebots' => true,
'hideanons' => false,
'hideliu' => true,
+ 'userExpLevel' => 'unregistered'
] + $allFalse,
[
'watchlisthideminor' => 0,
'watchlisthidebots' => 1,
- 'watchlisthideanons' => 1,
- 'watchlisthideliu' => 0,
+
+ 'watchlisthideanons' => 0,
+ 'watchlisthideliu' => 1,
],
[
'hidebots' => 1,
// Unregister the hooks for proper unit testing
$this->mergeMwGlobalArrayValue( 'wgHooks', [
- 'mailPasswordInternal' => [],
+ 'User::mailPasswordInternal' => [],
'SpecialPasswordResetOnSubmit' => [],
] );