You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 65270da
Browse filesBrowse the repository at this point in the historyBrowse files
Run the libSQL conformance suite itself, against the pinned sqld image,
42
+
with:
43
+
44
+
```bash
45
+
./mvnw -pl libsql-conformance -am verify
46
+
```
47
+
48
+
Last green result: 272 tests, 7 skipped, with `SavepointTest` included. The
49
+
parity queue (#54) closed at 268 tests, 7 skipped.
50
+
51
+
### Three-layer contract
52
+
53
+
When the layers disagree, the contract is:
54
+
55
+
1. Hrana 3 is the source of truth for transport, values, metadata,
56
+
batching, transactions, and error reporting. The protocol is specified
57
+
in [`../vendor/HRANA_3_SPEC.md`](../vendor/HRANA_3_SPEC.md); where
58
+
xerial behavior would require a primitive Hrana does not expose, the
59
+
Hrana behavior wins.
60
+
2.`java.sql` is the source of truth for the JDBC surface. Where JDBC
61
+
makes a feature optional or defines the observable behavior, the
62
+
driver follows `java.sql`, even when xerial chooses differently.
63
+
3. xerial is a behavioral reference and the conformance foundation, never
64
+
a copy target. Its tests define the selected subset and the control
65
+
probe; its driver internals, configuration surface, and native
66
+
behaviors are not reproduced.
67
+
68
+
### Compromise categories
69
+
70
+
Full parity is impossible without changing what the driver is: a remote
71
+
Hrana client with no local file, no shared connection, and no native
72
+
library. The rejected classes in the manifest group into four compromise
73
+
categories, each with a concrete example:
74
+
75
+
| Category | Why parity is impossible | Example |
76
+
|---|---|---|
77
+
| Native extension API | The test registers JVM callbacks or loads native code in-process; Hrana exposes no equivalent primitive, so this cannot be reversed without a new Hrana or native primitive. |`UDFTest` registers JVM user-defined functions through sqlite-jdbc's native extension API. |
78
+
| sqlite-jdbc configuration surface | The test exercises xerial's own configuration, `DataSource`, loading, or source conventions instead of portable JDBC over SQL; libSQL provides no counterpart. |`SQLiteConfigTest` tests the `SQLiteConfig` object, not the JDBC API. |
79
+
| Remote-model semantics | The test asserts local-file or in-process SQLite semantics (file locking and multi-connection waits, shared cache, native error wording and codes, or a deliberate driver-contract divergence) that a single remote sqld server over Hrana cannot reproduce; see "Hrana over HTTP" in `../vendor/HRANA_3_SPEC.md` for the baton and stream-expiry model behind this. |`TransactionTest` asserts SQLite file-locking and multi-connection wait behavior. |
80
+
| Build-flag dependence | The test passes only when the server binary is built with a compile-time option that the pinned sqld image does not guarantee; this is addressable by pinning the server build, not by driver work. |`MathFunctionsTest` requires the server binary to be compiled with `SQLITE_ENABLE_MATH_FUNCTIONS`. |
81
+
82
+
The first three categories are permanent: the class stays upstream unless
83
+
the underlying Hrana, sqld, or sqlite-jdbc surface changes. Build-flag
84
+
dependence is the exception: the class stays upstream only until the sqld
85
+
build is pinned to enable the flag.
86
+
87
+
### Driver-contract divergences
88
+
89
+
Hrana over HTTP has no connection. A stream is identified only by the `baton`
90
+
in the pipeline request: `baton: null` creates a new stream, and the server
91
+
closes streams after a short period of inactivity because there is no
92
+
connection that would let it detect an abandoned stream
93
+
([`../vendor/HRANA_3_SPEC.md`](../vendor/HRANA_3_SPEC.md), "Hrana over HTTP").
94
+
xerial `sqlite-jdbc` owns one SQLite connection per JDBC connection, so two
95
+
observable divergences follow from the remote model. Unlike the rejected
96
+
categories above, these occur in selected tests and are recorded per test as
97
+
`# divergence:` lines in the manifest.
98
+
99
+
#### Auto-commit holds no stream
100
+
101
+
An auto-commit statement runs as a one-shot pipeline that executes the
102
+
statement and closes the stream in the same round trip. The driver keeps no
103
+
session stream open between statements, so an idle connection consumes no
104
+
server stream slot and holds no baton for the idle expiry to invalidate.
105
+
Keeping one open only to preserve session state would reintroduce stale-baton
106
+
failures on idle connections.
107
+
108
+
Because `StmtResult.last_insert_rowid` describes the insert on one stream and
109
+
nothing else, a later `SELECT last_insert_rowid()` runs on a fresh stream and
110
+
returns `0`, even when the same `Statement` inserted a row immediately before.
111
+
xerial returns that insert's rowid instead. Use `Statement.getGeneratedKeys()`
112
+
after the insert, which the driver builds from `StmtResult.last_insert_rowid`
113
+
with no extra round trip, or run the insert and the query inside one explicit
114
+
transaction so both run on the same stream. `LibsqlGeneratedKeysTest` pins the
115
+
generated-keys path.
116
+
117
+
#### Transactions begin lazily
118
+
119
+
`setAutoCommit(false)` sends nothing. The next statement begins the
120
+
transaction on a new stream with `BEGIN`, `BEGIN IMMEDIATE`, or
0 commit comments