{"id":13505010,"url":"https://github.com/SwifQL/SwifQL","last_synced_at":"2025-03-29T22:31:18.828Z","repository":{"id":47542325,"uuid":"161410190","full_name":"SwifQL/SwifQL","owner":"SwifQL","description":"💎 A Swift DSL for type-safe, extensible, and transformable SQL queries.","archived":false,"fork":false,"pushed_at":"2023-09-11T02:12:55.000Z","size":487,"stargazers_count":292,"open_issues_count":6,"forks_count":20,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-05-22T23:21:55.027Z","etag":null,"topics":["dsl","mysql","postgresql","sql","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SwifQL.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-12-12T00:18:20.000Z","updated_at":"2024-05-22T21:47:21.000Z","dependencies_parsed_at":"2024-01-16T10:51:41.363Z","dependency_job_id":null,"html_url":"https://github.com/SwifQL/SwifQL","commit_stats":{"total_commits":258,"total_committers":9,"mean_commits":"28.666666666666668","dds":0.06201550387596899,"last_synced_commit":"e398112f94e6d85a971fc5d6af3da3fc06bd047f"},"previous_names":[],"tags_count":125,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SwifQL%2FSwifQL","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SwifQL%2FSwifQL/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SwifQL%2FSwifQL/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SwifQL%2FSwifQL/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SwifQL","download_url":"https://codeload.github.com/SwifQL/SwifQL/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245352571,"owners_count":20601183,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dsl","mysql","postgresql","sql","swift"],"created_at":"2024-08-01T00:00:56.761Z","updated_at":"2025-03-29T22:31:18.798Z","avatar_url":"https://github.com/SwifQL.png","language":"Swift","funding_links":[],"categories":["Packages"],"sub_categories":["Database"],"readme":"[![Mihael Isaev](https://user-images.githubusercontent.com/1272610/53677263-7ecbfe00-3cc6-11e9-9049-2d2b9a2d7947.png)](http://mihaelisaev.com)\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"LICENSE\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/license-MIT-brightgreen.svg\" alt=\"MIT License\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://swift.org\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/swift-5.2-brightgreen.svg\" alt=\"Swift 5.2\"\u003e\n    \u003c/a\u003e\n    \u003cimg src=\"https://img.shields.io/github/workflow/status/MihaelIsaev/SwifQL/test\" alt=\"Github Actions\"\u003e\n    \u003ca href=\"https://discord.gg/q5wCPYv\"\u003e\n        \u003cimg src=\"https://img.shields.io/discord/612561840765141005\" alt=\"Swift.Stream\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://swiftpackageindex.com/SwifQL/SwifQL\"\u003e\n        \u003cimg src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FSwifQL%2FSwifQL%2Fbadge%3Ftype%3Dswift-versions\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://swiftpackageindex.com/SwifQL/SwifQL\"\u003e\n        \u003cimg src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FSwifQL%2FSwifQL%2Fbadge%3Ftype%3Dplatforms\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\u003cbr\u003e\n\nThis lib can be used either stand alone, or with frameworks like Vapor, Kitura, Perfect and others\n\nWe recommend to use it with our [Bridges](https://github.com/SwifQL/Bridges) lib which is built on top of SwifQL and support all its flexibility\n\nIt supports PostgreSQL and MySQL. And it's not so hard to add other dialects 🙂 just check [SwifQL/Dialect](https://github.com/SwifQL/SwifQL/tree/master/Sources/SwifQL/Dialect) folder\n\nPlease feel free to ask any questions in issues, and also you could find me in the [Discord app](https://discordapp.com) as `@iMike#3049` or even better just join **#swifql** channel on [Vapor's Discord server](https://discord.gg/vapor) 🙂\n\n\u003e NOTE:\n\u003e\n\u003e If you haven't found some functions available out-of-the-box\n\u003e then please check files like `SwifQLable+Select` and others in `Sources/SwifQL` folder\n\u003e to ensure how easy it is to extend SwifQL to support anything you need 🚀\n\u003e\n\u003e And feel free to send pull requests with your awesome new extensions ❤️\n\n### Support SwifQL development by giving a ⭐️\n\n## Installation\n### With Vapor 4 + [Bridges](https://github.com/SwifQL/Bridges) + PostgreSQL\n```swift\n.package(url: \"https://github.com/vapor/vapor.git\", from:\"4.0.0-rc\"),\n.package(url: \"https://github.com/SwifQL/VaporBridges.git\", from:\"1.0.0-rc\"),\n.package(url: \"https://github.com/SwifQL/PostgresBridge.git\", from:\"1.0.0-rc\"),\n.target(name: \"App\", dependencies: [\n    .product(name: \"Vapor\", package: \"vapor\"),\n    .product(name: \"VaporBridges\", package: \"VaporBridges\"),\n    .product(name: \"PostgresBridge\", package: \"PostgresBridge\")\n]),\n```\n\n### With Vapor 4 + [Bridges](https://github.com/SwifQL/Bridges) + MySQL\n```swift\n.package(url: \"https://github.com/vapor/vapor.git\", from:\"4.0.0-rc\"),\n.package(url: \"https://github.com/SwifQL/VaporBridges.git\", from:\"1.0.0-rc\"),\n.package(url: \"https://github.com/SwifQL/MySQLBridge.git\", from:\"1.0.0-rc\"),\n.target(name: \"App\", dependencies: [\n    .product(name: \"Vapor\", package: \"vapor\"),\n    .product(name: \"VaporBridges\", package: \"VaporBridges\"),\n    .product(name: \"MySQLBridge\", package: \"MySQLBridge\")\n]),\n```\n\n### Pure\n```swift\n.package(url: \"https://github.com/MihaelIsaev/SwifQL.git\", from:\"2.0.0-beta\"),\n.target(name: \"App\", dependencies: [\n    .product(name: \"SwifQL\", package: \"SwifQL\"),\n]),\n```\n\n### Pure on NIO2\n```swift\n.package(url: \"https://github.com/MihaelIsaev/SwifQL.git\", from:\"2.0.0-beta\"),\n.package(url: \"https://github.com/MihaelIsaev/SwifQLNIO.git\", from:\"2.0.0\"),\n.target(name: \"App\", dependencies: [\n    .product(name: \"SwifQL\", package: \"SwifQL\"),\n    .product(name: \"SwifQLNIO\", package: \"SwifQLNIO\"),\n]),\n```\n\n#### Pure on NIO1 (deprecated)\n```swift\n.package(url: \"https://github.com/MihaelIsaev/SwifQL.git\", from:\"1.0.0\"),\n.package(url: \"https://github.com/MihaelIsaev/SwifQLNIO.git\", from:\"1.0.0\"),\n.target(name: \"App\", dependencies: [\"SwifQL\", \"SwifQLNIO\"]),\n```\n\n#### With Vapor 3 + Fluent (deprecated)\n```swift\n.package(url: \"https://github.com/MihaelIsaev/SwifQL.git\", from:\"1.0.0\"),\n.package(url: \"https://github.com/MihaelIsaev/SwifQLVapor.git\", from:\"1.0.0\"),\n.target(name: \"App\", dependencies: [\"Vapor\", \"SwifQL\", \"SwifQLVapor\"]),\n```\n\n## Philosophy\n\nThis lib gives an ability to build absolutely any SQL query from simplest to monster complex.\n\nExample of simple query\n```sql\nSELECT * FROM \"User\" WHERE \"email\" = 'john.smith@gmail.com'\n```\nbuild it with pure SwifQL this way\n```swift\nSwifQL.select(User.table.*).from(User.table).where(\\User.email == \"john.smith@gmail.com\")\n```\nor with SwifQL + [Bridges](https://github.com/SwifQL/Bridges)\n```swift\nSwifQL.select(User.table.*).from(User.table).where(\\User.$email == \"john.smith@gmail.com\")\n// or shorter\nUser.select.where(\\User.$email == \"john.smith@gmail.com\")\n```\n\n## Usage\n\n### Preparation\n\n\u003e 💡 TIP: It is simpler and more powerful with [Bridges](https://github.com/SwifQL/Bridges)\n\nOf course you have to import the lib\n```swift\nimport SwifQL\n```\n\n#### For v1 Your table models should be conformed to `Tableable` protocol\n```swift\nextension MyTable: Tableable {}\n```\n\n#### For v2 Your table models should be conformed to `Table` protocol\n```swift\nextension MyTable: Table {}\n```\n\n### How to build query\n\n\u003e Instead of writing `Model.self` you should write `Model.table`, cause without Vapor you should conform your models to `Table`, and with Vapor its `Model`s are already conforms to `Table`.\n\n```swift\nlet query = SwifQL.select(\\User.email, \\User.name, \\User.role)\n                  .from(User.table)\n                  .orderBy(.asc(\\User.name))\n                  .limit(10)\n```\nor with SwifQL + [Bridges](https://github.com/SwifQL/Bridges)\n```swift\nlet query = SwifQL.select(\\User.$email, \\User.$name, \\User.$role)\n                  .from(User.table)\n                  .orderBy(.asc(\\User.$name))\n                  .limit(10)\n// or shorter\nUser.select(\\.$email, \\.$name, \\.$role).orderBy(.asc(\\User.$name)).limit(10)\n```\n\n### How to print raw query\n\nThere are two options\n\n##### 1. Get just plain query\n```swift\nlet rawSQLString = query.prepare(.psql).plain\n```\n\nor when using SwifQLSelectBuilder() - see below\n\n```swift\nlet rawSQLBuilderString = query.build().prepare(.psql).plain\n```\n\n##### 2. Get object splitted into: formatted raw SQL string with $ symbols, and separated array with values\n```swift\nlet splittedQuery = query.prepare(.psql).splitted\nlet formattedSQLQuery = splittedQuery.query // formatted raw SQL string with $ symbols instead of values\nlet values = splittedQuery.values // an array of [Encodable] values\n```\n\nThen just put it into your database driver somehow 🙂 or use [Bridges](https://github.com/SwifQL/Bridges)\n\n### How to execute query?\n\nSwifQL is only about building queries. For execution you have to use your favourite database driver.\n\nBelow you can see an example for SwifQL + Vapor4 + [Bridges](https://github.com/SwifQL/Bridges) + PostgreSQL\n\n\u003e 💡 You can get connection on both `Application` and `Request` objects.\n\nExample for `Application` object e.g. for `configure.swift` file\n```swift\n// Called before your application initializes.\npublic func configure(_ app: Application) throws {\n    app.postgres.connection(to: .myDb1) { conn in\n        SwifQL.select(User.table.*).from(User.table).execute(on: conn).all(decoding: User.self).flatMap { rows in\n            print(\"yaaay it works and returned \\(rows.count) rows!\")\n        }\n    }.whenComplete {\n        switch $0 {\n        case .success: print(\"query was successful\")\n        case .failure(let error): print(\"query failed: \\(error)\")\n        }\n    }\n}\n```\nExample for `Request` object\n```swift\nfunc routes(_ app: Application) throws {\n    app.get(\"users\") { req -\u003e EventLoopFuture\u003c[User]\u003e in\n        req.postgres.connection(to: .myDb1) { conn in\n            SwifQL.select(User.table.*).from(User.table).execute(on: conn).all(decoding: User.self)\n        }\n    }\n}\n```\n\n\u003e 💡 In examples above we use `.all(decoding: User.self)` for decoding results, but we also can use `.first(decoding: User.self).unwrap(or: Abort(.notFound))` to get only first row and unwrap it since it may be nil.\n\n## Insert Into\n\n### Single record\nSQL example\n```sql\nINSERT INTO \"User\" (\"email\", \"name\") VALUES ('john@gmail.com', 'John Doe'), ('sam@gmail.com', 'Samuel Jackson')\n```\nSwifQL representation\n```swift\nSwifQL.insertInto(User.table, fields: \\User.email, \\User.name).values(\"john@gmail.com\", \"John Doe\")\n```\nor with SwifQL + [Bridges](https://github.com/SwifQL/Bridges)\n```swift\nUser(email: \"john@gmail.com\", name: \"John Doe\").insert(on: conn)\n```\n\n### Batch\nSQL example\n```sql\nINSERT INTO \"User\" (\"email\", \"name\") VALUES ('john@gmail.com', 'John Doe'), ('sam@gmail.com', 'Samuel Jackson')\n```\nSwifQL representation\n```swift\nSwifQL.insertInto(User.table, fields: \\User.email, \\User.name).values(array: [\"john@gmail.com\", \"John Doe\"], [\"sam@gmail.com\", \"Samuel Jackson\"])\n```\nor with SwifQL + [Bridges](https://github.com/SwifQL/Bridges)\n```swift\nlet user1 = User(email: \"hello@gmail.com\", name: \"John\")\nlet user2 = User(email: \"byebye@gmail.com\", name: \"Amily\")\nlet user3 = User(email: \"trololo@gmail.com\", name: \"Trololo\")\n[user1, user2, user3].batchInsert(on: conn)\n```\n## Update\n\n### General Update\nSQL example\n```sql\nUPDATE \"User\" SET \"name\" = 'Mike'\n```\nSwifQL representation\n```swift\nSwifQL.update(User.table).set[items: User.$name == \"Mike\"]\n```\n\n### In Schema Update\nSQL example\n```sql\nUPDATE \"VIP\".\"User\" SET \"name\" = 'Mike'\n```\nSwifQL representation\n```swift\nlet vip = User.inSchema(\"VIP\")\nSwifQL.update(vip.table).set[items: vip.$name == \"Mike\"]\n```\n\n## Builders\n\nFor now there are only one implemented builder\n\n### Select builder\n\n`SwifQLSelectBuilder` - by using it you could easily build a select query but in multiple lines without carying about ordering.\n\n```swift\nlet builder = SwifQLSelectBuilder()\nbuilder.where(\\User.id == 1)\nbuilder.from(User.table)\nbuilder.limit(1)\nbuilder.select(User.table.*)\nlet query = builder.build()\nreturn query.execute(on: req, as: .psql)\n            .first(decoding: User.self)\n            .unwrap(or: Abort(.notFound, reason: \"User not found\"))\n```\n\nSo it will build query like: `SELECT \"User\".* FROM \"User\" WHERE \"User\".\"id\" = 1 LIMIT 1`.\n\nAs you can see you shouldn't worry about parts ordering, it will sort them the right way before building.\n\n### More builders\n\nFeel free to make your own builders and send pull request with it here!\n\nAlso more conveniences are available in [Bridges](https://github.com/SwifQL/Bridges) lib which is created on top of SwifQL and support all its flexibility\n\n## More query examples\n\n*Let's use `SwifQLSelectBuilder` for some next examples below, cause it's really convenient especially for complex queries.*\n\n1. Let's imagine that you want to query count of users.\n\n```swift\n/// Just query\nlet query = SwifQL.select(Fn.count(\\User.id) =\u003e \"count\").from(User.table)\n\n/// Execution and decoding for Vapor\nstruct CountResult: Codable {\n  let count: Int64\n}\nquery.execute(on: req, as: .psql)\n     .first(decoding: CountResult.self)\n     .unwrap(or: Abort(.notFound)) // returns Future\u003cCountResult\u003e\n```\n\nHere you can see two interesting things: `Fn.count()` and `=\u003e \"count\"`\n\n`Fn` is a collection of function builders, so just call `Fn.` and take a look at the functions list on autocompletion.\n\n`=\u003e` uses for two things: 1) to write alias through `as` 2) to cast values to some other types\n\n`// TBD: Expand list of examples`\n\n## Aliasing\nUse `=\u003e` operator for that, e.g.:\n\nIf you want to write `SELECT \"User\".\"email\" as eml` then do it like this `SwifQL.select(\\User.email =\u003e \"eml\")`\n\nOr if to speak about table name aliasing:\n\nIf you want to reach `\"User\" as u` then do it like this `User.as(\"u\")`\n\nAnd then keypaths will work like\n\n```swift\nlet u = User.as(\"u\")\nlet emailKeypath = u.email\n```\n\n## Type casting\nUse `=\u003e` operator for that, e.g.:\n\nIf you want to write `SELECT \"User\".\"email\"::text` then do it like this `SwifQL.select(\\User.email =\u003e .text)`\n\n## Predicates\n| Infix operator  | SQL equivalent |\n| ------- | -------------- |\n| \u003e | \u003e |\n| \u003e= | \u003e= |\n| \u003c | \u003c |\n| \u003c= | \u003c= |\n| == | = |\n| == nil | IS NULL |\n| != | != |\n| != nil | IS NOT NULL |\n| \u0026\u0026 | AND |\n\nAnd also\n\n`||` is for `OR`\n\n`||\u003e` is for `@\u003e`\n\n`\u003c||` is for `\u003c@`\n\n\u003e Please feel free to add more predicates in `Predicates.swift` 😉\n\n## Operators\nPlease feel free to take a look at `Fn.Operator` enum in `Functions.swift`\n\n## Functions\nPlease feel free to take a look at the list of function in `Functions.swift`\n\n## Postgres JSON Object\nYou could build JSON objects by using `PostgresJsonObject`\n\nSQL example\n```sql\njsonb_build_object('id', \"User\".\"id\", 'email', \"User\".\"email\")\n```\nSwifQL representation\n```swift\nPgJsonObject().field(key: \"id\", value: \\User.id).field(key: \"email\", value: \\User.email)\n```\n\n## Postgres Array\nYou could build PostgreSQL arrays by using `PostgresArray`\n\nSQL example\n```sql\n$$[]$$\nARRAY[]\nARRAY[1,2,3]\n$$[]$$::uuid[]\nARRAY[]::text[]\n```\nSwifQL representation\n```swift\nPgArray(emptyMode: .dollar)\nPgArray()\nPgArray(1, 2, 3)\nPgArray(emptyMode: .dollar) =\u003e .uuidArray\nPgArray() =\u003e .textArray\n```\n\nPostgress range query examples\n```swift\n// var ingredients: [IngredientsEnum] \nSwifQL.select(FoodMenu.table.*).WHERE( \\FoodMenu.$ingredients ||\u003e [.tomato] )\n\n// var ingredients: [String]\nSwifQL.select(FoodMenu.table.*).WHERE( \\FoodMenu.$ingredients ||\u003e PgArray([\"tomato\"]) )\n\n// var vendors: [UUID]\nSwifQL.select(FoodMenu.table.*).WHERE( \\FoodMenu.$vendors ||\u003e PgArray([vendorUuid]) )\n```\n\n## Nesting array of objects inside of query result\nConsider such response object you want to achieve:\n\n```swift\nstruct Book {\n  let title: String\n  let authors: [Author]\n}\n\nstruct Author {\n  let name: String\n}\n```\n\nyou have to build it with use of subquery to dump Authors in JSON array and then attach them to result query. This will allow you to get all `Books` with their respective `Authors` \n\nThis example uses Pivot table `BookAuthor` to join `Books` with their `Authors`\n\n```swift\n    let authors = SwifQL.select(Fn.coalesce(Fn.array_agg(Fn.to_jsonb(Author.table)), PgArray() =\u003e .jsonbArray))\n\n    let query = SwifQLSelectBuilder()\n    query.select(Book.table.*)\n\n    query.from(Book.table)\n\n    query.join(.left, BookAuthor.table, on: \\Book.$id == \\BookAuthor.$bookID)\n    query.join(.left, Author.table, on: \\Author.$id == \\BookAuthor.$authorID)\n\n    // then query.group(...) as required in your case\n```\n\n## FILTER\nSQL example\n```sql\nCOUNT(\"User\".\"id\") FILTER (WHERE \\User.isAdmin = TRUE) as \"admins\"\n```\nSwifQL representation\n```swift\nFn.count(\\User.id).filter(where: \\User.isAdmin == true) =\u003e \"admins\"\n```\n\n## CASE ... WHEN ... THEN ... END\nSQL example\n```sql\nCASE\n  WHEN \"User\".\"email\" IS NULL\n  THEN NULL\n  ELSE \"User\".\"email\"\nEND\n```\nSwifQL representation\n```swift\nCase.when(\\User.email == nil).then(nil).else(\\User.email).end\n// or as many cases as needed\nCase.when(...).then(...).when(...).then(...).when(...).then(...).else(...).end\n```\n\n## Brackets\n\nYes, we really often use round brackets in our queries, e.g. in where clauses or in subqueries.\n\nSwifQL provides you with `|` prefix and postfix operators which is representates `(` and `)`.\n\nSo it's easy to wrap some part of query into brackets, e.g.:\nSQL example\n```sql\n\"User.role\" = 'admin' OR (\"User.role\" = 'user' AND \"User\".\"age\" \u003e= 21)\n```\nSwifQL representation\n```swift\nlet where = \\User.role == .admin || |\\User.role == .user \u0026\u0026 \\User.age \u003e= 21|\n```\n\n## Keypaths\n| SQL | SwiftQL | SwiftQL + Bridges |\n| ------- | -------------- | -------------- |\n| `\"User\"` | `User.table` | `the same` |\n| `\"User\" as u` | `User.as(\"u\")` you could declare it as `let u = User.as(\"u\")` | `the same` |\n| `\"User\".*` | `User.table.*` | `the same` |\n| `u.*` | `u.*` | `the same` |\n| `\"User\".\"email\"` | `\\User.email` | `\\User.$email` |\n| `u.\"email\"` | `u.email` | `u.$email` |\n| `\"User\".\"jsonObject\"-\u003e\"jsonField\"` | `\\User.jsonObject.jsonField` | `only through full path for now` |\n| `\"User\".\"jsonObject\"-\u003e\"jsonField\"` | `Path.Table(\"User\").column(\"jsonObject\", \"jsonField\")` | `the same` |\n\n## Tests\n\nFor now tests coverage is maybe around 70%. If you have timе and interest please feel free to send pull requests with more tests.\n\nYou could find tests in `Tests` folder\n\n### How it works under the hood\n\n`SwifQL` object needed just to start writing query, but it's just an empty object that conforms to `SwifQLable`.\n\nYou can build your query with everything which conforms to `SwifQLable`, because `SwifQLable` is that very piece which will be used for concatenation to build a query.\n\n\u003e If you take a look at the lib's files you may realize that the most of files are just extensions to `SwifQLable`.\n\nAll available operators like `select`, `from`, `where`, and `orderBy` realized just as a function in `SwifQLable` extension and these functions always returns `SwifQLable` as a result. That's why you can write a query by calling `SwifQL.select().from().where().orderBy()` one by one. That's awesome cause it feels like writing a raw SQL, but it also gives you an ordering limitation, so if you write `SwifQL.select().where().from()` then you'll get wrong query as a result. But this limitation is resolved by using special builders, like `SwifQLSelectBuilder` (read about it later below).\n\nSo let's take a look how lib builds a simple `SELECT \"User\".* FROM \"User\" WHERE \"User\".\"email\" = 'john.smith@gmail.com'` query\n\nFirst of all we should split query into the parts. Almost every word and punctuation here is a `SwifQLable` piece.\n\n- `SELECT` is `Fn.Operator.select`\n- ` ` is `Fn.Operator.space`\n- `\"User\"` is `User.table`\n- `.*` is `postfix operator .*`\n- ` ` is `Fn.Operator.space`\n- `FROM` is `Fn.Operator.from`\n- `\"User\"` is `User.table`\n- ` ` is `Fn.Operator.space`\n- `WHERE` is `Fn.Operator.where`\n- ` ` is `Fn.Operator.space`\n- `\"User\".\"email\"` is `\\User.email` keypath\n- ` ` is `Fn.Operator.space`\n- `==` is `infix operator ==`\n- ` ` is `Fn.Operator.space`\n- `'john.smith@gmail.com'` is `SwifQLPartUnsafeValue` (it means that this value should be passed as $1 to the database)\n\nThat's crazy, but awesome, right? 😄 But it's under the hood, so no worries! 😃 I just wanted to explain, that if you need something more than already provided then you'll be able to add needed operators/functions easily just by writing little extensions.\n\n\u003e And also there is no overhead, it works pretty fast, but I'd love to hear if you know how to make it faster.\n\nThis way gives you almost absolute flexibility in building queries. More than that as lib support `SQLDialect`'s it will build this query different way for PostgreSQL and MySQL, e.g.:\n\n- PostgreSQL: `SELECT \"User\".* FROM \"User\" WHERE \"User\".\"email\" = 'john.smith@gmail.com'`\n- MySQL: `SELECT User.* FROM User WHERE User.email = 'john.smith@gmail.com'`\n\n## Contributing\n\nPlease feel free to contribute!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSwifQL%2FSwifQL","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FSwifQL%2FSwifQL","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSwifQL%2FSwifQL/lists"}