shouldReadOnly()) $flags |= SQLITE3_OPEN_READONLY; else $flags |= SQLITE3_OPEN_READWRITE; if($connectionInfo->shouldCreate()) $flags |= SQLITE3_OPEN_CREATE; $this->connection = new SQLite3( $connectionInfo->getFileName(), $flags, $connectionInfo->getEncryptionKey() ); $this->connection->enableExceptions(true); } /** * Gets the number of rows affected by the last operation. * * @return int|string Number of rows affected by the last operation. */ public function getAffectedRows(): int|string { return $this->connection->changes(); } /** * Registers a PHP function for use as an SQL aggregate function. * * @see https://www.php.net/manual/en/sqlite3.createaggregate.php * @param string $name Name of the SQL aggregate. * @param callable $stepCallback Callback function to be called for each row of the result set. * Definition: step(mixed $context, int $rowNumber, mixed $value, mixed ...$values): mixed * @param callable $finalCallback Callback function to be called to finalize the aggregate operation and return the value. * Definition: fini(mixed $content, int $rowNumber): mixed * @param int $argCount Number of arguments this aggregate function takes, -1 for any amount. * @return bool true if the aggregate function was created successfully, false if not. */ public function createAggregate(string $name, callable $stepCallback, callable $finalCallback, int $argCount = -1): bool { return $this->connection->createAggregate($name, $stepCallback, $finalCallback, $argCount); } /** * Registers a PHP function for use as an SQL collating function. * * @see https://www.php.net/manual/en/sqlite3.createcollation.php * @param string $name Name of the SQL collating function. * @param callable $callback Callback function that returns -1, 0 or 1 to indicate sort order. * Definition: collation(mixed $value1, mixed $value2): int * @return bool true if the collating function was registered, false if not. */ public function createCollation(string $name, callable $callback): bool { return $this->connection->createCollation($name, $callback); } /** * Register a PHP function for use as an SQL scalar function. * * @see https://www.php.net/manual/en/sqlite3.createfunction.php * @param string $name Name of the SQL function. * @param callable $callback Callback function to register. * Definition: callback(mixed $value, mixed ...$values): mixed * @param int $argCount Number of arguments this aggregate function takes, -1 for any amount. * @param int $flags A bitset of flags. */ public function createFunction(string $name, callable $callback, int $argCount = -1, int $flags = 0): bool { return $this->connection->createFunction($name, $callback, $argCount, $flags); } /** * Sets a callback to be used as an authorizer to limit what statements can do. * * @param callable|null $callback An authorizer callback or null to remove the previous authorizer. * Definition: authorizer(int $actionCode, mixed $param2, mixed $param3, string $database, mixed $trigger): int * $param2 and $param3 differ based on $actionCode. * Must return one of the OK, DENY or IGNORE constants. * @return bool true if the action was successful, false if not. */ public function setAuthorizer(callable|null $callback): bool { return $this->connection->setAuthorizer($callback); } /** * Gets the last error string. * * @return string Last error string. */ public function getLastErrorString(): string { return $this->connection->lastErrorMsg(); } /** * Gets the last error code. * * @return int Last error code. */ public function getLastErrorCode(): int { return $this->connection->lastErrorCode(); } /** * Opens a BLOB field as a Stream. * * To be used instead of getStream on SQLiteResult. * * @param string $table Name of the source table. * @param string $column Name of the source column. * @param int $rowId ID of the source row. * @throws DataException If opening the BLOB failed. * @return Stream BLOB field as a Stream. */ public function getBlobStream(string $table, string $column, int $rowId): Stream { $handle = $this->connection->openBlob($table, $column, $rowId); if(!is_resource($handle)) throw new DataException((string)$this->getLastErrorString(), $this->getLastErrorCode()); return new GenericStream($this->connection->openBlob($table, $column, $rowId)); } public function getLastInsertId(): int|string { return $this->connection->lastInsertRowID(); } public function prepare(string $query): IDbStatement { $statement = $this->connection->prepare($query); if($statement === false) throw new QueryExecuteException((string)$this->getLastErrorString(), $this->getLastErrorCode()); return new SQLiteStatement($this, $statement); } public function query(string $query): IDbResult { $result = $this->connection->query($query); if($result === false) throw new QueryExecuteException($this->getLastErrorString(), $this->getLastErrorCode()); return new SQLiteResult($result); } public function execute(string $query): int|string { if(!$this->connection->exec($query)) throw new QueryExecuteException($this->getLastErrorString(), $this->getLastErrorCode()); return $this->connection->changes(); } public function setAutoCommit(bool $state): void { // there's not really a completely reliable way to set a persistent auto commit disable state if($state === $this->autoCommit) return; $this->autoCommit = $state; if($state) { $this->commit(); } else { $this->beginTransaction(); } } public function beginTransaction(): void { if(!$this->connection->exec('BEGIN;')) throw new BeginTransactionFailedException((string)$this->getLastErrorString(), $this->getLastErrorCode()); } public function commit(): void { if(!$this->connection->exec('COMMIT;')) throw new CommitFailedException((string)$this->getLastErrorString(), $this->getLastErrorCode()); if(!$this->autoCommit) $this->beginTransaction(); } public function rollback(?string $name = null): void { if(!$this->connection->exec(empty($name) ? 'ROLLBACK;' : "ROLLBACK TO {$name};")) throw new CommitFailedException((string)$this->getLastErrorString(), $this->getLastErrorCode()); if(!$this->autoCommit) $this->beginTransaction(); } public function savePoint(string $name): void { if(!$this->connection->exec("SAVEPOINT {$name};")) throw new SavePointFailedException((string)$this->getLastErrorString(), $this->getLastErrorCode()); } public function releaseSavePoint(string $name): void { if(!$this->connection->exec("RELEASE SAVEPOINT {$name};")) throw new ReleaseSavePointFailedException((string)$this->getLastErrorString(), $this->getLastErrorCode()); } public function close(): void { $this->connection->close(); } /** * Closes the connection and associated resources. */ public function __destruct() { $this->close(); } }