### SwiftUI App Example with Lighter Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/GettingStarted.md Demonstrates a basic SwiftUI application that utilizes the Lighter library to fetch data from a SQLite database. It shows how to initialize the database module and display fetched records in a List. Assumes the 'Northwind' database and associated Lighter module are set up. ```swift import SwiftUI @main struct TestOutLighterApp: App { let db = Northwind.module! // Assumes Northwind.module is correctly initialized @State var products = [ Products ]() var body: some Scene { WindowGroup { List(products) { product in Text("\(product.productName) (\(product.id))") } .task { // Fetches products from the database using Lighter's async/await API products = try! await db.products.fetch() } } } } ``` -------------------------------- ### Importing SQLite3 in Swift Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/GettingStarted.md Shows how to import the SQLite3 library directly in Swift. This is useful for lower-level SQLite operations or when working on Linux setups where Lighter might provide module definitions. ```swift import SQLite3 ``` -------------------------------- ### Swift Web Server Example using Lighter and MacroExpress Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Linux.md A basic Swift web server example that uses Lighter to interact with an SQLite database and MacroExpress to handle HTTP requests. It exposes a '/api/products' endpoint to fetch products from the database. ```swift #!/usr/bin/swift sh import MacroExpress // @Macro-swift import Northwind // @Northwind-swift/NorthwindSQLite.swift let db = Northwind.module! let app = express() app.get("/api/products") { _, res in res.send(try db.products.fetch()) } app.listen(1337) // start server ``` -------------------------------- ### Lighter.json Configuration Example Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md A comprehensive example of the Lighter.json configuration file, demonstrating global settings and per-target/per-database overrides for various aspects of code generation. ```json { "databaseExtensions" : [ "sqlite3", "db", "sqlite" ], "sqlExtensions" : [ "sql" ], "CodeStyle": { "functionCommentStyle" : "**", "indent" : " ", "lineLength" : 80 }, "EmbeddedLighter": { "inserts": 6 }, "ContactsTestDB": { "EmbeddedLighter": null, "OtherDB": { "CodeStyle": { "comments": { "types" : "", "properties" : "", "functions" : "" } }, "CodeGeneration": { "Raw" : "none", "readOnly" : true, "generateAsyncFunctions" : false, "embedRecordTypesInDatabaseType" : true } } } } ``` -------------------------------- ### Fetch Products from Northwind Database (Swift) Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Northwind.md Demonstrates how to import the Northwind module and fetch all products from the database using Lighter Swift. Assumes the Northwind package is added as a dependency. ```swift import Northwind let db = Northwind.module! for product in try db.products.fetch() { print("Product:", product.id, product.productName) } ``` -------------------------------- ### DocC Property Comment Style Example Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md Demonstrates the DocC comment style for Swift properties. ```swift /// A primary key var id : ID { ... } ``` -------------------------------- ### Swift Async/Await Example for Lighter Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md Demonstrates the usage of Swift's async/await feature with Lighter conformances for database operations. This allows for non-blocking asynchronous calls to fetch and modify data. ```swift let products = try await db.products.fetch { $0.age < 10 } try await db.transaction { tx in try tx.products.delete(10) } ``` -------------------------------- ### DocC Comment Style Example Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md Illustrates the DocC comment style used for documenting Swift types. ```swift /** * A type */ struct Person {...} ``` -------------------------------- ### Install SQLite3 Dev Package on Debian/Ubuntu Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Linux.md This command installs the SQLite3 development package required for compiling Swift code that uses SQLite on Debian or Ubuntu-based Linux distributions. Ensure your package list is updated before installation. ```shell apt-get update apt-get install libsqlite3-dev ``` -------------------------------- ### Non-DocC Line Comment Style Example Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md Illustrates the non-DocC line comment style for Swift properties. ```swift // A primary key var id : ID { ... } ``` -------------------------------- ### Swift Package.swift for Lighter Web API Example Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Linux.md This Package.swift file configures a Swift executable target for a web API using Lighter, NorthwindSQLite.swift, and MacroExpress. It specifies the Swift tools version, platform compatibility, and dependencies. ```swift // swift-tools-version:5.7 import PackageDescription var package = Package( name: "LighterExamples", platforms: [ .macOS(.v10_15), .iOS(.v13) ], products: [ .executable(name: "NorthwindWebAPI", targets: [ "NorthwindWebAPI" ]) ], dependencies: [ .package(url: "https://Lighter-swift/Lighter.git", from: "1.0.2"), .package(url: "https://Northwind-swift/NorthwindSQLite.swift.git", from: "1.0.0"), .package(url: "https://github.com/Macro-swift/MacroExpress.git", from: "1.0.2") ], targets: [ .executableTarget( name: "NorthwindWebAPI", dependencies: [ .product(name: "Northwind", package: "NorthwindSQLite.swift"), "MacroExpress" ], exclude: [ "views", "README.md" ] ) ] ) ``` -------------------------------- ### SQL Schema Creation and Versioning Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Migrations.md Example SQL statements for creating a 'contact' table and setting the user version. This demonstrates how to tag the schema version using PRAGMA user_version, which is crucial for migration detection. ```sql CREATE TABLE contact ( id INT NOT NULL PRIMARY KEY, name TEXT NOT NULL ); PRAGMA user_version = 1; -- tag the schema version ``` ```sql ALTER TABLE contact ADD COLUMN age INT NULL; PRAGMA user_version = 2; -- tag the new schema version ``` -------------------------------- ### Complete Lighter Swift Configuration Example Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md A comprehensive JSON configuration demonstrating various settings for Lighter Swift, including database extensions, code style, Lighter API generation, raw SQLite API control, and embedded Lighter options. ```json { "databaseExtensions" : [ "sqlite3", "db", "sqlite" ], "sqlExtensions" : [ "sql" ], "CodeStyle": { "functionCommentStyle" : "**", "indent" : " ", "lineLength" : 80 }, "ContactsTestDB": { "EmbeddedLighter": null, "CodeGeneration": { "Lighter": { "__doc__": "Can use re-export to re-export Lighter API as part of the DB.", "import": "import" } }, "OtherDB": { "CodeStyle": { "comments": { "types" : "", "properties" : "", "functions" : "" } }, "CodeGeneration": { "Raw" : "none", "readOnly" : true, "generateAsyncFunctions" : false, "embedRecordTypesInDatabaseType" : true } } }, "EmbeddedLighter": { "selects": { "syncYield" : "none", "syncArray" : { "columns": 6, "sorts": 2 }, "asyncArray" : { "columns": 6, "sorts": 2 } }, "updates": { "keyBased" : 6, "predicateBased" : 6 }, "inserts": 6 } } ``` -------------------------------- ### Non-DocC Block Comment Style Example Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md Shows the non-DocC block comment style for Swift types. ```swift /* * A type */ struct Person {...} ``` -------------------------------- ### Swift Public API Generation Example Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md Shows the difference in generated Swift code when the 'public' option is enabled versus disabled. This controls the access level of generated types and functions. ```swift public struct TestDatabase { public struct Person: TableRecord { ... } } ``` ```swift struct TestDatabase { struct Person: TableRecord { ... } } ``` -------------------------------- ### Resolve Relationships in SQLite with Lighter Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Lighter.md This Swift code example demonstrates how Lighter can generate code to resolve relationships defined in the SQLite database. It shows fetching a product by its ID and then fetching orders associated with that product. ```swift let product = try await db.products.find(42) let orders = try await db.orders.fetch(for: product) ``` -------------------------------- ### Swift Inlinable Function Example Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md Provides an example of a public Swift function generated with the '@inlinable' attribute. This attribute is used to expose function sources for better Swift optimizer performance. ```swift @inlinable public init(id: String, name: String, ...) ``` -------------------------------- ### Fetch All Records using Global or Record Style (Swift) Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/SQLiteAPI.md Provides examples for fetching all records from a 'products' table in an SQLite database using both global functions and record-style static methods. ```swift let allProducts = sqlite3_products_fetch(db) // global-style let allProducts = Product.fetch(in: db) // record-style ``` -------------------------------- ### Swift Package Manager Target Configuration with Enlighter Plugin Source: https://github.com/lighter-swift/lighter/blob/develop/README.md Example of configuring a Swift Package Manager target to use the 'Enlighter' build tool plugin. This automatically integrates generated database access code into the build process by scanning for database and SQL files. ```swift .target(name: "ContactsDB", dependencies: [ "Lighter" ], resources: [ .copy("ContactsDB.sqlite3") ], plugins: [ "Enlighter" ]) // <== tell SPM to use Enlighter on this target ``` -------------------------------- ### Swift Record Type Embedding Example Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md Illustrates how record types can be generated as subtypes of database types or as standalone types. This affects the structure of the generated Swift code. ```swift struct TestDatabase { struct Person: TableRecord { ... } } ``` ```swift struct TestDatabase { } struct Person: TableRecord { ... } ``` -------------------------------- ### Manual UUID Type Mapping Implementation Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Mapping.md Provides a manual implementation for mapping UUIDs to SQLite columns, using Strings as the underlying storage. This example shows the required initializers and properties for conforming to `SQLiteValueType`. ```swift extension UUID : SQLiteValueType { init(unsafeSQLite3StatementHandle stmt: OpaquePointer!, column: Int32) throws { let s = try String(unsafeSQLite3StatementHandle: stmt, column: column) guard let value = UUID(uuidString: s) else { throw Error() } self = value } init(unsafeSQLite3ValueHandle value: OpaquePointer?) throws { let s = try String(unsafeSQLite3ValueHandle: value) guard let value = UUID(uuidString: s) else { throw Error() } self = value } var sqlStringValue : String { uuidString.sqlStringValue } var requiresSQLBinding : Bool { true } func bind(unsafeSQLite3StatementHandle stmt: OpaquePointer!, index: Int32, then execute: () -> Void) { uuidString .bind(unsafeSQLite3StatementHandle: stmt, index: index, then: execute) } } ``` -------------------------------- ### Initialize Database Connection (Swift) Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/LighterAPI.md Demonstrates how to initialize a database connection using Lighter. It shows two common scenarios: using a pre-embedded database module or bootstrapping a new database instance. The latter allows for options like copying a prefilled resource database or overwriting it during development. ```swift let database = Northwind.module! // or let database = Northwind.bootstrap() ``` -------------------------------- ### Accessing SQLite Database with Lighter API Source: https://github.com/lighter-swift/lighter/blob/develop/README.md Demonstrates how to open a SQLite database embedded in module resources and perform common operations using the Lighter library. Includes fetching counts, filtering records, finding by ID, updating, deleting, and inserting records within a transaction. ```swift // Open a SQLite database embedded in the module resources: let db = ContactsDB.module! // Fetch the number of records: print("Total number of people stored:", try db.people.fetchCount()) // There are various ways to filter, including a plain Swift closure: let people = try db.people.filter { $0.title == nil } // Primary & foreign keys are directly supported: let person = try db.people.find(1) let addresses = try db.addresses.fetch(for: person) // Updates can be done one-shot or, better, using a transaction: try await db.transaction { tx in var person = try tx.people.find(2)! // Update a record. person.title = "ZEO" try tx.update(person) // Delete a record. try tx.delete(person) // Reinsert the same record let newPerson = try tx.insert(person) // gets new ID! } ``` -------------------------------- ### Runtime SQL Migration Execution in Swift Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Migrations.md Provides pseudo-code for executing SQL migrations at runtime in a Swift application. It checks the current database version and iterates through migration files, executing them sequentially. Requires `Bundle.main.urlForResource` to locate migration files. ```swift let fileVersion = try database.get(pragma: "user_version", as: Int.self) guard fileVersion < BodiesDB.userVersion else { return } for i in (fileVersion + 1)...BodiesDB.userVersion { let filename = "ContactsDB-\(leftpad(i, 3)).sql" // ;-) let url = Bundle.main.urlForResource(filename, ofType: "sql") let sql = try String(contentsOf: url) try database.execute(sql) } ``` -------------------------------- ### Fetching Individual Columns from SQLite with Lighter Source: https://github.com/lighter-swift/lighter/blob/develop/README.md Illustrates how to fetch only specific columns from a SQLite database using Lighter for improved efficiency. This allows for retrieving only the necessary data, rather than entire records. ```swift // Fetch just the `id` and `name` columns: ``` -------------------------------- ### Async/Await Query Execution (Swift) Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/LighterAPI.md Illustrates the use of Swift's async/await concurrency features for asynchronous database queries. This allows for non-blocking execution of database operations, improving application responsiveness. ```swift async let supplier = database.suppliers.find(for: product) async let category = database.categories.find(for: product) ( self.supplier, self.category ) = try await ( supplier, category ) ``` -------------------------------- ### User Defined Enum Type Mapping with SQLiteValueType Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Mapping.md Demonstrates how to define a Swift enumeration that can be directly mapped to an SQLite column by conforming to the `SQLiteValueType` protocol. This example uses a String-backed enum for representing solar body types. ```swift enum SolarBodyType: String, SQLiteValueType { case asteroid = "Asteroid" case moon = "Moon" case planet = "Planet" } ``` -------------------------------- ### Global Configuration: File Extensions Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md Defines the file extensions that the Lighter plugins will use to locate input files for database and SQL schemas. ```json { "databaseExtensions" : [ "sqlite3", "db", "sqlite" ], "sqlExtensions" : [ "sql" ] } ``` -------------------------------- ### Extending Category Struct for Image and Name Mapping Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Mapping.md Illustrates how to extend a Swift struct (`Category`) to provide convenient access to mapped data. This example adds a computed `name` property that unwraps an optional String and an `image` property that converts BLOB data to a UIImage. ```swift extension Category { var name : String { categoryName ?? "" } var image : UIImage? { UIImage(data: Data(picture ?? [])) } } ``` -------------------------------- ### Swift Variadic Function Example for Select Operation Source: https://github.com/lighter-swift/lighter/blob/develop/Plugins/Tools/GenerateInternalVariadics/README.md This Swift code demonstrates a variadic function generated by the GenerateInternalVariadics tool. It's designed for selecting data from tables or views with multiple specified columns and sorting options. The function is generic and includes type constraints for SQL columns and record types. ```swift @inlinable func select( from tableOrView: KeyPath, _ column1: KeyPath, _ column2: KeyPath, orderBy sortColumn: KeyPath, _ direction: SQLSortOrder = .ascending, _ limit: Int? = nil ) async throws -> [ ( column1: C1.Value, column2: C2.Value ) ] where C1: SQLColumn, C2: SQLColumn, CS: SQLColumn, T == C1.T, T == C2.T, T == CS.T ``` -------------------------------- ### Dependency-Free SQLite3 API Generation in Swift Source: https://github.com/lighter-swift/lighter/blob/develop/README.md Shows how to use generated Swift APIs for SQLite3 without requiring the Lighter dependency. This approach allows for direct interaction with the SQLite C API, making the generated code self-contained and easily portable. ```swift // Open the database, can also just use `sqlite3_open_v2`: var db : OpaquePointer! sqlite3_open_contacts("contacts.db", &db) defer { sqlite3_close(db) } // Fetch a person by primary key: let person = sqlite3_person_find(db, 2) // Fetch and filter people: let people = sqlite3_people_fetch(db) { $0.name.hasPrefix("Ja") } // Insert a record var person = Person(id: 0, name: "Jason Bourne") sqlite3_person_insert(db, &person) ``` -------------------------------- ### Perform CRUD Operations (Swift) Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/LighterAPI.md Illustrates basic Create, Read, Update, and Delete (CRUD) operations on a database using Lighter. It shows how to insert, update, and delete records, as well as fetch all records or a single record by its identifier. ```swift var newProduct = Product(name: "Maple Sirup") try database.insert(newProduct) newProduct.name = "Marmelade" try database.update(newProduct) try database.delete(newProduct) let allProducts = try database.products.fetch() let product31 = try database.products.find(31) ``` -------------------------------- ### Raw Configuration Dictionary Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md Allows detailed configuration of the raw SQLite API generation, including function prefix, relationship fetching, and hashable record structures. ```json { "Raw": { "prefix": "mydb_", "relationships": true, "hashable": true } } ``` -------------------------------- ### Open SQLite Database Connections in Swift Source: https://context7.com/lighter-swift/lighter/llms.txt Demonstrates various methods for opening SQLite database connections using Lighter, including accessing bundled resources, creating new databases from SQL schemas, and copying existing databases. Supports both synchronous and asynchronous operations. ```swift import Lighter // Open a database bundled as a resource in the module let db = ContactsDB.module! // Or open/create a database at a specific location let db = ContactsDB(url: databaseURL, readOnly: false) // Bootstrap a new database from SQL schema (creates if doesn't exist) let db = try ContactsDB.bootstrap( at: destinationURL, readOnly: false, overwrite: false // Set true during development to recreate on each run ) // Bootstrap with async/await let db = try await ContactsDB.bootstrap() // Copy an existing database to a new location let db = try ContactsDB.bootstrap( at: cacheURL, copying: ContactsDB.module!.connectionHandler.url ) ``` -------------------------------- ### Generate SQLite Swift Code (Command Plugin) Source: https://github.com/lighter-swift/lighter/blob/develop/Plugins/GenerateCodeForSQLite/README.md A Swift Package Manager command plugin that scans targets for SQLite databases and .sql files, generating Swift source code for database interaction. It groups generated types by the base filename and executes SQL scripts in a sorted order. Configuration can be done via Lighter.json. ```bash swift package plugin \ --allow-writing-to-package-directory \ sqlite2swift \ --target ContactsTestDB ``` -------------------------------- ### Execute Database Transactions (Swift) Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/LighterAPI.md Demonstrates how to group multiple database operations into a single transaction for isolation and performance. This ensures that either all operations within the transaction succeed or none of them do. ```swift try database.transaction { tx in tx.insert([ one, two, three, four, five ]) } ``` -------------------------------- ### Raw SQLite API Generation Options Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md Configures the generation of low-level, dependency-free SQLite API functions. Options include omitting them entirely, attaching them as methods to record types, or prefixing global functions with a custom string. ```json { "Raw": "none" /* Omit raw API */ } { "Raw": "RecordType" /* Attach to record types */ } { "Raw": "mydb_" /* Use custom prefix for global functions */ } ``` -------------------------------- ### Create Database with Global or Record Style (Swift) Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/SQLiteAPI.md Shows two methods for creating a new SQLite database: a global function style and a record-style class method. Both require a database path and a pointer to the database connection. ```swift var db : OpaquePointer! let rc = sqlite3_create_northwind("/tmp/MyDatabase.db", &db) // global-style let rc = Northwind.create("/tmp/MyDatabase.db", in: &db) // record-style assert(rc == SQLITE_OK) ``` -------------------------------- ### Perform Raw SQL Queries in Swift Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/LighterAPI.md Execute raw SQL queries directly against the database using the `fetch(sql:)` method. This method supports proper escaping through interpolations, allowing for dynamic query construction. It can fetch full records or specific fragments of data, with fragments having a lower memory cost compared to targeted select operations. ```swift let results = try db.solarBodies.fetch(sql: "SELECT * FROM solar_bodies") ``` ```swift let results = try db.persons.fetch(sql: "SELECT * FROM person WHERE \($0.personId) LIKE UPPER(\(name))" ) ``` ```swift let results = try db.solarBodies.fetch(sql: "SELECT id, name FROM solar_bodies" ) ``` -------------------------------- ### Development Database Bootstrap with Overwrite in Swift Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Migrations.md Shows how to use the `overwrite` parameter in the `bootstrap` function for development purposes. This ensures a clean database with the latest schema on startup during development builds. The `#if DEBUG` directive prevents accidental overwrites in production. ```swift @main struct BodiesApp: App { #if DEBUG let database = try! BodiesDB.bootstrap(overwrite: true) #else let database = try! BodiesDB.bootstrap() #endif ... } ``` -------------------------------- ### CodeStyle Configuration Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md Configures the style and formatting for the generated Swift code, including indentation, line length, and comment styles. ```json "CodeStyle": { "comments" : { "functions": "**" }, "indent" : " ", "lineLength" : 80 } ``` -------------------------------- ### Swift Extension for Parameterized Product Fetch Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/SQLiteAPI.md Provides a Swift extension on the Product model to encapsulate the parameterized fetch logic. This method prepares a statement, binds a text parameter, iterates through results, and returns an array of Product objects. It handles statement finalization using defer. ```swift extension Product { static func fetchWhereQuantityPerUnitContains( _ string: String, from db: OpaquePointer!) -> [ Product ]? { var statement : OpaquePointer? guard sqlite3_prepare_v2( db, "SELECT * FROM Products WHERE QuantityPerUnit LIKE ?", -1, &statement, nil ) == SQLITE3_OK else { return nil } defer { sqlite3_finalize(statement) } sqlite3_bind_text(statement, 1, "%\(string)%", -1, SQLITE_TRANSIENT) var products = [ Product ]() while sqlite3_step(statement) == SQLITE_ROW { products.append(Product(statement)) } return products } } ``` -------------------------------- ### Fetch Products with Swift Closure Filtering Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/SQLiteAPI.md Fetches all columns from 'Products' and 'Products2022' tables and applies a Swift closure to filter results based on the product name prefix. This demonstrates reusing generated structures for different tables with the same schema and applying custom logic. ```swift sqlite3_products_fetch(db, sql: "SELECT * FROM Products") { $0.name.hasPrefix("Gallions") } ``` ```swift sqlite3_products_fetch(db, sql: "SELECT * FROM Products2022") { $0.name.hasPrefix("Gallions") } ``` -------------------------------- ### Configure Swift Package Manager Target with Enlighter Plugin Source: https://github.com/lighter-swift/lighter/blob/develop/Plugins/Enlighter/README.md This snippet shows how to configure a Swift Package Manager target to include the Enlighter build plugin and copy SQLite database resources. It specifies the target name, dependencies, resources to be copied, and the plugins to be used during the build process. ```swift .target(name : "ContactsTestDB", dependencies : [ "Lighter" ], resources : [ .copy("ContactsDB.sqlite3") ], plugins : [ "Enlighter" ]) ``` -------------------------------- ### Perform Database Operations with Lighter Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Lighter.md This Swift code illustrates how to interact with the generated database schema using Lighter. It showcases fetching records based on a condition, updating an existing record, inserting a new record, and deleting a record, all within a transactional context. ```swift let people = try await db.people.fetch { $0.name.hasPrefix("Bour") } var jason = people[0] jason.name = "Bourne!" try await db.transaction { tx in try tx.update(jason) try tx.insert(jason) try tx.delete(jason) } ``` -------------------------------- ### Generate Swift Structs from SQLite Schema Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Lighter.md This snippet demonstrates how Lighter transforms a SQL CREATE TABLE statement into a Swift struct definition. It shows the generated Swift code for a 'person' table, including type mapping and conformance to common protocols like Identifiable and Codable. ```sql CREATE TABLE person ( person_id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, title TEXT NULL ); ``` ```swift struct ContactsDB { struct Person: Identifiable, Hashable, Codable { var id : Int var name : String var title : String? } } ``` -------------------------------- ### Swift: Compare Database Version with Code Version Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Migrations.md Swift code demonstrating how to compare the database's user version with the version embedded in the generated Swift code (BodiesDB.userVersion). This comparison is key to identifying if a migration is needed. ```swift let fileVersion = try database.get(pragma: "user_version", as: Int.self) if fileVersion != BodiesDB.userVersion { print("The database version has changed!") } ``` -------------------------------- ### Insert Record using Global or Record Style (Swift) Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/SQLiteAPI.md Illustrates inserting a new product record into an SQLite database using both the global function style and the record-style method. Assumes a 'Product' structure and an open database connection. ```swift var newProduct = Product(name: "Maple Sirup") sqlite3_products_insert(db, newProduct) // global-style newProduct.insert(into: db) // record-style ``` -------------------------------- ### Perform Raw SQL Queries (Swift) Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/SQLiteAPI.md Explains how to execute raw SQL queries using fetch functions. This method allows for direct SQL interaction and can fetch specific columns or the entire record. Be cautious of SQL injection when constructing SQL strings manually. ```swift let results = sqlite3_products_fetch(sql: "SELECT * FROM products WHERE stock_count > 10" ) let results = sqlite3_products_fetch(sql: "SELECT id, name FROM products WHERE stock_count > 10" ) ``` -------------------------------- ### Type-Safe Database Queries and Updates in Swift Source: https://github.com/lighter-swift/lighter/blob/develop/README.md Demonstrates type-safe selection and bulk update operations on a 'people' table using Lighter's Swift API. It ensures that only valid columns from the schema can be referenced, preventing runtime errors. ```swift let people = try await db.select(from: \.people, \.id, \.name) { $0.id > 2 && $0.title == nil } // Bulk update a specific column: try db.update(\.people, set: \.title, to: nil, where: { record in record.name.hasPrefix("Duck") }) ``` -------------------------------- ### Swift: Bootstrap Database with Versioned Filename Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Migrations.md Swift code snippet illustrating how to version database filenames. By appending the schema version to the filename, different versions of the database can coexist, which is useful for shared caches. ```swift let filename = "BodiesDB-\(BodiesDB.userVersion).sqlite3" let database = try BodiesDB.bootstrap(into: .cachesDirectory, filename: filename) ``` -------------------------------- ### Open SQLite Database Connection (Swift) Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/SQLiteAPI.md Demonstrates how to open a connection to an SQLite database using the standard SQLite3 API. It checks for success using an assertion. ```swift let db : OpaquePointer! let rc = sqlite3_open_v2( "/tmp/MyDatabase.db", &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, nil ) assert(rc == SQLITE_OK) ``` -------------------------------- ### Lighter JSON Configuration for UUID Serialization Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md A sample JSON configuration for Lighter, demonstrating how to specify the serialization format for UUID values. This affects how UUIDs are stored in the SQL database. ```json { "__doc__": "Lighter.json sample", "CodeGeneration": { "uuidSerialization": "text" } } ``` -------------------------------- ### Managing Multiple Database Versions in Swift Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Migrations.md Illustrates how to maintain generated Swift code for multiple database versions within a single application. This involves defining separate database structs (e.g., `OldContactsDB`, `NewContactsDB`) and configuring `embedRecordTypesInDatabaseType` to manage them. ```swift struct OldContactsDB: SQLDatabase { struct Contact: SQLTableRecord {} // the older version } struct NewContactsDB: SQLDatabase { } struct Contact: SQLTableRecord {} // the latest version ``` -------------------------------- ### Lighter Configuration Dictionary Source: https://github.com/lighter-swift/lighter/blob/develop/Sources/Lighter/Lighter.docc/Configuration.md Enables Lighter API generation and provides sub-configurations for import style, re-exporting, relationship functions, and SQLite value type binding. ```json { "Lighter": { "import": "import", "reexport": true, "relationships": true, "useSQLiteValueTypeBinds": true } } ``` -------------------------------- ### Dependency-Free Raw SQLite API in Swift Source: https://context7.com/lighter-swift/lighter/llms.txt This section shows how to interact with SQLite using only the raw SQLite3 C API in Swift, avoiding external library dependencies. It covers opening a database, fetching, inserting, updating, and deleting records, as well as fetching with sorting and relationships. ```swift import SQLite3 var db: OpaquePointer! let rc = sqlite3_open_v2("/path/to/database.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nil) defer { sqlite3_close(db) } let allProducts = sqlite3_products_fetch(db) let product = sqlite3_product_find(db, 31) let filtered = sqlite3_products_fetch(db) { product in product.name.lowercased().contains("e") } var newProduct = Product(id: 0, name: "New Item") sqlite3_product_insert(db, &newProduct) newProduct.name = "Updated Item" sqlite3_product_update(db, newProduct) sqlite3_product_delete(db, newProduct) let sorted = sqlite3_products_fetch(db, orderBy: "name ASC, price DESC") let supplier: Supplier = ... let supplierProducts = sqlite3_products_fetch(db, for: supplier) ``` -------------------------------- ### Record-Style Raw API in Swift Source: https://context7.com/lighter-swift/lighter/llms.txt This Swift code demonstrates an alternative Record-Style API for Lighter, where methods are attached directly to generated record types. It covers fetching, filtering, inserting, updating, and deleting records, as well as creating a database from a schema. ```swift // Record method style (configure in Lighter.json) let allProducts = Product.fetch(in: db) let product = Product.find(31, in: db) let filtered = Product.fetch(in: db) { $0.name.hasPrefix("So") } var product = Product(id: 0, name: "New Product") product.insert(into: db) product.name = "Updated" product.update(in: db) product.delete(in: db) // Create database from schema var db: OpaquePointer! let rc = Northwind.create("/tmp/MyDatabase.db", in: &db) ```