Releases: colliery-io/graphqlite
v0.4.4
What's Changed
- Release 0.4.4: fix all 7 sub-bugs of issue #61 + dispatcher hardening by @dylanbstorey in #62
Full Changelog: v0.4.3...v0.4.4
v0.4.3
Bug Fixes (#59)
- COUNT + OPTIONAL MATCH null handling:
COUNT(r)whereris null fromOPTIONAL MATCHnow correctly returns 0 instead of 1 - Edge variables through WITH: Relationship variables now pass through
WITHfortype(r)andr.propertyaccess - Functions in CREATE property maps:
CREATE (n {ts: timestamp(), upper: toUpper('hello')})now evaluates function calls - CALL subquery inner RETURN export:
CALL { WITH a RETURN a.id AS x } RETURN xnow propagates inner columns to outer scope - CALL subquery multi-row inner MATCH: Inner
MATCHnow processes all matching rows, not just the first
Test Coverage
- 937 CUnit tests, 47 functional SQL files, 351 Python tests, 250 Rust tests
Closed Issues
v0.4.2
Bug Fixes
- UNWIND $param write paths (#49):
UNWIND $param AS item CREATE/MERGE/SETnow works with parameterized lists, literal lists + SET, and per-item MERGE iteration - startNode(r)/endNode(r) alias collision (#50):
RETURN startNode(r).name, endNode(r).namenow produces distinct column names - CALL subquery MERGE scoping (#51):
CALL { WITH c MATCH (d) MERGE (c)-[:REL]->(d) }correctly resolves inner MATCH variables - OPTIONAL MATCH WHERE null preservation (#34b):
OPTIONAL MATCH ... WHERE r.prop = "x"preserves null rows when filter doesn't match - WITH+MATCH+MERGE dispatch:
MATCH (a) WITH a MATCH (b) MERGE (a)-[:REL]->(b)now routes correctly - Functions in SET with property refs:
SET n.trimmed = trim(n.name)resolves node properties in function arguments - SQL alias sanitization (#55): Backtick-quoted Cypher identifiers no longer produce invalid SQL aliases
Test Coverage
- 937 CUnit tests, 46 functional SQL files, 346 Python tests, 245 Rust tests
- New cross-clause hardening suite (
38_cross_clause_hardening.sql) - All 12 historical expected-failure issue repros promoted to passing regression suite
- Issue regression tests added to Python and Rust binding suites
Closed Issues
v0.4.1
What's New
CALL {} Subquery Support (openCypher)
Full implementation of CALL {} subqueries — a core openCypher feature for batch operations, correlated subqueries, and conditional writes.
-- Write-only: SET properties via outer variable binding
MATCH (n:Person) CALL { WITH n SET n.processed = true }
-- UNION branches inside CALL
MATCH (c:Company) CALL {
WITH c MERGE (c)-[:HAS_DEPT]->(:Dept {name: "Eng"})
UNION
WITH c MERGE (c)-[:HAS_DEPT]->(:Dept {name: "Sales"})
}
-- Standalone with RETURN
CALL { MATCH (n:Person) RETURN n.name ORDER BY n.name LIMIT 5 }
-- Nested CALL
CALL { CALL { RETURN 42 AS answer } }Supported patterns:
- Standalone
CALL { ... }with inner MATCH, RETURN, CREATE MATCH + CALL { WITH ... SET/MERGE/CREATE }— outer variable binding per rowCALL { ... UNION ... }— execute multiple branches with shared WITH importsWITH a AS xaliasing inside CALL scope- Nested
CALL { CALL { ... } } - Scope isolation: variables not imported via WITH are inaccessible
CREATE...RETURN Support
CREATE (n:Label {props}) RETURN n.prop now works — previously returned "not yet implemented". This also unblocked the functional test suite which was silently stopping at test 26.
Structured JSON Error Codes
All error responses from the C extension now return structured JSON with error codes:
{"error": "Line 1, Col 6: syntax error", "code": "PARSE_ERROR"}Architecture Hardening
From the architecture review (Wave 3):
- REC-02: Fixed integer overflow, unchecked realloc, and O(n²) strcat in result serialization
- REC-03/04/05: Eliminated strict-aliasing violations and fixed-size truncation buffers
- REC-07: Added scale guards for O(N²) graph algorithms
- REC-08: Migrated Graph API to parameterized queries (SQL injection prevention)
- REC-09: Deleted unused
bundled_init.c(593 lines of dead code) - REC-10: Single-pass result enumeration in
build_query_results - REC-11: Structured JSON error codes from C extension
- REC-12: Schema versioning via
PRAGMA user_version - REC-13: Hardened Rust extension extraction with atomic write and fallback
- REC-14: Migrated all static transform globals into per-query context (thread safety)
Test Coverage
- 926 CUnit tests (up from 770)
- 44 functional SQL test files (all running — previously stopped at test 26)
- 332 Python binding tests
- 233 Rust binding tests
Breaking Changes
None. All existing APIs are backward compatible.
Full Changelog
v0.4.0
What's New in v0.4.0
Bug Fixes (8)
- Integer storage widened to 64-bit (#43) — Integer properties were silently truncated to 32-bit, affecting
timestamp(), large IDs, and any value > 2.1 billion. Now usesint64_tthroughout the pipeline. size(labels(n))returns label count (#42) — Was returning the string length of the JSON representation instead of the number of labels.DELETE + RETURN COUNT(n)reports actual count (#39) — Was always returning 0 because the RETURN re-queried the already-empty graph.OPTIONAL MATCHrespects label filters (#34) —OPTIONAL MATCH (a)-->(r:Label)was ignoring the label constraint and returning unrelated nodes.UNWIND $paramaccepts parameters (#37) — Parameter references and map property access (item.id) now work in UNWIND expressions, enabling batch ingestion patterns.startNode(r).nameresolves properties (#41) —startNode()andendNode()now support property access and function composition.- MERGE variables persist through WITH (#36) —
MERGE ... SET ... WITH i MATCH ... MERGE ...now works via a new clause pipeline handler. SET n.prop = function()evaluates correctly (#35, #38) — Function calls and parameterized bulk SET (SET n += $param) now work in SET clauses.
Documentation
- Comprehensive Diátaxis documentation rewrite covering tutorials, how-to guides, reference, and explanation sections.
Testing
- 13 new reproduction tests covering all fixed bugs (Python + functional SQL)
- Rust test parallelism fix across CI and release workflows
Upgrading
This release changes integer storage from 32-bit to 64-bit. Existing databases are unaffected (SQLite INTEGER columns already support 64-bit). New integer values will now be stored at full precision.
Full Changelog: v0.3.10...v0.4.0
v0.3.10
What's New
Pattern predicates in WHERE clause (openCypher 9 compliance)
Bare relationship patterns now work as boolean expressions in WHERE clauses:
-- These are now equivalent:
MATCH (n) WHERE NOT (n)-[:BELONGS_TO]->() RETURN n
MATCH (n) WHERE NOT EXISTS((n)-[:BELONGS_TO]->()) RETURN nSupports all directions (->, <-, -), typed and untyped relationships, and combination with NOT/AND/OR/XOR.
Bug fixes
- EXISTS direction fix:
EXISTS(pattern)now correctly handles incoming (<-) and undirected (-) relationship patterns. Previously always assumed outgoing direction.
Testing
- Added Clotho bug reproduction tests to Rust integration suite, confirming
count(),OPTIONAL MATCH, property-match{key: value}, and undirected match all work correctly through the Rust binding path.
Full Changelog: v0.3.9...v0.3.10
v0.3.9
What's Changed
- feat: Cypher spec compliance push — 70% to 88% coverage by @dylanbstorey in #31
Full Changelog: v0.3.8...v0.3.9
GraphQLite 0.3.8
Bare relationship syntax is here. (a)--(b), -->, and <-- just work now. Undirected matches also got a correctness fix — they now properly query both edge directions instead of silently going forward-only.
Leading-zero strings stay strings. Zip codes like "02134" no longer get silently coerced to 2134 when returned via property access. Fixed at the C layer.
Rust bindings got a lot more ergonomic:
PropertyValueenum — pass typed values (42_i64,0.87_f64,true) directly to upsert, not just stringsValue::get("key")andIndex<&str>— no more pattern matching to read node propertiesget_edges_from(),get_edges_to(),get_edges_by_type()— edge queries without raw CypherGraph::query_params()— one-liner parameterized queriesGraphStatsfields renamed tonode_count/edge_count(breaking)
Python binding bug fixes:
- BFS/DFS and APSP now return actual results (were silently returning
[]) - Same
node_count/edge_countrename for consistency
Algorithm parameters work correctly — integer and double params passed to graph algorithms no longer cause segfaults (#29).
Big shout-out to @kynx for their first contribution to GraphQLite! Welcome aboard.
Full Changelog: v0.3.7...v0.3.8
v0.3.7
What's Changed
- Fix segfault on parameterized graph algorithm calls by @dylanbstorey in #28
Full Changelog: v0.3.6...v0.3.7
v0.3.5
What's Changed
- feat: make upsert_edge type-aware with property update support by @anonenity in #25
New Contributors
- @anonenity made their first contribution in #25
Full Changelog: v0.3.4...v0.3.5