Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Database/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -1464,4 +1464,11 @@ public function enableAlterLocks(bool $enable): self

return $this;
}

/**
* Handle non utf characters supported?
*
* @return bool
*/
abstract public function getSupportNonUtfCharacters(): bool;
}
10 changes: 10 additions & 0 deletions src/Database/Adapter/MariaDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Exception as DatabaseException;
use Utopia\Database\Exception\Character as CharacterException;
use Utopia\Database\Exception\Duplicate as DuplicateException;
use Utopia\Database\Exception\Limit as LimitException;
use Utopia\Database\Exception\NotFound as NotFoundException;
Expand Down Expand Up @@ -1838,6 +1839,10 @@ public function getInternalIndexesKeys(): array

protected function processException(PDOException $e): \Exception
{
if ($e->getCode() === '22007' && isset($e->errorInfo[1]) && $e->errorInfo[1] === 1366) {
return new CharacterException('Invalid character', $e->getCode(), $e);
}

// Timeout
if ($e->getCode() === '70100' && isset($e->errorInfo[1]) && $e->errorInfo[1] === 1969) {
return new TimeoutException('Query timed out', $e->getCode(), $e);
Expand Down Expand Up @@ -2230,4 +2235,9 @@ public function getSupportForAlterLocks(): bool
{
return true;
}

public function getSupportNonUtfCharacters(): bool
{
return true;
}
}
5 changes: 5 additions & 0 deletions src/Database/Adapter/Mongo.php
Original file line number Diff line number Diff line change
Expand Up @@ -3221,4 +3221,9 @@ public function getSupportForAlterLocks(): bool
{
return false;
}

public function getSupportNonUtfCharacters(): bool
{
return false;
}
}
5 changes: 5 additions & 0 deletions src/Database/Adapter/MySQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use PDOException;
use Utopia\Database\Database;
use Utopia\Database\Exception as DatabaseException;
use Utopia\Database\Exception\Character as CharacterException;
use Utopia\Database\Exception\Dependency as DependencyException;
use Utopia\Database\Exception\Structure as StructureException;
use Utopia\Database\Exception\Timeout as TimeoutException;
Expand Down Expand Up @@ -147,6 +148,10 @@ public function getSupportForCastIndexArray(): bool

protected function processException(PDOException $e): \Exception
{
if ($e->getCode() === 'HY000' && isset($e->errorInfo[1]) && $e->errorInfo[1] === 1366) {
return new CharacterException('Invalid character', $e->getCode(), $e);
}

// Timeout
if ($e->getCode() === 'HY000' && isset($e->errorInfo[1]) && $e->errorInfo[1] === 3024) {
return new TimeoutException('Query timed out', $e->getCode(), $e);
Expand Down
5 changes: 5 additions & 0 deletions src/Database/Adapter/Pool.php
Original file line number Diff line number Diff line change
Expand Up @@ -642,4 +642,9 @@ public function getSupportForAlterLocks(): bool
{
return $this->delegate(__FUNCTION__, \func_get_args());
}

public function getSupportNonUtfCharacters(): bool
{
return $this->delegate(__FUNCTION__, \func_get_args());
}
}
5 changes: 5 additions & 0 deletions src/Database/Adapter/Postgres.php
Original file line number Diff line number Diff line change
Expand Up @@ -2738,4 +2738,9 @@ protected function bindOperatorParams(\PDOStatement|PDOStatementProxy $stmt, Ope
break;
}
}

public function getSupportNonUtfCharacters(): bool
{
return false;
}
}
5 changes: 5 additions & 0 deletions src/Database/Adapter/SQLite.php
Original file line number Diff line number Diff line change
Expand Up @@ -1876,4 +1876,9 @@ public function getSupportForAlterLocks(): bool
{
return false;
}

public function getSupportNonUtfCharacters(): bool
{
return false;
}
}
1 change: 0 additions & 1 deletion src/Database/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -9358,5 +9358,4 @@ private function rollbackAttributeMetadata(Document $collection, array $attribut
);
$collection->setAttribute('attributes', \array_values($filteredAttributes));
}

}
9 changes: 9 additions & 0 deletions src/Database/Exception/Character.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Utopia\Database\Exception;

use Utopia\Database\Exception;

class Character extends Exception
{
}
44 changes: 43 additions & 1 deletion tests/e2e/Adapter/Scopes/DocumentTests.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
use Throwable;
use Utopia\Database\Adapter\SQL;
use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception as DatabaseException;
use Utopia\Database\Exception\Authorization as AuthorizationException;
use Utopia\Database\Exception\Character as CharacterException;
use Utopia\Database\Exception\Conflict as ConflictException;
use Utopia\Database\Exception\Duplicate as DuplicateException;
use Utopia\Database\Exception\Limit as LimitException;
Expand All @@ -22,6 +22,48 @@

trait DocumentTests
{
public function testNonUtfChars(): void
{
/** @var Database $database */
$database = $this->getDatabase();

if (!$database->getAdapter()->getSupportNonUtfCharacters()) {
$this->expectNotToPerformAssertions();
return;
}

$database->createCollection(__FUNCTION__);
$this->assertEquals(true, $database->createAttribute(__FUNCTION__, 'title', Database::VAR_STRING, 128, true));

$nonUtfString = "Hello\x00World\xC3\x28\xFF\xFE\xA0Test\x00End";

try {
$database->createDocument(__FUNCTION__, new Document([
'title' => $nonUtfString,
]));
$this->fail('Failed to throw exception');
} catch (Throwable $e) {
$this->assertTrue($e instanceof CharacterException);
}

/**
* Convert to UTF-8 and replace invalid bytes with empty string
*/
$nonUtfString = mb_convert_encoding($nonUtfString, 'UTF-8', 'UTF-8');

/**
* Remove null bytes
*/
$nonUtfString = str_replace("\0", '', $nonUtfString);

$document = $database->createDocument(__FUNCTION__, new Document([
'title' => $nonUtfString,
]));

$this->assertFalse($document->isEmpty());
$this->assertEquals('HelloWorld?(???TestEnd', $document->getAttribute('title'));
}

public function testBigintSequence(): void
{
/** @var Database $database */
Expand Down