}
// We can't separate explicit JOIN clauses with ',', use ' ' for those
- $implicitJoins = !empty( $ret ) ? implode( ',', $ret ) : "";
- $explicitJoins = !empty( $retJOIN ) ? implode( ' ', $retJOIN ) : "";
+ $implicitJoins = $ret ? implode( ',', $ret ) : "";
+ $explicitJoins = $retJOIN ? implode( ' ', $retJOIN ) : "";
// Compile our final table clause
return implode( ' ', [ $implicitJoins, $explicitJoins ] );
$rows = [ $rows ];
}
- $useTrx = !$this->trxLevel;
- if ( $useTrx ) {
- $this->begin( $fname, self::TRANSACTION_INTERNAL );
- }
try {
+ $this->startAtomic( $fname );
$affectedRowCount = 0;
foreach ( $rows as $row ) {
// Delete rows which collide with this one
$this->insert( $table, $row, $fname );
$affectedRowCount += $this->affectedRows();
}
+ $this->endAtomic( $fname );
+ $this->affectedRowCount = $affectedRowCount;
} catch ( Exception $e ) {
- if ( $useTrx ) {
- $this->rollback( $fname, self::FLUSHING_INTERNAL );
- }
+ $this->rollback( $fname, self::FLUSHING_INTERNAL );
throw $e;
}
- if ( $useTrx ) {
- $this->commit( $fname, self::FLUSHING_INTERNAL );
- }
-
- $this->affectedRowCount = $affectedRowCount;
}
/**
}
$affectedRowCount = 0;
- $useTrx = !$this->trxLevel;
- if ( $useTrx ) {
- $this->begin( $fname, self::TRANSACTION_INTERNAL );
- }
try {
+ $this->startAtomic( $fname );
# Update any existing conflicting row(s)
if ( $where !== false ) {
$ok = $this->update( $table, $set, $where, $fname );
# Now insert any non-conflicting row(s)
$ok = $this->insert( $table, $rows, $fname, [ 'IGNORE' ] ) && $ok;
$affectedRowCount += $this->affectedRows();
+ $this->endAtomic( $fname );
+ $this->affectedRowCount = $affectedRowCount;
} catch ( Exception $e ) {
- if ( $useTrx ) {
- $this->rollback( $fname, self::FLUSHING_INTERNAL );
- }
+ $this->rollback( $fname, self::FLUSHING_INTERNAL );
throw $e;
}
- if ( $useTrx ) {
- $this->commit( $fname, self::FLUSHING_INTERNAL );
- }
- $this->affectedRowCount = $affectedRowCount;
return $ok;
}
return $this->query( $sql, $fname );
}
- public function insertSelect(
+ final public function insertSelect(
$destTable, $srcTable, $varMap, $conds,
$fname = __METHOD__, $insertOptions = [], $selectOptions = [], $selectJoinConds = []
) {
- if ( $this->cliMode ) {
+ static $hints = [ 'NO_AUTO_COLUMNS' ];
+
+ $insertOptions = (array)$insertOptions;
+ $selectOptions = (array)$selectOptions;
+
+ if ( $this->cliMode && $this->isInsertSelectSafe( $insertOptions, $selectOptions ) ) {
// For massive migrations with downtime, we don't want to select everything
// into memory and OOM, so do all this native on the server side if possible.
return $this->nativeInsertSelect(
$varMap,
$conds,
$fname,
- $insertOptions,
+ array_diff( $insertOptions, $hints ),
$selectOptions,
$selectJoinConds
);
$varMap,
$conds,
$fname,
- $insertOptions,
+ array_diff( $insertOptions, $hints ),
$selectOptions,
$selectJoinConds
);
}
+ /**
+ * @param array $insertOptions INSERT options
+ * @param array $selectOptions SELECT options
+ * @return bool Whether an INSERT SELECT with these options will be replication safe
+ * @since 1.31
+ */
+ protected function isInsertSelectSafe( array $insertOptions, array $selectOptions ) {
+ return true;
+ }
+
/**
* Implementation of insertSelect() based on select() and insert()
*
$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.
$this->affectedRowCount = $affectedRowCount;
} else {
$this->rollback( $fname, self::FLUSHING_INTERNAL );
- $this->affectedRowCount = 0;
}
return $ok;
} catch ( Exception $e ) {
$this->rollback( $fname, self::FLUSHING_INTERNAL );
- $this->affectedRowCount = 0;
throw $e;
}
}
if ( !is_array( $insertOptions ) ) {
$insertOptions = [ $insertOptions ];
}
- $insertOptions = array_diff( (array)$insertOptions, [ 'NO_AUTO_COLUMNS' ] );
$insertOptions = $this->makeInsertOptions( $insertOptions );
} catch ( Exception $e ) {
// already logged; let LoadBalancer move on during mass-rollback
}
+
+ $this->affectedRowCount = 0; // for the sake of consistency
}
/**