Skip to content

Commit

Permalink
[12.x] Configure connection on SQLite connector (#54588)
Browse files Browse the repository at this point in the history
* fix SQLite connector

* formatting
  • Loading branch information
hafezdivandari authored Feb 13, 2025
1 parent f248edb commit 0f22107
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 236 deletions.
104 changes: 95 additions & 9 deletions Connectors/SQLiteConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,118 @@ class SQLiteConnector extends Connector implements ConnectorInterface
*
* @param array $config
* @return \PDO
*
* @throws \Illuminate\Database\SQLiteDatabaseDoesNotExistException
*/
public function connect(array $config)
{
$options = $this->getOptions($config);

$path = $this->parseDatabasePath($config['database']);

$connection = $this->createConnection("sqlite:{$path}", $config, $options);

$this->configureForeignKeyConstraints($connection, $config);
$this->configureBusyTimeout($connection, $config);
$this->configureJournalMode($connection, $config);
$this->configureSynchronous($connection, $config);

return $connection;
}

/**
* Get the absolute database path.
*
* @param string $path
* @return string
*
* @throws \Illuminate\Database\SQLiteDatabaseDoesNotExistException
*/
protected function parseDatabasePath(string $path): string
{
// SQLite supports "in-memory" databases that only last as long as the owning
// connection does. These are useful for tests or for short lifetime store
// querying. In-memory databases shall be anonymous (:memory:) or named.
if ($config['database'] === ':memory:' ||
str_contains($config['database'], '?mode=memory') ||
str_contains($config['database'], '&mode=memory')
if ($path === ':memory:' ||
str_contains($path, '?mode=memory') ||
str_contains($path, '&mode=memory')
) {
return $this->createConnection('sqlite:'.$config['database'], $config, $options);
return $path;
}

$path = realpath($config['database']) ?: realpath(base_path($config['database']));
$path = realpath($path) ?: realpath(base_path($path));

// Here we'll verify that the SQLite database exists before going any further
// as the developer probably wants to know if the database exists and this
// SQLite driver will not throw any exception if it does not by default.
if ($path === false) {
throw new SQLiteDatabaseDoesNotExistException($config['database']);
throw new SQLiteDatabaseDoesNotExistException($path);
}

return $path;
}

/**
* Enable or disable foreign key constraints if configured.
*
* @param \PDO $connection
* @param array $config
* @return void
*/
protected function configureForeignKeyConstraints($connection, array $config): void
{
if (! isset($config['foreign_key_constraints'])) {
return;
}

$foreignKeys = $config['foreign_key_constraints'] ? 1 : 0;

$connection->prepare("pragma foreign_keys = {$foreignKeys}")->execute();
}

/**
* Set the busy timeout if configured.
*
* @param \PDO $connection
* @param array $config
* @return void
*/
protected function configureBusyTimeout($connection, array $config): void
{
if (! isset($config['busy_timeout'])) {
return;
}

$connection->prepare("pragma busy_timeout = {$config['busy_timeout']}")->execute();
}

/**
* Set the journal mode if configured.
*
* @param \PDO $connection
* @param array $config
* @return void
*/
protected function configureJournalMode($connection, array $config): void
{
if (! isset($config['journal_mode'])) {
return;
}

$connection->prepare("pragma journal_mode = {$config['journal_mode']}")->execute();
}

/**
* Set the synchronous mode if configured.
*
* @param \PDO $connection
* @param array $config
* @return void
*/
protected function configureSynchronous($connection, array $config): void
{
if (! isset($config['synchronous'])) {
return;
}

return $this->createConnection("sqlite:{$path}", $config, $options);
$connection->prepare("pragma synchronous = {$config['synchronous']}")->execute();
}
}
111 changes: 0 additions & 111 deletions SQLiteConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,6 @@

class SQLiteConnection extends Connection
{
/**
* Create a new database connection instance.
*
* @param \PDO|\Closure $pdo
* @param string $database
* @param string $tablePrefix
* @param array $config
* @return void
*/
public function __construct($pdo, $database = '', $tablePrefix = '', array $config = [])
{
parent::__construct($pdo, $database, $tablePrefix, $config);

$this->configureForeignKeyConstraints();
$this->configureBusyTimeout();
$this->configureJournalMode();
$this->configureSynchronous();
}

/**
* {@inheritdoc}
*/
Expand All @@ -39,98 +20,6 @@ public function getDriverTitle()
return 'SQLite';
}

/**
* Enable or disable foreign key constraints if configured.
*
* @return void
*/
protected function configureForeignKeyConstraints(): void
{
$enableForeignKeyConstraints = $this->getConfig('foreign_key_constraints');

if ($enableForeignKeyConstraints === null) {
return;
}

$schemaBuilder = $this->getSchemaBuilder();

try {
$enableForeignKeyConstraints
? $schemaBuilder->enableForeignKeyConstraints()
: $schemaBuilder->disableForeignKeyConstraints();
} catch (QueryException $e) {
if (! $e->getPrevious() instanceof SQLiteDatabaseDoesNotExistException) {
throw $e;
}
}
}

/**
* Set the busy timeout if configured.
*
* @return void
*/
protected function configureBusyTimeout(): void
{
$milliseconds = $this->getConfig('busy_timeout');

if ($milliseconds === null) {
return;
}

try {
$this->getSchemaBuilder()->setBusyTimeout($milliseconds);
} catch (QueryException $e) {
if (! $e->getPrevious() instanceof SQLiteDatabaseDoesNotExistException) {
throw $e;
}
}
}

/**
* Set the journal mode if configured.
*
* @return void
*/
protected function configureJournalMode(): void
{
$mode = $this->getConfig('journal_mode');

if ($mode === null) {
return;
}

try {
$this->getSchemaBuilder()->setJournalMode($mode);
} catch (QueryException $e) {
if (! $e->getPrevious() instanceof SQLiteDatabaseDoesNotExistException) {
throw $e;
}
}
}

/**
* Set the synchronous mode if configured.
*
* @return void
*/
protected function configureSynchronous(): void
{
$mode = $this->getConfig('synchronous');

if ($mode === null) {
return;
}

try {
$this->getSchemaBuilder()->setSynchronous($mode);
} catch (QueryException $e) {
if (! $e->getPrevious() instanceof SQLiteDatabaseDoesNotExistException) {
throw $e;
}
}
}

/**
* Escape a binary value for safe SQL embedding.
*
Expand Down
77 changes: 15 additions & 62 deletions Schema/Grammars/SQLiteGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ public function compileAlter(Blueprint $blueprint, Fluent $command)
$table = $this->wrapTable($blueprint);
$columnNames = implode(', ', $columnNames);

$foreignKeyConstraintsEnabled = $this->connection->scalar('pragma foreign_keys');
$foreignKeyConstraintsEnabled = $this->connection->scalar($this->pragma('foreign_keys'));

return array_filter(array_merge([
$foreignKeyConstraintsEnabled ? $this->compileDisableForeignKeyConstraints() : null,
Expand Down Expand Up @@ -511,11 +511,14 @@ public function compileDropAllViews($schema = null)
/**
* Compile the SQL needed to rebuild the database.
*
* @param string|null $schema
* @return string
*/
public function compileRebuild()
public function compileRebuild($schema = null)
{
return 'vacuum';
return sprintf('vacuum %s',
$this->wrapValue($schema ?? 'main')
);
}

/**
Expand Down Expand Up @@ -672,7 +675,7 @@ public function compileRenameIndex(Blueprint $blueprint, Fluent $command)
*/
public function compileEnableForeignKeyConstraints()
{
return $this->pragma('foreign_keys', 'ON');
return $this->pragma('foreign_keys', 1);
}

/**
Expand All @@ -682,72 +685,22 @@ public function compileEnableForeignKeyConstraints()
*/
public function compileDisableForeignKeyConstraints()
{
return $this->pragma('foreign_keys', 'OFF');
}

/**
* Compile the command to set the busy timeout.
*
* @param int $milliseconds
* @return string
*/
public function compileSetBusyTimeout($milliseconds)
{
return $this->pragma('busy_timeout', $milliseconds);
}

/**
* Compile the command to set the journal mode.
*
* @param string $mode
* @return string
*/
public function compileSetJournalMode($mode)
{
return $this->pragma('journal_mode', $mode);
}

/**
* Compile the command to set the synchronous mode.
*
* @param string $mode
* @return string
*/
public function compileSetSynchronous($mode)
{
return $this->pragma('synchronous', $mode);
}

/**
* Compile the SQL needed to enable a writable schema.
*
* @return string
*/
public function compileEnableWriteableSchema()
{
return $this->pragma('writable_schema', 1);
}

/**
* Compile the SQL needed to disable a writable schema.
*
* @return string
*/
public function compileDisableWriteableSchema()
{
return $this->pragma('writable_schema', 0);
return $this->pragma('foreign_keys', 0);
}

/**
* Get the SQL to set a PRAGMA value.
* Get the SQL to get or set a PRAGMA value.
*
* @param string $name
* @param string $key
* @param mixed $value
* @return string
*/
protected function pragma(string $name, mixed $value): string
public function pragma(string $key, mixed $value = null): string
{
return sprintf('PRAGMA %s = %s;', $name, $value);
return sprintf('pragma %s%s',
$key,
is_null($value) ? '' : ' = '.$value
);
}

/**
Expand Down
Loading

0 comments on commit 0f22107

Please sign in to comment.