aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--includes/libs/rdbms/database/DatabaseMySQL.php109
-rw-r--r--tests/phpunit/unit/includes/libs/rdbms/database/DatabaseMySQLTest.php37
2 files changed, 44 insertions, 102 deletions
diff --git a/includes/libs/rdbms/database/DatabaseMySQL.php b/includes/libs/rdbms/database/DatabaseMySQL.php
index a71fbc4f37fa..57bd47b49cca 100644
--- a/includes/libs/rdbms/database/DatabaseMySQL.php
+++ b/includes/libs/rdbms/database/DatabaseMySQL.php
@@ -296,32 +296,28 @@ class DatabaseMySQL extends Database {
}
public function tableExists( $table, $fname = __METHOD__ ) {
- // Split database and table into proper variables as Database::tableName() returns
- // shared tables prefixed with their database, which do not work in SHOW TABLES statements
$components = $this->platform->qualifiedTableComponents( $table );
- $tableName = end( $components );
-
- if ( isset( $this->sessionTempTables[$tableName] ) ) {
- return true; // already known to exist and won't show in SHOW TABLES anyway
- }
- // We can't use buildLike() here, because it specifies an escape character
- // other than the backslash, which is the only one supported by SHOW TABLES
- // TODO: Avoid using platform's internal methods
- $encLike = $this->platform->escapeLikeInternal( $tableName, '\\' );
-
- // If the database has been specified (such as for shared tables), use "FROM"
- if ( count( $components ) > 1 ) {
- $database = reset( $components );
- $encDatabase = $this->platform->addIdentifierQuotes( $database );
- $sql = "SHOW TABLES FROM $encDatabase LIKE '$encLike'";
+ if ( count( $components ) === 1 ) {
+ $db = $this->currentDomain->getDatabase();
+ $tableName = $components[0];
+ } elseif ( count( $components ) === 2 ) {
+ [ $db, $tableName ] = $components;
} else {
- $sql = "SHOW TABLES LIKE '$encLike'";
+ throw new DBLanguageError( 'Too many table components' );
}
- $query = new Query( $sql, self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE, 'SHOW' );
- $res = $this->query( $query, $fname );
-
- return $res->numRows() > 0;
+ if ( isset( $this->sessionTempTables[$tableName] ) ) {
+ return true; // already known to exist and won't be found in the query anyway
+ }
+ return (bool)$this->newSelectQueryBuilder()
+ ->select( '1' )
+ ->from( 'information_schema.tables' )
+ ->where( [
+ 'table_schema' => $db,
+ 'table_name' => $tableName,
+ ] )
+ ->caller( $fname )
+ ->fetchField();
}
/**
@@ -650,21 +646,20 @@ class DatabaseMySQL extends Database {
* @return array
*/
public function listTables( $prefix = null, $fname = __METHOD__ ) {
- $query = new Query( "SHOW TABLES", self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE, 'SHOW' );
- $result = $this->query( $query, $fname );
-
- $endArray = [];
-
- foreach ( $result as $table ) {
- $vars = get_object_vars( $table );
- $table = array_pop( $vars );
-
- if ( !$prefix || strpos( $table, $prefix ) === 0 ) {
- $endArray[] = $table;
- }
- }
-
- return $endArray;
+ $qb = $this->newSelectQueryBuilder()
+ ->select( 'table_name' )
+ ->from( 'information_schema.tables' )
+ ->where( [
+ 'table_schema' => $this->currentDomain->getDatabase(),
+ 'table_type' => 'BASE TABLE'
+ ] )
+ ->caller( $fname );
+ if ( $prefix !== null && $prefix !== '' ) {
+ $qb->andWhere( $this->expr(
+ 'table_name', IExpression::LIKE, new LikeValue( $prefix, $this->anyString() )
+ ) );
+ }
+ return $qb->fetchFieldValues();
}
/**
@@ -677,34 +672,18 @@ class DatabaseMySQL extends Database {
* @since 1.22
*/
public function listViews( $prefix = null, $fname = __METHOD__ ) {
- // The name of the column containing the name of the VIEW
- $propertyName = 'Tables_in_' . $this->getDBname();
- $query = new Query(
- 'SHOW FULL TABLES WHERE TABLE_TYPE = "VIEW"',
- self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE,
- 'SHOW'
- );
- // Query for the VIEWS
- $res = $this->query( $query, $fname );
-
- $allViews = [];
- foreach ( $res as $row ) {
- $allViews[] = $row->$propertyName;
- }
-
- if ( $prefix === null || $prefix === '' ) {
- return $allViews;
- }
-
- $filteredViews = [];
- foreach ( $allViews as $viewName ) {
- // Does the name of this VIEW start with the table-prefix?
- if ( strpos( $viewName, $prefix ) === 0 ) {
- $filteredViews[] = $viewName;
- }
- }
-
- return $filteredViews;
+ $qb = $this->newSelectQueryBuilder()
+ ->select( 'table_name' )
+ ->from( 'information_schema.views' )
+ ->where( [ 'table_schema' => $this->currentDomain->getDatabase() ] )
+ ->caller( $fname );
+
+ if ( $prefix !== null && $prefix !== '' ) {
+ $qb->andWhere( $this->expr(
+ 'table_name', IExpression::LIKE, new LikeValue( $prefix, $this->anyString() )
+ ) );
+ }
+ return $qb->fetchFieldValues();
}
public function selectSQLText(
diff --git a/tests/phpunit/unit/includes/libs/rdbms/database/DatabaseMySQLTest.php b/tests/phpunit/unit/includes/libs/rdbms/database/DatabaseMySQLTest.php
index 8c6882e17fee..e1f29f0e9d47 100644
--- a/tests/phpunit/unit/includes/libs/rdbms/database/DatabaseMySQLTest.php
+++ b/tests/phpunit/unit/includes/libs/rdbms/database/DatabaseMySQLTest.php
@@ -29,9 +29,7 @@ use MediaWiki\Tests\Unit\Libs\Rdbms\AddQuoterMock;
use MediaWikiCoversValidator;
use Wikimedia\Rdbms\DatabaseDomain;
use Wikimedia\Rdbms\DatabaseMySQL;
-use Wikimedia\Rdbms\FakeResultWrapper;
use Wikimedia\Rdbms\IDatabase;
-use Wikimedia\Rdbms\IMaintainableDatabase;
use Wikimedia\Rdbms\MySQLPrimaryPos;
use Wikimedia\Rdbms\Platform\MySQLPlatform;
use Wikimedia\Rdbms\Replication\MysqlReplicationReporter;
@@ -44,41 +42,6 @@ class DatabaseMySQLTest extends \PHPUnit\Framework\TestCase {
use MediaWikiCoversValidator;
- private function getMockForViews(): IMaintainableDatabase {
- $db = $this->getMockBuilder( DatabaseMySQL::class )
- ->disableOriginalConstructor()
- ->onlyMethods( [ 'query', 'getDBname' ] )
- ->getMock();
-
- $db->method( 'query' )
- ->with( $this->anything() )
- ->willReturn( new FakeResultWrapper( [
- (object)[ 'Tables_in_' => 'view1' ],
- (object)[ 'Tables_in_' => 'view2' ],
- (object)[ 'Tables_in_' => 'myview' ]
- ] ) );
- $db->method( 'getDBname' )->willReturn( '' );
-
- return $db;
- }
-
- public function testListviews() {
- $db = $this->getMockForViews();
-
- $this->assertEquals( [ 'view1', 'view2', 'myview' ],
- $db->listViews() );
-
- // Prefix filtering
- $this->assertEquals( [ 'view1', 'view2' ],
- $db->listViews( 'view' ) );
- $this->assertEquals( [ 'myview' ],
- $db->listViews( 'my' ) );
- $this->assertEquals( [],
- $db->listViews( 'UNUSED_PREFIX' ) );
- $this->assertEquals( [ 'view1', 'view2', 'myview' ],
- $db->listViews( '' ) );
- }
-
/**
* @covers \Wikimedia\Rdbms\MySQLPrimaryPos
*/