{"id":33319385,"url":"https://github.com/ysdragon/ring-libsql","last_synced_at":"2025-11-19T20:02:10.211Z","repository":{"id":324313021,"uuid":"1096805854","full_name":"ysdragon/ring-libsql","owner":"ysdragon","description":"LibSQL client library for Ring with SQLite compatibility and support for local, remote, and embedded replica databases.","archived":false,"fork":false,"pushed_at":"2025-11-15T02:14:18.000Z","size":31447,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-11-15T03:35:50.962Z","etag":null,"topics":["libsql","sqlite","sqlite3","turso","turso-db"],"latest_commit_sha":null,"homepage":"","language":"C","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/ysdragon.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,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-15T01:29:07.000Z","updated_at":"2025-11-15T02:14:22.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ysdragon/ring-libsql","commit_stats":null,"previous_names":["ysdragon/ring-libsql"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/ysdragon/ring-libsql","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ysdragon%2Fring-libsql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ysdragon%2Fring-libsql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ysdragon%2Fring-libsql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ysdragon%2Fring-libsql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ysdragon","download_url":"https://codeload.github.com/ysdragon/ring-libsql/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ysdragon%2Fring-libsql/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":285319005,"owners_count":27151474,"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-11-19T02:00:05.673Z","response_time":65,"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":["libsql","sqlite","sqlite3","turso","turso-db"],"created_at":"2025-11-19T20:00:39.366Z","updated_at":"2025-11-19T20:02:10.204Z","avatar_url":"https://github.com/ysdragon.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# Ring LibSQL\n\n[ring]: https://img.shields.io/badge/Made_with_❤️_for-Ring-2D54CB?style=for-the-badge\n[license]: https://img.shields.io/github/license/ysdragon/ring-libsql?style=for-the-badge\u0026logo=opensourcehardware\u0026label=License\u0026logoColor=C0CAF5\u0026labelColor=414868\u0026color=8c73cc\n\n[![][ring]](https://ring-lang.net/)\n[![][license]](https://github.com/ysdragon/ring-libsql/blob/master/LICENSE)\n\n**LibSQL client library for Ring with SQLite compatibility and support for local, remote, and embedded replica databases.**\n\n\u003c/div\u003e\n\n## ✨ Features\n\n- Full SQLite-compatible database operations\n- Local file-based databases (`:memory:` or file paths)\n- Remote database access with authentication\n- Embedded replica support for offline-first applications with sync capabilities\n- Prepared statements with parameter binding (int, float, string, blob, null)\n- Encryption support for both local and remote databases\n- WebPKI support for secure HTTPS connections\n- Transaction support and connection management\n- Cross-platform support (Windows, Linux, macOS, FreeBSD)\n\n\u003e [!NOTE]\n\u003e This extension/library is built on top of the experimental c bindings of [libsql](https://github.com/tursodatabase/libsql).\n\n## 📦 Installation\n\nThis package can be installed using the Ring Package Manager (**RingPM**):\n\n```\nringpm install ring-libsql from ysdragon\n```\n\n## 💡 Usage\n\nFirst, load the library in your Ring script:\n\n```ring\nload \"libsql.ring\"\n```\n\n### Local Database (In-Memory)\n\n```ring\nload \"libsql.ring\"\n\n# Open in-memory database\ndb = new LibSQL\ndb.openExt(\":memory:\")\nconn = db.connect()\n\n# Create a table and insert data\nconn.execute(\"CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)\")\nconn.execute(\"INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')\")\nconn.execute(\"INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com')\")\n\n# Query data\nrows = conn.query(\"SELECT * FROM users\")\nwhile True\n\trow = rows.fetchRow()\n\tif isNull(row)\n\t\texit\n\tok\n\t\n\tdata = row.toList()\n\t? \"ID: \" + data[1] + \", Name: \" + data[2] + \", Email: \" + data[3]\nend\n\n# Or fetch all at once as associative array\nresults = conn.query(\"SELECT * FROM users\").fetchAllAssoc()\nfor user in results\n\t? user  # Prints [[\"id\", 1], [\"name\", \"Alice\"], [\"email\", \"alice@example.com\"]]\nnext\n\n# Cleanup\nconn.disconnect()\ndb.close()\n```\n\n### Local Database (File)\n\n```ring\nload \"libsql.ring\"\n\n# Open file-based database\ndb = new LibSQL\ndb.openFile(\"mydata.db\")\nconn = db.connect()\n\n# Use the database\nconn.execute(\"CREATE TABLE IF NOT EXISTS products (id INTEGER, name TEXT, price REAL)\")\nconn.execute(\"INSERT INTO products VALUES (1, 'Laptop', 999.99)\")\n\n# Cleanup\nconn.disconnect()\ndb.close()\n```\n\n### Remote Database (Turso or Self-Hosted)\n\n```ring\nload \"libsql.ring\"\n\n# Option 1: Connect to Turso hosted database\ndb = new LibSQL\ndb.openRemote(\"libsql://your-database.turso.io\", \"your-auth-token\")\nconn = db.connect()\n\n# Option 2: Connect to your self-hosted LibSQL server\n# Can be localhost, VPS, cloud server, or any remote machine\n# db = new LibSQL\n# db.openRemote(\"http://your-server.com:8080\", \"optional-auth-token\")\n# conn = db.connect()\n\n# Execute queries\nconn.execute(\"INSERT INTO logs (message, timestamp) VALUES ('Hello from Ring!', datetime('now'))\")\n\n# Query remote data\nrows = conn.query(\"SELECT * FROM logs ORDER BY timestamp DESC LIMIT 10\")\nlogs = rows.fetchAllAssoc()\nfor log in logs\n\t? log\nnext\n\n# Cleanup\nconn.disconnect()\ndb.close()\n```\n\n### Embedded Replica (Offline-First with Sync)\n\n```ring\nload \"libsql.ring\"\n\n# Open embedded replica with sync configuration\nconfig = [\n\t:db_path = \"local_replica.db\",\n\t:primary_url = \"libsql://your-database.turso.io\",\n\t:auth_token = \"your-auth-token\",\n\t:read_your_writes = 1,\n\t:sync_interval = 60  # Auto-sync every 60 seconds\n]\n\ndb = new LibSQL\ndb.openSyncWithConfig(config)\nconn = db.connect()\n\n# Work with local replica (works offline)\nconn.execute(\"INSERT INTO tasks (title, done) VALUES ('Learn Ring', 0)\")\nconn.execute(\"INSERT INTO tasks (title, done) VALUES ('Build App', 0)\")\n\n# Manually sync with remote\ndb.sync()\n\n# Get sync statistics\nsyncInfo = db.sync2()\n? \"Synced frames: \" + syncInfo[2]\n\n# Cleanup\nconn.disconnect()\ndb.close()\n```\n\n### Prepared Statements with Parameter Binding\n\n```ring\nload \"libsql.ring\"\n\ndb = new LibSQL\ndb.openExt(\":memory:\")\nconn = db.connect()\n\nconn.execute(\"CREATE TABLE users (id INTEGER, name TEXT, score REAL, active INTEGER)\")\n\n# Prepare statement\nstmt = conn.prepare(\"INSERT INTO users (id, name, score, active) VALUES (?, ?, ?, ?)\")\n\n# Method 1: Bind individually with type-specific methods\nstmt.bindInt(1, 1)\n    .bindString(2, \"Alice\")\n    .bindFloat(3, 95.5)\n    .bindInt(4, 1)\n    .execute()\n\n# Method 2: Bind all parameters at once (auto-detects types)\nstmt.reset()\n    .bindParams([2, \"Bob\", 87.3, 1])\n    .execute()\n\n# Method 3: Use smart bind (handles nulls and auto-types)\nstmt.reset()\n    .bind(1, 3)\n    .bind(2, \"Charlie\")\n    .bind(3, 92.0)\n    .bind(4, null)  # NULL value\n    .execute()\n\n# Query with prepared statements\nqueryStmt = conn.prepare(\"SELECT * FROM users WHERE score \u003e ?\")\nqueryStmt.bindFloat(1, 90.0)\nresults = queryStmt.query().fetchAllAssoc()\n\nfor user in results\n\t? user\nnext\n\n# Cleanup\nconn.disconnect()\ndb.close()\n```\n\n### Database Encryption\n\n```ring\nload \"libsql.ring\"\n\n# Embedded replica with encryption (syncs with remote server)\ndb = new LibSQL\ndb.openSync(\n\t\"local_encrypted.db\",\n\t\"libsql://your-database.turso.io\",  # Remote URL required\n\t\"your-auth-token\",\n\t1,   # read_your_writes\n\t\"my-encryption-key-32-bytes-long\"\n)\n\nconn = db.connect()\nconn.execute(\"CREATE TABLE IF NOT EXISTS secrets (id INTEGER, data TEXT)\")\nconn.execute(\"INSERT INTO secrets VALUES (1, 'Top Secret Data')\")\n\n# Sync encrypted data with remote\ndb.sync()\n\n# Cleanup\nconn.disconnect()\ndb.close()\n```\n\n### Working with Different Data Types\n\n```ring\nload \"libsql.ring\"\n\ndb = new LibSQL\ndb.openExt(\":memory:\")\nconn = db.connect()\n\nconn.execute(\"CREATE TABLE mixed_types (\n\tid INTEGER,\n\tname TEXT,\n\tprice REAL,\n\tdata BLOB,\n\tnullable TEXT\n)\")\n\n# Insert with different types\nstmt = conn.prepare(\"INSERT INTO mixed_types VALUES (?, ?, ?, ?, ?)\")\nstmt.bindInt(1, 1)\n    .bindString(2, \"Product\")\n    .bindFloat(3, 29.99)\n    .bindBlob(4, \"Binary Data Here\")\n    .bindNull(5)\n    .execute()\n\n# Fetch and access by type\nrows = conn.query(\"SELECT * FROM mixed_types\")\nrow = rows.fetchRow()\n\n? \"ID (int): \" + row.getIntValue(1)\n? \"Name (string): \" + row.getStringValue(2)\n? \"Price (float): \" + row.getFloatValue(3)\n? \"Data (blob): \" + row.getBlobValue(4)\nnullableVal = row.getValue(5)\nif isNull(nullableVal)\n\t? \"Nullable: NULL\"\nelse\n\t? \"Nullable: \" + nullableVal\nok\n\n# Cleanup\nconn.disconnect()\ndb.close()\n```\n\n## 📚 API Reference\n\n### LibSQL Class (Database)\n\nThe main database class for opening and managing database connections.\n\n#### Opening Databases\n\n- **`openFile(path)`** - Open local file database\n- **`openExt(path)`** - Open database (`:memory:`, file path, or URL)\n- **`openRemote(url, auth_token)`** - Open remote database\n- **`openRemoteWithWebPKI(url, auth_token)`** - Open remote with WebPKI\n- **`openRemoteWithEncryption(url, auth_token, key)`** - Open remote with encryption\n- **`openSync(db_path, url, token, read_your_writes, key)`** - Open embedded replica\n- **`openSyncWithWebPKI(db_path, url, token, read_your_writes, key)`** - Open embedded replica with WebPKI\n- **`openSyncWithConfig(config_list)`** - Open with configuration list\n\n#### Database Operations\n\n- **`connect()`** - Create connection, returns LibSQLConnection object\n- **`sync()`** - Manually sync embedded replica with remote\n- **`sync2()`** - Sync and return frame statistics `[frame_no, frames_synced]`\n- **`close()`** - Close database\n\n### LibSQLConnection Class (Connection)\n\nRepresents an active database connection for executing queries.\n\n#### Query Execution\n\n- **`execute(sql)`** - Execute SQL without returning rows\n- **`query(sql)`** - Execute query, returns LibSQLRows object\n- **`prepare(sql)`** - Prepare statement, returns LibSQLStatement object\n- **`changes()`** - Get number of rows affected by last operation\n- **`lastInsertRowID()`** - Get last inserted row ID\n\n#### Connection Management\n\n- **`disconnect()`** - Close connection\n- **`reset()`** - Reset connection state\n- **`loadExtension(path, entry_point)`** - Load SQLite extension\n- **`setReservedBytes(bytes)`** - Set reserved bytes for encryption\n- **`getReservedBytes()`** - Get reserved bytes\n\n### LibSQLStatement Class (Prepared Statement)\n\nPrepared statement with parameter binding.\n\n#### Parameter Binding\n\n- **`bindInt(index, value)`** - Bind integer (1-based index)\n- **`bindFloat(index, value)`** - Bind float (1-based index)\n- **`bindString(index, value)`** - Bind string (1-based index)\n- **`bindBlob(index, value)`** - Bind blob (1-based index)\n- **`bindNull(index)`** - Bind NULL (1-based index)\n- **`bind(index, value)`** - Smart bind (auto-detects type, 1-based index)\n- **`bindParams(params_list)`** - Bind all parameters from list (1-based)\n\n#### Execution\n\n- **`execute()`** - Execute statement without returning rows\n- **`query()`** - Execute statement, returns LibSQLRows object\n- **`reset()`** - Reset statement for reuse\n\n### LibSQLRows Class (Result Set)\n\nRepresents query results.\n\n#### Column Information\n\n- **`columnCount()`** - Get number of columns\n- **`columnName(index)`** - Get column name (1-based index)\n- **`columnNames()`** - Get list of all column names\n\n#### Fetching Rows\n\n- **`fetchRow()`** - Fetch next row, returns LibSQLRow or null\n- **`fetchAll()`** - Fetch all rows as list of lists\n- **`fetchAllAssoc()`** - Fetch all rows as associative arrays\n\n### LibSQLRow Class (Row Data)\n\nRepresents a single result row.\n\n#### Type-Specific Access\n\n- **`getIntValue(index)`** - Get integer value (1-based index)\n- **`getFloatValue(index)`** - Get float value\n- **`getStringValue(index)`** - Get string value\n- **`getBlobValue(index)`** - Get blob value\n- **`getType(index)`** - Get column type constant\n- **`getValue(index)`** - Get value with automatic type conversion\n\n#### Row Conversion\n\n- **`toList()`** - Convert row to list of values\n- **`toAssoc()`** - Convert row to associative array `[[\"col\", val], ...]`\n\n### Constants\n\n- **`LIBSQL_INT`** - Integer column type\n- **`LIBSQL_FLOAT`** - Float column type\n- **`LIBSQL_TEXT`** - Text column type\n- **`LIBSQL_BLOB`** - Blob column type\n- **`LIBSQL_NULL`** - NULL column type\n\n### Low-Level C Functions\n\nFor advanced users, all underlying C functions are also available:\n`libsql_open_*`, `libsql_connect`, `libsql_execute`, `libsql_query`, `libsql_prepare`,\n`libsql_bind_*`, `libsql_next_row`, `libsql_get_*`, etc.\n\n## 🛠️ Development\n\nIf you wish to contribute to the development of Ring LibSQL or build it from the source, follow these steps.\n\n### Prerequisites\n\n-   **CMake**: Version 3.16 or higher\n-   **C Compiler**: A C compiler compatible with your platform (e.g., GCC, Clang, MSVC)\n-   **Rust \u0026 Cargo**: Required to build libsql from source\n-   **Git**: For cloning repositories\n-   **[Ring](https://ring-lang.net/) Source Code**: Ring language source code must be available on your machine\n\n### Build Steps\n\n1.  **Clone the Repository:**\n\t```sh\n\tgit clone https://github.com/ysdragon/ring-libsql.git\n\tcd ring-libsql\n\t```\n\n\t\u003e **Note**\n\t\u003e If you installed the library via RingPM, you can skip this step.\n\n2.  **Set the `RING` Environment Variable:**\n\tThis variable must point to the root directory of the Ring language source code.\n\n\t-   **Windows (Command Prompt):**\n\t\t```cmd\n\t\tset RING=X:\\path\\to\\ring\n\t\t```\n\t-   **Windows (PowerShell):**\n\t\t```powershell\n\t\t$env:RING = \"X:\\path\\to\\ring\"\n\t\t```\n\t-   **Unix-like Systems (Linux, macOS or FreeBSD):**\n\t\t```bash\n\t\texport RING=/path/to/ring\n\t\t```\n\n3.  **Configure with CMake:**\n\tCreate a build directory and run CMake from within it. CMake will automatically:\n\t- Clone libsql from GitHub if not found\n\t- Build libsql using Cargo\n\t\n\t```sh\n\tmkdir build\n\tcd build\n\tcmake .. -DCMAKE_BUILD_TYPE=Release\n\t```\n\n4.  **Build the Project:**\n\tCompile the source code using the build toolchain configured by CMake.\n\t```sh\n\tcmake --build .\n\t```\n\n\tThe compiled library will be available in the `lib/\u003cos\u003e/\u003carch\u003e` directory.\n\n## 🤝 Contributing\n\nContributions are always welcome! If you have suggestions for improvements or have identified a bug, please feel free to open an issue or submit a pull request.\n\n## 📄 License\n\nThis project is licensed under the MIT License. See the [`LICENSE`](LICENSE) file for more details.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fysdragon%2Fring-libsql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fysdragon%2Fring-libsql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fysdragon%2Fring-libsql/lists"}