{"id":20668084,"url":"https://github.com/daelvn/grasp","last_synced_at":"2025-10-28T05:42:03.242Z","repository":{"id":94198989,"uuid":"260331998","full_name":"daelvn/grasp","owner":"daelvn","description":"Wrapper around the lsqlite3 API with a functional approach","archived":false,"fork":false,"pushed_at":"2021-01-27T09:16:04.000Z","size":48,"stargazers_count":10,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-18T07:47:59.255Z","etag":null,"topics":["lua","moonscript","sqlite3"],"latest_commit_sha":null,"homepage":"","language":"MoonScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/daelvn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","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,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-04-30T22:31:20.000Z","updated_at":"2022-04-10T12:39:02.000Z","dependencies_parsed_at":"2023-04-26T15:16:03.595Z","dependency_job_id":null,"html_url":"https://github.com/daelvn/grasp","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/daelvn/grasp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daelvn%2Fgrasp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daelvn%2Fgrasp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daelvn%2Fgrasp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daelvn%2Fgrasp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/daelvn","download_url":"https://codeload.github.com/daelvn/grasp/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daelvn%2Fgrasp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281391764,"owners_count":26492903,"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-28T02:00:06.022Z","response_time":60,"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":["lua","moonscript","sqlite3"],"created_at":"2024-11-16T19:47:35.047Z","updated_at":"2025-10-28T05:42:03.237Z","avatar_url":"https://github.com/daelvn.png","language":"MoonScript","readme":"# Grasp\n\nGrasp is a wrapper around the [LuaSQLite3](https://lua.sqlite.org/index.cgi/index) binding for sqlite3. Designed to be fairly similar to [Clutch](https://github.com/akojo/clutch), while having a more functional approach.\n\nOk, I admit it, the only reason I made this is because Clutch wouldn't run on 5.1, ok?! Really, go use that instead, it's a genius library. I guess you can use this as a last resort or if you really, really hate yourself.\n\nAs such, this README will be a close-looking copy of the clutch one, but in MoonScript, and with my syntax.\n\n## Table of contents\n\n- [Grasp](#grasp)\n  - [Table of contents](#table-of-contents)\n  - [Opening a database](#opening-a-database)\n  - [Querying the database](#querying-the-database)\n    - [`squery`](#squery)\n  - [Binding parameters](#binding-parameters)\n    - [Named parameters](#named-parameters)\n    - [Anonymous/positional parameters](#anonymouspositional-parameters)\n  - [Updating the database](#updating-the-database)\n  - [Preparing statements](#preparing-statements)\n    - [Resets](#resets)\n  - [Transactions](#transactions)\n  - [Error handling](#error-handling)\n  - [Query building](#query-building)\n    - [Supported statements](#supported-statements)\n      - [explain](#explain)\n      - [Transactions and Savepoints](#transactions-and-savepoints)\n      - [create](#create)\n      - [insert and replace](#insert-and-replace)\n      - [select](#select)\n      - [delete](#delete)\n      - [drop](#drop)\n      - [update](#update)\n  - [Installing](#installing)\n  - [Tests](#tests)\n  - [License](#license)\n\n## Opening a database\n\n```moon\nimport Database from require \"grasp\"\ndb = Database \"my.db\"\n```\n\nIt optionally takes a table of attributes, defined like this:\n\n```\nreadonly / ro :: boolean\nreadwrite / rw :: boolean\ncreate :: boolean\nuri :: boolean\nmemory :: boolean\nmutex :: boolean\ncache :: string [shared|private]\nvolatile :: boolean\n```\n\nAll of them, except for `volatile`, correspond to a `SQLITE_OPEN_*` open [flag](https://www.sqlite.org/c3ref/open.html). I think it's pretty easy to figure it out. `volatile` will remove the file (if it is not `:memory:`) on close. The default attributes table is `create=true, rw=true`.\n\nAs with Clutch, the filename `:memory:` will open an in-memory volatile database. This doesn't have anything to do with the `volatile` attribute. An empty filename will create a temporal on-disk database with `volatile` set to true. It uses `os.tmpname` to get a temporal filename, and you can get it with `db.filename`.\n\n## Querying the database\n\nYou use the `query`, `query1` and `iquery` functions to make a query to the database. They're all iterators, but they iterate in different ways. Here are the signatures:\n\n```\nquery :: Database -\u003e (string, table) -\u003e (_ -\u003e {string:_})\nquery1 :: Database -\u003e (string, table) -\u003e (_ -\u003e [_])\niquery :: Database -\u003e (string, table) -\u003e (_ -\u003e ...)\n```\n\nThis might mean nothing to you, so let's see a practical example:\n\n```moon\nimport query, query1, iquery from require \"grasp\"\nfor row in (query db) \"select * from t\"\n  print row.col1, row.col2\n\nfor row in (query1 db) \"select * from t\"\n  print row[1], row[2]\n\nfor col1, col2 in (iquery db) \"select * from t\"\n  print col1, col2\n```\n\nThese are all equivalent, so it's all up to preference. There's `queryone` and `queryall` shorthands too, but they might behave a bit differently.\n\n- `queryone db sql`: returns the first row out of all results.\n- `queryall db sql`: returns a table of all rows returned.\n\n### `squery`\n\nAs of Grasp 1.3, there is a new function `squery` which works similarly to `queryall`, but if no results were returned it will:\n\n- Return `{affected_rows: n}` if there's any affected rows.\n- Return `true` otherwise.\n\nThis is pretty much made to mimic `query` in [pgmoon](https://github.com/leafo/pgmoon), since I might be using Grasp to write a Lapis backend for SQLite.\n\n## Binding parameters\n\n### Named parameters\n\nThe `query*` functions take an optional table to provide parameters. It uses prepare/bind functions internally so you can use `:`, `$` and `@` just as you would with Clutch and sqlite3.\n\n```moon\n(query db) \"select * from t where value = :value\", value: \"example\"\n```\n\n### Anonymous/positional parameters\n\nJust sqlite3's `?` and `?n`.\n\n```moon\n(query db) \"select * from t where value = ?\", {\"example\"}\n(query db) \"select * from t where value = ?1 eulav = ?2\", {\"example\", \"elpmaxe\"}\n```\n\n## Updating the database\n\n`update(db)(sql)` is your function to pipe straight SQL to your database. It's signature is `update :: Database -\u003e (string, table) -\u003e (boolean, number)`, where the first string is the query, and it returns both a boolean (`sqlite.DONE` or not) and the result code.\n\nIt also prepares the statement behind the scenes, so you can pass a table to bind arguments.\n\n## Preparing statements\n\nThis library also lets you prepare statements manually via `Statement`, which has the signature `Statement :: Database -\u003e string -\u003e Statement`. You can know the SQL you passed to it with `stmt.sql`.\n\n```moon\nimport Statement from require \"grasp\"\n\nstmt = Statement \"select * from t where value = :value\"\n```\n\nYou can then call `query*` functions with an extra bindtable argument.\n\n```moon\n(query stmt) value: \"example\"\n```\n\nOf course, you can also bind them manually, with the several `bind*` functions:\n\n```\nbind :: Statement -\u003e table -\u003e (boolean, number)\nbindOne :: Statement -\u003e (number|string, _) -\u003e (boolean, number)\nbindMany :: Statement -\u003e [_]\n```\n\nWhich is better explained visually like this:\n\n```moon\nimport bind, bindOne, bindMany from require \"grasp\"\n(bind stmt) value: \"example\"\n(bindOne stmt) \"value\", \"example\"\n(bindMany stmt) 1, 2, 3, 4, 5\n```\n\nAll about preference!\n\n### Resets\n\nSimilarly to Clutch, calling `execute` and `query*` functions on a statement will cause it to be reset.\n\n## Transactions\n\nThe `Transaction` method takes a function which will run inside a transaction, built using savepoints. A very graphical example:\n\n```moon\nimport Transaction from require \"grasp\"\n(Transaction db) =\u003e\n  (update @) \"some sql statement\"\n  (update @) \"another sql statement\"\n```\n\n## Error handling\n\nUnlike Clutch, this will not error on user-called functions, but instead return a boolean status and the error code.\n\n## Query building\n\nGrasp 1.2 implements a query builder for SQL. It ain't much, but it's honest work. You use it by importing the `sql` function in `grasp.query`. It takes a function, and a lot of magic happens there, just see for yourself!\n\n```moon\nsql -\u003e\n  create \"tbl\", -\u003e columns:\n    ee: \"TEXT NOT NULL\"\n```\n\n### Supported statements\n\n#### explain\n\nTakes any SQL builder, and precedes it with `EXPLAIN` or `EXPLAIN QUERY PLAN`.\n\n```moon\nsql -\u003e explain queryplan, -\u003e ...\nsql -\u003e explain -\u003e ...\n```\n\n#### Transactions and Savepoints\n\n```moon\nsql -\u003e\n  -- begin transaction\n  begin!\n  begin deferred\n  begin immediate\n  begin exclusive\n  -- rollback transaction\n  rollback!\n  -- end transaction\n  commit!\n  End!\n\nsql -\u003e\n  -- savepoints\n  savepoint \"name\"\n  release   \"name\"\n  rollback  \"name\n```\n\n#### create\n\nWell, more like `CREATE TABLE`:\n\n```moon\nsql -\u003e create \"tablename\", -\u003e\n  temporary!     -- TEMPORARY\n  always!        -- removes IF NOT EXISTS\n  without_rowid! -- adds WITHOUT ROWID\n  columns:\n    whatever: \"TEXT NOT NULL\" -- and such\n```\n\n#### insert and replace\n\n`replace` works pretty much the same, but emitting `REPLACE` instead\n\n```moon\nsql -\u003e\n  insert -\u003e\n    replace!   -- OR REPLACE\n    rollback!  -- OR ROLLBACK\n    abort!     -- OR ABORT\n    fail!      -- OR FAIL\n    ignore!    -- OR IGNORE\n    into \"tablename\"\n    alias \"whatever\" -- AS whatever\n    values:\n      column: value\n  -- alternatively\n  insert into \"tablename\", -\u003e values:\n    column: value\n```\n\n#### select\n\n```moon\nsql -\u003e\n  select \"*\", -\u003e\n    distinct!\n    all!\n    From \"tablename\"\n    where \"expr\"\n    where a: v     -- WHERE a = v\n    order: \"expr\"  -- ORDER BY expr\n    limit: \"expr\"  -- LIMIT expr\n    offset: \"expr\" -- OFFSET expr\n  -- alternatively\n  select \"*\", From \"tablename\", -\u003e\n```\n\n#### delete\n\n```moon\nsql -\u003e\n  delete -\u003e\n    From \"tablename\"\n    where \"expr\"\n    where a: v     -- WHERE a = v\n  -- alternatively\n  delete From \"tablename\", -\u003e where a: v\n```\n\n#### drop\n\n```moon\nsql -\u003e\n  drop \"tablename\"\n  drop \"tablename\", -\u003e ifexists!\n```\n\n#### update\n\n```moon\nsql -\u003e\n  update \"tablename\", -\u003e\n    where id: 1\n    values:\n      login: \"user\"\n      email: \"ex@example.com\"\n```\n\n## Installing\n\nYou can get Grasp on LuaRocks:\n\n```sh\n$ luarocks install grasp\n```\n\nIf building from source:\n```sh\n$ moonc grasp\n$ luarocks make\n```\n\n## Tests\n\nYou can run the tests with `busted` (you will need MoonScript).\n\n```\n$ luarocks install busted\n$ luarocks install moonscript\n$ busted\n```\n\n## License\n\n`lsqlite3` uses the MIT license. Grasp is released onto the public domain.\n\n```\nThis is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to \u003chttp://unlicense.org/\u003e\n```","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaelvn%2Fgrasp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdaelvn%2Fgrasp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaelvn%2Fgrasp/lists"}