Releases: redbase-app/redb
v3.0.0
Added
-
PG Free: full v2-pvt query engine reaches Pro-parity (0.5.x → 0.6.1).
The PostgreSQL Free path got the feature-complete v2-pvt module ahead of
MSSql Free (commits 2026-05-21 … 2026-05-28). Before this series the Free
path was emitting-- not available in Open Sourcestubs for several
preview surfaces and was missing several Pro-only operators. Now in Free
on PG:- Universal "no black box" SQL preview for
GroupBy/Window/
GroupedWindow/Tree-*via two-pass compile (pvt_build_*_sql);
tree previews resolve the subtree and delegate to the matching non-tree
preview with a-- Tree …: subtree resolved to N object(s)header. Sql.Function<T>whitelist at the SQL boundary
(17_pvt_expr.sql) with a
hardcoded ELSIF chain andRAISE EXCEPTIONfor non-whitelisted names;
parser routesSql.Function<T>(name, args)to
CustomFunctionExpression(FREE-OVER-PRO §2.4).ValueTuplecomposite dict keys (Dictionary<(int,int), V>)
consistently encoded as Base64-JSON on both write and read sides
(FREE-OVER-PRO §2.2).arr.Length/coll.Countin filters via the array-aware
FacetFilterBuilder(.$countmodifier in Free);e.Tags.Any()
1-arg form mapped to<field>.$length > 0.Take(0)returns empty instead ofArgumentException.HAVINGparser +ArrayGroupBywith PVT agg arrayunnest
(19_pvt_agg_expr.sql) —
fixes42883 function sum(bigint[]) does not exist;
26_pvt_array_groupby.sql
added.ListItem.Value/.Aliasvia a singleLEFT JOIN _list_items
(v2-pvt 0.6.1) — plan-shape parity with Pro; replaces correlated
subquery per field.- Nested-dict CTE pushdown for
Field[key].Child(FREE-OVER-PRO §2.x):
outerWHEREreferences the already-built pivot column instead of a
redundantEXISTSover_values. - Auto-deploy of the v2-pvt bundle on version mismatch (see the
matching item below — same infrastructure serves both PG and MSSql).
The MSSql Free engine described next ports this PG Free baseline; the
parity line in the next item ("145/145 parity with PG Free") refers to
this newly-completed PG Free feature set, not a pre-existing one. - Universal "no black box" SQL preview for
-
MSSql Free: full v2-pvt query engine (0.1.0 → 0.1.3) — 145/145 parity
with PG Free. The old MSSql Free path generated a wide inline CASE WHEN
aggregate; it is now replaced with the Pro-shape CTE: a single pass over
_valuesusingMAX(CASE WHEN _id_structure = X AND _array_index IS NULL THEN ...)and a singleLEFT JOIN _list_items. All modes present in PG
Free are implemented: flat/tree, scalar/array/dict fields, ListItem
(.Id/.Value/.Alias), same-scheme nested POCO (compound path),
OrderBy/DistinctBy/Take/Skip,GroupBy/HAVING,ArrayGroupBy
(viaOUTER APPLY), array aggregates ($count,$sum/$avg/$min/$max
over_Long/_Double/_Numeric/_DateTimeOffset), array operators
($arrayContains,$arrayAny,$arrayCount*,$arrayAt,
$arrayStartsWith, etc.),Sql.Function(whitelist),$expr, null
semantics ($exists/$notNull). The SQL module is split into 27 source
files under redb.MSSql/sql/v2-pvt/ assembled
into a singlepvt_bundle.sqlby MSBuild. Delivery stages: Stage 1 (pivot
CTE) → 2a (tree TVFs) → 2b (tree provider) → 2c.E (nested-dict accessor
Field[key].Child) → 0.1.1 LIKE-pattern fix → 0.1.2 string$const
unwrap + ListItem$arrayContains→ 0.1.3 nested-dict CTE pushdown +
outerWHEREreferences pivot column instead of a redundantEXISTS.
Shape parity with Pro throughout:_id_scheme+extra_where+
tree-filter pushed into inner_objectssubquery, narrow-with-nested CTE
(skips_valuesJOIN when no scalar sids), stable defaultORDER BYwhen
paging without an explicit order. -
Auto-deploy v2-pvt bundle on version mismatch (both databases).
ISqlDialectgainedQuery_PvtRequiredVersion()— the semver the embedded
bundle ships.RedbServiceBase.EnsurePvtModuleDeployedAsyncreads
pvt_module_version()onInitializeAsync(), compares with an exact-match,
and automatically applies the embeddedpvt_bundle.sqlresource when the
deployed version differs. No more manualDROP FUNCTION … CREATE FUNCTION …
after a SQL change. The MSBuild targetConcatenateSqlFilesregenerates the
bundle whenever any.sqlsource changes (hooked toDispatchToInnerBuilds
for multi-TFM builds;EmbeddedResourceuses an explicitLogicalName—
without it MSBuild silently replaces-with_in resource paths, causing
GetManifestResourceStreamto returnnull). -
Pro:
GroupBy+HAVINGvia PVT pipeline on both providers
(Postgres.Pro + MSSql.Pro).HavingAsyncexisted in Free but had no Pro
counterpart. Added full HAVING parser in the shared facet layer
(FacetFilterBuilder), SQL generation in both Pro providers, and a base
test suite in
GroupByHavingTestsBase
with per-dialect wrappers (PG, PG.Pro, MSSql.Pro). 33/33 HAVING + 6/6
no-HAVING — all green. -
Pro:
GroupByover array fields (ArrayGroupBy) — unified implementation
for Postgres.Pro + MSSql.Pro. PG.Pro uses an inlineGroupByArrayoverride
with PVT agg arrayunnest; MSSql.Pro has its own override.
GroupBy(items => items.SelectMany(o => o.Skills))with aggregates works
on all four tiers (PG Free, PG.Pro, MSSql Free, MSSql.Pro). -
MSSql Pro:
AggregateBatchparity with PG.Pro — non-numeric MIN/MAX and
inline filter subquery.MinAsync/MaxAsyncoverstring/DateTime/Guid
fields and aWherefilter inside a batch aggregation now produce the same
query shape as PG.Pro (PVT CTE + outer aggregate). -
MSSql Free: pushdown parity with Pro/PG for expression-form predicates
and$expr— the filter-splitting optimizer
pvt_split_filternow pushes
top-level$eq/$ne/$lt/$lte/$gt/$gte/$like/$ilike/$in/$nin/$between/$null/ $notnull/$contains/$startsWith/$endsWithexpressions and arbitrary boolean
$exprtrees into the inner_objects osubquery (Shape A) when all
$fieldreferences resolve tokind='base'. If any props field is present
the node stays in the residual (Shape C). The new classifier
pvt_expr_is_base_onlymakes
this decision; the pushdown SQL itself is generated by the existing
pvt_build_where_from_json
walker (extended with a$exprbranch). Covered by 4 functional and 3
shape-inspect tests in
99_smoke_auto.sql
(195 PASS / 0 FAIL / 1 SKIP).
Fixed
- Schema sync now honors
Configuration.DefaultStrictDeleteExtra
(FREE-OVER-PRO §4 #1). Prior to this fixRedbServiceConfiguration.DefaultStrictDeleteExtra
was set by builders, copied across configuration clones and read from
appsettings, but no execution-path code consumed it —
SchemeSyncProviderBase.SyncSchemeAsync<T>
hardcodedstrictDeleteExtra: true, so old binaries restarting in a
multi-version rolling deploy would unconditionally remove_structures
rows added by the new binary, and every_valuesrow referencing those
structures along with them. On PostgreSQL this is done via the FK
_values._id_structure -> _structures._id ON DELETE CASCADE
(redbPostgre.sql:215). On MSSQL
the same effect is produced by theINSTEAD OF DELETEtrigger
TR__structures__cascade_values
(redbMSSQL.sql:717) — the FK
NO ACTIONat redbMSSQL.sql:270
is a workaround for the MSSQL multiple-cascade-paths restriction, not a
behavioral difference.SyncSchemeAsync<T>now reads
now readsConfiguration.DefaultStrictDeleteExtrainstead. The default
value is preserved (true) so users on the default config see no
behavioral change. Behavioral change: the built-in presets
Development,HighPerformance, andMigration(in
PredefinedConfigurations.cs)
already declaredDefaultStrictDeleteExtra = false; that setting was
silently ignored before and now actually takes effect — apps on those
presets will no longer auto-delete_structuresrows missing from the
Propsclass on startup.
Added
a fallback to ROW_NUMBER() OVER (PARTITION BY <key> ORDER BY (SELECT 1))
WHERE _rn = 1(symmetric with the Free path), plus support for
CoalesceExpressionin theDistinctBykey.
-
PG v2-pvt 0.6.1: ListItem
.Value/.Aliasnow uses a single
LEFT JOIN _list_itemsinstead of a correlated subquery per field —
plan-shape parity with Pro. Additionally: nested-dict predicates in the
outerWHEREnow reference_pvt_cte.[<field>](the already-built pivot
column) instead of re-running a separateEXISTSover_values. -
MSSql Free:
ORDER BY $expron base fields no longer produces "constant
in ORDER BY" — two regressions fixed: (1)
pvt_collect_fields
did not walk$exprnodes in order entries, so a field likeAgewas not
collected, the shape was classified as A, andpvt_b2_expr_sqlemitted
/*unknown-b2-field:Age*/NULLturningAge*2into a constant; (2)
[pvt_build_order_conditions](redb.MSSql/sql/v2-pvt...
v2.0.2
RedBase 2.0.2. See CHANGELOG.md for details. NuGet: https://www.nuget.org/profiles/relikt
v2.0.1
RedBase 2.0.1 — Pro EAV LINQ→SQL fix. License migrated MIT → Apache-2.0 for all OSS packages. Strong-name signing active for Pro assemblies. See CHANGELOG.md for details. NuGet: https://www.nuget.org/profiles/relikt
v1.3.0
What's Changed
Fixed
- Nullable .Value\ in \WhereRedb\ resolved to wrong column
- .HasValue\ generated \ield = true\ instead of \IS NOT NULL\
- Props cache skipped hashless objects
- Missing _hash\ in nested object SQL
- Lexicographic ArrayIndex sorting (10+ items)
- Duplicate RedbObject in SaveAsync / MERGE duplicate row in ChangeTracking
- Missing ArrayParentId for nested RedbObject refs
- Guid field not persisted
- \DeleteSubtreeAsync\ / \LoadTreeAsync(maxDepth: 1)\ fixes
- MsSql Pro: null checks, DistinctBy, DELETE stored procedures
- MsSql Free: WHERE null, OrderBy
- \get_object_json\ / \�uild_field_json\ fixes
- KeyGenerator domain isolation, SaveAsync deadlocks, MsSql reader-writer deadlocks
- SchemeFieldResolver / SyncSchemeAsync cache fixes
- GroupBy aliased keys, ListItem operators (Postgres + MsSql), Pro OrderBy ListItem
- GroupBy/Window base field filter crash (9 sites across Postgres.Pro and MsSql.Pro)
Added
- \save_object_json\ SQL functions (Postgres + MsSql)
- \DeadlockRetryHelper\ — automatic retry with exponential backoff
- \BcryptPasswordHasher\ — bcrypt work factor 12
Full changelog: https://github.com/redbase-app/redb/blob/main/CHANGELOG.md
v1.2.15
Initial Public Release
Public source code for RedBase open-source packages:
- redb.CLI - Command-line tool for database management (export, import, schema init)
- redb.Export - Database export/import library (JSONL/ZIP)
- redb.Examples - 150+ runnable examples covering CRUD, queries, trees, lists, aggregation, window functions
Install
dotnet tool install --global redb.CLISee README for full documentation.
NuGet packages: redb.Core | redb.Postgres | redb.MSSql