Jeroen De Dauw has submitted this change and it was merged.

Change subject: Implement MysqlDefinitionreader
......................................................................


Implement MysqlDefinitionreader

Change-Id: I94cee1121e631175ac784a8f8af8b228a4d98b1f
---
M src/MediaWiki/MediaWikiQueryInterface.php
M src/MySQL/MySqlTableDefinitionReader.php
M src/QueryInterface/QueryInterface.php
A tests/phpunit/MySQL/MySQLTableDefinitionReaderTest.php
4 files changed, 240 insertions(+), 6 deletions(-)

Approvals:
  Jeroen De Dauw: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/src/MediaWiki/MediaWikiQueryInterface.php 
b/src/MediaWiki/MediaWikiQueryInterface.php
index e4fc903..bea4790 100644
--- a/src/MediaWiki/MediaWikiQueryInterface.php
+++ b/src/MediaWiki/MediaWikiQueryInterface.php
@@ -142,16 +142,18 @@
         * @param string $tableName
         * @param array $fields
         * @param array $conditions
+        * @param array $options
         *
         * @return ResultIterator
         * @throws SelectFailedException
         */
-       public function select( $tableName, array $fields, array $conditions ) {
+       public function select( $tableName, array $fields, array $conditions, 
array $options = array() ) {
                $selectionResult = $this->getDB()->select(
                        $tableName,
                         $fields,
                        $conditions,
-                       __METHOD__
+                       __METHOD__,
+                       $options
                );
 
                if ( $selectionResult instanceof \ResultWrapper ) {
diff --git a/src/MySQL/MySqlTableDefinitionReader.php 
b/src/MySQL/MySqlTableDefinitionReader.php
index 43d251d..adcca72 100644
--- a/src/MySQL/MySqlTableDefinitionReader.php
+++ b/src/MySQL/MySqlTableDefinitionReader.php
@@ -3,6 +3,9 @@
 namespace Wikibase\Database\MySQL;
 
 use Wikibase\Database\QueryInterface\QueryInterface;
+use Wikibase\Database\QueryInterface\QueryInterfaceException;
+use Wikibase\Database\Schema\Definitions\FieldDefinition;
+use Wikibase\Database\Schema\Definitions\IndexDefinition;
 use Wikibase\Database\Schema\Definitions\TableDefinition;
 use Wikibase\Database\Schema\TableDefinitionReader;
 
@@ -10,11 +13,15 @@
  * @since 0.1
  * @licence GNU GPL v2+
  * @author Jeroen De Dauw < [email protected] >
+ * @author Adam Shorland
  */
 class MySqlTableDefinitionReader implements TableDefinitionReader {
 
        protected $queryInterface;
 
+       /**
+        * @param QueryInterface $queryInterface
+        */
        public function __construct( QueryInterface $queryInterface ) {
                $this->queryInterface = $queryInterface;
        }
@@ -24,10 +31,133 @@
         *
         * @param string $tableName
         *
+        * @throws QueryInterfaceException
         * @return TableDefinition
         */
        public function readDefinition( $tableName ) {
-               // TODO
+               if( !$this->queryInterface->tableExists( $tableName ) ){
+                       throw new QueryInterfaceException( "Unknown table 
{$tableName}" );
+               }
+
+               $fields = $this->getFields( $tableName );
+               $indexes = $this->getIndexes( $tableName );
+               return new TableDefinition( $tableName, $fields, $indexes );
+       }
+
+       /**
+        * @param $tableName string
+        * @return FieldDefinition[]
+        */
+       private function getFields( $tableName ) {
+               $results = $this->queryInterface->select(
+                       'information_schema.COLUMNS',
+                       array(
+                               'name' => 'COLUMN_NAME',
+                               'cannull' => 'IS_NULLABLE',
+                               'type' => 'DATA_TYPE',
+                               'default' => 'COLUMN_DEFAULT' ),
+                       array( 'TABLE_SCHEMA' => $tableName )
+               );
+
+               $fields = array();
+               foreach( $results as $field ){
+
+                       $fields[] = new FieldDefinition(
+                               $field['name'],
+                               $this->getDataType( $field['type'] ),
+                               $this->getNullable( $field['cannull'] ),
+                               $field['default'] );
+               }
+
+               return $fields;
+       }
+
+       /**
+        * @param $tableName string
+        * @throws QueryInterfaceException
+        * @return IndexDefinition[]
+        */
+       private function getIndexes( $tableName ) {
+               //TODO we currently don't notice FULLTEXT or SPATIAL indexes
+               $indexes = array();
+
+               $constraintsResult = $this->queryInterface->select(
+                       'information_schema.table_constraints',
+                       array(
+                               'name' => 'CONSTRAINT_NAME',
+                               'type' => 'CONSTRAINT_TYPE',
+                       ),
+                       array( 'TABLE_NAME' => $tableName )
+               );
+
+               foreach( $constraintsResult as $constraint ) {
+                       if( $constraint['type'] === 'PRIMARY KEY' ) {
+                               $type = IndexDefinition::TYPE_PRIMARY;
+                       } else if( $constraint['type'] === 'UNIQUE' ) {
+                               $type = IndexDefinition::TYPE_UNIQUE;
+                       } else {
+                               throw new QueryInterfaceException(
+                                       'Unknown Constraint when reading 
definition ' .
+                                       $constraint['name'] . ', ' . 
$constraint['type'] );
+                       }
+                       $indexes[] = new IndexDefinition( $constraint['name'] , 
$constraint['columns'] , $type );
+               }
+
+               $indexesResult = $this->queryInterface->select(
+                       'information_schema.statistics',
+                       array(
+                               'name' => 'index_name',
+                               'columns' => 'GROUP_CONCAT(column_name ORDER BY 
seq_in_index)' ),
+                       array( 'TABLE_NAME' => $tableName ),
+                       array( 'GROUP BY' => '1,2' )
+               );
+
+               foreach( $indexesResult as $index ){
+                       //ignore any indexes we already have (primary and 
unique)
+                       foreach( $constraintsResult as $constraint ){
+                               if( $constraint['name'] === $index['name'] ){
+                                       continue 2;
+                               }
+                       }
+                       $cols = array();
+                       foreach( explode( ',', $index['columns'] ) as $col ){
+                               $cols[ $col ] = 0;
+                       }
+                       $indexes[] = new IndexDefinition( $index['name'], $cols 
, IndexDefinition::TYPE_INDEX );
+               }
+
+               return $indexes;
+       }
+
+       /**
+        * Simplifies the datatype and returns something a FieldDefinition can 
expect
+        * @param $dataType string
+        * @return string
+        */
+       private function getDataType( $dataType ) {
+               if( stristr( $dataType, 'blob' ) ){
+                       return FieldDefinition::TYPE_TEXT;
+               } else if ( stristr( $dataType, 'tinyint' ) ){
+                       return FieldDefinition::TYPE_INTEGER;
+               } else if ( stristr( $dataType, 'int' ) ){
+                       return FieldDefinition::TYPE_INTEGER;
+               } else if ( stristr( $dataType, 'float' ) ){
+                       return FieldDefinition::TYPE_FLOAT;
+               } else {
+                       return $dataType;
+               }
+       }
+
+       /**
+        * @param $nullable string
+        * @return bool
+        */
+       private function getNullable( $nullable ) {
+               if( $nullable === 'YES' ){
+                       return true;
+               } else {
+                       return false;
+               }
        }
 
 }
diff --git a/src/QueryInterface/QueryInterface.php 
b/src/QueryInterface/QueryInterface.php
index 9556b41..2621e5f 100644
--- a/src/QueryInterface/QueryInterface.php
+++ b/src/QueryInterface/QueryInterface.php
@@ -67,18 +67,23 @@
 
        /**
         * Selects the specified fields from the rows that match the provided 
conditions.
-        * The conditions are provided as an associative array in
-        * which the keys are the field names.
+        *
+        * The conditions are provided as an associative array in which the 
keys are the field names.
+        *
+        * The optional options are provided as an array.
+        * Options are specified by using the key as the options and the value 
as the value
+        * Boolean options are specified by including them in the array as a 
string value with a numeric key.
         *
         * @since 0.1
         *
         * @param string $tableName
         * @param array $fields
         * @param array $conditions
+        * @param array $options
         *
         * @return ResultIterator
         * @throws SelectFailedException
         */
-       public function select( $tableName, array $fields, array $conditions );
+       public function select( $tableName, array $fields, array $conditions, 
array $options = array() );
 
 }
diff --git a/tests/phpunit/MySQL/MySQLTableDefinitionReaderTest.php 
b/tests/phpunit/MySQL/MySQLTableDefinitionReaderTest.php
new file mode 100644
index 0000000..9c2a991
--- /dev/null
+++ b/tests/phpunit/MySQL/MySQLTableDefinitionReaderTest.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace Wikibase\Database\Tests;
+
+use Wikibase\Database\MySQL\MySqlTableDefinitionReader;
+use Wikibase\Database\QueryInterface\ResultIterator;
+use Wikibase\Database\Schema\Definitions\FieldDefinition;
+use Wikibase\Database\Schema\Definitions\IndexDefinition;
+use Wikibase\Database\Schema\Definitions\TableDefinition;
+
+/**
+ * @since 0.1
+ * @licence GNU GPL v2+
+ * @author Adam Shorland
+ */
+class MySQLTableDefinitionReaderTest extends \PHPUnit_Framework_TestCase {
+
+       public function testCanConstruct() {
+               $this->newInstance();
+               $this->assertTrue( true );
+       }
+
+       protected function newInstance( $results = array() ) {
+               $mockQueryInterface = $this
+                       ->getMockBuilder( 
'Wikibase\Database\MediaWiki\MediaWikiQueryInterface' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+
+               $mockQueryInterface->expects( $this->any() )
+                       ->method( 'tableExists' )
+                       ->will( $this->returnValue( true ) );
+
+               foreach( $results as $key => $result ){
+                       $mockQueryInterface->expects( $this->at( $key + 1 ) )
+                               ->method( 'select' )
+                               ->will( $this->returnValue( new ResultIterator( 
$result ) ) );
+               }
+
+               return new MySqlTableDefinitionReader( $mockQueryInterface );
+       }
+
+       /**
+        * @dataProvider sqlAndDefinitionProvider
+        */
+       public function testReadDefinition( $results, TableDefinition 
$expectedDefinition ) {
+               $reader = $this->newInstance( $results );
+               $definition = $reader->readDefinition( 'dbNametableName' );
+               $this->assertEquals( $definition, $expectedDefinition );
+       }
+
+       public function sqlAndDefinitionProvider() {
+               $argLists = array();
+
+               $argLists[] = array(
+                       array(
+                               array(
+                                       array( 'name' => 'primaryField', 'type' 
=> 'INT', 'cannull' => 'NO', 'default' => null ),
+                                       array( 'name' => 'textField', 'type' => 
'BLOB', 'cannull' => 'YES', 'default' => null ),
+                                       array( 'name' => 'intField', 'type' => 
'INT', 'cannull' => 'NO', 'default' => 42 ),
+                               ),
+                               //TODO test UNIQUE and PRIMARY keys
+                               array( array( ) ),
+                               array( array( 'name' => 'indexName', 'columns' 
=> 'intField,textField' ) )
+                       ),
+                       new TableDefinition(
+                               'dbNametableName',
+                               array(
+                                       new FieldDefinition(
+                                               'primaryField',
+                                               FieldDefinition::TYPE_INTEGER,
+                                               FieldDefinition::NOT_NULL,
+                                               FieldDefinition::NO_DEFAULT
+                                       ),
+                                       new FieldDefinition(
+                                               'textField',
+                                               FieldDefinition::TYPE_TEXT
+                                       ),
+                                       new FieldDefinition(
+                                               'intField',
+                                               FieldDefinition::TYPE_INTEGER,
+                                               FieldDefinition::NOT_NULL, 42
+                                       ),
+                               ),
+                               array(
+                                       new IndexDefinition(
+                                               'indexName',
+                                               array( 'intField' => 0, 
'textField' => 0 ),
+                                               IndexDefinition::TYPE_INDEX
+                                       ),
+                               )
+                       )
+               );
+
+               return $argLists;
+       }
+
+}
\ No newline at end of file

-- 
To view, visit https://gerrit.wikimedia.org/r/84317
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I94cee1121e631175ac784a8f8af8b228a4d98b1f
Gerrit-PatchSet: 5
Gerrit-Project: mediawiki/extensions/WikibaseDatabase
Gerrit-Branch: master
Gerrit-Owner: Addshore <[email protected]>
Gerrit-Reviewer: Jeroen De Dauw <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to