diff options
-rw-r--r-- | includes/libs/rdbms/database/DatabaseMySQL.php | 109 | ||||
-rw-r--r-- | tests/phpunit/unit/includes/libs/rdbms/database/DatabaseMySQLTest.php | 37 |
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 */ |