{"id":28702052,"url":"https://github.com/rqlite/rqlite-jdbc","last_synced_at":"2026-01-18T05:57:48.968Z","repository":{"id":296327858,"uuid":"992706607","full_name":"rqlite/rqlite-jdbc","owner":"rqlite","description":"Type 4 JDBC driver for rqlite","archived":false,"fork":false,"pushed_at":"2026-01-17T17:25:13.000Z","size":126,"stargazers_count":11,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-18T03:35:48.958Z","etag":null,"topics":["java","jdbc","jdbc-driver"],"latest_commit_sha":null,"homepage":"","language":"Java","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/rqlite.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-05-29T15:28:26.000Z","updated_at":"2026-01-17T17:18:28.000Z","dependencies_parsed_at":"2025-07-26T18:14:26.372Z","dependency_job_id":"a46abc30-414e-4d66-8462-b612c675691e","html_url":"https://github.com/rqlite/rqlite-jdbc","commit_stats":null,"previous_names":["rqlite/rqlite-jdbc"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/rqlite/rqlite-jdbc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rqlite%2Frqlite-jdbc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rqlite%2Frqlite-jdbc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rqlite%2Frqlite-jdbc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rqlite%2Frqlite-jdbc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rqlite","download_url":"https://codeload.github.com/rqlite/rqlite-jdbc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rqlite%2Frqlite-jdbc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28531906,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T00:39:45.795Z","status":"online","status_checked_at":"2026-01-18T02:00:07.578Z","response_time":98,"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":["java","jdbc","jdbc-driver"],"created_at":"2025-06-14T12:09:38.917Z","updated_at":"2026-01-18T05:57:48.963Z","avatar_url":"https://github.com/rqlite.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rqlite JDBC Driver\n\nThis is a minimal (~130KB, zero dependencies),  Type 4 JDBC driver for [rqlite](https://github.com/rqlite/rqlite),\na lightweight, distributed relational database built on top of SQLite.\n\nThis driver enables Java applications to interact with `rqlite` over HTTP, supporting standard\nJDBC operations like queries, updates, and batch processing in a clustered environment.\n\n## Features\n\n- **JDBC Compliance**: Supports core JDBC APIs, including `Connection`, `Statement`, `PreparedStatement`, and `ResultSet`.\n- **Atomic Transactions**: Executes multiple statements atomically using rqlite’s `transaction=true` mode via batch operations.\n- **Clustered Environment Support**: Configurable options for read consistency, write queuing, and timeouts to handle rqlite’s distributed nature.\n- **Schema and Metadata Access**: Query table metadata, primary keys, foreign keys, and indexes (see [L4DriverTest](./src/test/java/io/rqlite/L4DriverTest.java)).\n\n## Getting Started\n\n### Prerequisites\n\n- Java 11 or higher\n- `rqlite` server running (e.g., `http://localhost:4001`)\n\nInstall from [Maven Central](https://mvnrepository.com/artifact/io.rqlite/rqlite-jdbc)\n\n    io.rqlite:rqlite-jdbc:[version]\n\nThe driver version corresponds to the last known `rqlite` [release](https://github.com/rqlite/rqlite/releases) the driver was tested against, followed by a build version of the driver itself.\n\n## Basic Usage\n\nConnect to an `rqlite` instance and execute queries using standard JDBC APIs.\n\n```\nimport java.sql.*;\n\nvar url = \"jdbc:rqlite:http://localhost:4001\";\n\ntry (Connection conn = DriverManager.getConnection(url)) {\n    var stmt = conn.createStatement();\n    stmt.execute(\"CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)\");\n\n    var ps = conn.prepareStatement(\"INSERT INTO users (name, age) VALUES (?, ?)\");\n    ps.setString(1, \"Alice\");\n    ps.setInt(2, 30);\n    ps.executeUpdate();\n\n    var rs = stmt.executeQuery(\"SELECT * FROM users\");\n    while (rs.next()) {\n        System.out.println(\"ID: \" + rs.getInt(\"id\") + \", Name: \" + rs.getString(\"name\") + \", Age: \" + rs.getInt(\"age\"));\n    }\n}\n```\n\n## Batch Processing for Transactions\n\n`rqlite` executes statements atomically with `transaction=true`. Use batch operations for multi-statement transactions.\n\nUsing `Statement`:\n\n```\nStatement stmt = conn.createStatement();\nstmt.addBatch(\"INSERT INTO users (name, age) VALUES ('Fiona', 25)\");\nstmt.addBatch(\"INSERT INTO users (name, age) VALUES ('Sinead', 28)\");\nint[] updateCounts = stmt.executeBatch(); // Executes atomically\n```\n\nUsing `PreparedStatement`:\n\n```\nPreparedStatement ps = conn.prepareStatement(\"INSERT INTO users (name, age) VALUES (?, ?)\");\nps.setString(1, \"Fiona\");\nps.setInt(2, 25);\nps.addBatch();\nps.setString(1, \"Sinead\");\nps.setInt(2, 28);\nps.addBatch();\nint[] updateCounts = ps.executeBatch(); // Executes atomically\n```\n\nSee [L4PsTest](./src/test/java/io/rqlite/L4PsTest.java) for advanced examples with various data types, streams, and LOBs.\n\n## Configuration Options\n\nCustomize the driver’s behavior via JDBC URL parameters, see [L4Options](./src/main/java/io/rqlite/rqlite/L4Options.java). Below are the available options, their defaults, and their purposes.\n\nThese options come from `rqlite`'s [Developer Guide](https://rqlite.io/docs/api)\n\n| Property Key                | Type      | Default Value            | Description                                                                 |\n|-----------------------------|-----------|--------------------------|-----------------------------------------------------------------------------|\n| `baseUrl`                   | `String`  | `null`                   | The base URL of the RQLite server (e.g., `http://localhost:4001`).           |\n| `user`                      | `String`  | `null`                   | Username for RQLite server authentication.                                   |\n| `password`                  | `String`  | `null`                   | Password for RQLite server authentication.                                   |\n| `cacert`                    | `String`  | `null`                   | Path to the CA certificate for SSL/TLS connections.                         |\n| `insecure`                  | `boolean` | `false`                  | If `true`, disables SSL/TLS verification (not recommended for production).   |\n| `timeoutSec`                | `long`    | `5`                      | Timeout for HTTP requests in seconds.                                       |\n| `queue`                     | `boolean` | `false`                  | If `true`, enables queuing of requests on the RQLite server.                |\n| `wait`                      | `boolean` | `true`                   | If `true`, waits for the request to be processed by the RQLite leader.      |\n| `level`                     | `L4Level` | `L4Level.linearizable`   | Consistency level for queries (`none`, `weak`, `strong`, `linearizable`).   |\n| `linearizableTimeoutSec`    | `long`    | `5`                      | Timeout for linearizable consistency queries in seconds.                    |\n| `freshnessSec`              | `long`    | `5`                      | Maximum age of data for freshness-based queries in seconds.                 |\n| `freshnessStrict`           | `boolean` | `false`                  | If `true`, enforces strict freshness for queries.                           |\n\nExample JDBC URL:\n\n```java\nString url = \"jdbc:rqlite:http://localhost:4001?timeoutSec=5\u0026level=strong\u0026freshnessSec=1\";\n```\n\n## Caveats\n\n### Memory Usage\n\nResult sets are held in memory (mapped from rqlite’s JSON responses to JDBC ResultSet). Write queries that return small datasets to avoid memory issues.\n\n### Catalog Support\n\nOnly the `main` SQLite database is reported as a catalog to JDBC.\n\n### Transaction Limitations\n\nThe driver offers deferred transaction support on `Connection` instances due to `rqlite`'s [Transaction support](https://rqlite.io/docs/api/api/#transactions) conventions, which deviate from the JDBC standard.\n\nTo execute multiple SQL statements as a transaction, you have two options.\n\n#### Batch statements\n\nPopulate a JDBC batch using [`Statement`](https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/java/sql/Statement.html#addBatch(java.lang.String)) or [`PreparedStatement`](https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/java/sql/PreparedStatement.html#addBatch()), which will get sent with `transaction=true` to the underlying `rqlite` HTTP request.\n\n#### Framework Compatibility\n\nCertain ORM frameworks (e.g., JetBrains Exposed) may require specific driver metadata for compatibility.\n\nIf you encounter issues with the reported database product name, use `L4DbMeta.setDriverName(\"SQLite JDBC\")` to override the default value before connecting.\n\nThis can help align the driver with framework expectations for SQLite-like dialects.\n\nSee also: [L4ExposedTest](./src/test/java/io/rqlite/L4ExposedTest.java)\n\n#### Synthetic/deferred transactions\n\nCall `setAutoCommit(false)` on a [`Connection`](https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/java/sql/Connection.html#setAutoCommit(boolean)), and run `insert`, `update` or `delete` statements.\n\nThe execution of these statements will get deferred until you call `commit()`.\n\nThis will send all statements to the database as a single batch, appending `transaction=true` to the underlying `rqlite` HTTP request.\n\nThis implies that you won't be able to inspect `ResultSet`s, metadata or row counts after executing each statement. A dummy resultset is provided only for compatibility with JDBC semantics.\n\nThe only guarantee is that if `commit()` succeeds, then all deferred statements were accepted by the database.\n\nLastly, make sure that all statements get executed through the same connection where the transaction was initiated.\n\n### Isolation Level\n\nOnly `TRANSACTION_SERIALIZABLE` is supported, with `linearizable` read consistency by default. Setting `level=weak` or `level=none` may introduce read inconsistencies.\n\n### Type Mapping\n\nUser-defined SQL types (UDTs) are not supported. `getTypeMap` and `setTypeMap` are implemented for compliance but have no effect.\n\n### Date/Time Handling\n\nThe driver normalizes all `java.sql.Date`, `Time`, and `Timestamp` values to UTC before storage in rqlite, ensuring consistent round-trip behavior regardless of the JVM's default timezone.\n\nThis is necessary because rqlite normalizes date/time outputs for typed columns (`DATE`, `DATETIME`, `TIMESTAMP`) to ISO 8601 format with a `'Z'` suffix (indicating UTC), which could otherwise cause shifts in the retrieved instant if local timezones are involved.\n\n#### Setters (`setDate`, `setTime`, `setTimestamp`)\n\nThe input value's instant (milliseconds since UTC epoch) is converted to UTC components and stored as a string (e.g., `'2025-08-23 13:00:00'` for timestamps, without `'Z'`). The optional `Calendar` parameter is ignored, as forcing UTC normalization preserves the original instant across environments.\n\nIf timezone-specific adjustments are needed, perform them in your application before creating the `Date`/`Time`/`Timestamp` objects.\n\n#### Getters (`getDate`, `getTime`, `getTimestamp`)\n\nValues are parsed assuming UTC (via `Instant.parse` for ISO strings with `'Z'`). The returned objects hold accurate UTC milliseconds internally.\n\nHowever, due to legacy `java.sql` types:\n\n- `toString()` on `Date`/`Time`/`Timestamp` formats components in the JVM's default timezone, which may show shifted values (e.g., a UTC midnight might display as the previous day in EST). This is a display artifact—the underlying instant is unchanged.\n- To ensure consistent display or interpretation, provide a `Calendar` set to UTC (e.g., `Calendar.getInstance(TimeZone.getTimeZone(\"UTC\"))`) in getters.\n\n#### Recommendations:\n\n- Store all dates/times in UTC to avoid complexity.\n- Test in multiple JVM timezones (e.g., via `-Duser.timezone=UTC`) to verify behavior.\n- If preserving original timezones is critical, store offsets or timezone names in separate columns, as rqlite/SQLite does not natively support timezone-aware types.\n\nThis approach deviates slightly from standard JDBC for timezone-agnostic databases but prioritizes reliability with rqlite's output quirks.\n\nFor examples, see [L4PsTest](./src/test/java/io/rqlite/L4PsTest.java).\n\n## Contributing\n\nContributions are welcome! Please submit issues or pull requests to this GitHub repository.\n\nRequires Gradle 8.1 or later.\n\nCreate a file with the following content at `~/.gsOrgConfig.json`:\n\n```\n{\n  \"orgConfigUrl\": \"https://raw.githubusercontent.com/rqlite/rqlite-jdbc/refs/heads/org-config/org-config.json\"\n}\n```\n\nThen run:\n\n```\ngradle clean build\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frqlite%2Frqlite-jdbc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frqlite%2Frqlite-jdbc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frqlite%2Frqlite-jdbc/lists"}