Release history
34 releases of Katzebase.
Be sure to check out the NuGet package: https://www.nuget.org/packages/NTDLS.Katzebase.Api/ 📦
Release Notes
Performance: transactions, locking and indexing
This release targets insert and select throughput. Single statements are now up to ~100× faster, concurrent workloads up to ~200× faster, and several index consistency bugs have been fixed.
Highlights
| Scenario | Before (ops/s) | After (ops/s) | Change |
|---|---|---|---|
Single-row INSERT (implicit transaction) |
33 | 3,780 | ~115× |
Bulk INSERT (rows/s, 1,000-row statements) |
6,631 | 13,377 | ~2× |
SELECT by unique key |
34 | 3,116 | ~92× |
SELECT by non-unique index (~230 rows) |
30 | 186 | ~6× |
SELECT by composite index |
24 | 228 | ~9× |
Concurrent SELECT by unique key (8 threads) |
29 | 6,957 | ~240× |
| 1 writer + 8 concurrent readers | 28 | 6,324 | ~225× |
UPDATE indexed column by unique key |
31 | 2,666 | ~86× |
Engine benchmark, median of three runs on the same machine, statements pre-parsed so parser time is excluded. 23,000 documents with a non-unique, a composite and a unique index.
Transactions
- Every transaction no longer creates and drops its own RocksDB column family. Doing so forced RocksDB to rewrite its MANIFEST, which took ~22 ms and was serialized across the whole database. Because every statement runs in a transaction, this capped the server at roughly 40 statements per second regardless of load or thread count. The undo log now lives in one shared
TransactionAtomscolumn family, keyed by transaction id and sequence. The overhead of an empty transaction dropped from ~22 ms to ~0.13 ms. - Transaction log sequence numbers are generated in memory, replacing a RocksDB read and write per logged change.
- Transaction log entries are stored in a compact binary format instead of JSON. One entry is written for every key a transaction creates, alters or deletes.
- The name of the API operation is now captured at compile time, so a stack trace is no longer captured on every statement.
Locking
- The lock table is now indexed by object, path and recursive path. Finding conflicting locks no longer scans every lock held in the engine.
- There is a new fast path for already-covered locks. A lock request that is already satisfied by a lock the transaction holds (for example, a document inside a schema it has locked) only needs a shared read of the lock table. The exclusive path is skipped.
- Blocked lock requests now wait instead of spinning. They sleep until a lock is released, or for at most 25 ms so that deadlock detection, lock-wait timeouts and cancellation still run. Previously, waiting transactions repeatedly took the global lock-management semaphore and starved every other transaction.
- Transactions are only registered as "waiting" once they are actually blocked.
- The redundant per-file grant semaphores were removed.
- Health counters are now lock-free on the hot path. Every IO read, cache hit and lock grant previously took a global write lock just to increment a counter.
Indexing
- New index storage layout: one entry per document. Previously each distinct indexed value had one entry holding the packed list of every matching document id. Every insert or delete then read and rewrote the whole list, so maintaining an index on a column with few distinct values got slower as the table grew. In testing, an index on a two-value column dropped from ~5,600 to ~700 rows/s by 200,000 rows. Each document now has its own entry, so inserts and deletes are a single small write; the same test stays flat at ~30,000 rows/s.
- Non-unique indexes are keyed by the values plus the document id. Unique indexes are keyed by the values alone, with the document id as the value, so unique lookups and uniqueness checks are a single key read.
- Building and rebuilding indexes is about 3.5× faster and reads about 25× less data. The build used to collect every document id and then read each document by id. RocksDB reads whole data blocks and the block cache is disabled, so each block was read once for every document it contained. Documents are now read in a single sequential scan and keyed in parallel chunks. With 500,000 documents,
CREATE INDEXwent from ~3.8 s to ~1.0 s (about 130,000 to 480,000 rows/s), and the data read per build from 395 MB to 16 MB. - Bloom filters are enabled on all RocksDB tables. Lookups for keys that don't exist, such as the existence check on every insert, can skip reading data from disk. They apply to newly written data files; existing files gain them as RocksDB compacts.
- The index catalog is cached. It was read from RocksDB and JSON-deserialized for every inserted, updated or deleted document and for every query. It is now cached per schema and invalidated by
CREATE INDEX,DROP INDEXandREBUILD INDEX, including on commit and rollback. - Multiple indexes are now intersected. Previously, when a condition group could use more than one index, only the last lookup chosen was kept, which was the least selective one. Lookups are now ranked (unique point lookup, then point lookup, then prefix seek, then full index scan) and the cheap ones are intersected.
- Composite indexes seek on all leading equality columns. Previously only the first column was used. When every column is constrained by an equality, the lookup is a single key read.
- Condition values are resolved once per lookup instead of once per scanned index key.
UPDATEskips index maintenance for any index whose values did not change.EXPLAINoutput lists every index used for a condition group and notes when the indexes are intersected.
Bulk inserts
- New
client.Document.StoreMany(schema, documents)API. It sends a batch of documents to the server in one round trip and stores them in a single atomic transaction. It returns the new document ids in the order they were given. With batches of 1,000 documents, inserts run at about 14,000 rows/s with three indexes and about 28,000 rows/s with none. That compares to about 4,100 rows/s with oneDocument.Storecall per row. NTDLS.Katzebase.SQLServerMigrationnow imports data withStoreMany, in batches of up to 1,000 rows or 4 MB.
Client API (NTDLS.Katzebase.Api)
- Typed exceptions. Server errors used to reach the client as plain
System.Exception, so callers could only tell them apart by message text. They are now rethrown as the same type the server raised (KbDuplicateKeyViolationException,KbObjectNotFoundException,KbDeadlockException,KbParserExceptionwith its line number, ...). Timeouts throwKbTimeoutException, and requests when not connected (or when the connection is lost) throw the newKbConnectionException. - New document operations by id:
Document.Get,Get<T>,Replace(replaces the whole document and updates indexes),DeleteandDeleteMany.Document.Storenow returns the new document's id. - Async methods. Every operation has an
...Asyncversion that accepts aCancellationToken. - Transaction scopes.
Transaction.Begin()returns a scope; disposing it rolls the transaction back unlessCommit()was called. - Schema
Attach/Detachmethods forATTACH SCHEMAandDETACH SCHEMA. - Simpler parameters. Each query method takes one
parametersargument: an anonymous object, any object, or a dictionary of names to values (with or without the leading@). Values are sent culture-invariantly, so1.5is no longer sent as"1,5"on machines using a comma decimal separator. Booleans are sent as1/0and dates in ISO 8601. - More robust result mapping (
Fetch<T>,MapTo<T>). Values are parsed culture-invariantly, booleans accept1/0, enums and nullable types are supported, and read-only properties are skipped instead of failing. Dispose()no longer throws when the server is unreachable, andDisconnect()is now public.
Client/server protocol and logging
- Compression has been removed from the client/server connection. Deflate compression of every message cost more time than it saved. Single-row inserts through the client are 10–20% faster without it (2,167 → 2,657 rows/s inside an explicit transaction).
- Trace logging no longer captures a stack trace when tracing is disabled. Every trace call captured a full stack trace to name the caller, even when verbose logging was off, and the engine traces every document read. Reads and updates are 30–55% faster as a result. For example, point selects went from 3,116 to 4,601 per second, and concurrent point selects from 6,957 to 10,778.
New: ATTACH SCHEMA and DETACH SCHEMA
Namespaces (a schema with all of its documents, indexes, policies and child schemas) can now be moved between databases and servers.
-- Remove a namespace from this database and move its files to a folder.
DETACH SCHEMA Sales:Archive TO 'D:\Exports\SalesArchive'
-- Copy a namespace from a folder into this (or another) database, under any name.
ATTACH SCHEMA Sales:Archive FROM 'D:\Exports\SalesArchive'
ATTACH SCHEMA <schema> FROM '<folder>'copies the folder into the database as a new schema; the source folder is never modified.- Each schema in the attached namespace gets a new id, so the same folder can be attached more than once.
- The statement's output reports any indexes created by an older version of Katzebase, which must be rebuilt before use.
DETACH SCHEMA <schema> TO '<folder>'removes the schema from the database and moves its folder out. It waits for other transactions using the schema to finish.- The folder can be a quoted string or a string variable. It must be an absolute path that does not yet exist (for
DETACH), and it must not be inside the server's data or transaction folders. - Both statements require an administrator, because they read and write arbitrary folders on the server. They can't be used inside an explicit transaction, because moving files can't be undone by the transaction log.
- Failures never leave a partially attached or detached namespace:
ATTACHcopies into a staging folder, checks that every schema in it can be opened, then renames the folder into place.DETACHunregisters the schema before moving its files, and puts them back if the move fails.
- Folder paths cannot end with a backslash (
'D:\Exports\'), because a trailing backslash escapes the closing quote.
Management UI
Explain Plan suggests indexes. For each schema in the query, the explain plan now lists the indexes that would let its conditions be answered by an index lookup instead of reading every document, as ready-to-run
CREATE INDEXstatements (also returned byQuery.ExplainPlanin the client API).- Fields compared with
=come first, followed by at most one range field (>,>=,<,<=,BETWEEN). - Nothing is suggested when the existing indexes already serve the conditions: an index whose leading fields cover them, a unique key that is fully matched, or several indexes whose lookups are intersected. Conditions that no index can serve (
LIKE,!=, expressions) are not considered. - Each
ORgroup is considered separately, since one unindexed group makes the whole schema scan. When anORgroup doesn't filter the schema at all, nothing is suggested for it, because no index could help. - Join conditions are considered for the joined schema.
- When an index in the old storage format would serve the conditions,
REBUILD INDEXis suggested instead of a new index.
- Fields compared with
Attach Schema... and Detach Schema... (right-click a schema) ask for a folder and open a ready-to-run
ATTACH SCHEMAorDETACH SCHEMAscript in a new tab. Attach adds the folder as a child of the schema that was clicked, named after the folder. Detach moves the schema into a new folder, named after the schema, inside the selected folder.Create Index (right-click a schema or its Indexes folder) now opens a ready-to-edit
CREATE INDEXscript for the schema, listing the schema's known fields.Find in Server Explorer (right-click an editor tab) now selects, in the server explorer, the schema referenced by the statement under the cursor, or the tab's server if the script doesn't reference one.
Opening a recent file that no longer exists now says so, and removes it from the Recent Files menu immediately.
Bug fixes
Reading a document by key after it was updated or deleted could return the stale cached version. Writes and deletes now evict the cached copy.
KbProcedure(schemaName, procedureName)assigned the schema and procedure names to each other.Creating or rebuilding an index leaked a RocksDB column family handle. Dropping a column family (which
CREATE INDEX,REBUILD INDEX,DROP INDEXand transaction rollback all do) never destroyed its handle. That kept part of the schema's database open after it was closed, so the schema's folder could not be moved or renamed until the server restarted.Index entries are now part of the transaction log. Previously they were written outside the log, which caused these problems:
- A rolled-back or failed
INSERT(including one that failed on a unique-key violation) left index entries pointing at documents that no longer existed. Later indexed queries failed withDocument with ID [n] does not exist, and unique values remained taken. - A rolled-back
DELETEdid not restore its index entries, so the document disappeared from index lookups.
- A rolled-back or failed
UPDATEdid not remove documents from their old index entries. The document was already modified when the old entry was looked up, so the stale entry remained. After updating a unique column, the old value could never be inserted again.Concurrent
UPDATEs on the same schema deadlocked.UPDATEtook a schema read lock and then document write locks. Each transaction's read lock blocked the others' write locks, which is a lock-upgrade deadlock. In testing, more than half of concurrent updates were terminated as deadlock victims.UPDATEs that named a column with different casing than the index definition (e.g.SET sub = …on an index overSub) skipped index maintenance.When deferred IO was enabled, reading a list of objects (such as the index catalog) skipped items not modified by the current transaction.
SQL Server migration could silently lose rows. Any error other than a deadlock was swallowed and the row was skipped. A deadlock rolled back the whole open transaction (up to 10,000 rows), but only the current row was retried. Now each batch is atomic, so a deadlocked batch is retried in full (up to 10 times with backoff). Any other error stops the import of that table, and the error message is shown in the grid.
ANALYZE SCHEMA ... WITH (IncludePhysicalPages = true)reported every non-unique index as having no documents. It now counts the new one-entry-per-document layout correctly, and reports indexes in the old format as needing a rebuild.IndexSelection.Clone()copied covered conditions into itself instead of the clone.Concurrent first use of a schema could fail with "Failed to create lock file ... being used by another process". Two requests that opened a schema's documents database at the same time could both try to open it, and the second failed (for example, two clients logging in at once both opening
Master:Account). The database is now opened exactly once.The server failed to start when a data folder was configured with a Windows 8.3 short name (such as
C:\Users\JPATTE~1\...). Some paths were expanded to their long form and others weren't, so the same RocksDB database was opened twice. Configured folders are now always stored as full, long paths.Scalar and aggregate function fixes:
IsInteger()returned the opposite result (0 for'15', 1 for'1.5'). It now also accepts integers larger than 32 bits.CountDistinct(values, caseSensitive)had its flag reversed. It now ignores case by default and compares case-sensitively when the flag is true.IsEmpty(),IsNumeric(),NullWhen()andNullWhenNumeric()were listed byShowScalarFunctionsbut failed with "not implemented". They now work, andIsEmpty()andIsNumeric()return1/0like the other boolean functions.
BETWEEN low AND highandNOT BETWEENnow work. The parser treated theANDinsideBETWEENas a connector between two conditions, andNOTwas always read asNOT LIKE, so both forms failed with a parser error. Only an undocumentedBETWEEN 'low:high'string form worked; that form has been removed.- The low and high values can be numbers, fields, variables or expressions, and are compared as numbers (culture-invariantly). A missing (null) value matches neither
BETWEENnorNOT BETWEEN. BETWEENworks in joinONconditions (ON n.Id BETWEEN r.Low AND r.High) and uses an index on the field when one is available.IsBetween()andIsNotBetween()no longer truncate decimal values to integers.
- The low and high values can be numbers, fields, variables or expressions, and are compared as numbers (culture-invariantly). A missing (null) value matches neither
A condition with a parenthesized value after a keyword, such as
Id BETWEEN (1 + 1) AND 4, failed with "Function is undefined: [Id]".EXECwith a name that isn't a system procedure failed with "Reimplement user procedures". It now throwsKbObjectNotFoundException("Procedure not found"), as doesProcedure.Executein the client API.Removed the
DocumentID()scalar function. It was left over from the page-based storage engine and always returned null. Document ids are returned by the client API.Debug builds failed to compile due to unqualified types in
SystemShowAggregateFunctions,SystemShowScalarFunctionsandSystemShowSystemFunctions.
Breaking changes
Client API changes:
- Query and procedure methods take a single
object? parametersargument instead of separate object/dictionary overloads. Pass timeouts by name (queryTimeout:) or using the(statement, TimeSpan)overloads. ATimeSpanpassed as parameters is rejected. - Procedures are identified by their fully qualified name (
"Schema:Procedure"); the separate schema/procedure-name overloads were removed. Schema.Indexes.Getreturns theKbIndex(or null) andSchema.Indexes.ListreturnsList<KbIndex>, rather than reply objects.Fetch<T>and friends returnList<T>.Server.StartSessionandServer.CloseSessionare internal; useConnectandDisconnect.- Parameters are sent with different representations: booleans as
1/0, dates in ISO 8601, numbers in the invariant culture. COMMIT(andTransaction.Commit()) with no open transaction is now an error (KbTransactionCancelledException). It used to silently succeed, so a transaction the server had rolled back, e.g. as a deadlock victim, looked committed.
- Query and procedure methods take a single
The wire protocol has changed: client/server compression has been removed. Clients and servers from this release cannot communicate with clients or servers from earlier releases. Upgrade the server and every application that uses
NTDLS.Katzebase.Api(including the management tools) together.The index storage format has changed. Every existing index must be rebuilt with
REBUILD INDEX <name> ON <schema>after upgrading. Until it is rebuilt, an index:- is ignored by queries, which fall back to scanning documents, so results stay correct but are slower;
- causes inserts, updates and deletes on its schema to fail with an error naming the index and the command to run.
Behavior changes
UPDATEnow acquires a write lock on the target schema up front, the same wayINSERTdoes. Concurrent updates to the same schema now run one after another instead of deadlocking. Updates to different schemas are unaffected.SHOW WAITING LOCKSnow only lists transactions that are actually blocked, not every in-flight lock request.
Upgrade notes
- Upgrade the server and all clients at the same time. See Breaking changes.
- The on-disk transaction log format has changed. Shut the server down cleanly before upgrading. Transactions that were left open by a crash of a previous version are not rolled back by this version.
- Rebuild every index (
REBUILD INDEX <name> ON <schema>) after upgrading. See Breaking changes. Rebuilding also removes any stale entries left by the index bugs fixed in this release. - Document and schema storage formats are unchanged.
Testing
- Added
TestIndexConsistency. It covers rolled-back inserts, updates and deletes; failed inserts; updates that move index entries; queries using multiple indexes; and concurrent updates. - Added
TestAttachDetach. It covers detaching and re-attaching a namespace (documents, indexes and child schemas), attaching the same folder twice, reporting outdated indexes, and invalid or unsafe requests. - Added the
InsertBenchmarktest application. It measures inserts through the client API in four ways: single-row SQLINSERTs without an explicit transaction, the same inside an explicit transaction committed every N rows,Document.Storeper row, andDocument.StoreManyin batches. By default it hosts its own server in-process;--server host:porttargets an existing server instead. Run it with--helpfor all options.--index-buildinstead loads--rowsdocuments and timesCREATE INDEX(non-unique, composite and unique) andREBUILD INDEXon them, including the bytes read and written by the embedded server (Windows).
- Dependency updates.
Be sure to check out the NuGet package: https://www.nuget.org/packages/NTDLS.Katzebase.Api/
Full Changelog: https://github.com/NTDLS/Katzebase/compare/0.38.0...0.38.1
Release Notes
- First compatibility with Linux (x64, and arm64)
Packages
Be sure to check out the Nuget package 📦
https://www.nuget.org/packages/NTDLS.Katzebase.Api/
Breaking Change
This release is not backwards compatible with databases created by previous versions. 🔥
Storage Engine
Introduced RocksDB as the primary storage engine, replacing the previous home-rolled B-tree
Improved RocksDB instance management with lazy initialization
Implemented efficient full-schema document scanning
Transactions
Added server cancellation tokens
Ensured robust transaction cleanup during commit
Safeguarded transaction rollback after lock wait timeout
Fixed re-entrant deadlock in TryCloseByProcessID
Fixed crash recovery re-processing the same transactions on every restart
Fixed column family persisting across restarts after recovery rollback
Locking
Refactored LockManager to use instance-level concurrency state
Added support for multiple engine instances in LockManager
Lock intentions are now keyed on CacheKey instead of raw disk path
Replaced single-hop deadlock detection with DFS-based cycle detection
Reconstructed full deadlock cycle chain; rewrote GetDeadlockExplanation
Fixed directory-granularity locks not matching file-level intentions in GetOverlappingLocks
Fixed two additional lock overlap detection edge cases
Fixed CPU busy-wait and missing cancellation check in Acquire spin loop
Fixed infinite loop when a coarser-granularity lock already covers a finer-grained request
Fixed incorrect blocked-key tracking for Stability locks
Schema drop now correctly acquires a recursive path lock
Query Engine
Switched expression parser from NCalc to NTDLS.ExpressionParser
Implemented query and condition hashing; centralized hash finalization
Optimized condition hash generation and usage
Reused mathematical expressions across schema joins
Improved math parsing speed
Stored query text and hash in PreparedQuery
Streamed primary schema rows in GatherIntersectedRows; applied WHERE clause after joins
Performance & Memory
Fixed unbounded memory growth caused by unenforced cache size limit
Fixed OOM crash during index rebuild from RocksDB HyperClockCache anonymous mmap failure
Parallelized index rebuild using the indexing thread pool
Added cache-read bypass during index builds to prevent unbounded cache growth
Fixed cache not being ejected on schema drop
Optimized numeric ORDER BY sorting
Upgraded memory manager; removed unused thread pool
Bug Fixes
Fixed null reference when evaluating a function call against a null field value
Fixed schema tree hanging when loading schemas with hundreds of children
Fixed LOCK file error when dropping a schema that has child schemas
Management UI
Added materialization thread view
Fixed UI lock and slow (~3 minute) detail loading during schema tree population
Prioritized the expanded schema node in the detail fetch queue
Server
Added configurable initial thread pool size
Marked background threads for graceful shutdown
- ReliableMessaging updates.
Be sure to check out the nuget pacakge: https://www.nuget.org/packages/NTDLS.Katzebase.Api/0.33.1
Full Changelog: https://github.com/NTDLS/Katzebase/compare/0.33.0...0.33.1
- Major updates to ReliableMessaging.
- Added ReadUncommitted, which is now used by the UI explorer and lazy schema updates.
- Corrected thread status display for system functions.
- Refactor of schema optimizer.
- Corrected indexing order priority.
Be sure to check out the client connectivity Nuget package: https://www.nuget.org/packages/NTDLS.Katzebase.Api/0.33.0
Full Changelog: https://github.com/NTDLS/Katzebase/compare/0.32.1...0.33.0
Updates several NuGet package dependencies to their latest compatible versions, including NTDLS.Helpers, NTDLS.ReliableMessaging, NTDLS.DelegateThreadPooling, NTDLS.FastMemoryCache, AvalonEdit, NTDLS.Persistence, NTDLS.WinFormsHelpers, and Microsoft.Data.SqlClient.
Full Changelog: https://github.com/NTDLS/Katzebase/compare/0.32.0...0.32.1
Engine
- Internal deadlock avoidance strategies.
UI
- n/a
Full Changelog: https://github.com/NTDLS/Katzebase/compare/0.31.0...0.32.0
Engine
- Magor steaming API fix for packet fragmentation.
- Lock0wait optimization and new wait time tracker types.
- Index optimize cleanup. Removed regression test duration constraint.
UI
- Column resize fix.
Full Changelog: https://github.com/NTDLS/Katzebase/compare/0.30.0...0.31.0
Engine
- Resolved issues with single value insert.
UI
- Added manual refresh for index, schema and field list.
Full Changelog: https://github.com/NTDLS/Katzebase/compare/0.29.0...0.30.0
Engine
- Added dedicated field sample API.
UI
- Added lazy-loaded schema fields to UI.
Full Changelog: https://github.com/NTDLS/Katzebase/compare/0.28.0...0.29.0
- Dependency updates.
- Dropped .net 6 and 7 support,
Full Changelog: https://github.com/NTDLS/Katzebase/compare/0.27.0...0.28.0
Engine
- Added support for left outer join.
- Added support for select distinct.
- Fixed drop of unique keys.
- Added validation to grouping queries to ensure that expressions are either aggregated or included in the grouping.
- Added heartbeat manager to cleanup abandoned connections where they could not be instantly terminated due to locking.
- Resolved abandoned process thread deadlocks.
UI
- Migration tool status is no longer modal.
Full Changelog: https://github.com/NTDLS/Katzebase/compare/0.26.0...0.27.0
Engine
- Added new account, role and membership to support the security policy.
- Added, Grant, Deny, Revoke, Create/Alter role and account.
- Changed user id to GUID.
- Added LEFT OUTER join support.
- Fixed bool scalar functions returning string true/false instead of 1/0.
- Fixed issue with unique key enforcement on first duplicate.
- Resolved lookup issue on partial match with single schema.
- Fixed issues parsing variables when not followed by whitespace.
- Fixed issue where schema names were being improperly lowercased.
- Better variable declarations using DECLARE.
- Standardize QueryHandlers, APIs and exceptions.
- Major cleanup of query routing.
- Added lots of new system and scalar functions.
- Sleep, Print, Abs, Ceil, Floor, Pow, SystemShowSchemaPolicy.
- DateAdd, DateDiff, FormatNumeric, FormatDateTime, Round, ToString, ToNumeric.
- IfNullNumeric, NullIf, IsNull, NullIf, NullIfNumeric, and quite a bit more.
- Major enhancements to null handling, all functions should allow null return.
- Null propagation for all expressions, including math.
- Insert now uses Values list or json notation.
- Initial schema now created using embedded scripts.
- Proper null serialization, nulls can now be persisted.
- Fixes to GROUP BY when using ordering results.
- Added ability to pass aggregate result to Scalar function.
UI
- Auto-size of result grids, now allow manual resize.
- Empty result-set now populate field names if supplied by engine.
- Resolved exception on close of form.
- Find/replace improvements,
- Default font change, change of output window font.
- Added drag/drop "macros" (right-hand pane)
- Added row number, which is not exported by context menu commands.
Full Changelog: https://github.com/NTDLS/Katzebase/compare/0.25.0...0.26.0
Engine
- Consolidated field materialization.
- Field aliases can now be strings.
- Fixed select, group and order constant expressions.
- Major update performance optimization.
- Dynamic configuration options.
UI
- Swapped results grid for DataGridView.
- Static analysis tool-tip delay.
- Fixed font saving. Recommend: Cascadia Mono SemiLight.
- Added scrolling to multiple result grids.
- Added double buffered schema explorer.
- Resolved issue updating static analysis when lazy loaded schema updates occur.
Full Changelog: https://github.com/NTDLS/Katzebase/compare/0.24.0...0.25.0
Engine
- Resolved issues deleting from indexes.
- Improved threading and thread saftey.
- Resolved issues with non string/numeric parameters (such as DateTime).
UI
- File association icon fix.
- Resolved issue deleting large number of script lines.
Full Changelog: https://github.com/NTDLS/Katzebase/compare/0.23.0...0.24.0
Engine
- Resolved issues stopping new thread pools.
- Resolved nullability issues with aggregate functions.
- Resolved infinite parameters for scalar functions.
- Fixed index analysis.
- Fixed NOT like.
- Resolved issues with basic UPDATE parsing.
- Added missing field defaulted to NULL warning, softening the missing field severity.
UI
- Optimization of schema cache.
- Resolved issues with non-functional context menus.
Full Changelog: https://github.com/NTDLS/Katzebase/compare/0.2.0...0.23.0
This is major release (still in alpha), but fundamental portions of the engine have been changed. This is the final part of a two-part push to overhaul the parser (previous release) and now the schema-intersection-engine. The only outstanding issue is reimplementing stored procedures, but we really want to take some time and think that out. Other than that, we are now focused on validating the functionality of all features.
Engine
- Rewrite of schema intersection processor, now with more parallelism and vastly improved speed and maintainability.
- Added support for UPDATE with joins.
- Added support for DELETE with joins.
- Added support for ORDER BY using expressions and scalar/aggregate functions.
- Moved parser to dedicated library.
- Memory manager now released LOH object for greatly enhanced memory management.
- Added function descriptions to engine prototypes.
- Fixes to parsing negative numeric values.
- Added CountDistinct()
- Removed batch splitting on "GO", parser now knows where queries begin.
- Standardized all exceptions.
- Added new system function: ShowThreadPools
UI
- Now allows for more than one server connection.
- Incorporates schema awareness using lazy-loading for validation while writing queries.
- Static analyzer using new dedicated parsing library provides query-text insights in real-time.
- Code folding for comments and regions using --region "text" and --endregion.
- Font and font size can now be modified.
- Setting dialog now provides more customizability.
Full Changelog: https://github.com/NTDLS/Katzebase/compare/0.21.0...0.22.0
What Changed
- Cleanup and dependency updates.
New Contributors
- @ingted
Full Changelog: https://github.com/NTDLS/NTDLS.Katzebase.Server/compare/0.19.0...0.20.1
What Changed
- Aggregation when no group-by is present.
- Added count(*) shortcut,
- Added IsNumeric, IsDouble and IsString scaler functions.
- More drastic performance improvements to schema locking, also reduces deadlocks.
- Consolidated Server, Management, and SQL Server Migration tool into one installer.
New Contributors
- @ingted
Full Changelog: https://github.com/NTDLS/NTDLS.Katzebase.Server/compare/0.19.0...0.20.0
- Fixed issue with scaler functions when optional parameters were not passed.
- Resolved issue with calculating mathematical expressions when in line with string concatenation.
- Added new "single" schema that is intended to mimic the Oracle "dual" function.
- Reimplemented insert of "ragged key/value" pairs. This is in addition to field/value insert style.
Full Changelog: https://github.com/NTDLS/NTDLS.Katzebase.Server/compare/0.18.0...0.19.0
- Reimplemented "set".
- Massively improved insert performance.
- Greatly reduced schema lock contention.
- Resolved issues with case-sensitivity of schema aliases in where clause and joins.
- Greatly reduced duration and memory requirements for creating and rebuilding indexes.
Full Changelog: https://github.com/NTDLS/NTDLS.Katzebase.Server/compare/0.17.0...0.18.0
- Reimplemented "select into".
- Reimplemented Sample, Analyze, List, Alter, Rebuild, Set, Kill, and Exec.
- Reimplemented system functions.
- Resolved issue with "select top" when offset is not specified.
- Client package update.
Full Changelog: https://github.com/NTDLS/NTDLS.Katzebase.Server/compare/0.16.0...0.17.0
Changes
- Rewrote tokenizer.
- Rewrote entire query parser.
- Parsers are now separated into separate static classes for each query type.
- Parsers are now reusable, allowing for the condition parser, field parser and the like to be reused inside other query parser types.
- Functions are now fully recursive and are parsed in select fields, group by, order by, insert, update, select, where clause and join clauses.
- Update statements now allow for joins.
- Delete statements now allow for joins.
- Introduced "insert select from" statements.
- Temporarily removed support for procedures, they will need to be reimplemented.
- Major changes to the way that indexes are selected and used. Multiple values for a single index are now handled in one index lookup operation.
- Condition parser rewrite is now more robust and understandable.
- Introduction of new dapper like queries using classes as return objects.
- Introduction of parameterized queries prevents sql-injection attacks.
- Scaler and aggregate function parser rewrite allowing for reusability in various parts of queries.
- Added inline query string concatenation.
- Added query field type detection for inline math and string aggregation to coexist without "casting" which would be found in other RDBMSs.
- Added windowing functionality with TOP and OFFSET.
Remaining to-do:
- Reimplement "SELECT INTO".
- Reimplement stored procedures.
- More robust parser validation.
What's Changed
- Implementation of robust parser in PR https://github.com/NTDLS/NTDLS.Katzebase.Server/pull/68
Full Changelog: https://github.com/NTDLS/NTDLS.Katzebase.Server/compare/0.15.0...0.16.0
- Separated thread pools for indexing and lookup operations.
- Added full support for composite index seeks and scans.
- Vastly improved query optimizer.
- Added API to show query plan and order of operations, this is also available in the UI.
- Added finer granularity and additional categories to performance trace operations
- Performance counter refactoring.
- Removed element compression in favor of full page compression for better performance and space usage
- Greatly improved locking and concurrency. Much less contention and higher performance.
Full Changelog: https://github.com/NTDLS/NTDLS.Katzebase.Server/compare/0.14.0...0.15.0
- Updated reliable messaging to allow async queries. Each connection can now handle more than one query at a time.
- Added configurable child thread pool queue depth.
- Updated delegate thread pooling to allows for consolidation of thread exceptions and process cancelation.
- Improved semaphore locking.
- Query explain, attached conditions to root schema, removed double optimize
- Cleaned up condition/indexing explanation.
- Cleaning up condition parser.
- Added condition inversion.
- Resolved selecting dynamic fields from specific schemas.
- Exception formatting.
- Added aggregate exception to one threaded call, need to do others.
- Condition parser improvements, thread exceptions, perf and refactoring.
- Added ShowVersion, faster string comparison, much faster like comparison
Full Changelog: https://github.com/NTDLS/NTDLS.Katzebase.Server/compare/0.13.0...0.14.0
- Added: SystemProcedures and SystemAggregateFunctions
- Added serilog.
- Removed delayed document materialization.
- Removed stability lock conversion.
- Corrected index analytics for root node calculations.
- Fixed parser issue which was not tagging NULL as a constant.
- Resolved null equality issues.
- Resolved issue where constant values were not filled out on one-to-many relationships.
- Vastly improved exception reporting.
- Refactoring of expressions, sub-expressions and conditions.
Full Changelog: https://github.com/NTDLS/NTDLS.Katzebase.Server/compare/0.12.0...0.13.0
- Major updates to dependency libraries.
- Lots of bug fixes.
- Lots of optimizations.
- Incredible amounts of refactoring.
Full Changelog: https://github.com/NTDLS/NTDLS.Katzebase.Server/compare/0.10.0...0.12.0
- Fully swapped out HTTP for ReliableMessaging library.
- Resolved import grid strobing.
- Added schema stability locks and ability to deescalate to them.
- Resolved race condition on deadlock... of all places.
- Added new lock type: delete.
- Added ShowLocks
- Bumped semaphore nuget.
- .net8.0 upgrade.
- Installer fixes.
- Icon changes.
- Namespace moves and fixed client API success code for non-query.
- Code standardization.
- Rearrange mgmt classes.
- Resolved issue with parent schema locking.
- Added app name, resolved index api create and added disconnect cleanup.
- Added default client app name.
- Reimplemented deadlock detection.
- Restructure and added SQL Server migration tool.
- Mssql migration tool refinements.
- Fixed issue with relative settings paths.
- SQL migration tool fixes.
- Resolved major issue with rolled-back transaction cache.
- Added reporting on new tx read cache.
- Handled deadlocks in migration tool.
- Increased aggressiveness of locks.
- Added block tree viewing EXEC ShowBlockTree
- Major revisions to locking.
- Track lock intention and key issue times.
- Added transaction-state snapshots.
- Moved system procedure implementations.
- Checkpoint, working on critical sections.
- Swapped in new critical section manager.
- Moved critical sections.
- Made locks more explicit.
- Changed mutable locking to CriticalResource.
- Finished converting semaphores.
- Updated semaphore nuget.
- Updated memory cache to use NTDLS semaphore
- Moved memory cache to nuget.
- Removed vestige
- Moved "global" critical sections.
- MemoryCache nuget update.
- License.
- Moved client to different repo.
- Swapped out cache and semaphore nugets.
- Change lock seeking to use optimistic locking mechanism.
- Swapped out pessimistic semaphore for optimistic semaphore.
- Resolved multiple locking issues.
- Version corrections.