neuron-explorer
Qwen3.5‑4B 전용 조향형 뉴런 탐색기, 모든 MLP 뉴런을 밀어 결과를 보관·탐색
SQL as a first-class language in Swift. Type-safe SQLite queries written clause by clause, in SQL's own order: Select, From, Join, Where, GroupBy, Having, With.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
SQL, as a first-class language in Swift.
Real SQLite, written in typed, composable, refactorable Swift.
No raw query strings for supported queries. No stringly typed columns.
No ORM hiding the SQL.
SQL is too important to bury in strings. SwiftQL takes a different approach:
it brings SQLite into Swift's type system using macros, generics, operators,
and result builders.
Tables are Swift structs. Columns are typed properties. Statements are values
written in SQL order. Selected rows decode back into the Swift type you asked
for.README 전문 보기 ↗SQL is too important to bury in strings. SwiftQL takes a different approach: it brings SQLite into Swift's type system using macros, generics, operators, and result builders.
Tables are Swift structs. Columns are typed properties. Statements are values written in SQL order. Selected rows decode back into the Swift type you asked for.
Concretely: rename a column and the compiler finds every query that used it, instead of your users finding them at runtime. A string-based query survives the rename, ships, and fails on a device you cannot reach.
import Foundation
import SwiftQL
@SQLTable
struct Person {
var id: String
var occupationId: String?
var name: String
var age: Int
}
let databaseURL = FileManager.default.temporaryDirectory
.appendingPathComponent(UUID().uuidString)
.appendingPathExtension("sqlite")
let database = try GRDBDatabase(url: databaseURL, logger: nil)
try database.makeRequest(with: sqlCreate(Person.self)).execute()
let query = sql { schema in
let person = schema.table(Person.self)
Select(person)
From(person)
Where(person.name == "Fred")
}
The temporary file keeps this example self-contained. In an application, use
your durable database URL and reuse one GRDBDatabase for that path. The basic
sqlCreate call uses CREATE TABLE IF NOT EXISTS; it creates this first table
but does not migrate an existing schema when Person changes.
That Swift expression emits recognizable SQLite:
SELECT t0.id AS id, t0.occupationId AS occupationId,
t0.name AS name, t0.age AS age
FROM Person AS t0
WHERE (t0.name == 'Fred')
Create a request and execute it without leaving Swift's type system:
let request = database.makeRequest(with: query)
let people: [Person] = try request.fetchAll()
let firstPerson: Person? = try request.fetchOne()
Select(person) fixes the row type when the query is constructed, so both
execution methods expose their result types directly. There are no untyped row
dictionaries or manual result casts.
The Where clause is ordinary Swift, too:
Where(person.name == "Fred")
There is no "name" lookup string to mistype. Xcode can complete and navigate
the table model, while the compiler catches missing fields, incompatible
expression types, and invalid clause ordering. Rename a model property and the
compiler leads you to the queries affected by it.
If you know SQLite, you already know the shape of SwiftQL: Select, From,
Join, Where, GroupBy, Having, and With appear in SQL order and retain
their SQL meaning.
Add the following line to the dependencies section in your Package.swift
file:
.package(url: "https://github.com/lukevanin/swiftql.git", from: "1.9.0")
1.9.0 is the latest published package. The examples above use APIs retained
by v1.3; the static-query surface remains available from version 1.2.0. Pin a
source revision only when intentionally testing later changes from main.
SwiftQL 1.x requires GRDB 6 (6.29.3..<7.0.0). If your package graph already
uses GRDB 7, SwiftPM cannot resolve SwiftQL 1.x. The
compatibility guide gives the reasons and links the GRDB 7
evaluation.
In Xcode, follow Apple's Adding package dependencies to your app,
and specify the package URL https://github.com/lukevanin/swiftql.git.
Getting started walks through defining a table, creating it, inserting, selecting, binding values, updating, deleting, and grouping work in a transaction. It is the fastest path from an empty file to a working query, and it doubles as a quick reference afterwards.
From there:
@SQLQuery.The Getting Started playground is that same walkthrough
with the code running beside the explanation: nine pages against a real SQLite
file, from defining a table through inserting, selecting, updating, deleting,
named bindings, lazy result sets, and transactions, to observing a live query.
Open Examples/SwiftQLExamples.xcworkspace, build the SwiftQLExamples scheme
for My Mac, and step through it.
Each page prints its results and states the output it expects next to the code producing it, so you can change a query and see immediately what moved.
Examples/TodoApp is a SwiftUI application for
iOS 17 and macOS 14 whose entire data layer is SwiftQL. It shows the parts a
guide covers one at a time working together: a four-table schema with a
many-to-many join, declared @SQLQueries reads including a join and a grouped
aggregate, one query serving every filter, sort, and search combination,
writes that return their row through RETURNING, an atomic move between
lists, and an interface fed entirely by live queries — completing a to-do
updates the list and the sidebar counts with no reload call anywhere. Its
queries are checked against a schema snapshot at build time, and its tests
cover the query layer.
Open Examples/TodoApp/TodoApp.xcodeproj and run the TodoApp scheme.
WHATSNEW.md describes each release in plain language — what you can do that you could not before, and whether it affects code you already wrote. CHANGELOG.md remains the exact record.
Swift has good persistence libraries. They differ mainly in how much of the relational model they ask you to give up.
| Shape | Where the SQL lives | Type safety comes from | |
|---|---|---|---|
| SwiftQL | Result builder, one clause per statement in SQL order | Visible, in SQL order, in Swift | Macros + generics, checked at compile time |
| StructuredQueries | Chained methods with typed closures and key paths | Emitted in SQL order; #sql escape hatch for typed SQL strings | @Table macro + key paths |
| GRDB | Records + query interface, with raw SQL always available | Visible when you write it; strings when you drop down | Codable records and column definitions |
| SQLite.swift | Expression DSL | Behind the DSL | Generic Expression types |
| SwiftData | Object graph | Hidden - no SQL surface | @Model macro over an opaque store |
| Fluent | Server-side ORM | Hidden behind the model layer | Model definitions and property wrappers |
SwiftQL is not a GRDB alternative - it is a typed query layer above it. Execution, connection management, transactions, and observation are GRDB's, and deliberately so: that part is mature, well understood, and not worth reimplementing. SwiftQL replaces the part where queries become strings.
What sets SwiftQL apart is positional correspondence with SQL. Every other typed query library in this table reaches SQL through a method chain: you start from a table type and attach clauses to it, in an order the library accepts rather than the order SQL defines. SwiftQL writes each clause once, under its SQL name, in SQL's grammatical order. The Swift source and the statement it produces have the same shape.
That is what makes porting mechanical rather than interpretive. A query moves between SQL and SwiftQL a clause at a time, in both directions, without first being redesigned into somebody's builder vocabulary. The porting guide is the proof: a clause-by-clause mapping table, worked ports up to recursive common table expressions, and an explicit list of the places the correspondence is not exact.
sqlCreate
creates a table but does not migrate an existing schema. Use GRDB's
DatabaseMigrator alongside SwiftQL - they compose, because SwiftQL sits on
GRDB rather than replacing it..select { }.where { } reads better to you than
Select / From / Where, that preference is the whole argument.6.29.3..<7.0.0), so SwiftPM cannot resolve the two together. The
compatibility guide gives the reasons and links the
GRDB 7 evaluation.@SQLTable and @SQLResult derive typed table, column, and result metadata
at compile time. There are no generated model files to keep in sync. A var
property with an initial value gives the generated initializer a default, so
a call can leave it out.USING joins; grouping and HAVING;
ordering and pagination; scalar and table subqueries; compound queries; and
ordinary or recursive common table expressions.insert(contentsOf:) writes a batch of rows
through one statement, rendered and prepared once for the call. A row whose
values cannot bind to that statement renders on its own, in the same
transaction.fetchAll() and fetchOne() results directly into Swift values.
@SQLBindings generates the typed packet for a statement's named bindings.
A misspelled name or a missing value is a compile error. A statement that
uses a binding the struct does not declare still throws when the packet is
built.SwiftQL does not replace the relational model with an object graph, and it does not make SQL disappear. It preserves the database concepts that make SQL powerful, then gives them native Swift names, types, composition, completion, and refactoring support.
The boundary is deliberate. Swift checks the APIs, table fields, result shapes, expression types, and supported statement composition that it can prove. SQLite remains the authority for the live schema, runtime constraints, coercion rules, and dialect-specific behavior. SwiftQL deliberately grows its SQLite coverage without blurring that line.
For maintainers, releasing SwiftQL documents exact-tag validation, artifact provenance, publication, verification, and recovery.
MIT license. See LICENSE.md.
@SQLQuery, or a whole
container of them with @SQLQueries, and call it like any other function.
Pass a parameter to like, regexp, or Limit. Observe a declaration
through its prepared form, or call it on a withTransaction scope. In a
SwiftPM target, a build-tool plugin finds every declaration and generates a
registry. makeManifest builds the build-validation manifest from that
registry. No hand-written query list is necessary. A second build-tool
plugin prepares every declared query against a schema snapshot at build
time. Both a SwiftPM target and an Xcode project target can run that
validation. See COMPATIBILITY.md for the build systems
it runs under.for try await over stream() and
streamOne(), the canonical live-query API. GRDB-backed Combine publishers
track the same database region a query reads, and XLObservableQuery or
XLQueryObserver adopt either one from SwiftUI. A declared query has a
prepared form, so a view observes it without a second copy of the
statement.-> and ->> selection operators and
jsonExtract, build documents with jsonArray and jsonObject, change them
with the insert, replace, set, remove, and patch functions, collect rows with
jsonGroupArray and jsonGroupObject, and address any of it with
XLJSONPath instead of a path string. An insert, replace, set, or remove on
a NOT NULL document gives a non-optional result. The call then assigns
back to the column without coalesce. A patch keeps its optional result.
A Swift Bool writes as a JSON boolean. The JSONB variants read and write
SQLite's binary representation. validJSONOrJSONBOrNull() checks a value
that can hold either form, on SQLite 3.45.0 and later.swiftql-index-advisor turns the verified recommendations into a checked-in
SQL file. It is advice throughout: nothing it reports can fail a build.like, glob, and regexp. REGEXP needs no setup: SQLite ships
no regexp function, so SwiftQL supplies one backed by Swift Regex,
keeps compiled patterns per connection rather than compiling once per row,
refuses an oversized pattern or subject rather than truncating it,
and matches a RegexBuilder pattern through XLRegexPattern.