River is a single-node relational database written in Java. It provides an embedded Java API, JDBC access, and a command-line client. Its storage engine uses MVCC, heap pages, B+trees, a write-ahead log, and checkpoints.
River 0.1.0-alpha.2 is an evaluation release. It is incomplete and may break. Read the release limits before using it with important data.
- Durable heap and B+tree storage with unique, non-unique, and nullable indexes.
- Write-ahead logging, group commit, checkpoints, WAL rotation, committed-WAL recovery, and torn checkpoint-page repair.
- Quiescent backup and restore, and offline physical inspection.
- Concurrent MVCC sessions with read-committed, repeatable-read, and serializable isolation.
- Statements and explicit transactions publish DML and catalog changes atomically.
- Key and range locks, deadlock resolution, statement rollback, and nested named savepoints.
- Tables, indexes, views, sequences, identities, defaults,
NOT NULL,CHECK,UNIQUE, and foreign keys. BIGINT,BOOLEAN,DECIMAL(p,s),VARCHAR(n),DATE,TIME(p), localTIMESTAMP(p), andTIMESTAMP(p) WITH TIME ZONE.- Multi-row
INSERT,UPDATE, andDELETE; indexed and scanned predicates; scalar expressions; and SQL three-valued logic. - Two-to-eight-role
INNERandLEFTjoins with bounded nested-loop, hash, and merge strategies. - Aggregation,
GROUP BY,HAVING,DISTINCT, ordering, limits, and bounded disk spill. - Derived tables and bounded scalar,
EXISTS,IN,NOT IN, and correlated subqueries. They can feed projections, aggregates, grouping, ordering, joins, and outer derived-table stages. ANALYZE,EXPLAIN, andEXPLAIN ANALYZEwith durable statistics and execution counters.- Streaming JDBC 4.3 results and prepared parameters. Loopback clients may use plain transport or TLS 1.3 with token authentication.
The SQL conformance profile defines the exact SQL grammar and semantics. The JDBC support matrix lists supported conversions, metadata, SQLSTATEs, and deliberate omissions.
| Area | Current limit |
|---|---|
| Table and result columns | 8 |
| Encoded table row | 4,096 bytes |
| Indexed-table capacity | 65,536 physical row/version slots per table |
| Text | VARCHAR(n), 1 <= n <= 255; at most 1,020 encoded bytes per value |
| Join shape | 2–8 left-associative roles |
| Materialized query stores | 65,536 rows and 256 MiB per bounded store |
| Network | Loopback only; authenticated access uses TLS 1.3 and a token |
| JDBC | One live statement per connection; forward-only, read-only results |
| Operations | Offline backup; no replication, failover, or online migration |
River requires JDK 25. Gradle verifies dependency checksums.
Build all module JARs and the CLI distribution:
./gradlew assembleRiver does not yet ship a standalone server service. A host application opens
the database through EmbeddedRiver and starts LoopbackRiverServer. The
database how-to gives the lifecycle code and shutdown rules.
After starting a plain loopback server, install and run the SQL client:
./gradlew :river-cli:installDist
river-cli/build/install/river-cli/bin/river-cli 9191 < setup.sqlThe CLI reads semicolon-terminated SQL, emits tab-separated rows, and stops at the first error. See the CLI reference for TLS and token authentication.
Run the ordinary test matrix while developing:
./gradlew testRun the clean, reproducible release check at an integration checkpoint:
./verify./verify rebuilds reproducible archives, runs clean check, enforces source
and dependency policies, and uses an isolated repository-local Gradle home by
default.
River uses the GNU Affero General Public License v3.