Hashar has uploaded a new change for review. https://gerrit.wikimedia.org/r/94119
Change subject: MySQL method to find out view + fix fatal in tests ...................................................................... MySQL method to find out view + fix fatal in tests We were missing a method to list out views defined in a database. This patch adds in MysqlBase::isView() and MysqlBse::listViews(). Since listViews() cache its result in DatabaseBase::$allViews, we also introduce a final DatabaseBase::clearViewsCache() to let us clear the per process cache. Finally, fixed fatal error when duplicating VIEWs in MySQL. Conflicts: RELEASE-NOTES-1.22 bug: 43571 Change-Id: I8650baa4b721fe69ea3e1d557dd76745c0c7754e (cherry picked from commit e9d53667f43230e84302d0a6653ea7e78a7841ce) --- M CREDITS M RELEASE-NOTES-1.22 M includes/db/Database.php M includes/db/DatabaseMysqlBase.php M tests/phpunit/MediaWikiTestCase.php M tests/phpunit/includes/db/DatabaseMysqlBaseTest.php 6 files changed, 184 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core refs/changes/19/94119/1 diff --git a/CREDITS b/CREDITS index 7927c3d..54aca71 100644 --- a/CREDITS +++ b/CREDITS @@ -22,6 +22,7 @@ * church of emacs * Daniel Friesen * Daniel Kinzler +* Daniel Renfro * Danny B. * David McCabe * Derk-Jan Hartman diff --git a/RELEASE-NOTES-1.22 b/RELEASE-NOTES-1.22 index 8aa2fb4..1eba236 100644 --- a/RELEASE-NOTES-1.22 +++ b/RELEASE-NOTES-1.22 @@ -260,6 +260,11 @@ * A hidden, empty input field was added to the edit form, and any edit that fills it in will be rejected. This prevents against the simplest form of spambots. Previously in the "SimpleAntiSpam" extension by Ryan Schmidt. +* populateRevisionLength.php maintenance script updated to also populate + archive.ar_len field. +* (bug 43571) DatabaseMySQLBase learned to list views, optionally filtered by a + prefix. Also fixed PHPUnit test suite when using a MySQL backend containing + views. === Bug fixes in 1.22 === * Disable Special:PasswordReset when $wgEnableEmail is false. Previously one diff --git a/includes/db/Database.php b/includes/db/Database.php index 42f8482..1064560 100644 --- a/includes/db/Database.php +++ b/includes/db/Database.php @@ -287,6 +287,12 @@ */ protected $fileHandle = null; + /** + * @since 1.22 + * @var Process cache of VIEWs names in the database + */ + protected $allViews = null; + # ------------------------------------------------------------------------------ # Accessors # ------------------------------------------------------------------------------ @@ -3361,6 +3367,40 @@ } /** + * Reset the views process cache set by listViews() + * @since 1.22 + */ + final public function clearViewsCache() { + $this->allViews = null; + } + + /** + * Lists all the VIEWs in the database + * + * For caching purposes the list of all views should be stored in + * $this->allViews. The process cache can be cleared with clearViewsCache() + * + * @param string $prefix Only show VIEWs with this prefix, eg. unit_test_ + * @param string $fname Name of calling function + * @throws MWException + * @since 1.22 + */ + public function listViews( $prefix = null, $fname = __METHOD__ ) { + throw new MWException( 'DatabaseBase::listViews is not implemented in descendant class' ); + } + + /** + * Differentiates between a TABLE and a VIEW + * + * @param $name string: Name of the database-structure to test. + * @throws MWException + * @since 1.22 + */ + public function isView( $name ) { + throw new MWException( 'DatabaseBase::isView is not implemented in descendant class' ); + } + + /** * Convert a timestamp in one of the formats accepted by wfTimestamp() * to the format used for inserting into timestamp fields in this DBMS. * diff --git a/includes/db/DatabaseMysqlBase.php b/includes/db/DatabaseMysqlBase.php index 49579b6..26c9d24 100644 --- a/includes/db/DatabaseMysqlBase.php +++ b/includes/db/DatabaseMysqlBase.php @@ -996,6 +996,55 @@ return $status; } + /** + * Lists VIEWs in the database + * + * @param string $prefix Only show VIEWs with this prefix, eg. + * unit_test_, or $wgDBprefix. Default: null, would return all views. + * @param string $fname Name of calling function + * @return array + * @since 1.22 + */ + public function listViews( $prefix = null, $fname = __METHOD__ ) { + + if ( !isset( $this->allViews ) ) { + + // The name of the column containing the name of the VIEW + $propertyName = 'Tables_in_' . $this->mDBname; + + // Query for the VIEWS + $result = $this->query( 'SHOW FULL TABLES WHERE TABLE_TYPE = "VIEW"' ); + $this->allViews = array(); + while ( ($row = $this->fetchRow($result)) !== false ) { + array_push( $this->allViews, $row[$propertyName] ); + } + } + + if ( is_null($prefix) || $prefix === '' ) { + return $this->allViews; + } + + $filteredViews = array(); + foreach ( $this->allViews as $viewName ) { + // Does the name of this VIEW start with the table-prefix? + if ( strpos( $viewName, $prefix ) === 0 ) { + array_push( $filteredViews, $viewName ); + } + } + return $filteredViews; + } + + /** + * Differentiates between a TABLE and a VIEW. + * + * @param $name string: Name of the TABLE/VIEW to test + * @return bool + * @since 1.22 + */ + public function isView( $name, $prefix = null ) { + return in_array( $name, $this->listViews( $prefix ) ); + } + } diff --git a/tests/phpunit/MediaWikiTestCase.php b/tests/phpunit/MediaWikiTestCase.php index 8c849bc..6ce78b5 100644 --- a/tests/phpunit/MediaWikiTestCase.php +++ b/tests/phpunit/MediaWikiTestCase.php @@ -537,6 +537,12 @@ global $wgDBprefix; $tables = $db->listTables( $wgDBprefix, __METHOD__ ); + + if ( $db->getType() === 'mysql' ) { + # bug 43571: cannot clone VIEWs under MySQL + $views = $db->listViews( $wgDBprefix, __METHOD__ ); + $tables = array_diff( $tables, $views ); + } $tables = array_map( array( __CLASS__, 'unprefixTable' ), $tables ); // Don't duplicate test tables from the previous fataled run diff --git a/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php b/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php index 134f856..ba63c09 100644 --- a/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php +++ b/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php @@ -123,4 +123,87 @@ return json_decode( '"' . $str . '"' ); } + function getMockForViews() { + $db = $this->getMockBuilder( 'DatabaseMysql' ) + ->disableOriginalConstructor() + ->setMethods( array( 'fetchRow', 'query' ) ) + ->getMock(); + + $db->expects( $this->any() ) + ->method( 'query' ) + ->with( $this->anything() ) + ->will( + $this->returnValue( null ) + ); + + $db->expects( $this->any() ) + ->method( 'fetchRow' ) + ->with( $this->anything() ) + ->will( $this->onConsecutiveCalls( + array( 'Tables_in_' => 'view1' ), + array( 'Tables_in_' => 'view2' ), + array( 'Tables_in_' => 'myview' ), + false # no more rows + )); + return $db; + } + /** + * @covers DatabaseMysqlBase::listViews + */ + function testListviews() { + $db = $this->getMockForViews(); + + // The first call populate an internal cache of views + $this->assertEquals( array( 'view1', 'view2', 'myview'), + $db->listViews() ); + $this->assertEquals( array( 'view1', 'view2', 'myview'), + $db->listViews() ); + + // Prefix filtering + $this->assertEquals( array( 'view1', 'view2' ), + $db->listViews( 'view' ) ); + $this->assertEquals( array( 'myview' ), + $db->listViews( 'my' ) ); + $this->assertEquals( array(), + $db->listViews( 'UNUSED_PREFIX' ) ); + $this->assertEquals( array( 'view1', 'view2', 'myview'), + $db->listViews( '' ) ); + } + + /** + * @covers DatabaseMysqlBase::isView + * @dataProvider provideViewExistanceChecks + */ + function testIsView( $isView, $viewName ) { + $db = $this->getMockForViews(); + + switch( $isView ) { + case true: + $this->assertTrue( $db->isView( $viewName ), + "$viewName should be considered a view" ); + break; + + case false: + $this->assertFalse( $db->isView( $viewName ), + "$viewName has not been defined as a view" ); + break; + } + + } + + function provideViewExistanceChecks() { + return array( + // format: whether it is a view, view name + array( true, 'view1' ), + array( true, 'view2' ), + array( true, 'myview' ), + + array( false, 'user' ), + + array( false, 'view10' ), + array( false, 'my' ), + array( false, 'OH_MY_GOD' ), # they killed kenny! + ); + } + } -- To view, visit https://gerrit.wikimedia.org/r/94119 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I8650baa4b721fe69ea3e1d557dd76745c0c7754e Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/core Gerrit-Branch: REL1_22 Gerrit-Owner: Hashar <has...@free.fr> Gerrit-Reviewer: AlephNull <dren...@vistaprint.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits