diff options
author | jenkins-bot <jenkins-bot@gerrit.wikimedia.org> | 2023-09-11 20:03:13 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@wikimedia.org> | 2023-09-11 20:03:13 +0000 |
commit | 2f2802eb75266605df7b2e664be3c4efea9363f9 (patch) | |
tree | 205dc3da48e709b7adb77c157205e0e9ab9b366f | |
parent | 82478bd60d7ebf962a133ab92857afa54b3e12f4 (diff) | |
parent | bd40cfa516ddc73e4e0beed43ed7ed702fdcfd34 (diff) | |
download | mediawikicore-2f2802eb75266605df7b2e664be3c4efea9363f9.tar.gz mediawikicore-2f2802eb75266605df7b2e664be3c4efea9363f9.zip |
Merge "rdbms: Small clean ups to query builders"
13 files changed, 121 insertions, 24 deletions
diff --git a/RELEASE-NOTES-1.41 b/RELEASE-NOTES-1.41 index ce41e547b5ff..c3618083bb25 100644 --- a/RELEASE-NOTES-1.41 +++ b/RELEASE-NOTES-1.41 @@ -701,6 +701,21 @@ because of Phabricator reports. - SiteConfiguration -> MediaWiki\Config\SiteConfiguration * RevisionStore::getQueryInfo() and RevisionFactory::getQueryInfo() have been deprecated. Use ::newSelectQueryBuilder() instead. +* Following methods in rdbms library have been made internal: + - IDatabase::getLBInfo() + - IDatabase::setLBInfo() + - IDatabase::insert() Use InsertQueryBuilder instead. + - IDatabase::update() Use UpdateQueryBuilder instead. + - IDatabase::replace() Use ReplaceQueryBuilder instead. + - IDatabase::upsert() Use InsertQueryBuilder instead. + - IDatabase::delete() Use DeleteQueryBuilder instead. + - IReadableDatabase::selectField() Use SelectQueryBuilder instead. + - IReadableDatabase::selectFieldValues() Use SelectQueryBuilder instead. + - IReadableDatabase::select() Use SelectQueryBuilder instead. + - IReadableDatabase::selectRow() Use SelectQueryBuilder instead. + - IReadableDatabase::estimateRowCount() Use SelectQueryBuilder instead. + - IReadableDatabase::selectRowCount() Use SelectQueryBuilder instead. + - ISQLPlatform::unionQueries() Use UnionQueryBuilder instead. * The following methods, previously deprecated, now emit deprecation warnings: - ConfigFactory::getDefaultInstance(), deprecated since 1.27 - AbstractContent::getNativeData(), deprecated since 1.33 diff --git a/includes/libs/rdbms/database/IDatabase.php b/includes/libs/rdbms/database/IDatabase.php index 5fe793b95de8..6f6b156e985c 100644 --- a/includes/libs/rdbms/database/IDatabase.php +++ b/includes/libs/rdbms/database/IDatabase.php @@ -145,6 +145,8 @@ interface IDatabase extends IReadableDatabase { /** * Get properties passed down from the server info array of the load balancer * + * @internal should not be called outside of rdbms library. + * * @param string|null $name The entry of the info array to get, or null to get the whole array * @return array|mixed|null */ @@ -155,6 +157,8 @@ interface IDatabase extends IReadableDatabase { * * Keys matching the IDatabase::LB_* constants are also used internally by subclasses * + * @internal should not be called outside of rdbms library. + * * @param array|string $nameOrArray The new array or the name of a key to set * @param array|mixed|null $value If $nameOrArray is a string, the new key value (null to unset) */ @@ -349,6 +353,8 @@ interface IDatabase extends IReadableDatabase { * This operation will be seen by affectedRows()/insertId() as one query statement, * regardless of how many statements are actually sent by the class implementation. * + * @internal callers outside of rdbms library should use InsertQueryBuilder instead. + * * @param string $table Table name * @param array|array[] $rows Row(s) to insert, as either: * - A string-keyed map of (column name => value) defining a new row. Values are @@ -373,6 +379,8 @@ interface IDatabase extends IReadableDatabase { * This operation will be seen by affectedRows()/insertId() as one query statement, * regardless of how many statements are actually sent by the class implementation. * + * @internal callers outside of rdbms library should use UpdateQueryBuilder instead. + * * @param string $table Table name * @param array $set Combination map/list where each string-keyed entry maps a column * to a literal assigned value and each integer-keyed value is a SQL expression in the @@ -432,6 +440,8 @@ interface IDatabase extends IReadableDatabase { * This operation will be seen by affectedRows()/insertId() as one query statement, * regardless of how many statements are actually sent by the class implementation. * + * @internal callers outside of rdbms library should use ReplaceQueryBuilder instead. + * * @param string $table The table name * @param string|string[]|string[][] $uniqueKeys Column name or non-empty list of column * name lists that define all applicable unique keys on the table. There must only be @@ -460,7 +470,7 @@ interface IDatabase extends IReadableDatabase { * This operation will be seen by affectedRows()/insertId() as one query statement, * regardless of how many statements are actually sent by the class implementation. * - * @see IDatabase::buildExcludedValue() + * @internal callers outside of rdbms library should use InsertQueryBuilder instead. * * @param string $table Table name * @param array|array[] $rows Row(s) to insert, in the form of either: @@ -529,6 +539,8 @@ interface IDatabase extends IReadableDatabase { * This operation will be seen by affectedRows()/insertId() as one query statement, * regardless of how many statements are actually sent by the class implementation. * + * @internal callers outside of rdbms library should use DeleteQueryBuilder instead. + * * @param string $table Table name * @param string|array $conds Array of conditions. See $conds in IDatabase::select() * In order to prevent possible performance or replication issues or damaging a data diff --git a/includes/libs/rdbms/database/IReadableDatabase.php b/includes/libs/rdbms/database/IReadableDatabase.php index 26fca45e51d1..0be8be5294d2 100644 --- a/includes/libs/rdbms/database/IReadableDatabase.php +++ b/includes/libs/rdbms/database/IReadableDatabase.php @@ -161,6 +161,8 @@ interface IReadableDatabase extends ISQLPlatform, DbQuoter, IDatabaseFlags { * New callers should use {@link newSelectQueryBuilder} with {@link SelectQueryBuilder::fetchField} * instead, which is more readable and less error-prone. * + * @internal callers outside of rdbms library should use SelectQueryBuilder instead. + * * @param string|array $table Table name. {@see select} for details. * @param string|array $var The field name to select. This must be a valid SQL fragment: do not * use unvalidated user input. Can be an array, but must contain exactly 1 element then. @@ -184,6 +186,8 @@ interface IReadableDatabase extends ISQLPlatform, DbQuoter, IDatabaseFlags { * New callers should use {@link newSelectQueryBuilder} with {@link SelectQueryBuilder::fetchFieldValues} * instead, which is more readable and less error-prone. * + * @internal callers outside of rdbms library should use SelectQueryBuilder instead. + * * @param string|array $table Table name. {@see select} for details. * @param string $var The field name to select. This must be a valid SQL * fragment: do not use unvalidated user input. @@ -380,6 +384,7 @@ interface IReadableDatabase extends ISQLPlatform, DbQuoter, IDatabaseFlags { * * [ 'page' => [ 'LEFT JOIN', 'page_latest=rev_id' ] ] * + * @internal * @return IResultWrapper Resulting rows * @throws DBError If an error occurs, {@see query} */ @@ -402,6 +407,7 @@ interface IReadableDatabase extends ISQLPlatform, DbQuoter, IDatabaseFlags { * New callers should use {@link newSelectQueryBuilder} with {@link SelectQueryBuilder::fetchRow} * instead, which is more readable and less error-prone. * + * @internal * @param string|array $table Table name * @param string|array $vars Field names * @param string|array $conds Conditions @@ -436,6 +442,7 @@ interface IReadableDatabase extends ISQLPlatform, DbQuoter, IDatabaseFlags { * New callers should use {@link newSelectQueryBuilder} with {@link SelectQueryBuilder::estimateRowCount} * instead, which is more readable and less error-prone. * + * @internal * @param string|string[] $tables Table name(s) * @param string $var Column for which NULL values are not counted [default "*"] * @param array|string $conds Filters on the table @@ -461,6 +468,7 @@ interface IReadableDatabase extends ISQLPlatform, DbQuoter, IDatabaseFlags { * * @since 1.27 Added $join_conds parameter * + * @internal * @param string|string[] $tables Table name(s) * @param string $var Column for which NULL values are not counted [default "*"] * @param array|string $conds Filters on the table diff --git a/includes/libs/rdbms/platform/ISQLPlatform.php b/includes/libs/rdbms/platform/ISQLPlatform.php index 3637c570c3c1..4f9c2ecbca32 100644 --- a/includes/libs/rdbms/platform/ISQLPlatform.php +++ b/includes/libs/rdbms/platform/ISQLPlatform.php @@ -323,6 +323,9 @@ interface ISQLPlatform { * * This is used for providing overload point for other DB abstractions * not compatible with the MySQL syntax. + * + * @internal callers outside of rdbms library should use UnionQueryBuilder instead. + * * @param array $sqls SQL statements to combine * @param bool $all Either {@link IDatabase::UNION_ALL} or {@link IDatabase::UNION_DISTINCT} * @param array $options Query options diff --git a/includes/libs/rdbms/querybuilder/DeleteQueryBuilder.php b/includes/libs/rdbms/querybuilder/DeleteQueryBuilder.php index 81cf79438a98..b88f1b5d8246 100644 --- a/includes/libs/rdbms/querybuilder/DeleteQueryBuilder.php +++ b/includes/libs/rdbms/querybuilder/DeleteQueryBuilder.php @@ -72,6 +72,7 @@ class DeleteQueryBuilder { * @param array $info Associative array of query info, with keys: * - table: The table name to be passed to IDatabase::delete() * - conds: The conditions + * - caller: The caller signature * * @return $this */ @@ -82,6 +83,9 @@ class DeleteQueryBuilder { if ( isset( $info['conds'] ) ) { $this->where( $info['conds'] ); } + if ( isset( $info['caller'] ) ) { + $this->caller( $info['caller'] ); + } return $this; } @@ -225,11 +229,16 @@ class DeleteQueryBuilder { * @return array The query info array, with keys: * - table: The table name * - conds: The conditions + * - caller: The caller signature */ public function getQueryInfo(): array { - return [ + $info = [ 'table' => $this->table, 'conds' => $this->conds, ]; + if ( $this->caller !== __CLASS__ ) { + $info['caller'] = $this->caller; + } + return $info; } } diff --git a/includes/libs/rdbms/querybuilder/InsertQueryBuilder.php b/includes/libs/rdbms/querybuilder/InsertQueryBuilder.php index 57f580cd0430..130e069a36d1 100644 --- a/includes/libs/rdbms/querybuilder/InsertQueryBuilder.php +++ b/includes/libs/rdbms/querybuilder/InsertQueryBuilder.php @@ -95,6 +95,10 @@ class InsertQueryBuilder { * - table: The table name to be passed to Database::insert() * - rows: The rows to be inserted * - options: The query options + * - upsert: Whether it's insert or upsert + * - uniqueIndexFields: Fields of the unique index + * - set: The set array + * - caller: The caller signature * * @return $this */ @@ -117,6 +121,9 @@ class InsertQueryBuilder { if ( isset( $info['set'] ) ) { $this->set( (array)$info['set'] ); } + if ( isset( $info['caller'] ) ) { + $this->caller( $info['caller'] ); + } return $this; } @@ -205,7 +212,8 @@ class InsertQueryBuilder { * @return $this */ public function row( array $row ) { - return $this->rows( [ $row ] ); + $this->rows[] = $row; + return $this; } /** @@ -337,9 +345,13 @@ class InsertQueryBuilder { * - table: The table name * - rows: The rows array * - options: The query options + * - upsert: Whether it's insert or upsert + * - uniqueIndexFields: Fields of the unique index + * - set: The set array + * - caller: The caller signature */ public function getQueryInfo() { - return [ + $info = [ 'table' => $this->table, 'rows' => $this->rows, 'upsert' => $this->upsert, @@ -347,5 +359,9 @@ class InsertQueryBuilder { 'uniqueIndexFields' => $this->uniqueIndexFields, 'options' => $this->options, ]; + if ( $this->caller !== __CLASS__ ) { + $info['caller'] = $this->caller; + } + return $info; } } diff --git a/includes/libs/rdbms/querybuilder/ReplaceQueryBuilder.php b/includes/libs/rdbms/querybuilder/ReplaceQueryBuilder.php index cd3c0be97db6..5aafb254a9b4 100644 --- a/includes/libs/rdbms/querybuilder/ReplaceQueryBuilder.php +++ b/includes/libs/rdbms/querybuilder/ReplaceQueryBuilder.php @@ -43,7 +43,7 @@ class ReplaceQueryBuilder { protected $db; /** - * Only for use in subclasses. To create a InsertQueryBuilder instance, + * Only for use in subclasses. To create a ReplaceQueryBuilder instance, * use `$db->newReplaceQueryBuilder()` instead. * * @param IDatabase $db @@ -77,9 +77,10 @@ class ReplaceQueryBuilder { * The parameters must be formatted as required by Database::replace. * * @param array $info Associative array of query info, with keys: - * - table: The table name to be passed to Database::insert() + * - table: The table name to be passed to Database::replace() * - rows: The rows to be inserted * - options: The query options + * - caller: The caller signature * * @return $this */ @@ -100,7 +101,7 @@ class ReplaceQueryBuilder { } /** - * Manually set the table name to be passed to IDatabase::insert() + * Manually set the table name to be passed to IDatabase::replace() * * @param string $table The table name * @return $this @@ -175,7 +176,7 @@ class ReplaceQueryBuilder { } /** - * Run the constructed INSERT query and return the result. + * Run the constructed REPLACE query and return the result. */ public function execute() { if ( !$this->rows ) { @@ -195,19 +196,23 @@ class ReplaceQueryBuilder { /** * Get an associative array describing the query in terms of its raw parameters to - * Database::insert(). This can be used to interface with legacy code. + * Database::replace(). This can be used to interface with legacy code. * * @return array The query info array, with keys: * - table: The table name * - rows: The rows array * - options: The query options + * - caller: The caller signature */ public function getQueryInfo() { - return [ + $info = [ 'table' => $this->table, 'rows' => $this->rows, 'uniqueIndexFields' => $this->uniqueIndexFields, - 'caller' => $this->caller, ]; + if ( $this->caller !== __CLASS__ ) { + $info['caller'] = $this->caller; + } + return $info; } } diff --git a/includes/libs/rdbms/querybuilder/SelectQueryBuilder.php b/includes/libs/rdbms/querybuilder/SelectQueryBuilder.php index e2afb816870a..d2704d7cd98b 100644 --- a/includes/libs/rdbms/querybuilder/SelectQueryBuilder.php +++ b/includes/libs/rdbms/querybuilder/SelectQueryBuilder.php @@ -14,7 +14,7 @@ namespace Wikimedia\Rdbms; * Note that the methods in this class are not stable to override. * This class may be extended to create query builders for specific database * tables, such {@link \MediaWiki\Page\PageSelectQueryBuilder}, whilst still - * provoding the same fluent interface for adding arbitrary additional + * providing the same fluent interface for adding arbitrary additional * conditions and such. * * @since 1.35 @@ -104,6 +104,7 @@ class SelectQueryBuilder extends JoinGroupBase { * - join_conds: The join conditions * - joins: Alias for join_conds. If both joins and join_conds are * specified, the values will be merged. + * - caller: The caller signature * * @return $this */ @@ -126,6 +127,9 @@ class SelectQueryBuilder extends JoinGroupBase { if ( isset( $info['joins'] ) ) { $this->joinConds( (array)$info['joins'] ); } + if ( isset( $info['caller'] ) ) { + $this->caller( $info['caller'] ); + } return $this; } @@ -830,6 +834,7 @@ class SelectQueryBuilder extends JoinGroupBase { * - join_conds: The join conditions. This can also be given a different * name by passing a $joinsName parameter, since some legacy code uses * the name "joins". + * - caller: The caller signature */ public function getQueryInfo( $joinsName = 'join_conds' ) { $info = [ @@ -838,6 +843,9 @@ class SelectQueryBuilder extends JoinGroupBase { 'conds' => $this->conds, 'options' => $this->options, ]; + if ( $this->caller !== __CLASS__ ) { + $info['caller'] = $this->caller; + } $info[ $joinsName ] = $this->joinConds; return $info; } diff --git a/includes/libs/rdbms/querybuilder/UpdateQueryBuilder.php b/includes/libs/rdbms/querybuilder/UpdateQueryBuilder.php index 526c36255bf3..5d625995958e 100644 --- a/includes/libs/rdbms/querybuilder/UpdateQueryBuilder.php +++ b/includes/libs/rdbms/querybuilder/UpdateQueryBuilder.php @@ -48,7 +48,7 @@ class UpdateQueryBuilder { protected $db; /** - * Only for use in subclasses. To create a SelectQueryBuilder instance, + * Only for use in subclasses. To create a UpdateQueryBuilder instance, * use `$db->newUpdateQueryBuilder()` instead. * * @param IDatabase $db @@ -86,6 +86,7 @@ class UpdateQueryBuilder { * - set: The set conditions * - conds: The conditions * - options: The query options + * - caller: The caller signature. * * @return $this */ @@ -102,6 +103,9 @@ class UpdateQueryBuilder { if ( isset( $info['options'] ) ) { $this->options( (array)$info['options'] ); } + if ( isset( $info['caller'] ) ) { + $this->caller( $info['caller'] ); + } return $this; } @@ -232,8 +236,8 @@ class UpdateQueryBuilder { } /** - * Add conditions to the query. The supplied conditions will be appended - * to the existing conditions, separated by AND. + * Add SET part to the query. It takes an array containing arrays of column names map to + * the set values. * * @param string|array $set * @@ -329,13 +333,18 @@ class UpdateQueryBuilder { * - set: The set array * - conds: The conditions * - options: The query options + * - caller: The caller signature */ public function getQueryInfo() { - return [ + $info = [ 'table' => $this->table, 'set' => $this->set, 'conds' => $this->conds, 'options' => $this->options, ]; + if ( $this->caller !== __CLASS__ ) { + $info['caller'] = $this->caller; + } + return $info; } } diff --git a/tests/phpunit/unit/includes/libs/rdbms/querybuilder/DeleteQueryBuilderTest.php b/tests/phpunit/unit/includes/libs/rdbms/querybuilder/DeleteQueryBuilderTest.php index 191d6191bf7a..5e3b76f36214 100644 --- a/tests/phpunit/unit/includes/libs/rdbms/querybuilder/DeleteQueryBuilderTest.php +++ b/tests/phpunit/unit/includes/libs/rdbms/querybuilder/DeleteQueryBuilderTest.php @@ -61,11 +61,13 @@ class DeleteQueryBuilderTest extends PHPUnit\Framework\TestCase { public function testGetQueryInfo() { $this->dqb ->deleteFrom( 't' ) - ->where( [ 'a' => 'b' ] ); + ->where( [ 'a' => 'b' ] ) + ->caller( 'foo' ); $this->assertEquals( [ 'table' => 't' , 'conds' => [ 'a' => 'b' ], + 'caller' => 'foo', ], $this->dqb->getQueryInfo() ); } diff --git a/tests/phpunit/unit/includes/libs/rdbms/querybuilder/InsertQueryBuilderTest.php b/tests/phpunit/unit/includes/libs/rdbms/querybuilder/InsertQueryBuilderTest.php index bb224916f578..6fb47c2fa0e8 100644 --- a/tests/phpunit/unit/includes/libs/rdbms/querybuilder/InsertQueryBuilderTest.php +++ b/tests/phpunit/unit/includes/libs/rdbms/querybuilder/InsertQueryBuilderTest.php @@ -92,7 +92,8 @@ class InsertQueryBuilderTest extends PHPUnit\Framework\TestCase { $this->iqb ->insertInto( 't' ) ->ignore() - ->row( [ 'a' => 'b', 'd' => 'l' ] ); + ->row( [ 'a' => 'b', 'd' => 'l' ] ) + ->caller( 'foo' ); $this->assertEquals( [ 'table' => 't' , @@ -101,6 +102,7 @@ class InsertQueryBuilderTest extends PHPUnit\Framework\TestCase { 'upsert' => false, 'set' => [], 'uniqueIndexFields' => [], + 'caller' => 'foo', ], $this->iqb->getQueryInfo() ); } @@ -111,7 +113,8 @@ class InsertQueryBuilderTest extends PHPUnit\Framework\TestCase { ->row( [ 'f' => 'g', 'd' => 'l' ] ) ->onDuplicateKeyUpdate() ->uniqueIndexFields( [ 'd' ] ) - ->set( [ 'f' => 'm' ] ); + ->set( [ 'f' => 'm' ] ) + ->caller( 'foo' ); $this->assertEquals( [ 'table' => 't' , @@ -120,6 +123,7 @@ class InsertQueryBuilderTest extends PHPUnit\Framework\TestCase { 'set' => [ 'f' => 'm' ], 'uniqueIndexFields' => [ 'd' ], 'options' => [], + 'caller' => 'foo' ], $this->iqb->getQueryInfo() ); } diff --git a/tests/phpunit/unit/includes/libs/rdbms/querybuilder/SelectQueryBuilderTest.php b/tests/phpunit/unit/includes/libs/rdbms/querybuilder/SelectQueryBuilderTest.php index 5b094f41f5e9..bc72ff8b7927 100644 --- a/tests/phpunit/unit/includes/libs/rdbms/querybuilder/SelectQueryBuilderTest.php +++ b/tests/phpunit/unit/includes/libs/rdbms/querybuilder/SelectQueryBuilderTest.php @@ -556,14 +556,16 @@ class SelectQueryBuilderTest extends MediaWikiUnitTestCase { ->from( 't' ) ->conds( [ 'a' => 'b' ] ) ->join( 'u', 'u', 'tt=uu' ) - ->limit( 1 ); + ->limit( 1 ) + ->caller( 'foo' ); $this->assertEquals( [ 'tables' => [ 't', 'u' => 'u' ], 'fields' => [ 'f' ], 'conds' => [ 'a' => 'b' ], 'options' => [ 'LIMIT' => 1 ], - 'join_conds' => [ 'u' => [ 'JOIN', 'tt=uu' ] ] + 'join_conds' => [ 'u' => [ 'JOIN', 'tt=uu' ] ], + 'caller' => 'foo', ], $this->sqb->getQueryInfo() ); } @@ -587,14 +589,16 @@ class SelectQueryBuilderTest extends MediaWikiUnitTestCase { ->from( 't' ) ->conds( [ 'a' => 'b' ] ) ->join( 'u', 'u', 'tt=uu' ) - ->limit( 1 ); + ->limit( 1 ) + ->caller( 'foo' ); $this->assertEquals( [ 'tables' => [ 't', 'u' => 'u' ], 'fields' => [ 'f' ], 'conds' => [ 'a' => 'b' ], 'options' => [ 'LIMIT' => 1 ], - 'joins' => [ 'u' => [ 'JOIN', 'tt=uu' ] ] + 'joins' => [ 'u' => [ 'JOIN', 'tt=uu' ] ], + 'caller' => 'foo', ], $this->sqb->getQueryInfo( 'joins' ) ); } diff --git a/tests/phpunit/unit/includes/libs/rdbms/querybuilder/UpdateQueryBuilderTest.php b/tests/phpunit/unit/includes/libs/rdbms/querybuilder/UpdateQueryBuilderTest.php index aa601a588586..b10976a04497 100644 --- a/tests/phpunit/unit/includes/libs/rdbms/querybuilder/UpdateQueryBuilderTest.php +++ b/tests/phpunit/unit/includes/libs/rdbms/querybuilder/UpdateQueryBuilderTest.php @@ -116,13 +116,15 @@ class UpdateQueryBuilderTest extends PHPUnit\Framework\TestCase { ->ignore() ->set( [ 'f' => 'g' ] ) ->andSet( [ 'd' => 'l' ] ) - ->where( [ 'a' => 'b' ] ); + ->where( [ 'a' => 'b' ] ) + ->caller( 'foo' ); $this->assertEquals( [ 'table' => 't' , 'set' => [ 'f' => 'g', 'd' => 'l' ], 'conds' => [ 'a' => 'b' ], 'options' => [ 'IGNORE' ], + 'caller' => 'foo', ], $this->uqb->getQueryInfo() ); } |