-
-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
1,169 additions
and
2 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace Nextras\Dbal\Drivers\PdoSqlite; | ||
|
||
|
||
use DateTimeZone; | ||
use Exception; | ||
use Nextras\Dbal\Connection; | ||
use Nextras\Dbal\Drivers\Exception\ConnectionException; | ||
use Nextras\Dbal\Drivers\Exception\DriverException; | ||
use Nextras\Dbal\Drivers\Exception\ForeignKeyConstraintViolationException; | ||
use Nextras\Dbal\Drivers\Exception\NotNullConstraintViolationException; | ||
use Nextras\Dbal\Drivers\Exception\QueryException; | ||
use Nextras\Dbal\Drivers\Exception\UniqueConstraintViolationException; | ||
use Nextras\Dbal\Drivers\Pdo\PdoDriver; | ||
use Nextras\Dbal\Exception\NotSupportedException; | ||
use Nextras\Dbal\ILogger; | ||
use Nextras\Dbal\Platforms\IPlatform; | ||
use Nextras\Dbal\Platforms\SqlitePlatform; | ||
use Nextras\Dbal\Result\IResultAdapter; | ||
use PDOStatement; | ||
|
||
|
||
/** | ||
* Driver for php_pdo_sqlite ext. | ||
* | ||
* Supported configuration options: | ||
* - filename - file path to database or `:memory:`; defaults to :memory: | ||
*/ | ||
class PdoSqliteDriver extends PdoDriver | ||
{ | ||
public function connect(array $params, ILogger $logger): void | ||
{ | ||
$file = $params['filename'] ?? ':memory:'; | ||
$dsn = "sqlite:$file"; | ||
$this->connectPdo($dsn, '', '', [], $logger); | ||
|
||
$this->connectionTz = new DateTimeZone('UTC'); | ||
$this->loggedQuery('PRAGMA foreign_keys = 1'); | ||
} | ||
|
||
|
||
public function createPlatform(Connection $connection): IPlatform | ||
{ | ||
return new SqlitePlatform($connection); | ||
} | ||
|
||
|
||
public function setTransactionIsolationLevel(int $level): void | ||
{ | ||
static $levels = [ | ||
Connection::TRANSACTION_READ_UNCOMMITTED => 'READ UNCOMMITTED', | ||
Connection::TRANSACTION_READ_COMMITTED => 'READ COMMITTED', | ||
Connection::TRANSACTION_REPEATABLE_READ => 'REPEATABLE READ', | ||
Connection::TRANSACTION_SERIALIZABLE => 'SERIALIZABLE', | ||
]; | ||
if (!isset($levels[$level])) { | ||
throw new NotSupportedException("Unsupported transaction level $level"); | ||
} | ||
$this->loggedQuery("SET SESSION TRANSACTION ISOLATION LEVEL {$levels[$level]}"); | ||
} | ||
|
||
|
||
protected function createResultAdapter(PDOStatement $statement): IResultAdapter | ||
{ | ||
return (new PdoSqliteResultAdapter($statement))->toBuffered(); | ||
} | ||
|
||
|
||
protected function convertIdentifierToSql(string $identifier): string | ||
{ | ||
return '[' . strtr($identifier, '[]', ' ') . ']'; | ||
} | ||
|
||
|
||
protected function createException(string $error, int $errorNo, string $sqlState, ?string $query = null): Exception | ||
{ | ||
if (stripos($error, 'FOREIGN KEY constraint failed') !== false) { | ||
return new ForeignKeyConstraintViolationException($error, $errorNo, '', null, $query); | ||
} elseif ( | ||
strpos($error, 'must be unique') !== false | ||
|| strpos($error, 'is not unique') !== false | ||
|| strpos($error, 'are not unique') !== false | ||
|| strpos($error, 'UNIQUE constraint failed') !== false | ||
) { | ||
return new UniqueConstraintViolationException($error, $errorNo, '', null, $query); | ||
} elseif ( | ||
strpos($error, 'may not be NULL') !== false | ||
|| strpos($error, 'NOT NULL constraint failed') !== false | ||
) { | ||
return new NotNullConstraintViolationException($error, $errorNo, '', null, $query); | ||
} elseif (stripos($error, 'unable to open database') !== false) { | ||
return new ConnectionException($error, $errorNo, ''); | ||
} elseif ($query !== null) { | ||
return new QueryException($error, $errorNo, '', null, $query); | ||
} else { | ||
return new DriverException($error, $errorNo, ''); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace Nextras\Dbal\Drivers\PdoSqlite; | ||
|
||
|
||
use Nextras\Dbal\Exception\NotSupportedException; | ||
use Nextras\Dbal\Result\FullyBufferedResultAdapter; | ||
use Nextras\Dbal\Result\IResultAdapter; | ||
use Nextras\Dbal\Utils\StrictObjectTrait; | ||
use PDO; | ||
use PDOStatement; | ||
use function strtolower; | ||
|
||
|
||
class PdoSqliteResultAdapter implements IResultAdapter | ||
{ | ||
use StrictObjectTrait; | ||
|
||
|
||
/** @var array<string, int> */ | ||
protected static $types = [ | ||
'int' => self::TYPE_INT, | ||
'integer' => self::TYPE_INT, | ||
'tinyint' => self::TYPE_INT, | ||
'smallint' => self::TYPE_INT, | ||
'mediumint' => self::TYPE_INT, | ||
'bigint' => self::TYPE_INT, | ||
'unsigned big int' => self::TYPE_INT, | ||
'int2' => self::TYPE_INT, | ||
'int8' => self::TYPE_INT, | ||
|
||
'real' => self::TYPE_FLOAT, | ||
'double' => self::TYPE_FLOAT, | ||
'double precision' => self::TYPE_FLOAT, | ||
'float' => self::TYPE_FLOAT, | ||
'numeric' => self::TYPE_FLOAT, | ||
'decimal' => self::TYPE_FLOAT, | ||
|
||
'bool' => self::TYPE_BOOL, | ||
|
||
'date' => self::TYPE_DATETIME, | ||
'datetime' => self::TYPE_DATETIME, | ||
]; | ||
|
||
/** @var PDOStatement<mixed> */ | ||
protected $statement; | ||
|
||
/** @var bool */ | ||
protected $beforeFirstFetch = true; | ||
|
||
|
||
/** | ||
* @param PDOStatement<mixed> $statement | ||
*/ | ||
public function __construct(PDOStatement $statement) | ||
{ | ||
$this->statement = $statement; | ||
} | ||
|
||
|
||
public function toBuffered(): IResultAdapter | ||
{ | ||
return new FullyBufferedResultAdapter($this); | ||
} | ||
|
||
|
||
public function toUnbuffered(): IResultAdapter | ||
{ | ||
return $this; | ||
} | ||
|
||
|
||
public function seek(int $index): void | ||
{ | ||
if ($index === 0 && $this->beforeFirstFetch) { | ||
return; | ||
} | ||
|
||
throw new NotSupportedException("PDO does not support rewinding or seeking. Use Result::buffered() before first consume of the result."); | ||
} | ||
|
||
|
||
public function fetch(): ?array | ||
{ | ||
$this->beforeFirstFetch = false; | ||
$fetched = $this->statement->fetch(PDO::FETCH_ASSOC); | ||
return $fetched !== false ? $fetched : null; | ||
} | ||
|
||
|
||
public function getTypes(): array | ||
{ | ||
$types = []; | ||
$count = $this->statement->columnCount(); | ||
|
||
for ($i = 0; $i < $count; $i++) { | ||
$field = $this->statement->getColumnMeta($i); | ||
if ($field === false) { // @phpstan-ignore-line | ||
// Sqlite does not return meta for special queries (PRAGMA, etc.) | ||
continue; | ||
} | ||
|
||
$type = strtolower($field['sqlite:decl_type'] ?? $field['native_type'] ?? ''); | ||
|
||
$types[(string) $field['name']] = [ | ||
0 => self::$types[$type] ?? dump(self::TYPE_AS_IS, $field), | ||
1 => $type, | ||
]; | ||
} | ||
|
||
return $types; | ||
} | ||
|
||
|
||
public function getRowsCount(): int | ||
{ | ||
return $this->statement->rowCount(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.