return;
}
+ $insertOpts = [ 'IGNORE' ];
+ $selectOpts = [];
+
+ // If wl_id exists, make insertSelect() more replication-safe by
+ // ordering on that column. If not, hint that it should be safe anyway.
+ if ( $this->db->fieldExists( 'watchlist', 'wl_id', __METHOD__ ) ) {
+ $selectOpts['ORDER BY'] = 'wl_id';
+ } else {
+ $insertOpts[] = 'NO_AUTO_COLUMNS';
+ }
+
$this->output( "Adding missing watchlist talk page rows... " );
$this->db->insertSelect( 'watchlist', 'watchlist',
[
'wl_namespace' => 'wl_namespace | 1',
'wl_title' => 'wl_title',
'wl_notificationtimestamp' => 'wl_notificationtimestamp'
- ], [ 'NOT (wl_namespace & 1)' ], __METHOD__, 'IGNORE' );
+ ], [ 'NOT (wl_namespace & 1)' ], __METHOD__, $insertOpts, $selectOpts );
$this->output( "done.\n" );
$this->output( "Adding missing watchlist subject page rows... " );
'wl_namespace' => 'wl_namespace & ~1',
'wl_title' => 'wl_title',
'wl_notificationtimestamp' => 'wl_notificationtimestamp'
- ], [ 'wl_namespace & 1' ], __METHOD__, 'IGNORE' );
+ ], [ 'wl_namespace & 1' ], __METHOD__, $insertOpts, $selectOpts );
$this->output( "done.\n" );
}
'tl_title' => 'pl_title'
], [
'pl_namespace' => 10
- ], __METHOD__
+ ], __METHOD__,
+ [ 'NO_AUTO_COLUMNS' ] // There's no "tl_id" auto-increment field
);
}
$this->output( "Done. Please run maintenance/refreshLinks.php for a more " .
$fname = __METHOD__,
$insertOptions = [], $selectOptions = [], $selectJoinConds = []
) {
+ $insertOptions = array_diff( (array)$insertOptions, [ 'NO_AUTO_COLUMNS' ] );
+
// 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 ( !is_array( $insertOptions ) ) {
$insertOptions = [ $insertOptions ];
}
+ $insertOptions = array_diff( (array)$insertOptions, [ 'NO_AUTO_COLUMNS' ] );
$insertOptions = $this->makeInsertOptions( $insertOptions );
$destTable, $srcTable, $varMap, $conds,
$fname = __METHOD__, $insertOptions = [], $selectOptions = [], $selectJoinConds = []
) {
- if ( $this->insertSelectIsSafe === null ) {
+ $isSafe = in_array( 'NO_AUTO_COLUMNS', $insertOptions, true );
+ if ( !$isSafe && $this->insertSelectIsSafe === null ) {
// In MySQL, an INSERT SELECT is only replication safe with row-based
// replication or if innodb_autoinc_lock_mode is 0. When those
// conditions aren't met, use non-native mode.
(int)$row->innodb_autoinc_lock_mode === 0;
}
- if ( !$this->insertSelectIsSafe ) {
+ if ( !$isSafe && !$this->insertSelectIsSafe ) {
return $this->nonNativeInsertSelect(
$destTable,
$srcTable,
* @param string $fname The function name of the caller, from __METHOD__
*
* @param array $insertOptions Options for the INSERT part of the query, see
- * IDatabase::insert() for details.
+ * IDatabase::insert() for details. Also, one additional option is
+ * available: pass 'NO_AUTO_COLUMNS' to hint that the query does not use
+ * an auto-increment or sequence to determine any column values.
* @param array $selectOptions Options for the SELECT part of the query, see
* IDatabase::select() for details.
* @param array $selectJoinConds Join conditions for the SELECT part of the query, see
'srcTable' => [ 'select_table1', 'select_table2' ],
'varMap' => [ 'field_insert' => 'field_select', 'field' => 'field2' ],
'conds' => [ 'field' => 2 ],
+ 'insertOptions' => [ 'NO_AUTO_COLUMNS' ],
'selectOptions' => [ 'ORDER BY' => 'field', 'FORCE INDEX' => [ 'select_table1' => 'index1' ] ],
'selectJoinConds' => [
'select_table2' => [ 'LEFT JOIN', [ 'select_table1.foo = select_table2.bar' ] ],