} else {
$useIndex = '';
}
+ if ( isset( $options['IGNORE INDEX'] ) && is_string( $options['IGNORE INDEX'] ) ) {
+ $ignoreIndex = $this->ignoreIndexClause( $options['IGNORE INDEX'] );
+ } else {
+ $ignoreIndex = '';
+ }
- return [ $startOpts, $useIndex, $preLimitTail, $postLimitTail ];
+ return [ $startOpts, $useIndex, $preLimitTail, $postLimitTail, $ignoreIndex ];
}
/**
$useIndexes = ( isset( $options['USE INDEX'] ) && is_array( $options['USE INDEX'] ) )
? $options['USE INDEX']
: [];
+ $ignoreIndexes = ( isset( $options['IGNORE INDEX'] ) && is_array( $options['IGNORE INDEX'] ) )
+ ? $options['IGNORE INDEX']
+ : [];
if ( is_array( $table ) ) {
$from = ' FROM ' .
- $this->tableNamesWithUseIndexOrJOIN( $table, $useIndexes, $join_conds );
+ $this->tableNamesWithIndexClauseOrJOIN( $table, $useIndexes, $ignoreIndexes, $join_conds );
} elseif ( $table != '' ) {
if ( $table[0] == ' ' ) {
$from = ' FROM ' . $table;
} else {
$from = ' FROM ' .
- $this->tableNamesWithUseIndexOrJOIN( [ $table ], $useIndexes, [] );
+ $this->tableNamesWithIndexClauseOrJOIN( [ $table ], $useIndexes, $ignoreIndexes, [] );
}
} else {
$from = '';
}
- list( $startOpts, $useIndex, $preLimitTail, $postLimitTail ) =
+ list( $startOpts, $useIndex, $preLimitTail, $postLimitTail, $ignoreIndex ) =
$this->makeSelectOptions( $options );
if ( !empty( $conds ) ) {
if ( is_array( $conds ) ) {
$conds = $this->makeList( $conds, LIST_AND );
}
- $sql = "SELECT $startOpts $vars $from $useIndex WHERE $conds $preLimitTail";
+ $sql = "SELECT $startOpts $vars $from $useIndex $ignoreIndex WHERE $conds $preLimitTail";
} else {
- $sql = "SELECT $startOpts $vars $from $useIndex $preLimitTail";
+ $sql = "SELECT $startOpts $vars $from $useIndex $ignoreIndex $preLimitTail";
}
if ( isset( $options['LIMIT'] ) ) {
/**
* Get the aliased table name clause for a FROM clause
- * which might have a JOIN and/or USE INDEX clause
+ * which might have a JOIN and/or USE INDEX or IGNORE INDEX clause
*
* @param array $tables ( [alias] => table )
* @param array $use_index Same as for select()
+ * @param array $ignore_index Same as for select()
* @param array $join_conds Same as for select()
* @return string
*/
- protected function tableNamesWithUseIndexOrJOIN(
- $tables, $use_index = [], $join_conds = []
+ protected function tableNamesWithIndexClauseOrJOIN(
+ $tables, $use_index = [], $ignore_index = [], $join_conds = []
) {
$ret = [];
$retJOIN = [];
$use_index = (array)$use_index;
+ $ignore_index = (array)$ignore_index;
$join_conds = (array)$join_conds;
foreach ( $tables as $alias => $table ) {
$tableClause .= ' ' . $use;
}
}
+ if ( isset( $ignore_index[$alias] ) ) { // has IGNORE INDEX?
+ $ignore = $this->ignoreIndexClause( implode( ',', (array)$ignore_index[$alias] ) );
+ if ( $ignore != '' ) {
+ $tableClause .= ' ' . $ignore;
+ }
+ }
$on = $this->makeList( (array)$conds, LIST_AND );
if ( $on != '' ) {
$tableClause .= ' ON (' . $on . ')';
implode( ',', (array)$use_index[$alias] )
);
+ $ret[] = $tableClause;
+ } elseif ( isset( $ignore_index[$alias] ) ) {
+ // Is there an INDEX clause for this table?
+ $tableClause = $this->tableNameWithAlias( $table, $alias );
+ $tableClause .= ' ' . $this->ignoreIndexClause(
+ implode( ',', (array)$ignore_index[$alias] )
+ );
+
$ret[] = $tableClause;
} else {
$tableClause = $this->tableNameWithAlias( $table, $alias );
return '';
}
+ /**
+ * IGNORE INDEX clause. Unlikely to be useful for anything but MySQL. This
+ * is only needed because a) MySQL must be as efficient as possible due to
+ * its use on Wikipedia, and b) MySQL 4.0 is kind of dumb sometimes about
+ * which index to pick. Anyway, other databases might have different
+ * indexes on a given table. So don't bother overriding this unless you're
+ * MySQL.
+ * @param string $index
+ * @return string
+ */
+ public function ignoreIndexClause( $index ) {
+ return '';
+ }
+
public function replace( $table, $uniqueIndexes, $rows, $fname = __METHOD__ ) {
$quotedTable = $this->tableName( $table );
$selectOptions = [ $selectOptions ];
}
- list( $startOpts, $useIndex, $tailOpts ) = $this->makeSelectOptions( $selectOptions );
+ list( $startOpts, $useIndex, $tailOpts, $ignoreIndex ) = $this->makeSelectOptions(
+ $selectOptions );
if ( is_array( $srcTable ) ) {
$srcTable = implode( ',', array_map( [ &$this, 'tableName' ], $srcTable ) );
$sql = "INSERT $insertOptions INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' .
" SELECT $startOpts " . implode( ',', $varMap ) .
- " FROM $srcTable $useIndex ";
+ " FROM $srcTable $useIndex $ignoreIndex ";
if ( $conds != '*' ) {
if ( is_array( $conds ) ) {
if ( !is_array( $selectOptions ) ) {
$selectOptions = [ $selectOptions ];
}
- list( $startOpts, $useIndex, $tailOpts ) = $this->makeSelectOptions( $selectOptions );
+ list( $startOpts, $useIndex, $tailOpts, $ignoreIndex ) =
+ $this->makeSelectOptions( $selectOptions );
if ( is_array( $srcTable ) ) {
$srcTable = implode( ',', array_map( [ &$this, 'tableName' ], $srcTable ) );
} else {
$sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' .
" SELECT $startOpts " . implode( ',', $varMap ) .
- " FROM $srcTable $useIndex ";
+ " FROM $srcTable $useIndex $ignoreIndex ";
if ( $conds != '*' ) {
$sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
}
$useIndex = '';
}
- return [ $startOpts, $useIndex, $preLimitTail, $postLimitTail ];
+ if ( isset( $options['IGNORE INDEX'] ) && !is_array( $options['IGNORE INDEX'] ) ) {
+ $ignoreIndex = $this->ignoreIndexClause( $options['IGNORE INDEX'] );
+ } else {
+ $ignoreIndex = '';
+ }
+
+ return [ $startOpts, $useIndex, $preLimitTail, $postLimitTail, $ignoreIndex ];
}
public function delete( $table, $conds, $fname = __METHOD__ ) {
if ( !is_array( $selectOptions ) ) {
$selectOptions = [ $selectOptions ];
}
- list( $startOpts, $useIndex, $tailOpts ) = $this->makeSelectOptions( $selectOptions );
+ list( $startOpts, $useIndex, $tailOpts, $ignoreIndex ) =
+ $this->makeSelectOptions( $selectOptions );
if ( is_array( $srcTable ) ) {
$srcTable = implode( ',', array_map( [ &$this, 'tableName' ], $srcTable ) );
} else {
$sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' .
" SELECT $startOpts " . implode( ',', $varMap ) .
- " FROM $srcTable $useIndex";
+ " FROM $srcTable $useIndex $ignoreIndex ";
if ( $conds != '*' ) {
$sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
*/
function makeSelectOptions( $options ) {
$preLimitTail = $postLimitTail = '';
- $startOpts = $useIndex = '';
+ $startOpts = $useIndex = $ignoreIndex = '';
$noKeyOptions = [];
foreach ( $options as $key => $option ) {
$startOpts .= 'DISTINCT';
}
- return [ $startOpts, $useIndex, $preLimitTail, $postLimitTail ];
+ return [ $startOpts, $useIndex, $preLimitTail, $postLimitTail, $ignoreIndex ];
}
function getDBname() {