Commit 51f555bb authored by Benjamin Eberlei's avatar Benjamin Eberlei

Merge pull request #469 from deeky666/DBAL-553

[DBAL-553] Add support for native JSON type on capable platforms
parents cb7da62a 96f011e9
......@@ -52,6 +52,7 @@ PostgreSQL
^^^^^^^^^^
- ``PostgreSqlPlatform`` for all versions.
- ``PostgreSQL92Platform`` for version 9.2 and above.
SAP Sybase SQL Anywhere
^^^^^^^^^^^^^^^^^^^^^^^
......
......@@ -268,6 +268,21 @@ abstract class AbstractPlatform
return $this->getVarcharTypeDeclarationSQL($field);
}
/**
* Returns the SQL snippet to declare a JSON field.
*
* By default this maps directly to a CLOB and only maps to more
* special datatypes when the underlying databases support this datatype.
*
* @param array $field
*
* @return string
*/
public function getJsonTypeDeclarationSQL(array $field)
{
return $this->getClobTypeDeclarationSQL($field);
}
/**
* @param integer $length
* @param boolean $fixed
......@@ -2874,6 +2889,16 @@ abstract class AbstractPlatform
return false;
}
/**
* Does this platform have native JSON type.
*
* @return boolean
*/
public function hasNativeJsonType()
{
return false;
}
/**
* @deprecated
* @todo Remove in 3.0
......
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms\Keywords;
/**
* PostgreSQL 9.2 reserved keywords list.
*
* @author Steve Müller <st.mueller@dzh-online.de>
* @link www.doctrine-project.org
* @since 2.5
*/
class PostgreSQL92Keywords extends PostgreSQLKeywords
{
/**
* {@inheritdoc}
*/
public function getName()
{
return 'PostgreSQL92';
}
/**
* {@inheritdoc}
*
* @link http://www.postgresql.org/docs/9.2/static/sql-keywords-appendix.html
*/
protected function getKeywords()
{
return array(
'ALL',
'ANALYSE',
'ANALYZE',
'AND',
'ANY',
'ARRAY',
'AS',
'ASC',
'ASYMMETRIC',
'AUTHORIZATION',
'BINARY',
'BOTH',
'CASE',
'CAST',
'CHECK',
'COLLATE',
'COLLATION',
'COLUMN',
'CONCURRENTLY',
'CONSTRAINT',
'CREATE',
'CROSS',
'CURRENT_CATALOG',
'CURRENT_DATE',
'CURRENT_ROLE',
'CURRENT_SCHEMA',
'CURRENT_TIME',
'CURRENT_TIMESTAMP',
'CURRENT_USER',
'DEFAULT',
'DEFERRABLE',
'DESC',
'DISTINCT',
'DO',
'ELSE',
'END',
'EXCEPT',
'FALSE',
'FETCH',
'FOR',
'FOREIGN',
'FREEZE',
'FROM',
'FULL',
'GRANT',
'GROUP',
'HAVING',
'ILIKE',
'IN',
'INITIALLY',
'INNER',
'INTERSECT',
'INTO',
'IS',
'ISNULL',
'JOIN',
'LEADING',
'LEFT',
'LIKE',
'LIMIT',
'LOCALTIME',
'LOCALTIMESTAMP',
'NATURAL',
'NOT',
'NOTNULL',
'NULL',
'OFFSET',
'ON',
'ONLY',
'OR',
'ORDER',
'OUTER',
'OVER',
'OVERLAPS',
'PLACING',
'PRIMARY',
'REFERENCES',
'RETURNING',
'RIGHT',
'SELECT',
'SESSION_USER',
'SIMILAR',
'SOME',
'SYMMETRIC',
'TABLE',
'THEN',
'TO',
'TRAILING',
'TRUE',
'UNION',
'UNIQUE',
'USER',
'USING',
'VARIADIC',
'VERBOSE',
'WHEN',
'WHERE',
'WINDOW',
'WITH',
);
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
/**
* Provides the behavior, features and SQL dialect of the PostgreSQL 9.2 database platform.
*
* @author Steve Müller <st.mueller@dzh-online.de>
* @link www.doctrine-project.org
* @since 2.5
*/
class PostgreSQL92Platform extends PostgreSqlPlatform
{
/**
* {@inheritdoc}
*/
public function getJsonTypeDeclarationSQL(array $field)
{
return 'JSON';
}
/**
* {@inheritdoc}
*/
public function hasNativeJsonType()
{
return true;
}
/**
* {@inheritdoc}
*/
protected function getReservedKeywordsClass()
{
return 'Doctrine\DBAL\Platforms\Keywords\PostgreSQL92Keywords';
}
/**
* {@inheritdoc}
*/
protected function initializeDoctrineTypeMappings()
{
parent::initializeDoctrineTypeMappings();
$this->doctrineTypeMapping['json'] = 'json_array';
}
}
......@@ -39,6 +39,7 @@ class ReservedWordsCommand extends Command
'sqlserver2012' => 'Doctrine\DBAL\Platforms\Keywords\SQLServer2012Keywords',
'sqlite' => 'Doctrine\DBAL\Platforms\Keywords\SQLiteKeywords',
'pgsql' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQLKeywords',
'pgsql92' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQL92Keywords',
'oracle' => 'Doctrine\DBAL\Platforms\Keywords\OracleKeywords',
'db2' => 'Doctrine\DBAL\Platforms\Keywords\DB2Keywords',
'sqlanywhere' => 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhereKeywords',
......@@ -91,6 +92,7 @@ The following keyword lists are currently shipped with Doctrine:
* mysql
* pgsql
* pgsql92
* sqlite
* oracle
* sqlserver
......@@ -119,6 +121,7 @@ EOT
$keywordLists = array(
'mysql',
'pgsql',
'pgsql92',
'sqlite',
'oracle',
'sqlserver',
......
......@@ -34,7 +34,7 @@ class JsonArrayType extends Type
*/
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getClobTypeDeclarationSQL($fieldDeclaration);
return $platform->getJsonTypeDeclarationSQL($fieldDeclaration);
}
/**
......@@ -76,6 +76,6 @@ class JsonArrayType extends Type
*/
public function requiresSQLCommentHint(AbstractPlatform $platform)
{
return true;
return ! $platform->hasNativeJsonType();
}
}
......@@ -29,6 +29,7 @@ class TypeConversionTest extends \Doctrine\Tests\DbalFunctionalTestCase
$table->addColumn('test_time', 'time', array('notnull' => false));
$table->addColumn('test_text', 'text', array('notnull' => false));
$table->addColumn('test_array', 'array', array('notnull' => false));
$table->addColumn('test_json_array', 'json_array', array('notnull' => false));
$table->addColumn('test_object', 'object', array('notnull' => false));
$table->addColumn('test_float', 'float', array('notnull' => false));
$table->addColumn('test_decimal', 'decimal', array('notnull' => false, 'scale' => 2, 'precision' => 10));
......@@ -61,6 +62,7 @@ class TypeConversionTest extends \Doctrine\Tests\DbalFunctionalTestCase
array('time', new \DateTime('10:10:10'), 'DateTime'),
array('text', str_repeat('foo ', 1000), 'string'),
array('array', array('foo' => 'bar'), 'array'),
array('json_array', array('foo' => 'bar'), 'array'),
array('object', $obj, 'object'),
array('float', 1.5, 'float'),
array('decimal', 1.55, 'string'),
......
......@@ -31,6 +31,14 @@ class MockPlatform extends \Doctrine\DBAL\Platforms\AbstractPlatform
return 'DUMMYCLOB';
}
/**
* {@inheritdoc}
*/
public function getJsonTypeDeclarationSQL(array $field)
{
return 'DUMMYJSON';
}
/**
* {@inheritdoc}
*/
......
......@@ -8,6 +8,7 @@ use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\Types\Type;
abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase
{
......@@ -575,4 +576,29 @@ abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase
{
$this->_platform->getBinaryTypeDeclarationSQL(array());
}
/**
* @group DBAL-553
*/
public function hasNativeJsonType()
{
$this->assertFalse($this->_platform->hasNativeJsonType());
}
/**
* @group DBAL-553
*/
public function testReturnsJsonTypeDeclarationSQL()
{
$column = array(
'length' => 666,
'notnull' => true,
'type' => Type::getType('json_array'),
);
$this->assertSame(
$this->_platform->getClobTypeDeclarationSQL($column),
$this->_platform->getJsonTypeDeclarationSQL($column)
);
}
}
<?php
namespace Doctrine\Tests\DBAL\Platforms;
use Doctrine\DBAL\Platforms\PostgreSQL92Platform;
class PostgreSQL92PlatformTest extends PostgreSqlPlatformTest
{
/**
* {@inheritdoc}
*/
public function createPlatform()
{
return new PostgreSQL92Platform();
}
/**
* @group DBAL-553
*/
public function testHasNativeJsonType()
{
$this->assertTrue($this->_platform->hasNativeJsonType());
}
/**
* @group DBAL-553
*/
public function testReturnsJsonTypeDeclarationSQL()
{
$this->assertSame('JSON', $this->_platform->getJsonTypeDeclarationSQL(array()));
}
/**
* @group DBAL-553
*/
public function testInitializesJsonTypeMapping()
{
$this->assertTrue($this->_platform->hasDoctrineTypeMappingFor('json'));
$this->assertEquals('json_array', $this->_platform->getDoctrineTypeMapping('json'));
}
}
<?php
namespace Doctrine\Tests\DBAL\Types;
use Doctrine\DBAL\Types\Type;
use Doctrine\Tests\DBAL\Mocks\MockPlatform;
require_once __DIR__ . '/../../TestInit.php';
class JsonArrayTest extends \Doctrine\Tests\DbalTestCase
{
/**
* @var \Doctrine\Tests\DBAL\Mocks\MockPlatform
*/
protected $platform;
/**
* @var \Doctrine\DBAL\Types\JsonArrayType
*/
protected $type;
/**
* {@inheritdoc}
*/
protected function setUp()
{
$this->platform = new MockPlatform();
$this->type = Type::getType('json_array');
}
public function testReturnsBindingType()
{
$this->assertSame(\PDO::PARAM_STR, $this->type->getBindingType());
}
public function testReturnsName()
{
$this->assertSame(Type::JSON_ARRAY, $this->type->getName());
}
public function testReturnsSQLDeclaration()
{
$this->assertSame('DUMMYJSON', $this->type->getSQLDeclaration(array(), $this->platform));
}
public function testJsonNullConvertsToPHPValue()
{
$this->assertSame(array(), $this->type->convertToPHPValue(null, $this->platform));
}
public function testJsonStringConvertsToPHPValue()
{
$value = array('foo' => 'bar', 'bar' => 'foo');
$databaseValue = json_encode($value);
$phpValue = $this->type->convertToPHPValue($databaseValue, $this->platform);
$this->assertEquals($value, $phpValue);
}
public function testJsonResourceConvertsToPHPValue()
{
$value = array('foo' => 'bar', 'bar' => 'foo');
$databaseValue = fopen('data://text/plain;base64,' . base64_encode(json_encode($value)), 'r');
$phpValue = $this->type->convertToPHPValue($databaseValue, $this->platform);
$this->assertSame($value, $phpValue);
}
public function testRequiresSQLCommentHint()
{
$this->assertTrue($this->type->requiresSQLCommentHint($this->platform));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment