Refactor entire codebase and rewrite documentation
This commit is contained in:
98
Sources/DataLiteCore/Docs.docc/Articles/SQLScripts.md
Normal file
98
Sources/DataLiteCore/Docs.docc/Articles/SQLScripts.md
Normal file
@@ -0,0 +1,98 @@
|
||||
# Running SQL Scripts
|
||||
|
||||
Execute and automate SQL migrations, seed data, and test fixtures with DataLiteCore.
|
||||
|
||||
``SQLScript`` and ``ConnectionProtocol/execute(sql:)`` let you run sequences of prepared statements
|
||||
as a single script. The loader splits content by semicolons, removes comments and whitespace, and
|
||||
compiles each statement individually. Scripts run in autocommit mode by default — execution stops at
|
||||
the first failure and throws the corresponding ``SQLiteError``.
|
||||
|
||||
## Building Scripts
|
||||
|
||||
Create a script inline or load it from a bundled resource. ``SQLScript`` automatically strips
|
||||
comments and normalizes whitespace.
|
||||
|
||||
```swift
|
||||
let script = SQLScript(string: """
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY,
|
||||
username TEXT NOT NULL UNIQUE
|
||||
);
|
||||
INSERT INTO users (username) VALUES ('ada'), ('grace');
|
||||
""")
|
||||
```
|
||||
|
||||
Load a script from your module or app bundle using ``SQLScript/init(byResource:extension:in:)``:
|
||||
|
||||
```swift
|
||||
let bootstrap = try? SQLScript(
|
||||
byResource: "bootstrap",
|
||||
extension: "sql",
|
||||
in: .module
|
||||
)
|
||||
```
|
||||
|
||||
## Executing Scripts
|
||||
|
||||
Run the script through ``ConnectionProtocol/execute(sql:)``. Statements execute sequentially in the
|
||||
order they appear.
|
||||
|
||||
```swift
|
||||
let connection = try Connection(
|
||||
location: .file(path: dbPath),
|
||||
options: [.readwrite, .create]
|
||||
)
|
||||
try connection.execute(sql: script)
|
||||
```
|
||||
|
||||
In autocommit mode, each statement commits as soon as it succeeds. If any statement fails, execution
|
||||
stops and previously executed statements remain committed. To ensure all-or-nothing execution, wrap
|
||||
the script in an explicit transaction:
|
||||
|
||||
```swift
|
||||
try connection.beginTransaction(.immediate)
|
||||
do {
|
||||
try connection.execute(sql: script)
|
||||
try connection.commitTransaction()
|
||||
} catch {
|
||||
try? connection.rollbackTransaction()
|
||||
throw error
|
||||
}
|
||||
```
|
||||
|
||||
- Important: SQLScript must not include BEGIN, COMMIT, or ROLLBACK. Always manage transactions at
|
||||
the connection level.
|
||||
|
||||
## Executing Raw SQL
|
||||
|
||||
Use ``ConnectionProtocol/execute(raw:)`` to run multi-statement SQL directly, without parsing or
|
||||
preprocessing. This method executes the script exactly as provided, allowing you to manage
|
||||
transactions explicitly within the SQL itself.
|
||||
|
||||
```swift
|
||||
let migrations = """
|
||||
BEGIN;
|
||||
CREATE TABLE categories (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL UNIQUE
|
||||
);
|
||||
INSERT INTO categories (name) VALUES ('Swift'), ('SQLite');
|
||||
COMMIT;
|
||||
"""
|
||||
|
||||
try connection.execute(raw: migrations)
|
||||
```
|
||||
|
||||
Each statement runs in sequence until completion or until the first error occurs. If a statement
|
||||
fails, execution stops and remaining statements are skipped. Open transactions are not rolled back
|
||||
automatically — they must be handled explicitly inside the script or by the caller.
|
||||
|
||||
## Handling Errors
|
||||
|
||||
Inspect the thrown ``SQLiteError`` to identify the failing statement’s result code and message. For
|
||||
longer scripts, wrap execution in logging to trace progress and isolate the exact statement that
|
||||
triggered the exception.
|
||||
|
||||
- SeeAlso: ``SQLScript``
|
||||
- SeeAlso: ``ConnectionProtocol/execute(sql:)``
|
||||
- SeeAlso: ``ConnectionProtocol/execute(raw:)``
|
||||
Reference in New Issue
Block a user