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

Reply via email to