{"id":17202317,"url":"https://github.com/s4cha/squeal","last_synced_at":"2026-03-07T15:04:52.646Z","repository":{"id":230084643,"uuid":"778402708","full_name":"s4cha/SQueaL","owner":"s4cha","description":"Type Safe SQL for Swift","archived":false,"fork":false,"pushed_at":"2025-01-22T19:38:15.000Z","size":821,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-27T10:58:09.080Z","etag":null,"topics":["orm","postgres","postgressql","sql","sqlite","swift","type","type-safe"],"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/s4cha.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,"dei":null}},"created_at":"2024-03-27T16:50:17.000Z","updated_at":"2025-03-22T06:24:19.000Z","dependencies_parsed_at":"2024-04-12T09:26:49.838Z","dependency_job_id":"1b267409-0a91-4628-9181-8c529a0dae14","html_url":"https://github.com/s4cha/SQueaL","commit_stats":null,"previous_names":["s4cha/squeal"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/s4cha/SQueaL","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s4cha%2FSQueaL","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s4cha%2FSQueaL/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s4cha%2FSQueaL/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s4cha%2FSQueaL/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/s4cha","download_url":"https://codeload.github.com/s4cha/SQueaL/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s4cha%2FSQueaL/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279014326,"owners_count":26085492,"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","status":"online","status_checked_at":"2025-10-13T02:00:06.723Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["orm","postgres","postgressql","sql","sqlite","swift","type","type-safe"],"created_at":"2024-10-15T02:14:20.919Z","updated_at":"2026-03-07T15:04:52.634Z","avatar_url":"https://github.com/s4cha.png","language":"Swift","readme":"# SQueaL\nType Safe SQL for Swift\n\n![SQueaL demo](demo.gif)\n\n*Squeal is the sound you make when you realize there's a typo in your SQL statement.*\n\n## Demo time 🍿\nRaw SQL\n```sql\nlet query = \"\"\"\n    SELECT id, name, email \n    FROM users\n    WHERE id = 1\n    AND name = 'jack' \n    LIMIT 1\n\"\"\"\n```\nUsing Squeal\n```swift\nlet query = SQL\n    .SELECT(\\.id, \\.name, \\.email)\n    .FROM(users)\n    .WHERE(\\.id == 1)\n    .AND(\\.name == \"jack\")\n    .LIMIT(1)\n```\nhint: `users` is a `Table` object that represents the `users` table in the database schema.\n\n\n## Benefits: \n - [X] Type safety\n - [X] Autocompletion\n - [X] Valid SQL Syntax enforcement\n - [X] Safer refactorings\n - [X] Generates a SQL string so you can escape the tool whenever needed.\n\n\n## Disclaimer\n - This is early, use at your own risk\n - Only supports Postgres syntax at the moment\n\n## Why\n- ORMS have a lot of issues (see below), mainly:\n    - Need to learn an other pseudo language \n    - Complex \n    - Hides what's really going on under the hood\n    - Performace issues\n  \n\n- The alternative, writing Pure SQL comes with major drawbacks:\n  - No more type safety\n  - No IDE support\n  - Risky refactorings\n  - No syntax enforcement.\n\n\n**What if we could have the best of both worlds?**\n\n## How\n- By leveraging the **incredible Swift 6 type system** we can create a strongly typed DSL that **match SQL syntax almost one to one**.\n- By having a strongly typed table reference we can **enforce correctness** and **simplify refactorings**.\n- By using protocols we can enforce **correct SQL syntax** and have **autocompletion** only suggest valid SQL clauses.\n\n## What: Example Queries\n\nFirst define your Type safe schema like so:\n```swift\n@Table(schema: \"users\") // Name of your database table\nstruct Users {\n    let uuid: UUID // Name of your database columns with their type.\n    let id: Int\n    let name: String\n    let age: Int\n}\n```\nThe macro will generate the associated `UsersTable` struct.\n\n\n### SELECT FROM\n```swift\nlet users = UsersTable()\n```\n\n```swift\nlet query = SQL\n  .SELECT(*)\n  .FROM(users)\n  .LIMIT(10)\n```\n\n```swift\n let query = SQL\n    .SELECT(COUNT(*))\n    .FROM(users)\n```\n\n```swift\n let query = SQL\n    .SELECT(COUNT(*))\n    .FROM(users)\n```\n\n```swift\nlet query = TSQL\n  .SELECT(\n    (\\.uuid, AS: \"unique_id\"),\n    (\\.id, AS: \"user_id\"),\n    (\\.name, AS: \"username\"))\n  .FROM(users)\n```\n\n### WHERE / AND / OR\n\n```swift\nlet query = SQL\n  .SELECT(\\.id)\n  .FROM(users)\n  .WHERE(\\.id \u003c 65)\n  .AND(\\.name == \"Jack\")\n  .OR(\\.name == \"john\")\n```\n\n### INSERT\n```swift\nlet query = SQL\n  .INSERT(INTO: studies,\n    columns: \\.name, \\.starting_cash, \\.partitioning, \\.prolific_study_id, \\.completion_link, \\.shows_results, \\.allows_fractional_investing,\n    VALUES: study.name, study.startingCash, study.partitioning, study.prolificStudyId, study.completionLink, study.showsResults, study.allowsFractionalInvesting)\n  .RETURNING(\\.id)\n```\n\n### UPDATE\n```swift\nlet query = SQL\n  .UPDATE(stocks,\n    SET:\n      (\\.volatility, stock.volatility),\n      (\\.expectedReturn, stock.expectedReturn),\n      (\\.currentPrice, stock.currentPrice)\n    )\n  .WHERE(\\.id == stock.id!)\n```\n\n### DELETE\n```swift\nlet query = SQL\n  .DELETE_FROM(users)\n   .WHERE(\\.id == 243)\n```\n\n## ORM issues great reads\n[What ORMs have taught me: just learn SQL](https://wozniak.ca/blog/2014/08/03/1/index.html)  \n[Don't use an ORM - Prime reacts](https://youtu.be/bpGvVI7NM_k?feature=shared)  \n[The Vietnam of Computer Science](https://web.archive.org/web/20220823105749/http://blogs.tedneward.com/post/the-vietnam-of-computer-science/)  \n[Object-Relational Mapping is the Vietnam of Computer Science](https://blog.codinghorror.com/object-relational-mapping-is-the-vietnam-of-computer-science/)  \n[ORM is an anti-pattern](https://seldo.com/posts/orm_is_an_antipattern)  \n[In defence of SQL](https://seldo.com/posts/in_defence_of_sql)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fs4cha%2Fsqueal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fs4cha%2Fsqueal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fs4cha%2Fsqueal/lists"}