Removed the logic of using BLOB columns for BINARY type of fields

parent 69b8cefa
...@@ -102,6 +102,12 @@ The Drizzle project is abandoned and is therefore not supported by Doctrine DBAL ...@@ -102,6 +102,12 @@ The Drizzle project is abandoned and is therefore not supported by Doctrine DBAL
- `Configuration::getSQLLogger()` does not return `null` anymore, but a `NullLogger` implementation. - `Configuration::getSQLLogger()` does not return `null` anymore, but a `NullLogger` implementation.
- `Configuration::setSQLLogger()` does not allow `null` anymore. - `Configuration::setSQLLogger()` does not allow `null` anymore.
## BC BREAK: Changes to handling binary fields
- Binary fields whose length exceeds the maximum field size on a given platform are no longer represented as `BLOB`s.
Use binary fields of a size which fits all target platforms, or use blob explicitly instead.
- Binary fields are no longer represented as streams in PHP. They are represented as strings.
# Upgrade to 2.9 # Upgrade to 2.9
## Deprecated `Configuration::getFilterSchemaAssetsExpression()`, `::setFilterSchemaAssetsExpression()` and `AbstractSchemaManager::getFilterSchemaAssetsExpression()`. ## Deprecated `Configuration::getFilterSchemaAssetsExpression()`, `::setFilterSchemaAssetsExpression()` and `AbstractSchemaManager::getFilterSchemaAssetsExpression()`.
......
...@@ -28,7 +28,6 @@ use Doctrine\DBAL\TransactionIsolationLevel; ...@@ -28,7 +28,6 @@ use Doctrine\DBAL\TransactionIsolationLevel;
use Doctrine\DBAL\Types; use Doctrine\DBAL\Types;
use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Type;
use InvalidArgumentException; use InvalidArgumentException;
use const E_USER_DEPRECATED;
use function addcslashes; use function addcslashes;
use function array_map; use function array_map;
use function array_merge; use function array_merge;
...@@ -53,7 +52,6 @@ use function strlen; ...@@ -53,7 +52,6 @@ use function strlen;
use function strpos; use function strpos;
use function strtolower; use function strtolower;
use function strtoupper; use function strtoupper;
use function trigger_error;
/** /**
* Base class for all DatabasePlatforms. The DatabasePlatforms are the central * Base class for all DatabasePlatforms. The DatabasePlatforms are the central
...@@ -281,20 +279,6 @@ abstract class AbstractPlatform ...@@ -281,20 +279,6 @@ abstract class AbstractPlatform
$fixed = $field['fixed'] ?? false; $fixed = $field['fixed'] ?? false;
$maxLength = $this->getBinaryMaxLength();
if ($field['length'] > $maxLength) {
if ($maxLength > 0) {
@trigger_error(sprintf(
'Binary field length %d is greater than supported by the platform (%d). Reduce the field length or use a BLOB field instead.',
$field['length'],
$maxLength
), E_USER_DEPRECATED);
}
return $this->getBlobTypeDeclarationSQL($field);
}
return $this->getBinaryTypeDeclarationSQLSnippet($field['length'], $fixed); return $this->getBinaryTypeDeclarationSQLSnippet($field['length'], $fixed);
} }
......
...@@ -4,11 +4,9 @@ namespace Doctrine\DBAL\Types; ...@@ -4,11 +4,9 @@ namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\AbstractPlatform;
use function fopen;
use function fseek;
use function fwrite;
use function is_resource; use function is_resource;
use function is_string; use function is_string;
use function stream_get_contents;
/** /**
* Type that maps ab SQL BINARY/VARBINARY to a PHP resource stream. * Type that maps ab SQL BINARY/VARBINARY to a PHP resource stream.
...@@ -32,14 +30,11 @@ class BinaryType extends Type ...@@ -32,14 +30,11 @@ class BinaryType extends Type
return null; return null;
} }
if (is_string($value)) { if (is_resource($value)) {
$fp = fopen('php://temp', 'rb+'); $value = stream_get_contents($value);
fwrite($fp, $value);
fseek($fp, 0);
$value = $fp;
} }
if (! is_resource($value)) { if (! is_string($value)) {
throw ConversionException::conversionFailed($value, self::BINARY); throw ConversionException::conversionFailed($value, self::BINARY);
} }
......
...@@ -7,11 +7,10 @@ namespace Doctrine\Tests\DBAL\Functional\Types; ...@@ -7,11 +7,10 @@ namespace Doctrine\Tests\DBAL\Functional\Types;
use Doctrine\DBAL\Driver\IBMDB2\DB2Driver; use Doctrine\DBAL\Driver\IBMDB2\DB2Driver;
use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Types\Type;
use Doctrine\Tests\DbalFunctionalTestCase; use Doctrine\Tests\DbalFunctionalTestCase;
use function is_resource;
use function random_bytes; use function random_bytes;
use function str_replace; use function str_replace;
use function stream_get_contents;
class BinaryTest extends DbalFunctionalTestCase class BinaryTest extends DbalFunctionalTestCase
{ {
...@@ -74,14 +73,6 @@ class BinaryTest extends DbalFunctionalTestCase ...@@ -74,14 +73,6 @@ class BinaryTest extends DbalFunctionalTestCase
[ParameterType::BINARY] [ParameterType::BINARY]
); );
// Currently, `BinaryType` mistakenly converts string values fetched from the DB to a stream. return Type::getType('binary')->convertToPHPValue($value, $this->connection->getDatabasePlatform());
// It should be the opposite. Streams should be used to represent large objects, not binary
// strings. The confusion comes from the PostgreSQL's type system where binary strings and
// large objects are represented by the same BYTEA type
if (is_resource($value)) {
$value = stream_get_contents($value);
}
return $value;
} }
} }
...@@ -509,27 +509,21 @@ abstract class AbstractMySQLPlatformTestCase extends AbstractPlatformTestCase ...@@ -509,27 +509,21 @@ abstract class AbstractMySQLPlatformTestCase extends AbstractPlatformTestCase
self::assertSame('VARBINARY(255)', $this->platform->getBinaryTypeDeclarationSQL([])); self::assertSame('VARBINARY(255)', $this->platform->getBinaryTypeDeclarationSQL([]));
self::assertSame('VARBINARY(255)', $this->platform->getBinaryTypeDeclarationSQL(['length' => 0])); self::assertSame('VARBINARY(255)', $this->platform->getBinaryTypeDeclarationSQL(['length' => 0]));
self::assertSame('VARBINARY(65535)', $this->platform->getBinaryTypeDeclarationSQL(['length' => 65535])); self::assertSame('VARBINARY(65535)', $this->platform->getBinaryTypeDeclarationSQL(['length' => 65535]));
self::assertSame('VARBINARY(65536)', $this->platform->getBinaryTypeDeclarationSQL(['length' => 65536]));
self::assertSame('BINARY(255)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true])); self::assertSame('BINARY(255)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true]));
self::assertSame('BINARY(255)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 0])); self::assertSame('BINARY(255)', $this->platform->getBinaryTypeDeclarationSQL([
self::assertSame('BINARY(65535)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 65535])); 'fixed' => true,
} 'length' => 0,
]));
/** self::assertSame('BINARY(65535)', $this->platform->getBinaryTypeDeclarationSQL([
* @group legacy 'fixed' => true,
* @expectedDeprecation Binary field length 65536 is greater than supported by the platform (65535). Reduce the field length or use a BLOB field instead. 'length' => 65535,
* @expectedDeprecation Binary field length 16777215 is greater than supported by the platform (65535). Reduce the field length or use a BLOB field instead. ]));
* @expectedDeprecation Binary field length 16777216 is greater than supported by the platform (65535). Reduce the field length or use a BLOB field instead. self::assertSame('BINARY(65536)', $this->platform->getBinaryTypeDeclarationSQL([
*/ 'fixed' => true,
public function testReturnsBinaryTypeLongerThanMaxDeclarationSQL() 'length' => 65536,
{ ]));
self::assertSame('MEDIUMBLOB', $this->platform->getBinaryTypeDeclarationSQL(['length' => 65536]));
self::assertSame('MEDIUMBLOB', $this->platform->getBinaryTypeDeclarationSQL(['length' => 16777215]));
self::assertSame('LONGBLOB', $this->platform->getBinaryTypeDeclarationSQL(['length' => 16777216]));
self::assertSame('MEDIUMBLOB', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 65536]));
self::assertSame('MEDIUMBLOB', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 16777215]));
self::assertSame('LONGBLOB', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 16777216]));
} }
public function testDoesNotPropagateForeignKeyCreationForNonSupportingEngines() public function testDoesNotPropagateForeignKeyCreationForNonSupportingEngines()
......
...@@ -848,11 +848,6 @@ abstract class AbstractPlatformTestCase extends DbalTestCase ...@@ -848,11 +848,6 @@ abstract class AbstractPlatformTestCase extends DbalTestCase
$this->platform->getBinaryTypeDeclarationSQL([]); $this->platform->getBinaryTypeDeclarationSQL([]);
} }
public function testReturnsBinaryTypeLongerThanMaxDeclarationSQL()
{
$this->markTestSkipped('Not applicable to the platform');
}
/** /**
* @group DBAL-553 * @group DBAL-553
*/ */
......
...@@ -985,18 +985,14 @@ abstract class AbstractSQLServerPlatformTestCase extends AbstractPlatformTestCas ...@@ -985,18 +985,14 @@ abstract class AbstractSQLServerPlatformTestCase extends AbstractPlatformTestCas
self::assertSame('VARBINARY(8000)', $this->platform->getBinaryTypeDeclarationSQL(['length' => 8000])); self::assertSame('VARBINARY(8000)', $this->platform->getBinaryTypeDeclarationSQL(['length' => 8000]));
self::assertSame('BINARY(255)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true])); self::assertSame('BINARY(255)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true]));
self::assertSame('BINARY(255)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 0])); self::assertSame('BINARY(255)', $this->platform->getBinaryTypeDeclarationSQL([
self::assertSame('BINARY(8000)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 8000])); 'fixed' => true,
} 'length' => 0,
]));
/** self::assertSame('BINARY(8000)', $this->platform->getBinaryTypeDeclarationSQL([
* @group legacy 'fixed' => true,
* @expectedDeprecation Binary field length 8001 is greater than supported by the platform (8000). Reduce the field length or use a BLOB field instead. 'length' => 8000,
*/ ]));
public function testReturnsBinaryTypeLongerThanMaxDeclarationSQL()
{
self::assertSame('VARBINARY(MAX)', $this->platform->getBinaryTypeDeclarationSQL(['length' => 8001]));
self::assertSame('VARBINARY(MAX)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 8001]));
} }
/** /**
......
...@@ -415,16 +415,6 @@ class DB2PlatformTest extends AbstractPlatformTestCase ...@@ -415,16 +415,6 @@ class DB2PlatformTest extends AbstractPlatformTestCase
self::assertSame('CHAR(254) FOR BIT DATA', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 0])); self::assertSame('CHAR(254) FOR BIT DATA', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 0]));
} }
/**
* @group legacy
* @expectedDeprecation Binary field length 32705 is greater than supported by the platform (32704). Reduce the field length or use a BLOB field instead.
*/
public function testReturnsBinaryTypeLongerThanMaxDeclarationSQL()
{
self::assertSame('BLOB(1M)', $this->platform->getBinaryTypeDeclarationSQL(['length' => 32705]));
self::assertSame('BLOB(1M)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 32705]));
}
/** /**
* @group DBAL-234 * @group DBAL-234
*/ */
......
...@@ -481,18 +481,14 @@ class OraclePlatformTest extends AbstractPlatformTestCase ...@@ -481,18 +481,14 @@ class OraclePlatformTest extends AbstractPlatformTestCase
self::assertSame('RAW(2000)', $this->platform->getBinaryTypeDeclarationSQL(['length' => 2000])); self::assertSame('RAW(2000)', $this->platform->getBinaryTypeDeclarationSQL(['length' => 2000]));
self::assertSame('RAW(255)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true])); self::assertSame('RAW(255)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true]));
self::assertSame('RAW(2000)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 0])); self::assertSame('RAW(2000)', $this->platform->getBinaryTypeDeclarationSQL([
self::assertSame('RAW(2000)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 2000])); 'fixed' => true,
} 'length' => 0,
]));
/** self::assertSame('RAW(2000)', $this->platform->getBinaryTypeDeclarationSQL([
* @group legacy 'fixed' => true,
* @expectedDeprecation Binary field length 2001 is greater than supported by the platform (2000). Reduce the field length or use a BLOB field instead. 'length' => 2000,
*/ ]));
public function testReturnsBinaryTypeLongerThanMaxDeclarationSQL()
{
self::assertSame('BLOB', $this->platform->getBinaryTypeDeclarationSQL(['length' => 2001]));
self::assertSame('BLOB', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 2001]));
} }
public function testDoesNotPropagateUnnecessaryTableAlterationOnBinaryType() public function testDoesNotPropagateUnnecessaryTableAlterationOnBinaryType()
......
...@@ -926,18 +926,14 @@ class SQLAnywherePlatformTest extends AbstractPlatformTestCase ...@@ -926,18 +926,14 @@ class SQLAnywherePlatformTest extends AbstractPlatformTestCase
self::assertSame('VARBINARY(32767)', $this->platform->getBinaryTypeDeclarationSQL(['length' => 32767])); self::assertSame('VARBINARY(32767)', $this->platform->getBinaryTypeDeclarationSQL(['length' => 32767]));
self::assertSame('BINARY(1)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true])); self::assertSame('BINARY(1)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true]));
self::assertSame('BINARY(1)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 0])); self::assertSame('BINARY(1)', $this->platform->getBinaryTypeDeclarationSQL([
self::assertSame('BINARY(32767)', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 32767])); 'fixed' => true,
} 'length' => 0,
]));
/** self::assertSame('BINARY(32767)', $this->platform->getBinaryTypeDeclarationSQL([
* @group legacy 'fixed' => true,
* @expectedDeprecation Binary field length 32768 is greater than supported by the platform (32767). Reduce the field length or use a BLOB field instead. 'length' => 32767,
*/ ]));
public function testReturnsBinaryTypeLongerThanMaxDeclarationSQL()
{
self::assertSame('LONG BINARY', $this->platform->getBinaryTypeDeclarationSQL(['length' => 32768]));
self::assertSame('LONG BINARY', $this->platform->getBinaryTypeDeclarationSQL(['fixed' => true, 'length' => 32768]));
} }
/** /**
......
...@@ -7,9 +7,11 @@ use Doctrine\DBAL\Types\BinaryType; ...@@ -7,9 +7,11 @@ use Doctrine\DBAL\Types\BinaryType;
use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Type;
use Doctrine\Tests\DBAL\Mocks\MockPlatform; use Doctrine\Tests\DBAL\Mocks\MockPlatform;
use Doctrine\Tests\DbalTestCase; use Doctrine\Tests\DbalTestCase;
use function array_map;
use function base64_encode; use function base64_encode;
use function fopen; use function fopen;
use function stream_get_contents; use function implode;
use function range;
class BinaryTest extends DbalTestCase class BinaryTest extends DbalTestCase
{ {
...@@ -50,11 +52,10 @@ class BinaryTest extends DbalTestCase ...@@ -50,11 +52,10 @@ class BinaryTest extends DbalTestCase
public function testBinaryStringConvertsToPHPValue() public function testBinaryStringConvertsToPHPValue()
{ {
$databaseValue = 'binary string'; $databaseValue = $this->getBinaryString();
$phpValue = $this->type->convertToPHPValue($databaseValue, $this->platform); $phpValue = $this->type->convertToPHPValue($databaseValue, $this->platform);
self::assertInternalType('resource', $phpValue); self::assertSame($databaseValue, $phpValue);
self::assertEquals($databaseValue, stream_get_contents($phpValue));
} }
public function testBinaryResourceConvertsToPHPValue() public function testBinaryResourceConvertsToPHPValue()
...@@ -62,7 +63,15 @@ class BinaryTest extends DbalTestCase ...@@ -62,7 +63,15 @@ class BinaryTest extends DbalTestCase
$databaseValue = fopen('data://text/plain;base64,' . base64_encode('binary string'), 'r'); $databaseValue = fopen('data://text/plain;base64,' . base64_encode('binary string'), 'r');
$phpValue = $this->type->convertToPHPValue($databaseValue, $this->platform); $phpValue = $this->type->convertToPHPValue($databaseValue, $this->platform);
self::assertSame($databaseValue, $phpValue); self::assertSame('binary string', $phpValue);
}
/**
* Creates a binary string containing all possible byte values.
*/
private function getBinaryString() : string
{
return implode(array_map('chr', range(0, 255)));
} }
/** /**
......
...@@ -6,10 +6,6 @@ use Doctrine\DBAL\Types\BlobType; ...@@ -6,10 +6,6 @@ use Doctrine\DBAL\Types\BlobType;
use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Type;
use Doctrine\Tests\DBAL\Mocks\MockPlatform; use Doctrine\Tests\DBAL\Mocks\MockPlatform;
use Doctrine\Tests\DbalTestCase; use Doctrine\Tests\DbalTestCase;
use function base64_encode;
use function chr;
use function fopen;
use function stream_get_contents;
class BlobTest extends DbalTestCase class BlobTest extends DbalTestCase
{ {
...@@ -32,37 +28,4 @@ class BlobTest extends DbalTestCase ...@@ -32,37 +28,4 @@ class BlobTest extends DbalTestCase
{ {
self::assertNull($this->type->convertToPHPValue(null, $this->platform)); self::assertNull($this->type->convertToPHPValue(null, $this->platform));
} }
public function testBinaryStringConvertsToPHPValue()
{
$databaseValue = $this->getBinaryString();
$phpValue = $this->type->convertToPHPValue($databaseValue, $this->platform);
self::assertInternalType('resource', $phpValue);
self::assertSame($databaseValue, stream_get_contents($phpValue));
}
public function testBinaryResourceConvertsToPHPValue()
{
$databaseValue = fopen('data://text/plain;base64,' . base64_encode($this->getBinaryString()), 'r');
$phpValue = $this->type->convertToPHPValue($databaseValue, $this->platform);
self::assertSame($databaseValue, $phpValue);
}
/**
* Creates a binary string containing all possible byte values.
*
* @return string
*/
private function getBinaryString()
{
$string = '';
for ($i = 0; $i < 256; $i++) {
$string .= chr($i);
}
return $string;
}
} }
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