Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Tags: orneryd/NornicDB

Tags

v1.0.11-preview

Toggle v1.0.11-preview's commit message
perf(release): document untagged latest changes

Add a consolidated untagged changelog for the latest image build (WAL durability hardening, Bolt/PackStream perf+correctness, Cypher parsing/traversal optimizations, storage/Badger cleanups) and link it from CHANGELOG.md.

v1.0.10-hotfix

Toggle v1.0.10-hotfix's commit message
refactor(multidb): enforce strict namespacing end-to-end and fix asyn…

…c/embed correctness

- Enforce namespaced IDs at the storage layer (no unprefixed keys)
- Persist db name in WAL entries and replay per-entry database on recovery
- Make search + k-means clustering per-database; remove default-only search service
- Make inference/Auto‑TLP per-database; remove default-only inference service
- Fix AsyncEngine flush/count races and embedding-update counting
- Fix nil GPU manager panic in clustered search
- Fix stale embeddings/indexes when deleting nodes before async flush commits
- Prevent system DB leakage into default queries; harden manager wiring + cleanup
- Add regression tests covering routing, WAL/async, and embedding/index cleanup

v1.0.10

Toggle v1.0.10's commit message
tagging release

v1.0.9

Toggle v1.0.9's commit message
v1.0.9 - GraphQL API & Neo4j Compatibility Improvements

Features:
- Add full GraphQL API with gqlgen (schema, resolvers, introspection)
- GraphQL endpoints: /graphql, /graphql/playground
- Complete CRUD mutations (createNode, updateNode, deleteNode, merge, bulk ops)
- GraphQL queries: search, similar, cypher, stats, schema, labels
- Admin mutations: triggerEmbedding, rebuildSearchIndex, runDecay, clearAll

Fixes:
- Fix Cypher map projection returns without explicit AS aliases
- Fix aggregation query alias handling in RETURN clauses
- Fix embed queue pending embeddings index tracking
- Improve Neo4j driver compatibility in UI Browser responses

Tests:
- Add GraphQL resolver and handler tests
- Add storage pending embeddings index tests
- Add node needs embedding tests
- Add Cypher return alias tests

Docs:
- Add GraphQL README with usage examples
- Add QUERIES.md with sample GraphQL operations

v1.0.8

Toggle v1.0.8's commit message
fixing parsing AS after map projection

v1.0.7

Toggle v1.0.7's commit message
Release v1.0.7 (2025-12-14)

Added:
- Documentation: `DIY.md` with Vulkan/Makefile build instructions and targets.

Changed:
- Makefile/docs: added AMD64 Vulkan build targets and documented usage.

Fixed:
- Neo4j compatibility: return `*storage.Node` and `*storage.Edge` directly from Cypher query results with correct Bolt protocol serialization and property access handling.
- Neo4j compatibility: improved integer handling in Cypher/driver interoperability.

See CHANGELOG.md for full details

v1.0.6

Toggle v1.0.6's commit message
Release v1.0.6 (2025-12-12)

Added:
- Timer-based K-means clustering scheduler; runs on startup and periodically (default 15m)
- New config: NORNICDB_KMEANS_CLUSTER_INTERVAL

Changed:
- Switched K-means from embed-queue trigger to timer-based scheduler; skips runs when no embedding changes
- DB lifecycle starts/stops clustering ticker cleanly

Fixed:
- Prevent excessive K-means executions
- Cypher YIELD/RETURN compatibility: RETURN after YIELD for property access, ORDER BY/LIMIT/SKIP handling

Tests:
- Added pkg/cypher/yield_return_test.go and updated neo4j compatibility tests

See CHANGELOG.md for full details

1.0.4-aml-preview

Toggle 1.0.4-aml-preview's commit message
locking down server auth

v1.0.5

Toggle v1.0.5's commit message
- **Critical: Node/Edge Count Returns 0 After Delete+Recreate Cycles*…

…* - `MATCH (n) RETURN count(n)` returned 0 even when nodes existed in the database

  - Atomic counters (`nodeCount`, `edgeCount`) in `BadgerEngine` became out of sync during delete+recreate cycles
  - Root cause: Nodes created via implicit transactions (MERGE, CREATE) bypass `CreateNode()` and use `UpdateNode()`
  - `UpdateNode()` checks if key exists to determine `wasInsert=true/false`, only incrementing counter when `wasInsert=true`
  - During delete+recreate, keys could still exist in BadgerDB from previous sessions, causing `wasInsert=false` for genuinely new nodes
  - The counter would increment for only 1 node, leaving `nodeCount=1` even with 234 nodes in the database
  - **Production symptom**: After deleting all nodes and re-importing 234 nodes via MERGE, `/metrics` showed `nornicdb_nodes_total 0` while `MATCH (n:Label)` returned all 234 nodes correctly
  - **Solution**: Changed `BadgerEngine.NodeCount()` and `EdgeCount()` to scan actual keys with prefix iteration instead of trusting atomic counter
  - Key-only iteration (no value loading) provides fast O(n) counting with guaranteed correctness
  - Atomic counter is updated after each scan to keep it synchronized for future calls
  - **Impact**: Count queries now always reflect reality. Embeddings worked because they scan actual data; node counts failed because they used broken counter.

- **Critical: Aggregation Query Caching Caused Stale Counts** - `MATCH (n) RETURN count(n)` was being cached, returning stale results after node creation/deletion
  - `SmartQueryCache` was caching aggregation queries (COUNT, SUM, AVG, etc.) which must always be fresh
  - Modified `pkg/cypher/executor.go` to detect aggregation via `HasAggregation` flag and skip caching entirely
  - Modified `pkg/cypher/query_info.go` to analyze queries and set `HasAggregation=true` for COUNT/SUM/AVG/MIN/MAX/COLLECT
  - Modified `pkg/cypher/cache.go` to invalidate queries with no labels when any node is created/deleted (affects `MATCH (n)` count queries)
  - **Impact**: Count queries always return fresh data, no manual cache clear needed

- **Performance Trade-off: NodeCount() and EdgeCount() Now O(n)** - Changed from O(1) atomic counter to O(n) key scan for correctness
  - Key-only iteration is very fast (no value decoding, just prefix scan)
  - BadgerDB iterators are highly optimized for this access pattern
  - Correctness > speed for core count operations
  - Future optimization: Maintain accurate counter through all write paths

- Modified `pkg/storage/badger.go`:
  - `NodeCount()` now uses `BadgerDB.View()` with key-only iterator (`PrefetchValues=false`)
  - `EdgeCount()` uses same pattern for edge prefix scan
  - Both methods sync atomic counter after scan to reduce overhead on subsequent calls
- Modified `pkg/storage/async_engine.go`:
  - Fixed `NodeCount()` calculation to include `inFlightCreates` to prevent race condition during flush
  - Prevented double-counting during flush window when nodes transition from cache to engine
- Modified `pkg/cypher/executor.go`:
  - Added aggregation detection to skip caching for COUNT/SUM/AVG/MIN/MAX queries
- Modified `pkg/cypher/query_info.go`:
  - Added `HasAggregation` field to `QueryInfo` struct
  - Updated `analyzeQuery()` to detect aggregation functions
- Modified `pkg/cypher/cache.go`:
  - Fixed `InvalidateLabels()` to also invalidate queries with no labels (e.g., `MATCH (n)`)

- All existing tests pass with updated expectations
- Modified `pkg/storage/realtime_count_test.go` to account for transient over-counting before flush
- Modified `pkg/cypher/executor_cache_test.go` to use non-aggregation queries (since aggregations aren't cached)
- Added comprehensive logging and debugging to trace count calculation flow
- Production issue validated as fixed: 234 nodes now counted correctly after delete+reimport

v1.0.4

Toggle v1.0.4's commit message
- **Critical: ORDER BY Ignored for Relationship Patterns** - `ORDER B…

…Y`, `SKIP`, and `LIMIT` clauses were completely ignored for queries with relationship patterns

  - Queries like `MATCH (p:Person)-[:WORKS_IN]->(a:Area) RETURN p.name ORDER BY p.name` returned unordered results
  - `executeMatchWithRelationships()` was returning immediately without applying post-processing clauses
  - Fixed by capturing result, applying ORDER BY/SKIP/LIMIT, then returning
  - Affects all queries with relationship traversal: `(a)-[:TYPE]->(b)`, `(a)<-[:TYPE]-(b)`, chained patterns
  - **Impact**: Fixes data integrity issues where clients relied on sorted results

- **Critical: Cartesian Product MATCH Returns Zero Rows** - Comma-separated node patterns returned empty results instead of cartesian product
  - `MATCH (p:Person), (a:Area) RETURN p.name, a.code` returned 0 rows (should return N×M combinations)
  - `executeMatch()` only parsed first pattern, ignoring subsequent comma-separated patterns
  - Fixed by detecting multiple patterns via `splitNodePatterns()` and routing to new `executeCartesianProductMatch()`
  - Now correctly generates all combinations of matched nodes
  - Supports WHERE filtering, aggregation, ORDER BY, SKIP, LIMIT on cartesian results
  - **Impact**: Critical for Northwind-style bulk insert patterns like `MATCH (s), (c) CREATE (p)-[:REL]->(c)`

- **Critical: Cartesian Product CREATE Only Creates One Relationship** - `MATCH` with multiple patterns followed by `CREATE` only created relationships for first match
  - `MATCH (p:Person), (a:Area) CREATE (p)-[:WORKS_IN]->(a)` created 1 relationship (should create 3 for 3 persons × 1 area)
  - `executeMatchCreateBlock()` was collecting only first matching node per pattern variable
  - Fixed by collecting ALL matching nodes and iterating through cartesian product combinations
  - Each CREATE now executes once per combination in the cartesian product
  - **Impact**: Fixes bulk relationship creation patterns used in data import workflows

- **UNWIND CREATE with RETURN Returns Variable Name Instead of Values** - Return clause after `UNWIND...CREATE` returned literal variable names
  - `UNWIND ['A','B','C'] AS name CREATE (n {name: name}) RETURN n.name` returned `["name","name","name"]` (should be `["A","B","C"]`)
  - `replaceVariableInQuery()` failed to handle variables inside curly braces like `{name: name}`
  - String splitting on spaces left `name}` which didn't match variable `name`
  - Fixed by properly trimming braces `{}[]()` and preserving surrounding punctuation during replacement
  - **Impact**: Fixes all UNWIND+CREATE+RETURN workflows, critical for bulk data ingestion with result tracking

- **Cartesian Product Performance** - New `executeCartesianProductMatch()` efficiently handles multi-pattern queries
  - Builds combinations incrementally to avoid memory explosion on large datasets
  - Supports early filtering with WHERE clause before building full product
  - Properly integrates with query optimizer (ORDER BY, SKIP, LIMIT applied after filtering)

- Modified `pkg/cypher/match.go`:
  - Added `executeCartesianProductMatch()` for comma-separated pattern handling
  - Added `executeCartesianAggregation()` for aggregation over cartesian results
  - Added `evaluateWhereForContext()` for WHERE clause evaluation on node contexts
  - Fixed `executeMatch()` to detect and route multiple patterns correctly
  - Fixed relationship pattern path to apply ORDER BY/SKIP/LIMIT before returning
- Modified `pkg/cypher/create.go`:
  - Updated `executeMatchCreateBlock()` to collect all pattern matches (not just first)
  - Added cartesian product iteration for CREATE execution
  - Now creates relationships for every combination in MATCH cartesian product
- Modified `pkg/cypher/clauses.go`:
  - Fixed `replaceVariableInQuery()` to handle variables in property maps `{key: value}`
  - Improved punctuation preservation during variable substitution

- All existing tests pass (100% backwards compatibility)
- Fixed `TestWorksInRelationshipTypeAlternation` - ORDER BY now works correctly
- Fixed `TestUnwindWithCreate/UNWIND_CREATE_with_RETURN` - Returns actual values, not variable names
- Cartesian product patterns now pass all Northwind benchmark compatibility tests