Known Limitations
This page consolidates all known limitations across Stoolap. Each limitation is categorized by feature area and links to the relevant documentation for more details.
JSON
- No modification functions: JSON_SET, JSON_INSERT, JSON_REPLACE, and JSON_REMOVE are not yet supported. JSON values can be read and queried but not modified in place.
- No path query functions: JSON_CONTAINS and JSON_CONTAINS_PATH are not yet available.
- No JSON property indexing: Indexes cannot be created on values within JSON documents.
See JSON Support for supported JSON features.
Foreign Keys
- Single-column only: Composite foreign keys (referencing multiple columns) are not yet supported.
- Self-referencing insertion order: Self-referencing foreign keys require careful ordering of inserts.
See Foreign Keys for full FK documentation.
Date and Time
- UTC only: Timestamps are normalized to UTC internally. There are no explicit functions for time zone conversion.
See Date and Time Handling for supported date/time features.
Temporal Queries (AS OF)
- No subqueries with AS OF: AS OF clauses cannot be combined with subqueries.
- System clock dependency: Timestamp resolution depends on the system clock precision.
- VACUUM removes history: Running VACUUM permanently removes all historical row versions not needed by currently active transactions. After a VACUUM, AS OF queries referencing timestamps before the VACUUM will return no results.
See Temporal Queries for AS OF usage.
Views
- Read-only: INSERT, UPDATE, and DELETE on views are not supported.
- Shared namespace: View names and table names share the same namespace and cannot conflict.
- Nesting limit: Maximum nesting depth of 32 levels prevents infinite recursion from circular definitions.
See Views for view documentation.
ALTER TABLE
- Blocking: ALTER TABLE operations may temporarily block concurrent writes.
- No composite PK changes: Composite primary key modifications are not supported.
See ALTER TABLE for full syntax.
Upsert (ON CONFLICT / ON DUPLICATE KEY)
- No MySQL VALUES() syntax: Stoolap uses
EXCLUDED.column(PostgreSQL-style) instead of MySQL’sVALUES(column)to reference incoming insert values. - No WHERE on conflict action: PostgreSQL’s
ON CONFLICT ... DO UPDATE SET ... WHERE ...conditional update is not yet supported.
See Upsert for full upsert documentation.
WebAssembly (WASM)
| Feature | Status |
|---|---|
| File persistence | Not available (in-memory only, data lost on page reload) |
| Background threads | Not available (no parallel execution, no automatic cleanup) |
| Cleanup | Manual only (use VACUUM or PRAGMA vacuum) |
| WAL / Snapshots | Not available (no crash recovery needed) |
See WebAssembly for WASM usage.
Cold Segments (Frozen Volumes)
- AS OF on cold rows: Historical point-in-time queries (AS OF TRANSACTION) are not supported on tables with cold segments because cold rows lack version chains. AS OF CURRENT queries work correctly.
- Compaction memory: Compaction materializes the full cold dataset in memory before rewriting. For tables with millions of cold rows, this causes a temporary memory spike. Similarly, parallel GROUP BY on 4+ volumes materializes one group map per volume simultaneously before merging.
- Skip-set cloning: Each scan builds per-volume skip sets by cloning cumulative row_id sets. For tables with many volumes, this is O(N*V). Compaction keeps volume counts low (default threshold: 4).
- WAL growth under continuous writes: WAL truncation requires all hot buffers to be empty. Under continuous writes, new rows may arrive between the seal pass and the truncation check. The checkpoint cycle force-seals small tables below the normal threshold, but truly continuous writes can delay truncation until a quiet period or clean close.
-
Snapshot transactions limit seal throughput: Active snapshot isolation transactions use cutoff-filtered seal: only rows committed before the earliest snapshot’s begin_seq are sealed. Rows committed after remain in the hot buffer. Under long-running snapshots with high write throughput, the hot buffer grows proportionally to the writes since the snapshot started. Compaction similarly filters: only volumes sealed before the snapshot and tombstones committed before the snapshot are physically applied.
- Multi-column DISTINCT on large tables:
SELECT DISTINCT col1, col2 FROM ton tables with cold volumes does not use dictionary extraction and falls through to a full row scan. Single-column DISTINCT uses dictionary metadata. - Window functions + LIMIT on large tables: Window functions materialize all rows before LIMIT is applied.
ROW_NUMBER() OVER (...) LIMIT 10on a large table processes every row. Workaround: use PARTITION BY to enable the streaming window path.
See Persistence for full details.
Cold Segments (Accepted Tradeoffs)
These are deliberate design decisions, not bugs:
- Binary search only for Integer/Timestamp columns: Float, Text, and Boolean columns in cold segments fall back to linear scan with zone map pruning. Binary search is only available on sorted i64-based columns.
- ALTER TABLE only modifies hot schema: Cold volumes retain their original schema. Column additions, drops, and renames are normalized at scan time. DROP COLUMN does not reclaim cold storage space until the next compaction cycle.
Transactions
- No primary key updates: UPDATE on primary key columns is rejected with an error. The engine uses row_id == pk_value as a core invariant. Use DELETE + INSERT to change a row’s primary key value.
General SQL
- No stored procedures or triggers: Only built-in functions and SQL statements are supported.
- No user-defined functions: Custom functions cannot be registered through SQL.
- No GRANT/REVOKE: There is no access control or permission system. Stoolap is an embedded database, so access control is managed at the application level.
- No full-text search: Only pattern matching (LIKE, ILIKE, GLOB, REGEXP) is available.
- No materialized views: Views are always computed on demand.
- No event-based notifications: There is no LISTEN/NOTIFY mechanism.
Data Types
- No BLOB/BINARY type: Binary data is not directly supported as a column type.
- No ARRAY type: Array columns are not supported. Use JSON arrays as an alternative.
- No ENUM type: Enumerated types are not available. Use TEXT with CHECK constraints as an alternative.
- No INTERVAL type as column: INTERVAL is supported in expressions (e.g.,
NOW() - INTERVAL '1 day') but not as a stored column type.