Anomie has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/358054 )
Change subject: DB: Add join conditions to selectField, selectFieldValues, and insertSelect ...................................................................... DB: Add join conditions to selectField, selectFieldValues, and insertSelect selectField() and selectFieldValues() are trivial, they just need to pass it through to select(). In fact, selectFieldValues() was already doing it, just no one ever updated IDatabase. insertSelect() is a little more work. nativeInsertSelect() was originally written as largely a copy-paste of select() and has since gotten well out of sync. Now that we have selectSQLText(), we should be able to just use that. DatabasePostgres's implementation can wrap the parent implementation instead of being another copy-paste, but DatabaseOracle seems to still need to be special. Change-Id: I0e6a9e6daa510639d3212641606047a5db96c500 --- M includes/db/DatabaseOracle.php M includes/libs/rdbms/database/DBConnRef.php M includes/libs/rdbms/database/Database.php M includes/libs/rdbms/database/DatabaseMssql.php M includes/libs/rdbms/database/DatabasePostgres.php M includes/libs/rdbms/database/IDatabase.php 6 files changed, 48 insertions(+), 80 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core refs/changes/54/358054/1 diff --git a/includes/db/DatabaseOracle.php b/includes/db/DatabaseOracle.php index b728786..556fe75 100644 --- a/includes/db/DatabaseOracle.php +++ b/includes/db/DatabaseOracle.php @@ -558,19 +558,9 @@ } function nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__, - $insertOptions = [], $selectOptions = [] + $insertOptions = [], $selectOptions = [], $selectJoinConds = [] ) { $destTable = $this->tableName( $destTable ); - if ( !is_array( $selectOptions ) ) { - $selectOptions = [ $selectOptions ]; - } - list( $startOpts, $useIndex, $tailOpts, $ignoreIndex ) = - $this->makeSelectOptions( $selectOptions ); - if ( is_array( $srcTable ) ) { - $srcTable = implode( ',', array_map( [ $this, 'tableName' ], $srcTable ) ); - } else { - $srcTable = $this->tableName( $srcTable ); - } $sequenceData = $this->getSequenceData( $destTable ); if ( $sequenceData !== false && @@ -585,13 +575,16 @@ $val = $val . ' field' . ( $i++ ); } - $sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' . - " SELECT $startOpts " . implode( ',', $varMap ) . - " FROM $srcTable $useIndex $ignoreIndex "; - if ( $conds != '*' ) { - $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND ); - } - $sql .= " $tailOpts"; + $selectSql = $this->selectSQLText( + $srcTable, + array_values( $varMap ), + $conds, + $fname, + $selectOptions, + $selectJoinConds + ); + + $sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ') ' . $selectSql; if ( in_array( 'IGNORE', $insertOptions ) ) { $this->ignoreDupValOnIndex = true; diff --git a/includes/libs/rdbms/database/DBConnRef.php b/includes/libs/rdbms/database/DBConnRef.php index b6167aa..c4aeab7 100644 --- a/includes/libs/rdbms/database/DBConnRef.php +++ b/includes/libs/rdbms/database/DBConnRef.php @@ -243,13 +243,13 @@ } public function selectField( - $table, $var, $cond = '', $fname = __METHOD__, $options = [] + $table, $var, $cond = '', $fname = __METHOD__, $options = [], $join_conds = [] ) { return $this->__call( __FUNCTION__, func_get_args() ); } public function selectFieldValues( - $table, $var, $cond = '', $fname = __METHOD__, $options = [] + $table, $var, $cond = '', $fname = __METHOD__, $options = [], $join_conds = [] ) { return $this->__call( __FUNCTION__, func_get_args() ); } @@ -407,7 +407,7 @@ public function insertSelect( $destTable, $srcTable, $varMap, $conds, - $fname = __METHOD__, $insertOptions = [], $selectOptions = [] + $fname = __METHOD__, $insertOptions = [], $selectOptions = [], $selectJoinConds = [] ) { return $this->__call( __FUNCTION__, func_get_args() ); } diff --git a/includes/libs/rdbms/database/Database.php b/includes/libs/rdbms/database/Database.php index ee7644f..2021c86 100644 --- a/includes/libs/rdbms/database/Database.php +++ b/includes/libs/rdbms/database/Database.php @@ -1140,7 +1140,7 @@ } public function selectField( - $table, $var, $cond = '', $fname = __METHOD__, $options = [] + $table, $var, $cond = '', $fname = __METHOD__, $options = [], $join_conds = [] ) { if ( $var === '*' ) { // sanity throw new DBUnexpectedError( $this, "Cannot use a * field: got '$var'" ); @@ -1152,7 +1152,7 @@ $options['LIMIT'] = 1; - $res = $this->select( $table, $var, $cond, $fname, $options ); + $res = $this->select( $table, $var, $cond, $fname, $options, $join_conds ); if ( $res === false || !$this->numRows( $res ) ) { return false; } @@ -2346,7 +2346,7 @@ public function insertSelect( $destTable, $srcTable, $varMap, $conds, - $fname = __METHOD__, $insertOptions = [], $selectOptions = [] + $fname = __METHOD__, $insertOptions = [], $selectOptions = [], $selectJoinConds = [] ) { if ( $this->cliMode ) { // For massive migrations with downtime, we don't want to select everything @@ -2358,7 +2358,8 @@ $conds, $fname, $insertOptions, - $selectOptions + $selectOptions, + $selectJoinConds ); } @@ -2370,7 +2371,9 @@ $fields[] = $this->fieldNameWithAlias( $sourceColumnOrSql, $dstColumn ); } $selectOptions[] = 'FOR UPDATE'; - $res = $this->select( $srcTable, implode( ',', $fields ), $conds, $fname, $selectOptions ); + $res = $this->select( + $srcTable, implode( ',', $fields ), $conds, $fname, $selectOptions, $selectJoinConds + ); if ( !$res ) { return false; } @@ -2391,7 +2394,7 @@ */ protected function nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__, - $insertOptions = [], $selectOptions = [] + $insertOptions = [], $selectOptions = [], $selectJoinConds = [] ) { $destTable = $this->tableName( $destTable ); @@ -2401,32 +2404,18 @@ $insertOptions = $this->makeInsertOptions( $insertOptions ); - if ( !is_array( $selectOptions ) ) { - $selectOptions = [ $selectOptions ]; - } - - list( $startOpts, $useIndex, $tailOpts, $ignoreIndex ) = $this->makeSelectOptions( - $selectOptions ); - - if ( is_array( $srcTable ) ) { - $srcTable = implode( ',', array_map( [ $this, 'tableName' ], $srcTable ) ); - } else { - $srcTable = $this->tableName( $srcTable ); - } + $selectSql = $this->selectSQLText( + $srcTable, + array_values( $varMap ), + $conds, + $fname, + $selectOptions, + $selectJoinConds + ); $sql = "INSERT $insertOptions" . - " INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' . - " SELECT $startOpts " . implode( ',', $varMap ) . - " FROM $srcTable $useIndex $ignoreIndex "; - - if ( $conds != '*' ) { - if ( is_array( $conds ) ) { - $conds = $this->makeList( $conds, self::LIST_AND ); - } - $sql .= " WHERE $conds"; - } - - $sql .= " $tailOpts"; + " INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ') ' . + $selectSql; return $this->query( $sql, $fname ); } diff --git a/includes/libs/rdbms/database/DatabaseMssql.php b/includes/libs/rdbms/database/DatabaseMssql.php index 782727a..8f3cab8 100644 --- a/includes/libs/rdbms/database/DatabaseMssql.php +++ b/includes/libs/rdbms/database/DatabaseMssql.php @@ -717,11 +717,12 @@ * @param string $fname * @param array $insertOptions * @param array $selectOptions + * @param array $selectJoinConds * @return null|ResultWrapper * @throws Exception */ public function nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__, - $insertOptions = [], $selectOptions = [] + $insertOptions = [], $selectOptions = [], $selectJoinConds = [] ) { $this->mScrollableCursor = false; try { @@ -732,7 +733,8 @@ $conds, $fname, $insertOptions, - $selectOptions + $selectOptions, + $selectJoinConds ); } catch ( Exception $e ) { $this->mScrollableCursor = true; diff --git a/includes/libs/rdbms/database/DatabasePostgres.php b/includes/libs/rdbms/database/DatabasePostgres.php index 2fe275b..fe5cfa1 100644 --- a/includes/libs/rdbms/database/DatabasePostgres.php +++ b/includes/libs/rdbms/database/DatabasePostgres.php @@ -681,14 +681,13 @@ * @param string $fname * @param array $insertOptions * @param array $selectOptions + * @param array $selectJoinConds * @return bool */ public function nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__, - $insertOptions = [], $selectOptions = [] + $insertOptions = [], $selectOptions = [], $selectJoinConds = [] ) { - $destTable = $this->tableName( $destTable ); - if ( !is_array( $insertOptions ) ) { $insertOptions = [ $insertOptions ]; } @@ -705,28 +704,9 @@ $savepoint->savepoint(); } - if ( !is_array( $selectOptions ) ) { - $selectOptions = [ $selectOptions ]; - } - list( $startOpts, $useIndex, $tailOpts, $ignoreIndex ) = - $this->makeSelectOptions( $selectOptions ); - if ( is_array( $srcTable ) ) { - $srcTable = implode( ',', array_map( [ $this, 'tableName' ], $srcTable ) ); - } else { - $srcTable = $this->tableName( $srcTable ); - } + $res = parent::nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname, + $insertOptions, $selectOptions, $selectJoinConds ); - $sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' . - " SELECT $startOpts " . implode( ',', $varMap ) . - " FROM $srcTable $useIndex $ignoreIndex "; - - if ( $conds != '*' ) { - $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND ); - } - - $sql .= " $tailOpts"; - - $res = (bool)$this->query( $sql, $fname, $savepoint ); if ( $savepoint ) { $bar = pg_result_error( $this->mLastResult ); if ( $bar != false ) { diff --git a/includes/libs/rdbms/database/IDatabase.php b/includes/libs/rdbms/database/IDatabase.php index bec26a6..d3c365c 100644 --- a/includes/libs/rdbms/database/IDatabase.php +++ b/includes/libs/rdbms/database/IDatabase.php @@ -560,11 +560,12 @@ * @param string|array $cond The condition array. See IDatabase::select() for details. * @param string $fname The function name of the caller. * @param string|array $options The query options. See IDatabase::select() for details. + * @param string|array $join_conds The query join conditions. See IDatabase::select() for details. * * @return bool|mixed The value from the field, or false on failure. */ public function selectField( - $table, $var, $cond = '', $fname = __METHOD__, $options = [] + $table, $var, $cond = '', $fname = __METHOD__, $options = [], $join_conds = [] ); /** @@ -581,12 +582,13 @@ * @param string|array $cond The condition array. See IDatabase::select() for details. * @param string $fname The function name of the caller. * @param string|array $options The query options. See IDatabase::select() for details. + * @param string|array $join_conds The query join conditions. See IDatabase::select() for details. * * @return bool|array The values from the field, or false on failure * @since 1.25 */ public function selectFieldValues( - $table, $var, $cond = '', $fname = __METHOD__, $options = [] + $table, $var, $cond = '', $fname = __METHOD__, $options = [], $join_conds = [] ); /** @@ -1239,12 +1241,14 @@ * IDatabase::insert() for details. * @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 + * IDatabase::select() for details. * * @return IResultWrapper */ public function insertSelect( $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__, - $insertOptions = [], $selectOptions = [] + $insertOptions = [], $selectOptions = [], $selectJoinConds = [] ); /** -- To view, visit https://gerrit.wikimedia.org/r/358054 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I0e6a9e6daa510639d3212641606047a5db96c500 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/core Gerrit-Branch: master Gerrit-Owner: Anomie <bjor...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits