{"id":35377619,"url":"https://github.com/udoprog/sqll","last_synced_at":"2026-01-13T19:29:58.534Z","repository":{"id":136203752,"uuid":"485229270","full_name":"udoprog/sqll","owner":"udoprog","description":"Efficient interface to SQLite that doesn't get in your way","archived":false,"fork":false,"pushed_at":"2026-01-12T13:10:22.000Z","size":2788,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-12T19:39:54.961Z","etag":null,"topics":["rust","sqlite","sqlite3"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/udoprog.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-04-25T05:02:13.000Z","updated_at":"2026-01-12T13:10:41.000Z","dependencies_parsed_at":"2023-12-16T15:47:10.818Z","dependency_job_id":"6fb32a1e-df0b-43ce-b82f-af56df65893e","html_url":"https://github.com/udoprog/sqll","commit_stats":null,"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"purl":"pkg:github/udoprog/sqll","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/udoprog%2Fsqll","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/udoprog%2Fsqll/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/udoprog%2Fsqll/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/udoprog%2Fsqll/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/udoprog","download_url":"https://codeload.github.com/udoprog/sqll/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/udoprog%2Fsqll/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28397826,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["rust","sqlite","sqlite3"],"created_at":"2026-01-02T04:49:39.935Z","updated_at":"2026-01-13T19:29:58.528Z","avatar_url":"https://github.com/udoprog.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sqll\n\n[\u003cimg alt=\"github\" src=\"https://img.shields.io/badge/github-udoprog/sqll-8da0cb?style=for-the-badge\u0026logo=github\" height=\"20\"\u003e](https://github.com/udoprog/sqll)\n[\u003cimg alt=\"crates.io\" src=\"https://img.shields.io/crates/v/sqll.svg?style=for-the-badge\u0026color=fc8d62\u0026logo=rust\" height=\"20\"\u003e](https://crates.io/crates/sqll)\n[\u003cimg alt=\"docs.rs\" src=\"https://img.shields.io/badge/docs.rs-sqll-66c2a5?style=for-the-badge\u0026logoColor=white\u0026logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K\" height=\"20\"\u003e](https://docs.rs/sqll)\n[\u003cimg alt=\"build status\" src=\"https://img.shields.io/github/actions/workflow/status/udoprog/sqll/ci.yml?branch=main\u0026style=for-the-badge\" height=\"20\"\u003e](https://github.com/udoprog/sqll/actions?query=branch%3Amain)\n\nEfficient interface to [SQLite] that doesn't get in your way.\n\n\u003cbr\u003e\n\n## Usage\n\nThe two primary methods to interact with an SQLite database through this\ncrate is through [`execute`] and [`prepare`].\n\nThe [`execute`] function is used for batch statements, and allows for\nmultiple queries to be specified. [`prepare`] only allows for a single\nstatement to be specified, but in turn permits [reading rows] and [binding\nquery parameters].\n\nSpecial consideration needs to be taken about the thread safety of\nconnections. You can read more about that in the [`Connection`]\ndocumentation.\n\nYou can find simple examples of this below.\n\n\u003cbr\u003e\n\n#### Examples\n\n* [`examples/persons.rs`] - A simple table with users, a primary key,\n  inserting and querying.\n* [`examples/axum.rs`] - Create an in-memory database connection and serve\n  it using [`axum`]. This showcases how do properly handle external\n  synchronization for the best performance.\n\n\u003cbr\u003e\n\n#### Connecting and querying\n\nHere is a simple example of setting up an in-memory connection, creating a\ntable, insert and query some rows:\n\n```rust\nuse sqll::{Connection, Result};\n\nlet c = Connection::open_in_memory()?;\n\nc.execute(r#\"\n    CREATE TABLE users (name TEXT, age INTEGER);\n\n    INSERT INTO users VALUES ('Alice', 42);\n    INSERT INTO users VALUES ('Bob', 52);\n\"#)?;\n\nlet results = c.prepare(\"SELECT name, age FROM users ORDER BY age\")?\n    .iter::\u003c(String, u32)\u003e()\n    .collect::\u003cResult\u003cVec\u003c_\u003e\u003e\u003e()?;\n\nassert_eq!(results, [(\"Alice\".to_string(), 42), (\"Bob\".to_string(), 52)]);\n```\n\n\u003cbr\u003e\n\n#### The [`Row`] trait.\n\nThe [`Row`] trait can be used to conveniently read rows from a statement\nusing [`next`]. It can be conveniently implemented using the [`Row`\nderive].\n\n```rust\nuse sqll::{Connection, Row};\n\n#[derive(Row)]\nstruct Person\u003c'stmt\u003e {\n    name: \u0026'stmt str,\n    age: u32,\n}\n\nlet mut c = Connection::open_in_memory()?;\n\nc.execute(r#\"\n    CREATE TABLE users (name TEXT, age INTEGER);\n\n    INSERT INTO users VALUES ('Alice', 42);\n    INSERT INTO users VALUES ('Bob', 52);\n\"#)?;\n\nlet mut results = c.prepare(\"SELECT name, age FROM users ORDER BY age\")?;\n\nwhile let Some(person) = results.next::\u003cPerson\u003c'_\u003e\u003e()? {\n    println!(\"{} is {} years old\", person.name, person.age);\n}\n```\n\n\u003cbr\u003e\n\n#### The [`Bind`] trait.\n\nThe [`Bind`] trait can be used to conveniently [`bind`] parameters to\nprepared statements, and it can conveniently be implemented for structs\nusing the [`Bind` derive].\n\n```rust\nuse sqll::{Bind, Connection, Row};\n\n#[derive(Bind, Row, PartialEq, Debug)]\n#[sql(named)]\nstruct Person\u003c'stmt\u003e {\n    name: \u0026'stmt str,\n    age: u32,\n}\n\nlet c = Connection::open_in_memory()?;\n\nc.execute(r#\"\n   CREATE TABLE persons (name TEXT, age INTEGER);\n\"#)?;\n\nlet mut stmt = c.prepare(\"INSERT INTO persons (name, age) VALUES (:name, :age)\")?;\nstmt.execute(Person { name: \"Alice\", age: 30 })?;\nstmt.execute(Person { name: \"Bob\", age: 40 })?;\n\nlet mut query = c.prepare(\"SELECT name, age FROM persons ORDER BY age\")?;\n\nlet p = query.next::\u003cPerson\u003c'_\u003e\u003e()?;\nassert_eq!(p, Some(Person { name: \"Alice\", age: 30 }));\n\nlet p = query.next::\u003cPerson\u003c'_\u003e\u003e()?;\nassert_eq!(p, Some(Person { name: \"Bob\", age: 40 }));\n```\n\n\u003cbr\u003e\n\n#### Efficient use of prepared Statements\n\nCorrect handling of prepared statements are crucial to get good performance\nout of sqlite. They contain all the state associated with a query and are\nexpensive to construct so they should be re-used.\n\nUsing a [`Prepare::PERSISTENT`] prepared statement to perform multiple\nqueries:\n\n```rust\nuse sqll::{Connection, Prepare};\n\nlet c = Connection::open_in_memory()?;\n\nc.execute(r#\"\n    CREATE TABLE users (name TEXT, age INTEGER);\n\n    INSERT INTO users VALUES ('Alice', 42);\n    INSERT INTO users VALUES ('Bob', 52);\n\"#)?;\n\nlet mut stmt = c.prepare_with(\"SELECT * FROM users WHERE age \u003e ?\", Prepare::PERSISTENT)?;\n\nlet mut rows = Vec::new();\n\nfor age in [40, 50] {\n    stmt.bind(age)?;\n\n    while let Some(row) = stmt.next::\u003c(String, i64)\u003e()? {\n        rows.push(row);\n    }\n}\n\nlet expected = vec![\n    (String::from(\"Alice\"), 42),\n    (String::from(\"Bob\"), 52),\n    (String::from(\"Bob\"), 52),\n];\n\nassert_eq!(rows, expected);\n```\n\n\u003cbr\u003e\n\n## Features\n\n* `std` - Enable usage of the Rust standard library. Enabled by default.\n* `alloc` - Enable usage of the Rust alloc library. This is required and is\n  enabled by default. Disabling this option will currently cause a compile\n  error.\n* `derive` - Add a dependency to and re-export of the [`Row` derive]\n  macro.\n* `bundled` - Use a bundled version of sqlite. The bundle is provided by the\n  [`sqll-sys`] crate and the sqlite version used is part of the build\n  metadata of that crate[^sqll-sys].\n* `threadsafe` - Enable usage of sqlite with the threadsafe option set. We\n  assume any system level libraries have this build option enabled. If this\n  is disabled the `bundled` feature has to be enabled. If `threadsafe` is\n  disabled, `Connection` and `Statement` does not implement `Send`. But it\n  is also important to understand that if this option is not set, sqlite\n  **may not be used by multiple threads at all** even if threads have\n  distinct connections. To disable mutexes which allows for efficient one\n  connection per thread the [`OpenOptions::no_mutex`] option should be used\n  instead[^sqll-sys].\n* `strict` - Enable usage of sqlite with the strict compiler options\n  enabled[^sqll-sys].\n\n[^sqll-sys]: This is a forwarded sqll-sys option, see \u003chttps://docs.rs/sqll-sys\u003e.\n\n\u003cbr\u003e\n\n## Why do we need another sqlite interface?\n\nFor other low-level crates, it is difficult to set up and use prepared\nstatements, They are mostly implemented in a manner which requires the\ncaller to borrow the connection in use.\n\nThis library implements database objects through the v2 API which ensures\nthat the database remains alive for as long as objects associated with it\nare alive. This is implemented in the SQLite library itself.\n\nPrepared statements can be expensive to create and *should* be stored and\nre-used to achieve the best performance. This is something that crates like\n`rusqlite` implements, but can easily be done manually, with no overhead, by\nsimply storing the [`Statement`] object directly behind a mutex. Statements\ncan also benefit from using the [`Prepare::PERSISTENT`] option which this\nlibrary supports through [`prepare_with`].\n\nThis library is designed to the extent possible to avoid intermediary\nallocations. For example [calling `execute`] doesn't allocate externally of\nthe sqlite3 bindings or we require that c-strings are used when SQLite\nitself doesn't provide an API for using Rust strings directly. It's also\nimplemented as a thing layer on top of SQLite with minimal added\nabstractions ensuring you get the best possible performance.\n\n\u003cbr\u003e\n\n## License\n\nThis is a rewrite of the [`sqlite` crate], and components used from there\nhave been copied under the MIT license.\n\n[`axum`]: https://docs.rs/axum\n[`Bind` derive]: https://docs.rs/sqll/latest/sqll/derive.Bind.html\n[`bind`]: https://docs.rs/sqll/latest/sqll/struct.Statement.html#method.bind\n[`Bind`]: https://docs.rs/sqll/latest/sqll/trait.Bind.html\n[`Connection`]: https://docs.rs/sqll/latest/sqll/struct.Connection.html#thread-safety\n[`examples/axum.rs`]: https://github.com/udoprog/sqll/blob/main/examples/axum.rs\n[`examples/persons.rs`]: https://github.com/udoprog/sqll/blob/main/examples/persons.rs\n[`execute`]: https://docs.rs/sqll/latest/sqll/struct.Connection.html#method.execute\n[`Row` derive]: https://docs.rs/sqll/latest/sqll/derive.Row.html\n[`Row`]: https://docs.rs/sqll/latest/sqll/trait.Row.html\n[`next`]: https://docs.rs/sqll/latest/sqll/struct.Statement.html#method.next\n[`OpenOptions::no_mutex`]: https://docs.rs/sqll/latest/sqll/struct.OpenOptions.html#method.no_mutex\n[`prepare_with`]: https://docs.rs/sqll/latest/sqll/struct.Connection.html#method.prepare_with\n[`Prepare::PERSISTENT`]: https://docs.rs/sqll/latest/sqll/struct.Prepare.html#associatedconstant.PERSISTENT\n[`prepare`]: https://docs.rs/sqll/latest/sqll/struct.Connection.html#method.prepare\n[`sqlite` crate]: https://github.com/stainless-steel/sqlite\n[`sqll-sys`]: https://crates.io/crates/sqll-sys\n[`Statement`]: https://docs.rs/sqll/latest/sqll/struct.Statement.html\n[binding query parameters]: https://docs.rs/sqll/latest/sqll/struct.Statement.html#method.bind\n[calling `execute`]: https://docs.rs/sqll/latest/sqll/struct.Connection.html#method.execute\n[reading rows]: https://docs.rs/sqll/latest/sqll/struct.Statement.html#method.next\n[SQLite]: https://www.sqlite.org\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fudoprog%2Fsqll","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fudoprog%2Fsqll","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fudoprog%2Fsqll/lists"}