-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add binary/blob column support for MSSQL and Oracle #917
Changes from all commits
4666ee6
23e6914
0e5d08b
823bd07
7de19ea
d9fc53f
a2428ea
0146c6c
6be9357
4b0a454
d6ede23
87ab17b
45d134a
5658474
c603bbf
8b04590
83a567d
c6be56a
d9f34a8
62732af
7eaf533
914533c
97a6ccc
e68ec3e
d76e992
25b5d37
1dacebd
9b7b8c0
06a17df
9a05394
09582cb
87d7c22
06aaa61
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Atk4\Data\Persistence\Sql; | ||
|
||
use Atk4\Data\Exception; | ||
use Atk4\Data\Field; | ||
use Doctrine\DBAL\Platforms\OraclePlatform; | ||
use Doctrine\DBAL\Platforms\PostgreSQL94Platform; | ||
use Doctrine\DBAL\Platforms\SQLServer2012Platform; | ||
use Doctrine\DBAL\Types\Type; | ||
|
||
trait BinaryTypeCompatibilityTypecastTrait | ||
{ | ||
private function binaryTypeValueGetPrefixConst(): string | ||
{ | ||
return 'atk__binary__u5f8mzx4vsm8g2c9__'; | ||
} | ||
|
||
private function binaryTypeValueEncode(string $value): string | ||
{ | ||
$hex = bin2hex($value); | ||
|
||
return $this->binaryTypeValueGetPrefixConst() . hash('crc32b', $hex) . $hex; | ||
} | ||
|
||
private function binaryTypeValueIsEncoded(string $value): bool | ||
{ | ||
return str_starts_with($value, $this->binaryTypeValueGetPrefixConst()); | ||
} | ||
|
||
private function binaryTypeValueDecode(string $value): string | ||
{ | ||
if (!$this->binaryTypeValueIsEncoded($value)) { | ||
throw new Exception('Unexpected unencoded binary value'); | ||
} | ||
|
||
$hexCrc = substr($value, strlen($this->binaryTypeValueGetPrefixConst()), 8); | ||
$hex = substr($value, strlen($this->binaryTypeValueGetPrefixConst()) + 8); | ||
if ((strlen($hex) % 2) !== 0 || $hexCrc !== hash('crc32b', $hex)) { | ||
throw new Exception('Unexpected binary value crc'); | ||
} | ||
|
||
return hex2bin($hex); | ||
} | ||
|
||
private function binaryTypeIsEncodeNeeded(Type $type): bool | ||
{ | ||
// TODO PostgreSQL tests fail without binary compatibility typecast | ||
$platform = $this->getDatabasePlatform(); | ||
if ($platform instanceof PostgreSQL94Platform | ||
|| $platform instanceof SQLServer2012Platform | ||
|| $platform instanceof OraclePlatform) { | ||
if (in_array($type->getName(), ['binary', 'blob'], true)) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
public function typecastSaveField(Field $field, $value) | ||
{ | ||
$value = parent::typecastSaveField($field, $value); | ||
|
||
if ($value !== null && $this->binaryTypeIsEncodeNeeded($field->getTypeObject())) { | ||
$value = $this->binaryTypeValueEncode($value); | ||
} | ||
|
||
return $value; | ||
} | ||
|
||
public function typecastLoadField(Field $field, $value) | ||
{ | ||
$value = parent::typecastLoadField($field, $value); | ||
|
||
if ($value !== null && $this->binaryTypeIsEncodeNeeded($field->getTypeObject())) { | ||
$value = $this->binaryTypeValueDecode($value); | ||
} | ||
|
||
return $value; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -212,6 +212,16 @@ protected static function connectDbalConnection(array $dsn) | |
if (isset($dsn['pdo'])) { | ||
$pdo = $dsn['pdo']; | ||
} else { | ||
$enforceCharset = [ | ||
'mysql' => 'utf8mb4', | ||
'oci' => 'AL32UTF8', | ||
][$dsn['driverSchema']] ?? null; | ||
|
||
if ($enforceCharset !== null) { | ||
$dsn['dsn'] = preg_replace('~; *charset=[^;]+~i', '', $dsn['dsn']) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So we always enforce utf8? What if user database is not utf8? Previously utf8 was used by default, but user could use different charset too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because of many hidden issues. UTF-8 is defacto standard. This is about the connection charset, you can store any data you want in binary fields, actually, this is one of the feature thi PR adds and fixes. |
||
. ';charset=' . $enforceCharset; | ||
} | ||
|
||
$pdo = new \PDO($dsn['dsn'], $dsn['user'], $dsn['pass']); | ||
} | ||
|
||
|
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason which I don't remember now we had separated Oracle 12 support.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a different compatibility layer previously for Oracle 12, but I purged some time ago it in favor of generic layer for Oracle 11 and all tests are run againt this version in CI.