jenkins-bot has submitted this change and it was merged.

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.

bug: 43571
Change-Id: I8650baa4b721fe69ea3e1d557dd76745c0c7754e
---
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, 182 insertions(+), 0 deletions(-)

Approvals:
  Hashar: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/CREDITS b/CREDITS
index 23636ae..01505b0 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 bc4de40..1c364ff 100644
--- a/RELEASE-NOTES-1.22
+++ b/RELEASE-NOTES-1.22
@@ -260,6 +260,9 @@
   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 ===
 * (bug 47271) $wgContentHandlerUseDB should be set to false during the upgrade
diff --git a/includes/db/Database.php b/includes/db/Database.php
index cd907e9..284fd6c 100644
--- a/includes/db/Database.php
+++ b/includes/db/Database.php
@@ -301,6 +301,12 @@
         */
        protected $fileHandle = null;
 
+       /**
+        * @since 1.22
+        * @var Process cache of VIEWs names in the database
+        */
+       protected $allViews = null;
+
 # 
------------------------------------------------------------------------------
 # Accessors
 # 
------------------------------------------------------------------------------
@@ -3445,6 +3451,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/65301
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I8650baa4b721fe69ea3e1d557dd76745c0c7754e
Gerrit-PatchSet: 17
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: AlephNull <dren...@vistaprint.com>
Gerrit-Reviewer: AlephNull <dren...@vistaprint.com>
Gerrit-Reviewer: Brian Wolff <bawolff...@gmail.com>
Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de>
Gerrit-Reviewer: Hashar <has...@free.fr>
Gerrit-Reviewer: Physikerwelt <w...@physikerwelt.de>
Gerrit-Reviewer: Springle <sprin...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to