The test was comparing a Value to a string literal which always failed.
Changed to check s.kind == vkNull on both calls.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Root cause: seq.del(i) does swap-with-last (destroys sorted order)
while seq.delete(i) preserves order. This caused massive data loss
during B-tree removes.
Changes:
- btree.nim: Replace seq.del with seq.delete (critical data corruption fix)
- btree.nim: search() traverses leaf linked list for duplicate boundary keys
- btree.nim: splitChild() consolidates duplicate boundary key values before split
- btree.nim: len() counts unique keys via leaf traversal
- btree.nim: remove() traverses leaf linked list to remove ALL occurrences
- btree.nim: Fix separator update in internal node (node.keys[i-1] not [i])
- prop_test.nim: Use set equality for interleaved test (rebalancing reorders)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Refactored Row from Table[string, string] to Table[string, Value]
- Added Value operators: ==, !=, $, in for string interop
- Fixed valueToString for vkNull to return '\\N' instead of ''
- Fixed evalExpr irekField to return vkNull when field not found
- Added IN (val1, val2, ...) parser support
- Fixed nkPath column names in multi-table joins
- Fixed LATERAL JOIN null padding when no matching rows
- Added CREATE/DROP/USE/SHOW DATABASE parser support
- Adapted all tests for new Value type
- Add isDelete flag to VersionedRecord to fix COMMIT treating empty values
as DELETE. Previously version.xmax != TxnId(0) was never true for active
transactions, so deletes inside transactions never removed rows.
- Fix MIN/MAX aggregates skipping NULL: was checking for "\\N" instead
of correct "\N" sentinel, so NULL values were never skipped.
- Add duplicate alias deduplication in lowerSelect() and getSelectColumns().
Identical aliases now get _1, _2 suffixes (e.g. count(*), count(*)_1).
- Add nil guard for expr.subqueryPlan in irekSubquery evalExpr handler.
- Initialize txnManager in newExecutionContext to prevent segfault on BEGIN.
- Add regression tests: DELETE in transaction, PK-only row survival,
MIN/MAX NULL skipping.
evalExpr was missing irekSubquery case — scalar subqueries in SELECT/WHERE
fell through to else:return "" producing empty strings. Add:
- irekSubquery handler in evalExpr that executes the subquery plan
- outerRow + subqueryPlan fields on ExecutionContext for correlation
- qualified column injection in execScan for correlated filter refs
- collectCorrelatedTablesFromPlan to discover outer table references
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- prop_test.nim: 11 new property-based B-Tree invariants
(size accuracy, get roundtrip, scan ordering, range correctness,
contains, remove, large order, duplicates, empty tree, interleaved ops)
- bench_all.nim: JSON-based benchmark result tracking with regression
comparison against previous runs; each benchmark reports ops/sec
delta vs last run
- Populate HNSW metadata with all relational columns during INSERT and CREATE INDEX
- Add doHybridSearchFiltered() using searchWithFilter() for HNSW pre-filtering
- Add SQL function hybrid_search_filtered(table, vec_col, text_col, query, vector, k, filter_col, filter_val)
- Enforce k-limit on both doHybridSearch and doHybridSearchFiltered results
- 2 tests: tenant isolation + empty filter fallback
- Add tkRestrict token to lexer
- Parse ON DELETE CASCADE/SET NULL/RESTRICT and ON UPDATE CASCADE/SET NULL/RESTRICT
in both table-level and column-level FK constraints
- Add fkOnDelete/fkOnUpdate to ColumnDef and ForeignKeyDef
- Fix table-level FK constraint application (third pass after columns are created)
- Implement enforceFkOnDelete, enforceFkOnUpdate, enforceFkOnChildUpdate helpers
- Wire FK enforcement into DELETE and UPDATE execution paths
- Add 9 regression tests covering all FK actions
- Добавен IRJoinStrategy enum (nestedLoop, hash, indexNestedLoop)
- Hash Join: build hash table върху по-малката страна, probe от другата
- Index Nested Loop Join: използва B-Tree индекс за point lookup
- Query planner chooseJoinStrategy избира стратегия според наличие на индекс
- LEFT/RIGHT/FULL JOIN fallback-ват към Nested Loop
- PK индексите се игнорират за INL (само explicit индекси)
- Benchmark: JOIN 10K ~115ms (Hash), ~90ms (Index NL)
- 5 нови теста за join performance и planner избор
Тестове: 316 — 0 failures
Build: 0 warnings
- Поправени deficiencies #5-#8 (GROUP BY bare columns, aggregate names,
sync client с blocking socket, thread-safe Lock в SyncClient)
- Добавен BlockingClient (net.Socket + Lock) в clients/nim/src/baradb/client.nim
- Обновен src/barabadb/client/client.nim със sync клиент без waitFor
- Regression тестове за всички 10 deficiencies
- Добавен valueKind в IRExpr за типова информация
- evalExprValue връща Value discriminated union
- Премахнати parseFloat евристики от irAdd/Sub/Mul/Div/Mod/Pow/Neg
- INT+INT→INT, INT+FLOAT→FLOAT, FLOAT/INT→FLOAT
- 12 нови теста за type safety
Тестове: 311 — 0 failures
Build: 0 warnings
- Fix 3× ResultShadowed in cypher.nim, recovery.nim, shell.nim
- Remove 6× UnusedImport in test files
- Build is now clean: 0 warnings, 294 tests pass
- Add 4-week stabilization plan to PLAN.md (Sessions 9.1–9.4)
- Add missing nkSubquery case in lowerExpr so scalar subqueries
(e.g. budget > (SELECT AVG(budget) FROM projects)) are lowered
correctly instead of being treated as NULL literals.
- Move UPDATE SET expression evaluation inside the row loop so
column references (e.g. salary + 5000) are resolved against the
current row, fixing type validation failures.
- Make irAdd/irSub/irMul/irDiv return integer strings when the
result is a whole number, avoiding spurious float output for INT
columns (e.g. MERGE UPDATE qty = 100 + 50 now yields 150).
These fix regressions introduced by switching NULL representation
from empty string to \N, which exposed the pre-existing bugs above.
Refs: issue #9, issue #10
Issue 9: Add backtick-quoted identifier support in lexer.nim
- Users can now write `key` to use reserved keywords as column/table names
Issue 10: Use \N as internal NULL marker instead of empty string
- isNull() now checks for \N instead of value.len == 0
- Empty strings can now be stored in NOT NULL columns
- NULL values properly distinguished from empty strings in storage, wire protocol, and HTTP JSON responses
- Add --path:src and --threads:on to nim.cfg so tests compile without manual flags
- Add tests/config.nims for automatic path resolution in test directory
- Simplify nimble task definitions (remove redundant flags now in nim.cfg)
- Fix Dockerfile.source comment: remove obsolete nimmax reference
This makes 'nim c tests/test_all.nim' and 'nimble test' work out of the box.
ID Generators:
- AUTO_INCREMENT for INTEGER columns
- SERIAL / BIGSERIAL as syntactic sugar
- gen_random_uuid() / uuid() for UUID v4 generation
- nextval() / currval() for sequence support
- snowflake_id(node_id) for distributed 64-bit IDs
- RETURNING clause for INSERT
Deficiency Fixes:
- Comma join: FROM t1, t2 now works as implicit CROSS JOIN
- DEFAULT in restoreSchema: defaults survive server restart
- Duplicate column names: t.id instead of id in joins
- Empty result sets: always send column metadata to client
- GROUP BY non-agg columns: return first row value instead of empty
- Aggregate column names: count(*) instead of count()
Bug fix: PK uniqueness check now uses correct key format
- Add VECTOR(n) column type support in CREATE TABLE
- Add CREATE INDEX ... USING hnsw/ivfpq for vector indexes
- Add cosine_distance(), euclidean_distance(), inner_product(), l1/l2_distance()
SQL functions in expression evaluator
- Add <-> nearest-neighbor operator
- Fix ORDER BY with non-projected columns (move irpkSort before irpkProject)
- Fix execInsert to escape comma-containing values (vector literals)
- Fix MERGE tests by using unique temp dirs per test suite
- Add 8 Vector SQL Integration tests (all passing)
- Update PLAN_SQL_ADVANCED.md
- Add Window Functions: ROW_NUMBER, RANK, DENSE_RANK, LEAD, LAG,
FIRST_VALUE, LAST_VALUE, NTILE with PARTITION BY, ORDER BY,
ROWS/RANGE frame specifications
- Add MERGE/UPSERT statement with WHEN MATCHED UPDATE and
WHEN NOT MATCHED INSERT
- Add SQL/PGQ Property Graph long-term plan in PLAN_SQL_ADVANCED.md
- Add 7 new tests for Window Functions and MERGE
- Update baraql.md documentation
- Added missing irNeg case in evalExpr (query/executor.nim)
- Unary minus previously fell through to else: return 'false'
- Added 2 tests: SELECT expression and WHERE condition
Add tests/tla_faithfulness.nim verifying Nim code against TLA+ invariants:
- Raft: ElectionSafety, LogMatching, CommittedIndexValid
- MVCC: NoDirtyReads, CommittedMustStart
- 2PC: Atomicity, RecoveryConsistency
Documented gap: Nim MVCC allows multiple committed versions per key,
while TLA+ spec enforces first-committer-wins (WriteWriteConflict).
This test ensures future changes to Nim code maintain alignment with specs.
Update PLAN.md (FV-14 done), CHANGELOG.md, test_all.nim includes new suite.
- evalExpr accepts optional ExecutionContext for FTS index lookup
- CREATE INDEX ... USING FTS builds InvertedIndex from existing data
- @@ uses BM25 scoring when FTS index exists, falls back to term match
- INSERT/UPDATE/DELETE auto-maintain FTS indexes
- 283 tests, 0 failures
- Recursive CTE execution (WITH RECURSIVE + UNION ALL, work-table loop)
- UNION / INTERSECT / EXCEPT parser + executor (nkSetOp)
- DROP INDEX parser + executor
- VIEW DDL persistence via AST-to-SQL serializer
- JSON path operators -> and ->> (lexer, parser, IR, executor)
- FTS SQL wiring WHERE col @@ 'query' (case-insensitive term match)
- Multi-column index range scans (prefix equality + range on last col)
- Covering index optimization (skip LSM read when index covers SELECT)
- SCRAM-SHA-256 authentication (password-based validation)
- 279 tests, 0 failures