@atscript/db 0.1.150 → 0.1.152
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agg.d.cts +1 -1
- package/dist/agg.d.mts +1 -1
- package/dist/{buckets-XOz0Bw5x.d.mts → buckets-Cb0zmhDc.d.mts} +38 -1
- package/dist/{buckets-24Ac4sIS.d.cts → buckets-tzd8iIM2.d.cts} +38 -1
- package/dist/{column-diff-CKKBVDvx.cjs → column-diff-CU7KHj9-.cjs} +270 -79
- package/dist/{column-diff-CKLDWBbo.mjs → column-diff-CnyLjbQ8.mjs} +270 -79
- package/dist/{fk-diff-CCLiJ9sJ.d.cts → fk-diff-Bw26lwSc.d.cts} +8 -1
- package/dist/{fk-diff-R8eU7gq-.d.mts → fk-diff-lcAnwvm9.d.mts} +8 -1
- package/dist/index.cjs +24 -2
- package/dist/index.d.cts +15 -16
- package/dist/index.d.mts +15 -16
- package/dist/index.mjs +24 -2
- package/dist/{nested-writer-BUQvk6QT.cjs → nested-writer-BzbOPSUp.cjs} +129 -7
- package/dist/{nested-writer-CUBoq1ZO.mjs → nested-writer-cvbVAkNo.mjs} +124 -8
- package/dist/rel.cjs +2 -2
- package/dist/rel.d.cts +2 -2
- package/dist/rel.d.mts +2 -2
- package/dist/rel.mjs +2 -2
- package/dist/{relation-helpers-DjVJN2ng.d.cts → relation-helpers-Bdo4NHPC.d.mts} +1 -1
- package/dist/{relation-helpers-H7UEVkHs.d.mts → relation-helpers-DxIZKvnJ.d.cts} +1 -1
- package/dist/{relation-loader-ByY1Byrl.mjs → relation-loader-DYab07lw.mjs} +1 -1
- package/dist/{relation-loader-D8OrdH-r.cjs → relation-loader-fNjHgBMs.cjs} +1 -1
- package/dist/sync.cjs +1 -1
- package/dist/sync.d.cts +2 -2
- package/dist/sync.d.mts +2 -2
- package/dist/sync.mjs +1 -1
- package/package.json +8 -8
package/dist/index.d.cts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { $ as TDbReferentialAction, $t as TDbSpaceOptions, A as TCrudOp, An as andFilters, At as TRowResolveOptions, B as TDbDefaultValue, Bn as TReadControls, Bt as TypedWithRelation, C as NavPropsOf, Cn as REL_FILTER_MAX_DEPTH, Ct as TIdentification, D as TCascadeResolver, Dn as TRelationFilterJunction, Dt as TPrimaryKeyChange, E as PrimaryKeyOf, En as TRelGuardState, Et as TMetadataOverrides, F as TDbActionProcessor, Fn as relationStaticFilter, Ft as TTouchManyOptions, G as TDbIndexField, Gn as TRowOrderKey, Gt as isGeoIndexableType, H as TDbFieldMeta, Hn as TGenericLogger, Ht as UniqueryControls, I as TDbActionTargetSummary, In as DbEncryption, It as TValueFormatterPair, J as TDbInsertIgnoreSlot, Jt as ALL_VIEW_CAPABILITIES, K as TDbIndexType, Kn as UniquSelect, Kt as isGeoPointType, L as TDbAvailableActions, Ln as TDbEncryptionOptions, Lt as TViewJsonType, M as TDbActionInfo, Mn as forEachResolvedRelation, Mt as TSyncColumnResult, N as TDbActionIntent, Nn as hasRelationOp, Nt as TTableOptionDiff, O as TCascadeTarget, On as TRelationFilterTable, Ot as TReferencingForeignKey, P as TDbActionLevel, Pn as isResolvedRelationFilter, Pt as TTableResolver, Q as TDbObjectKind, Qt as TAdapterFactory, R as TDbCollation, Rn as DocumentFieldMapper, Rt as TWriteOptions, S as FlatOf, Sn as resolveDesignType, St as TIdResolveOptions, T as OwnPropsOf, Tn as ResolvedRelationFilter, Tt as TMetaResponse, U as TDbForeignKey, Un as TExprAggregate, Ut as WithRelation, V as TDbDeleteResult, Vn as NoopLogger, Vt as Uniquery, W as TDbIndex, Wn as TFirstLast, Wt as TableMetadata, X as TDbInsertManyResult, Xt as TViewCapability, Y as TDbInsertManyIgnoreResult, Yt as BaseDbAdapter, Z as TDbInsertResult, Zt as DbSpace, _ as DbPatch, _n as IntegrityStrategy, _t as TExistingTableOption, a as isJsonValueField, an as AtscriptExprNode, at as TDbUpdateResult, b as FieldOpsFor, bn as AtscriptDbReadable, bt as TFkLookupTarget, c as resolveCalendarBuckets, cn as AtscriptQueryFieldRef, ct as TDbWriteCheckContext, d as AggregateFn, dn as TViewJoin, dt as TDeleteOptions, en as AtscriptDbView, et as TDbRelation, f as AggregateQuery, fn as TViewPlan, ft as TDerivedChangeReason, g as DbControls, gn as AtscriptDbTable, gt as TExistingForeignKey, h as AtscriptDbWritable, hn as translateQueryTree, ht as TExistingColumn, i as isBucketableField, in as aliasTargetOf, it as TDbUpdateOptions, j as TCrudPermissions, jn as containsRelationFilter, jt as TSearchIndexInfo, k as TColumnDiff, kn as TRelationStaticFilter, kt as TRelationInfo, l as AggregateControls, ln as AtscriptQueryNode, lt as TDbWriteGuard, mn as isFieldRef, mt as TEnsureTableOptions, n as TComputedSelect, nn as isAtscriptDbView, nt as TDbRemoveGuardContext, o as jsonValueAncestor, on as AtscriptOrderItem, ot as TDbWriteAction, p as AggregateResult, pn as evaluateExpr, pt as TDerivedColumn, q as TDbInsertIgnoreResult, qt as ALL_BUCKET_UNITS, r as TResolvedBucket, rn as isViewType, rt as TDbStorageType, s as normalizeComputedSelect, sn as AtscriptQueryComparison, st as TDbWriteCheck, t as TBucketFieldSource, tn as TViewColumnMapping, tt as TDbRemoveGuard, u as AggregateExpr, un as AtscriptRef, ut as TDbWriteGuardContext, v as DbQuery, vn as NativeIntegrity, vt as TFieldMeta, w as NullableOptional, wn as REL_FILTER_MAX_NODES, wt as TInsertOptions, x as FilterExpr, xn as DbResponse, xt as TIdDescriptor, y as DbRow, yn as TCascadePin, yt as TFkLookupResolver, z as TDbDefaultFn, zn as FieldMappingStrategy, zt as TWriteTableResolver } from "./buckets-
|
|
1
|
+
import { $ as TDbReferentialAction, $t as TDbSpaceOptions, A as TCrudOp, An as andFilters, At as TRowResolveOptions, B as TDbDefaultValue, Bn as TReadControls, Bt as TypedWithRelation, C as NavPropsOf, Cn as REL_FILTER_MAX_DEPTH, Ct as TIdentification, D as TCascadeResolver, Dn as TRelationFilterJunction, Dt as TPrimaryKeyChange, E as PrimaryKeyOf, En as TRelGuardState, Et as TMetadataOverrides, F as TDbActionProcessor, Fn as relationStaticFilter, Ft as TTouchManyOptions, G as TDbIndexField, Gn as TRowOrderKey, Gt as isGeoIndexableType, H as TDbFieldMeta, Hn as TGenericLogger, Ht as UniqueryControls, I as TDbActionTargetSummary, In as DbEncryption, It as TValueFormatterPair, J as TDbInsertIgnoreSlot, Jt as ALL_VIEW_CAPABILITIES, K as TDbIndexType, Kn as UniquSelect, Kt as isGeoPointType, L as TDbAvailableActions, Ln as TDbEncryptionOptions, Lt as TViewJsonType, M as TDbActionInfo, Mn as forEachResolvedRelation, Mt as TSyncColumnResult, N as TDbActionIntent, Nn as hasRelationOp, Nt as TTableOptionDiff, O as TCascadeTarget, On as TRelationFilterTable, Ot as TReferencingForeignKey, P as TDbActionLevel, Pn as isResolvedRelationFilter, Pt as TTableResolver, Q as TDbObjectKind, Qt as TAdapterFactory, R as TDbCollation, Rn as DocumentFieldMapper, Rt as TWriteOptions, S as FlatOf, Sn as resolveDesignType, St as TIdResolveOptions, T as OwnPropsOf, Tn as ResolvedRelationFilter, Tt as TMetaResponse, U as TDbForeignKey, Un as TExprAggregate, Ut as WithRelation, V as TDbDeleteResult, Vn as NoopLogger, Vt as Uniquery, W as TDbIndex, Wn as TFirstLast, Wt as TableMetadata, X as TDbInsertManyResult, Xt as TViewCapability, Y as TDbInsertManyIgnoreResult, Yt as BaseDbAdapter, Z as TDbInsertResult, Zt as DbSpace, _ as DbPatch, _n as IntegrityStrategy, _t as TExistingTableOption, a as isJsonValueField, an as AtscriptExprNode, at as TDbUpdateResult, b as FieldOpsFor, bn as AtscriptDbReadable, bt as TFkLookupTarget, c as resolveCalendarBuckets, cn as AtscriptQueryFieldRef, ct as TDbWriteCheckContext, d as AggregateFn, dn as TViewJoin, dt as TDeleteOptions, en as AtscriptDbView, et as TDbRelation, f as AggregateQuery, fn as TViewPlan, ft as TDerivedChangeReason, g as DbControls, gn as AtscriptDbTable, gt as TExistingForeignKey, h as AtscriptDbWritable, hn as translateQueryTree, ht as TExistingColumn, i as isBucketableField, in as aliasTargetOf, it as TDbUpdateOptions, j as TCrudPermissions, jn as containsRelationFilter, jt as TSearchIndexInfo, k as TColumnDiff, kn as TRelationStaticFilter, kt as TRelationInfo, l as AggregateControls, ln as AtscriptQueryNode, lt as TDbWriteGuard, mn as isFieldRef, mt as TEnsureTableOptions, n as TComputedSelect, nn as isAtscriptDbView, nt as TDbRemoveGuardContext, o as jsonValueAncestor, on as AtscriptOrderItem, ot as TDbWriteAction, p as AggregateResult, pn as evaluateExpr, pt as TDerivedColumn, q as TDbInsertIgnoreResult, qt as ALL_BUCKET_UNITS, r as TResolvedBucket, rn as isViewType, rt as TDbStorageType, s as normalizeComputedSelect, sn as AtscriptQueryComparison, st as TDbWriteCheck, t as TBucketFieldSource, tn as TViewColumnMapping, tt as TDbRemoveGuard, u as AggregateExpr, un as AtscriptRef, ut as TDbWriteGuardContext, v as DbQuery, vn as NativeIntegrity, vt as TFieldMeta, w as NullableOptional, wn as REL_FILTER_MAX_NODES, wt as TInsertOptions, x as FilterExpr, xn as DbResponse, xt as TIdDescriptor, y as DbRow, yn as TCascadePin, yt as TFkLookupResolver, z as TDbDefaultFn, zn as FieldMappingStrategy, zt as TWriteTableResolver } from "./buckets-tzd8iIM2.cjs";
|
|
2
2
|
import { _ as separateFieldOps, a as $mul, c as $update, d as TDbFieldOp, f as TFieldOps, g as separateCas, h as reconcileCas, i as $insert, l as $upsert, m as isDbFieldOp, n as $dec, o as $remove, p as getDbFieldOp, r as $inc, s as $replace, t as $cas, u as TDbCas } from "./ops-AqhV7s9o.cjs";
|
|
3
3
|
import { a as isPlainObject, i as isEmptyObject, n as findAncestorInSet, o as selfOrAncestor, r as getPath, t as deletePath } from "./object-CtPYTIvy.cjs";
|
|
4
4
|
import { c as CalendarBucketLabel, d as WeekStart, g as ALL_AGGREGATE_FNS, l as ComputedExpr, o as BucketExpr, s as BucketUnit, u as ResolvedBucket } from "./agg-42CSpGDR.cjs";
|
|
5
5
|
import { _ as aggregateFailure, a as buildValidationContext, c as isNavRelation, d as getKeyProps, f as CasExhaustedError, g as aggregateExpressionsNotSupported, h as DbErrorCode, l as TArrayPatch, m as DbError, n as ValidatorMode, p as CasMismatchError, r as buildDbValidator, s as forceNavNonOptional, t as ValidationContext, u as TDbPatch, v as bucketTimeZoneUnavailable, y as isConflict } from "./validator-tBNvM1qc.cjs";
|
|
6
6
|
import { n as createDbValidatorPlugin, t as DbValidationContext } from "./db-validator-plugin-BWy60OvG.cjs";
|
|
7
|
-
import { r as fkColumns, s as isColumnTypeChanged } from "./fk-diff-
|
|
8
|
-
import { i as tableNameOf } from "./relation-helpers-
|
|
7
|
+
import { r as fkColumns, s as isColumnTypeChanged } from "./fk-diff-Bw26lwSc.cjs";
|
|
8
|
+
import { i as tableNameOf } from "./relation-helpers-DxIZKvnJ.cjs";
|
|
9
9
|
import { AggregateQuery as AggregateQuery$1, FilterExpr as FilterExpr$1, FilterVisitor, RELATION_OPS, RelationOp, RelationOp as RelationOp$1, ResolvedRowOrderKey, ResolvedSelectExpr, Uniquery as Uniquery$1, computeInsights, isPrimitive, isRelationOp, walkFilter } from "@uniqu/core";
|
|
10
10
|
import { AtscriptExprNode as AtscriptExprNode$1, TAtscriptAnnotatedType } from "@atscript/typescript/utils";
|
|
11
11
|
|
|
@@ -50,19 +50,13 @@ declare class RelationalFieldMapper extends FieldMappingStrategy {
|
|
|
50
50
|
*/
|
|
51
51
|
private translateControls;
|
|
52
52
|
/**
|
|
53
|
-
* Flattens nested
|
|
54
|
-
*
|
|
53
|
+
* Flattens nested objects into __-separated keys and JSON-stringifies
|
|
54
|
+
* @db.json / array fields — with `prepareCommon` folded in: primary-key
|
|
55
|
+
* values prepared (`adapter.prepareId`), top-level ignored fields (skipped
|
|
56
|
+
* by {@link writeFlattenedField}) and derived fields left out. `payload`
|
|
57
|
+
* itself is not modified.
|
|
55
58
|
*/
|
|
56
|
-
private
|
|
57
|
-
/**
|
|
58
|
-
* Classifies and writes a single field to the result object.
|
|
59
|
-
* Recurses into nested objects that should be flattened.
|
|
60
|
-
*/
|
|
61
|
-
private writeFlattenedField;
|
|
62
|
-
/**
|
|
63
|
-
* When a parent object is null/undefined, set all its flattened children to null.
|
|
64
|
-
*/
|
|
65
|
-
private setFlattenedChildrenNull;
|
|
59
|
+
private flattenWritePayload;
|
|
66
60
|
}
|
|
67
61
|
//#endregion
|
|
68
62
|
//#region src/strategies/application-integrity.d.ts
|
|
@@ -93,7 +87,12 @@ declare class ApplicationIntegrity extends IntegrityStrategy {
|
|
|
93
87
|
* leave the parent behind). Any other filter → `undefined`.
|
|
94
88
|
*/
|
|
95
89
|
cascadeBeforeDelete(filter: FilterExpr$1, tableName: string, meta: TableMetadata, cascadeResolver: TCascadeResolver, translateFilter: (f: FilterExpr$1) => FilterExpr$1, adapter: BaseDbAdapter): Promise<TCascadePin>;
|
|
96
|
-
|
|
90
|
+
/**
|
|
91
|
+
* A resolver is set and — when `tableName` is given (since 0.1.151) — some
|
|
92
|
+
* table references `tableName` with an `onDelete` action: a delete from a
|
|
93
|
+
* table nothing references needs no cascade pass (nor its transaction).
|
|
94
|
+
*/
|
|
95
|
+
needsCascade(cascadeResolver: TCascadeResolver | undefined, tableName?: string): boolean;
|
|
97
96
|
private recordKey;
|
|
98
97
|
/**
|
|
99
98
|
* Builds a filter for child records whose FK matches the deleted parent's PK values.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { $ as TDbReferentialAction, $t as TDbSpaceOptions, A as TCrudOp, An as andFilters, At as TRowResolveOptions, B as TDbDefaultValue, Bn as TReadControls, Bt as TypedWithRelation, C as NavPropsOf, Cn as REL_FILTER_MAX_DEPTH, Ct as TIdentification, D as TCascadeResolver, Dn as TRelationFilterJunction, Dt as TPrimaryKeyChange, E as PrimaryKeyOf, En as TRelGuardState, Et as TMetadataOverrides, F as TDbActionProcessor, Fn as relationStaticFilter, Ft as TTouchManyOptions, G as TDbIndexField, Gn as TRowOrderKey, Gt as isGeoIndexableType, H as TDbFieldMeta, Hn as TGenericLogger, Ht as UniqueryControls, I as TDbActionTargetSummary, In as DbEncryption, It as TValueFormatterPair, J as TDbInsertIgnoreSlot, Jt as ALL_VIEW_CAPABILITIES, K as TDbIndexType, Kn as UniquSelect, Kt as isGeoPointType, L as TDbAvailableActions, Ln as TDbEncryptionOptions, Lt as TViewJsonType, M as TDbActionInfo, Mn as forEachResolvedRelation, Mt as TSyncColumnResult, N as TDbActionIntent, Nn as hasRelationOp, Nt as TTableOptionDiff, O as TCascadeTarget, On as TRelationFilterTable, Ot as TReferencingForeignKey, P as TDbActionLevel, Pn as isResolvedRelationFilter, Pt as TTableResolver, Q as TDbObjectKind, Qt as TAdapterFactory, R as TDbCollation, Rn as DocumentFieldMapper, Rt as TWriteOptions, S as FlatOf, Sn as resolveDesignType, St as TIdResolveOptions, T as OwnPropsOf, Tn as ResolvedRelationFilter, Tt as TMetaResponse, U as TDbForeignKey, Un as TExprAggregate, Ut as WithRelation, V as TDbDeleteResult, Vn as NoopLogger, Vt as Uniquery, W as TDbIndex, Wn as TFirstLast, Wt as TableMetadata, X as TDbInsertManyResult, Xt as TViewCapability, Y as TDbInsertManyIgnoreResult, Yt as BaseDbAdapter, Z as TDbInsertResult, Zt as DbSpace, _ as DbPatch, _n as IntegrityStrategy, _t as TExistingTableOption, a as isJsonValueField, an as AtscriptExprNode, at as TDbUpdateResult, b as FieldOpsFor, bn as AtscriptDbReadable, bt as TFkLookupTarget, c as resolveCalendarBuckets, cn as AtscriptQueryFieldRef, ct as TDbWriteCheckContext, d as AggregateFn, dn as TViewJoin, dt as TDeleteOptions, en as AtscriptDbView, et as TDbRelation, f as AggregateQuery, fn as TViewPlan, ft as TDerivedChangeReason, g as DbControls, gn as AtscriptDbTable, gt as TExistingForeignKey, h as AtscriptDbWritable, hn as translateQueryTree, ht as TExistingColumn, i as isBucketableField, in as aliasTargetOf, it as TDbUpdateOptions, j as TCrudPermissions, jn as containsRelationFilter, jt as TSearchIndexInfo, k as TColumnDiff, kn as TRelationStaticFilter, kt as TRelationInfo, l as AggregateControls, ln as AtscriptQueryNode, lt as TDbWriteGuard, mn as isFieldRef, mt as TEnsureTableOptions, n as TComputedSelect, nn as isAtscriptDbView, nt as TDbRemoveGuardContext, o as jsonValueAncestor, on as AtscriptOrderItem, ot as TDbWriteAction, p as AggregateResult, pn as evaluateExpr, pt as TDerivedColumn, q as TDbInsertIgnoreResult, qt as ALL_BUCKET_UNITS, r as TResolvedBucket, rn as isViewType, rt as TDbStorageType, s as normalizeComputedSelect, sn as AtscriptQueryComparison, st as TDbWriteCheck, t as TBucketFieldSource, tn as TViewColumnMapping, tt as TDbRemoveGuard, u as AggregateExpr, un as AtscriptRef, ut as TDbWriteGuardContext, v as DbQuery, vn as NativeIntegrity, vt as TFieldMeta, w as NullableOptional, wn as REL_FILTER_MAX_NODES, wt as TInsertOptions, x as FilterExpr, xn as DbResponse, xt as TIdDescriptor, y as DbRow, yn as TCascadePin, yt as TFkLookupResolver, z as TDbDefaultFn, zn as FieldMappingStrategy, zt as TWriteTableResolver } from "./buckets-
|
|
1
|
+
import { $ as TDbReferentialAction, $t as TDbSpaceOptions, A as TCrudOp, An as andFilters, At as TRowResolveOptions, B as TDbDefaultValue, Bn as TReadControls, Bt as TypedWithRelation, C as NavPropsOf, Cn as REL_FILTER_MAX_DEPTH, Ct as TIdentification, D as TCascadeResolver, Dn as TRelationFilterJunction, Dt as TPrimaryKeyChange, E as PrimaryKeyOf, En as TRelGuardState, Et as TMetadataOverrides, F as TDbActionProcessor, Fn as relationStaticFilter, Ft as TTouchManyOptions, G as TDbIndexField, Gn as TRowOrderKey, Gt as isGeoIndexableType, H as TDbFieldMeta, Hn as TGenericLogger, Ht as UniqueryControls, I as TDbActionTargetSummary, In as DbEncryption, It as TValueFormatterPair, J as TDbInsertIgnoreSlot, Jt as ALL_VIEW_CAPABILITIES, K as TDbIndexType, Kn as UniquSelect, Kt as isGeoPointType, L as TDbAvailableActions, Ln as TDbEncryptionOptions, Lt as TViewJsonType, M as TDbActionInfo, Mn as forEachResolvedRelation, Mt as TSyncColumnResult, N as TDbActionIntent, Nn as hasRelationOp, Nt as TTableOptionDiff, O as TCascadeTarget, On as TRelationFilterTable, Ot as TReferencingForeignKey, P as TDbActionLevel, Pn as isResolvedRelationFilter, Pt as TTableResolver, Q as TDbObjectKind, Qt as TAdapterFactory, R as TDbCollation, Rn as DocumentFieldMapper, Rt as TWriteOptions, S as FlatOf, Sn as resolveDesignType, St as TIdResolveOptions, T as OwnPropsOf, Tn as ResolvedRelationFilter, Tt as TMetaResponse, U as TDbForeignKey, Un as TExprAggregate, Ut as WithRelation, V as TDbDeleteResult, Vn as NoopLogger, Vt as Uniquery, W as TDbIndex, Wn as TFirstLast, Wt as TableMetadata, X as TDbInsertManyResult, Xt as TViewCapability, Y as TDbInsertManyIgnoreResult, Yt as BaseDbAdapter, Z as TDbInsertResult, Zt as DbSpace, _ as DbPatch, _n as IntegrityStrategy, _t as TExistingTableOption, a as isJsonValueField, an as AtscriptExprNode, at as TDbUpdateResult, b as FieldOpsFor, bn as AtscriptDbReadable, bt as TFkLookupTarget, c as resolveCalendarBuckets, cn as AtscriptQueryFieldRef, ct as TDbWriteCheckContext, d as AggregateFn, dn as TViewJoin, dt as TDeleteOptions, en as AtscriptDbView, et as TDbRelation, f as AggregateQuery, fn as TViewPlan, ft as TDerivedChangeReason, g as DbControls, gn as AtscriptDbTable, gt as TExistingForeignKey, h as AtscriptDbWritable, hn as translateQueryTree, ht as TExistingColumn, i as isBucketableField, in as aliasTargetOf, it as TDbUpdateOptions, j as TCrudPermissions, jn as containsRelationFilter, jt as TSearchIndexInfo, k as TColumnDiff, kn as TRelationStaticFilter, kt as TRelationInfo, l as AggregateControls, ln as AtscriptQueryNode, lt as TDbWriteGuard, mn as isFieldRef, mt as TEnsureTableOptions, n as TComputedSelect, nn as isAtscriptDbView, nt as TDbRemoveGuardContext, o as jsonValueAncestor, on as AtscriptOrderItem, ot as TDbWriteAction, p as AggregateResult, pn as evaluateExpr, pt as TDerivedColumn, q as TDbInsertIgnoreResult, qt as ALL_BUCKET_UNITS, r as TResolvedBucket, rn as isViewType, rt as TDbStorageType, s as normalizeComputedSelect, sn as AtscriptQueryComparison, st as TDbWriteCheck, t as TBucketFieldSource, tn as TViewColumnMapping, tt as TDbRemoveGuard, u as AggregateExpr, un as AtscriptRef, ut as TDbWriteGuardContext, v as DbQuery, vn as NativeIntegrity, vt as TFieldMeta, w as NullableOptional, wn as REL_FILTER_MAX_NODES, wt as TInsertOptions, x as FilterExpr, xn as DbResponse, xt as TIdDescriptor, y as DbRow, yn as TCascadePin, yt as TFkLookupResolver, z as TDbDefaultFn, zn as FieldMappingStrategy, zt as TWriteTableResolver } from "./buckets-Cb0zmhDc.mjs";
|
|
2
2
|
import { _ as separateFieldOps, a as $mul, c as $update, d as TDbFieldOp, f as TFieldOps, g as separateCas, h as reconcileCas, i as $insert, l as $upsert, m as isDbFieldOp, n as $dec, o as $remove, p as getDbFieldOp, r as $inc, s as $replace, t as $cas, u as TDbCas } from "./ops-AqhV7s9o.mjs";
|
|
3
3
|
import { a as isPlainObject, i as isEmptyObject, n as findAncestorInSet, o as selfOrAncestor, r as getPath, t as deletePath } from "./object-CtPYTIvy.mjs";
|
|
4
4
|
import { c as CalendarBucketLabel, d as WeekStart, g as ALL_AGGREGATE_FNS, l as ComputedExpr, o as BucketExpr, s as BucketUnit, u as ResolvedBucket } from "./agg-Wo-smrYV.mjs";
|
|
5
5
|
import { _ as aggregateFailure, a as buildValidationContext, c as isNavRelation, d as getKeyProps, f as CasExhaustedError, g as aggregateExpressionsNotSupported, h as DbErrorCode, l as TArrayPatch, m as DbError, n as ValidatorMode, p as CasMismatchError, r as buildDbValidator, s as forceNavNonOptional, t as ValidationContext, u as TDbPatch, v as bucketTimeZoneUnavailable, y as isConflict } from "./validator-tBNvM1qc.mjs";
|
|
6
6
|
import { n as createDbValidatorPlugin, t as DbValidationContext } from "./db-validator-plugin-BWy60OvG.mjs";
|
|
7
|
-
import { r as fkColumns, s as isColumnTypeChanged } from "./fk-diff-
|
|
8
|
-
import { i as tableNameOf } from "./relation-helpers-
|
|
7
|
+
import { r as fkColumns, s as isColumnTypeChanged } from "./fk-diff-lcAnwvm9.mjs";
|
|
8
|
+
import { i as tableNameOf } from "./relation-helpers-Bdo4NHPC.mjs";
|
|
9
9
|
import { AtscriptExprNode as AtscriptExprNode$1, TAtscriptAnnotatedType } from "@atscript/typescript/utils";
|
|
10
10
|
import { AggregateQuery as AggregateQuery$1, FilterExpr as FilterExpr$1, FilterVisitor, RELATION_OPS, RelationOp, RelationOp as RelationOp$1, ResolvedRowOrderKey, ResolvedSelectExpr, Uniquery as Uniquery$1, computeInsights, isPrimitive, isRelationOp, walkFilter } from "@uniqu/core";
|
|
11
11
|
|
|
@@ -50,19 +50,13 @@ declare class RelationalFieldMapper extends FieldMappingStrategy {
|
|
|
50
50
|
*/
|
|
51
51
|
private translateControls;
|
|
52
52
|
/**
|
|
53
|
-
* Flattens nested
|
|
54
|
-
*
|
|
53
|
+
* Flattens nested objects into __-separated keys and JSON-stringifies
|
|
54
|
+
* @db.json / array fields — with `prepareCommon` folded in: primary-key
|
|
55
|
+
* values prepared (`adapter.prepareId`), top-level ignored fields (skipped
|
|
56
|
+
* by {@link writeFlattenedField}) and derived fields left out. `payload`
|
|
57
|
+
* itself is not modified.
|
|
55
58
|
*/
|
|
56
|
-
private
|
|
57
|
-
/**
|
|
58
|
-
* Classifies and writes a single field to the result object.
|
|
59
|
-
* Recurses into nested objects that should be flattened.
|
|
60
|
-
*/
|
|
61
|
-
private writeFlattenedField;
|
|
62
|
-
/**
|
|
63
|
-
* When a parent object is null/undefined, set all its flattened children to null.
|
|
64
|
-
*/
|
|
65
|
-
private setFlattenedChildrenNull;
|
|
59
|
+
private flattenWritePayload;
|
|
66
60
|
}
|
|
67
61
|
//#endregion
|
|
68
62
|
//#region src/strategies/application-integrity.d.ts
|
|
@@ -93,7 +87,12 @@ declare class ApplicationIntegrity extends IntegrityStrategy {
|
|
|
93
87
|
* leave the parent behind). Any other filter → `undefined`.
|
|
94
88
|
*/
|
|
95
89
|
cascadeBeforeDelete(filter: FilterExpr$1, tableName: string, meta: TableMetadata, cascadeResolver: TCascadeResolver, translateFilter: (f: FilterExpr$1) => FilterExpr$1, adapter: BaseDbAdapter): Promise<TCascadePin>;
|
|
96
|
-
|
|
90
|
+
/**
|
|
91
|
+
* A resolver is set and — when `tableName` is given (since 0.1.151) — some
|
|
92
|
+
* table references `tableName` with an `onDelete` action: a delete from a
|
|
93
|
+
* table nothing references needs no cascade pass (nor its transaction).
|
|
94
|
+
*/
|
|
95
|
+
needsCascade(cascadeResolver: TCascadeResolver | undefined, tableName?: string): boolean;
|
|
97
96
|
private recordKey;
|
|
98
97
|
/**
|
|
99
98
|
* Builds a filter for child records whose FK matches the deleted parent's PK values.
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as aggregateExpressionsNotSupported, c as isConflict, l as spaceClosedError, n as CasMismatchError, o as aggregateFailure, r as DbError, s as bucketTimeZoneUnavailable, t as CasExhaustedError } from "./db-error-Az85UhTX.mjs";
|
|
2
|
-
import { $ as DocumentFieldMapper, A as resolveDesignType, B as checkHavingKeys, C as ALL_BUCKET_UNITS, D as IntegrityStrategy, E as createFailureCollector, F as ENCRYPTED_REASON, G as guardFilter, H as collectQueryPaths, I as acceptedOperatorsHint, J as guardQuery, K as guardPath, L as assertGeoPoint, M as searchIndexNotFoundMessage, N as vectorIndexNotFoundMessage, O as NativeIntegrity, P as ADAPTER_FILTER_REASON, Q as RelationalFieldMapper, R as bucketSourceVerdict, S as ApplicationIntegrity, T as BaseDbAdapter, U as groupSourceVerdict, V as classifyQueryPath, W as guardAggregate, X as sortFieldNames, Y as narrowerFilterOps, Z as unsupportedOperatorMessage, _ as isViewType, _t as NoopLogger, at as describeFulltext, b as assertNoVersionWrites, ct as TableMetadata, dt as aliasTargetOf, et as FieldMappingStrategy, f as fkColumns, ft as isBucketableField, g as isAtscriptDbView, gt as resolveCalendarBuckets, h as AtscriptDbView, ht as normalizeComputedSelect, it as defaultFulltextIndex, j as geoIndexNotFoundMessage, k as AtscriptDbReadable, lt as isGeoIndexableType, mt as jsonValueAncestor, n as isColumnTypeChanged, nt as numericOperandProblem, ot as searchTermInteger, pt as isJsonValueField, q as guardPaths, rt as INTEGER_REGEX_OP, st as splitFulltextFields, tt as UniquSelect, ut as isGeoPointType, v as AtscriptDbTable, w as ALL_VIEW_CAPABILITIES, x as decomposePatch, y as isVersionExemptPatch, z as canFilterLeaf } from "./column-diff-
|
|
2
|
+
import { $ as DocumentFieldMapper, A as resolveDesignType, B as checkHavingKeys, C as ALL_BUCKET_UNITS, D as IntegrityStrategy, E as createFailureCollector, F as ENCRYPTED_REASON, G as guardFilter, H as collectQueryPaths, I as acceptedOperatorsHint, J as guardQuery, K as guardPath, L as assertGeoPoint, M as searchIndexNotFoundMessage, N as vectorIndexNotFoundMessage, O as NativeIntegrity, P as ADAPTER_FILTER_REASON, Q as RelationalFieldMapper, R as bucketSourceVerdict, S as ApplicationIntegrity, T as BaseDbAdapter, U as groupSourceVerdict, V as classifyQueryPath, W as guardAggregate, X as sortFieldNames, Y as narrowerFilterOps, Z as unsupportedOperatorMessage, _ as isViewType, _t as NoopLogger, at as describeFulltext, b as assertNoVersionWrites, ct as TableMetadata, dt as aliasTargetOf, et as FieldMappingStrategy, f as fkColumns, ft as isBucketableField, g as isAtscriptDbView, gt as resolveCalendarBuckets, h as AtscriptDbView, ht as normalizeComputedSelect, it as defaultFulltextIndex, j as geoIndexNotFoundMessage, k as AtscriptDbReadable, lt as isGeoIndexableType, mt as jsonValueAncestor, n as isColumnTypeChanged, nt as numericOperandProblem, ot as searchTermInteger, pt as isJsonValueField, q as guardPaths, rt as INTEGER_REGEX_OP, st as splitFulltextFields, tt as UniquSelect, ut as isGeoPointType, v as AtscriptDbTable, w as ALL_VIEW_CAPABILITIES, x as decomposePatch, y as isVersionExemptPatch, z as canFilterLeaf } from "./column-diff-CnyLjbQ8.mjs";
|
|
3
3
|
import { n as ALL_AGGREGATE_FNS } from "./aggregate-fns-CyaZyb9I.mjs";
|
|
4
|
-
import { A as
|
|
4
|
+
import { A as hasRelationOp, C as REL_FILTER_MAX_DEPTH, D as containsRelationFilter, E as andFilters, G as evaluateExpr, H as tableNameOf, K as isFieldRef, P as relationStaticFilter, S as uniqueKeyTuple, T as ResolvedRelationFilter, j as isResolvedRelationFilter, k as forEachResolvedRelation, q as translateQueryTree, w as REL_FILTER_MAX_NODES } from "./nested-writer-cvbVAkNo.mjs";
|
|
5
5
|
import { i as DB_ENTITY_ANNOTATIONS, n as searchMemberKind } from "./search-fields-DBIZKwyb.mjs";
|
|
6
6
|
import { a as isPlainObject, i as isEmptyObject, n as findAncestorInSet, o as selfOrAncestor, r as getPath, t as deletePath } from "./object-TkiJQ-Dp.mjs";
|
|
7
7
|
import { t as DEFAULT_DB_SPACE } from "./consts-C_-5_pFq.mjs";
|
|
@@ -235,6 +235,12 @@ var DbSpace = class {
|
|
|
235
235
|
_readables = /* @__PURE__ */ new WeakMap();
|
|
236
236
|
/** All tables created in this space — used for reverse FK lookup during cascade. */
|
|
237
237
|
_allTables = /* @__PURE__ */ new Set();
|
|
238
|
+
/**
|
|
239
|
+
* Per-table-name memo of {@link _getCascadeTargets} / {@link _getFkLookupTarget}
|
|
240
|
+
* (since 0.1.151) — both scan every table; cleared whenever a table is added.
|
|
241
|
+
*/
|
|
242
|
+
_cascadeTargets = /* @__PURE__ */ new Map();
|
|
243
|
+
_fkLookupTargets = /* @__PURE__ */ new Map();
|
|
238
244
|
/** Every table / view handle the space created — flagged closed on {@link close}. */
|
|
239
245
|
_handles = /* @__PURE__ */ new Set();
|
|
240
246
|
/** Lazily created adapter for administrative ops (drop table/view) that don't need a registered readable. */
|
|
@@ -284,6 +290,8 @@ var DbSpace = class {
|
|
|
284
290
|
return resolved instanceof AtscriptDbTable ? resolved : void 0;
|
|
285
291
|
});
|
|
286
292
|
this._allTables.add(readable);
|
|
293
|
+
this._cascadeTargets.clear();
|
|
294
|
+
this._fkLookupTargets.clear();
|
|
287
295
|
readable.setCascadeResolver((tableName) => this._getCascadeTargets(tableName));
|
|
288
296
|
readable.setFkLookupResolver((tableName) => this._getFkLookupTarget(tableName));
|
|
289
297
|
readable.setEncryption(this._encryption);
|
|
@@ -412,6 +420,14 @@ var DbSpace = class {
|
|
|
412
420
|
* Accesses `table.foreignKeys` which triggers `_flatten()` if needed.
|
|
413
421
|
*/
|
|
414
422
|
_getCascadeTargets(tableName) {
|
|
423
|
+
let targets = this._cascadeTargets.get(tableName);
|
|
424
|
+
if (targets === void 0) {
|
|
425
|
+
targets = this._scanCascadeTargets(tableName);
|
|
426
|
+
this._cascadeTargets.set(tableName, targets);
|
|
427
|
+
}
|
|
428
|
+
return targets;
|
|
429
|
+
}
|
|
430
|
+
_scanCascadeTargets(tableName) {
|
|
415
431
|
const targets = [];
|
|
416
432
|
for (const table of this._allTables) for (const fk of table.foreignKeys.values()) if (fk.targetTable === tableName && fk.onDelete) targets.push({
|
|
417
433
|
fk,
|
|
@@ -427,6 +443,12 @@ var DbSpace = class {
|
|
|
427
443
|
* Searches all registered tables for one with the matching table name.
|
|
428
444
|
*/
|
|
429
445
|
_getFkLookupTarget(tableName) {
|
|
446
|
+
if (this._fkLookupTargets.has(tableName)) return this._fkLookupTargets.get(tableName);
|
|
447
|
+
const target = this._scanFkLookupTarget(tableName);
|
|
448
|
+
this._fkLookupTargets.set(tableName, target);
|
|
449
|
+
return target;
|
|
450
|
+
}
|
|
451
|
+
_scanFkLookupTarget(tableName) {
|
|
430
452
|
for (const table of this._allTables) if (table.tableName === tableName) return { count: (filter) => table.count({ filter }) };
|
|
431
453
|
}
|
|
432
454
|
};
|
|
@@ -676,6 +676,68 @@ function uniqueKeyTuple(row, fields) {
|
|
|
676
676
|
}
|
|
677
677
|
return JSON.stringify(parts);
|
|
678
678
|
}
|
|
679
|
+
/**
|
|
680
|
+
* For every equality `filters[i]`, the FIRST row of `rows` that
|
|
681
|
+
* {@link rowMatchesKey} matches it — `rows.find(…)` per filter, answered from
|
|
682
|
+
* one hash index per distinct filter key set instead of a scan per filter.
|
|
683
|
+
* A filter holding a `null` / `undefined` value (where {@link sameKey}
|
|
684
|
+
* differs from string identity) is matched by the scan. `undefined` = no row.
|
|
685
|
+
* @since 0.1.151
|
|
686
|
+
*/
|
|
687
|
+
function findRowsByKeys(rows, filters) {
|
|
688
|
+
const out = Array.from({ length: filters.length });
|
|
689
|
+
if (rows.length * filters.length <= 64) {
|
|
690
|
+
for (let i = 0; i < filters.length; i++) out[i] = rows.find((r) => rowMatchesKey(r, filters[i]));
|
|
691
|
+
return out;
|
|
692
|
+
}
|
|
693
|
+
const indexes = /* @__PURE__ */ new Map();
|
|
694
|
+
for (let i = 0; i < filters.length; i++) {
|
|
695
|
+
const filter = filters[i];
|
|
696
|
+
const fields = Object.keys(filter);
|
|
697
|
+
let indexable = fields.length > 0;
|
|
698
|
+
for (const field of fields) {
|
|
699
|
+
const value = filter[field];
|
|
700
|
+
if (value === null || value === void 0) {
|
|
701
|
+
indexable = false;
|
|
702
|
+
break;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
if (!indexable) {
|
|
706
|
+
out[i] = rows.find((r) => rowMatchesKey(r, filter));
|
|
707
|
+
continue;
|
|
708
|
+
}
|
|
709
|
+
const signature = JSON.stringify(fields);
|
|
710
|
+
let index = indexes.get(signature);
|
|
711
|
+
if (index === void 0) {
|
|
712
|
+
index = /* @__PURE__ */ new Map();
|
|
713
|
+
for (const row of rows) {
|
|
714
|
+
const key = keyTupleString(row, fields);
|
|
715
|
+
if (key !== void 0 && !index.has(key)) index.set(key, row);
|
|
716
|
+
}
|
|
717
|
+
indexes.set(signature, index);
|
|
718
|
+
}
|
|
719
|
+
out[i] = index.get(keyTupleString(filter, fields, true));
|
|
720
|
+
}
|
|
721
|
+
return out;
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* The {@link keyString} tuple of `fields` of `source` (dot-paths read nested
|
|
725
|
+
* for a row, plain keys for a filter); `undefined` when a component is null /
|
|
726
|
+
* missing (it can only equal a null filter value, which is never indexed).
|
|
727
|
+
*/
|
|
728
|
+
function keyTupleString(source, fields, plain = false) {
|
|
729
|
+
if (fields.length === 1) {
|
|
730
|
+
const value = plain ? source[fields[0]] : require_object.getPath(source, fields[0]);
|
|
731
|
+
return value === null || value === void 0 ? void 0 : keyString(value);
|
|
732
|
+
}
|
|
733
|
+
const parts = [];
|
|
734
|
+
for (const field of fields) {
|
|
735
|
+
const value = plain ? source[field] : require_object.getPath(source, field);
|
|
736
|
+
if (value === null || value === void 0) return void 0;
|
|
737
|
+
parts.push(keyString(value));
|
|
738
|
+
}
|
|
739
|
+
return JSON.stringify(parts);
|
|
740
|
+
}
|
|
679
741
|
//#endregion
|
|
680
742
|
//#region src/table/error-utils.ts
|
|
681
743
|
/**
|
|
@@ -944,10 +1006,11 @@ async function batchReplaceNestedFrom(host, originals, maxDepth, depth, plan) {
|
|
|
944
1006
|
if (relation.direction !== "from" || !hasNavValue(originals, navField)) continue;
|
|
945
1007
|
const target = fromWriteTarget(host, relation, navField, plan, maxDepth, depth);
|
|
946
1008
|
if (!target) continue;
|
|
947
|
-
|
|
948
|
-
|
|
1009
|
+
const replacing = originals.filter((original) => Array.isArray(original[navField]) && original[parentPKField] !== void 0);
|
|
1010
|
+
const current = await currentChildrenOf(target, replacing.map((original) => original[parentPKField]), replacing.flatMap((original) => original[navField]));
|
|
1011
|
+
for (const original of replacing) {
|
|
949
1012
|
const parentPK = original[parentPKField];
|
|
950
|
-
|
|
1013
|
+
await fromReplace(target, original[navField], parentPK, current?.get(keyString(parentPK)));
|
|
951
1014
|
}
|
|
952
1015
|
}
|
|
953
1016
|
}
|
|
@@ -1105,12 +1168,24 @@ async function batchPatchNestedFrom(host, originals, maxDepth, depth, plan) {
|
|
|
1105
1168
|
const target = fromWriteTarget(host, relation, navField, plan, maxDepth, depth);
|
|
1106
1169
|
if (!target) continue;
|
|
1107
1170
|
const { targetTable, fkField, childPKs } = target;
|
|
1171
|
+
const patching = [];
|
|
1108
1172
|
for (const original of originals) {
|
|
1109
1173
|
const navValue = original[navField];
|
|
1110
1174
|
const parentPK = original[parentPKField];
|
|
1111
1175
|
if (navValue === void 0 || navValue === null || parentPK === void 0) continue;
|
|
1112
|
-
|
|
1113
|
-
|
|
1176
|
+
patching.push({
|
|
1177
|
+
parentPK,
|
|
1178
|
+
ops: extractNavPatchOps(navValue)
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
const current = new Set(patching.map(({ parentPK }) => keyString(parentPK))).size < patching.length ? void 0 : await currentChildrenOf(target, patching.filter(({ ops }) => ops.replace).map(({ parentPK }) => parentPK), patching.flatMap(({ ops }) => [
|
|
1182
|
+
...ops.replace ?? [],
|
|
1183
|
+
...ops.update ?? [],
|
|
1184
|
+
...ops.upsert ?? [],
|
|
1185
|
+
...ops.insert ?? []
|
|
1186
|
+
]));
|
|
1187
|
+
for (const { parentPK, ops } of patching) {
|
|
1188
|
+
if (ops.replace) await fromReplace(target, ops.replace, parentPK, current?.get(keyString(parentPK)));
|
|
1114
1189
|
if (ops.remove && ops.remove.length > 0) {
|
|
1115
1190
|
const removeFilters = ops.remove.map((child) => {
|
|
1116
1191
|
const rec = child;
|
|
@@ -1395,7 +1470,7 @@ async function fromUpdate(target, items) {
|
|
|
1395
1470
|
* FROM $replace helper: delete the parent's orphans, replace its keyed
|
|
1396
1471
|
* children, insert the rest.
|
|
1397
1472
|
*/
|
|
1398
|
-
async function fromReplace(target, children, parentPK) {
|
|
1473
|
+
async function fromReplace(target, children, parentPK, current) {
|
|
1399
1474
|
const { targetTable, navField, fkField, childPKs, maxDepth, depth } = target;
|
|
1400
1475
|
const toReplace = [];
|
|
1401
1476
|
const toInsert = [];
|
|
@@ -1410,7 +1485,7 @@ async function fromReplace(target, children, parentPK) {
|
|
|
1410
1485
|
toReplace.push(childData);
|
|
1411
1486
|
} else toInsert.push(childData);
|
|
1412
1487
|
}
|
|
1413
|
-
const existing = await targetTable.findMany({
|
|
1488
|
+
const existing = current ?? await targetTable.findMany({
|
|
1414
1489
|
filter: { [fkField]: parentPK },
|
|
1415
1490
|
controls: childPKs.length > 0 ? { $select: [...childPKs] } : {}
|
|
1416
1491
|
});
|
|
@@ -1427,6 +1502,47 @@ async function fromReplace(target, children, parentPK) {
|
|
|
1427
1502
|
}));
|
|
1428
1503
|
}
|
|
1429
1504
|
/**
|
|
1505
|
+
* The current (keyed) children of several parents in ONE read — what
|
|
1506
|
+
* {@link fromReplace} reads per parent, grouped by parent key (since 0.1.151).
|
|
1507
|
+
* The writes stay per parent and in order; only this read is shared, which is
|
|
1508
|
+
* safe because each parent's writes are pinned to its own children (the
|
|
1509
|
+
* foreign key is filtered on and never SET) and no child entry of the batch
|
|
1510
|
+
* (`entries`) carries nested navigation data (no nested write of a child can
|
|
1511
|
+
* reach another parent's children); a row removed meanwhile by a delete cascade is a no-op orphan
|
|
1512
|
+
* delete or the same `CONFLICT` either way. Done only where grouping cannot
|
|
1513
|
+
* differ from the store's own matching: two or more DISTINCT integer parent
|
|
1514
|
+
* keys (no collation can merge two of them) and a child table with a primary
|
|
1515
|
+
* key; a fetched row that maps to no parent key (a representation the
|
|
1516
|
+
* grouping does not know) also falls back. `undefined` → read per parent.
|
|
1517
|
+
*/
|
|
1518
|
+
async function currentChildrenOf(target, parentPKs, entries) {
|
|
1519
|
+
const { targetTable, fkField, childPKs } = target;
|
|
1520
|
+
if (parentPKs.length < 2 || childPKs.length === 0) return void 0;
|
|
1521
|
+
const childNav = targetTable.getMetadata().navFields;
|
|
1522
|
+
if (childNav.size > 0) for (const entry of entries) for (const navField of childNav) {
|
|
1523
|
+
const value = entry?.[navField];
|
|
1524
|
+
if (value !== void 0 && value !== null) return void 0;
|
|
1525
|
+
}
|
|
1526
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1527
|
+
for (const pk of parentPKs) {
|
|
1528
|
+
if (!(typeof pk === "number" && Number.isInteger(pk)) && typeof pk !== "bigint") return;
|
|
1529
|
+
const key = keyString(pk);
|
|
1530
|
+
if (groups.has(key)) return void 0;
|
|
1531
|
+
groups.set(key, []);
|
|
1532
|
+
}
|
|
1533
|
+
const rows = await targetTable.findMany({
|
|
1534
|
+
filter: { [fkField]: { $in: parentPKs } },
|
|
1535
|
+
controls: { $select: [...new Set([...childPKs, fkField])] }
|
|
1536
|
+
});
|
|
1537
|
+
for (const row of rows) {
|
|
1538
|
+
const value = row[fkField];
|
|
1539
|
+
const group = value === null || value === void 0 ? void 0 : groups.get(keyString(value));
|
|
1540
|
+
if (!group) return void 0;
|
|
1541
|
+
group.push(row);
|
|
1542
|
+
}
|
|
1543
|
+
return groups;
|
|
1544
|
+
}
|
|
1545
|
+
/**
|
|
1430
1546
|
* Links `targets` to the parent: keyed entries by their key, unkeyed ones
|
|
1431
1547
|
* inserted first — then one junction insert.
|
|
1432
1548
|
*/
|
|
@@ -1621,6 +1737,12 @@ Object.defineProperty(exports, "findRemoteFK", {
|
|
|
1621
1737
|
return findRemoteFK;
|
|
1622
1738
|
}
|
|
1623
1739
|
});
|
|
1740
|
+
Object.defineProperty(exports, "findRowsByKeys", {
|
|
1741
|
+
enumerable: true,
|
|
1742
|
+
get: function() {
|
|
1743
|
+
return findRowsByKeys;
|
|
1744
|
+
}
|
|
1745
|
+
});
|
|
1624
1746
|
Object.defineProperty(exports, "forEachResolvedRelation", {
|
|
1625
1747
|
enumerable: true,
|
|
1626
1748
|
get: function() {
|
|
@@ -676,6 +676,68 @@ function uniqueKeyTuple(row, fields) {
|
|
|
676
676
|
}
|
|
677
677
|
return JSON.stringify(parts);
|
|
678
678
|
}
|
|
679
|
+
/**
|
|
680
|
+
* For every equality `filters[i]`, the FIRST row of `rows` that
|
|
681
|
+
* {@link rowMatchesKey} matches it — `rows.find(…)` per filter, answered from
|
|
682
|
+
* one hash index per distinct filter key set instead of a scan per filter.
|
|
683
|
+
* A filter holding a `null` / `undefined` value (where {@link sameKey}
|
|
684
|
+
* differs from string identity) is matched by the scan. `undefined` = no row.
|
|
685
|
+
* @since 0.1.151
|
|
686
|
+
*/
|
|
687
|
+
function findRowsByKeys(rows, filters) {
|
|
688
|
+
const out = Array.from({ length: filters.length });
|
|
689
|
+
if (rows.length * filters.length <= 64) {
|
|
690
|
+
for (let i = 0; i < filters.length; i++) out[i] = rows.find((r) => rowMatchesKey(r, filters[i]));
|
|
691
|
+
return out;
|
|
692
|
+
}
|
|
693
|
+
const indexes = /* @__PURE__ */ new Map();
|
|
694
|
+
for (let i = 0; i < filters.length; i++) {
|
|
695
|
+
const filter = filters[i];
|
|
696
|
+
const fields = Object.keys(filter);
|
|
697
|
+
let indexable = fields.length > 0;
|
|
698
|
+
for (const field of fields) {
|
|
699
|
+
const value = filter[field];
|
|
700
|
+
if (value === null || value === void 0) {
|
|
701
|
+
indexable = false;
|
|
702
|
+
break;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
if (!indexable) {
|
|
706
|
+
out[i] = rows.find((r) => rowMatchesKey(r, filter));
|
|
707
|
+
continue;
|
|
708
|
+
}
|
|
709
|
+
const signature = JSON.stringify(fields);
|
|
710
|
+
let index = indexes.get(signature);
|
|
711
|
+
if (index === void 0) {
|
|
712
|
+
index = /* @__PURE__ */ new Map();
|
|
713
|
+
for (const row of rows) {
|
|
714
|
+
const key = keyTupleString(row, fields);
|
|
715
|
+
if (key !== void 0 && !index.has(key)) index.set(key, row);
|
|
716
|
+
}
|
|
717
|
+
indexes.set(signature, index);
|
|
718
|
+
}
|
|
719
|
+
out[i] = index.get(keyTupleString(filter, fields, true));
|
|
720
|
+
}
|
|
721
|
+
return out;
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* The {@link keyString} tuple of `fields` of `source` (dot-paths read nested
|
|
725
|
+
* for a row, plain keys for a filter); `undefined` when a component is null /
|
|
726
|
+
* missing (it can only equal a null filter value, which is never indexed).
|
|
727
|
+
*/
|
|
728
|
+
function keyTupleString(source, fields, plain = false) {
|
|
729
|
+
if (fields.length === 1) {
|
|
730
|
+
const value = plain ? source[fields[0]] : getPath(source, fields[0]);
|
|
731
|
+
return value === null || value === void 0 ? void 0 : keyString(value);
|
|
732
|
+
}
|
|
733
|
+
const parts = [];
|
|
734
|
+
for (const field of fields) {
|
|
735
|
+
const value = plain ? source[field] : getPath(source, field);
|
|
736
|
+
if (value === null || value === void 0) return void 0;
|
|
737
|
+
parts.push(keyString(value));
|
|
738
|
+
}
|
|
739
|
+
return JSON.stringify(parts);
|
|
740
|
+
}
|
|
679
741
|
//#endregion
|
|
680
742
|
//#region src/table/error-utils.ts
|
|
681
743
|
/**
|
|
@@ -944,10 +1006,11 @@ async function batchReplaceNestedFrom(host, originals, maxDepth, depth, plan) {
|
|
|
944
1006
|
if (relation.direction !== "from" || !hasNavValue(originals, navField)) continue;
|
|
945
1007
|
const target = fromWriteTarget(host, relation, navField, plan, maxDepth, depth);
|
|
946
1008
|
if (!target) continue;
|
|
947
|
-
|
|
948
|
-
|
|
1009
|
+
const replacing = originals.filter((original) => Array.isArray(original[navField]) && original[parentPKField] !== void 0);
|
|
1010
|
+
const current = await currentChildrenOf(target, replacing.map((original) => original[parentPKField]), replacing.flatMap((original) => original[navField]));
|
|
1011
|
+
for (const original of replacing) {
|
|
949
1012
|
const parentPK = original[parentPKField];
|
|
950
|
-
|
|
1013
|
+
await fromReplace(target, original[navField], parentPK, current?.get(keyString(parentPK)));
|
|
951
1014
|
}
|
|
952
1015
|
}
|
|
953
1016
|
}
|
|
@@ -1105,12 +1168,24 @@ async function batchPatchNestedFrom(host, originals, maxDepth, depth, plan) {
|
|
|
1105
1168
|
const target = fromWriteTarget(host, relation, navField, plan, maxDepth, depth);
|
|
1106
1169
|
if (!target) continue;
|
|
1107
1170
|
const { targetTable, fkField, childPKs } = target;
|
|
1171
|
+
const patching = [];
|
|
1108
1172
|
for (const original of originals) {
|
|
1109
1173
|
const navValue = original[navField];
|
|
1110
1174
|
const parentPK = original[parentPKField];
|
|
1111
1175
|
if (navValue === void 0 || navValue === null || parentPK === void 0) continue;
|
|
1112
|
-
|
|
1113
|
-
|
|
1176
|
+
patching.push({
|
|
1177
|
+
parentPK,
|
|
1178
|
+
ops: extractNavPatchOps(navValue)
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
const current = new Set(patching.map(({ parentPK }) => keyString(parentPK))).size < patching.length ? void 0 : await currentChildrenOf(target, patching.filter(({ ops }) => ops.replace).map(({ parentPK }) => parentPK), patching.flatMap(({ ops }) => [
|
|
1182
|
+
...ops.replace ?? [],
|
|
1183
|
+
...ops.update ?? [],
|
|
1184
|
+
...ops.upsert ?? [],
|
|
1185
|
+
...ops.insert ?? []
|
|
1186
|
+
]));
|
|
1187
|
+
for (const { parentPK, ops } of patching) {
|
|
1188
|
+
if (ops.replace) await fromReplace(target, ops.replace, parentPK, current?.get(keyString(parentPK)));
|
|
1114
1189
|
if (ops.remove && ops.remove.length > 0) {
|
|
1115
1190
|
const removeFilters = ops.remove.map((child) => {
|
|
1116
1191
|
const rec = child;
|
|
@@ -1395,7 +1470,7 @@ async function fromUpdate(target, items) {
|
|
|
1395
1470
|
* FROM $replace helper: delete the parent's orphans, replace its keyed
|
|
1396
1471
|
* children, insert the rest.
|
|
1397
1472
|
*/
|
|
1398
|
-
async function fromReplace(target, children, parentPK) {
|
|
1473
|
+
async function fromReplace(target, children, parentPK, current) {
|
|
1399
1474
|
const { targetTable, navField, fkField, childPKs, maxDepth, depth } = target;
|
|
1400
1475
|
const toReplace = [];
|
|
1401
1476
|
const toInsert = [];
|
|
@@ -1410,7 +1485,7 @@ async function fromReplace(target, children, parentPK) {
|
|
|
1410
1485
|
toReplace.push(childData);
|
|
1411
1486
|
} else toInsert.push(childData);
|
|
1412
1487
|
}
|
|
1413
|
-
const existing = await targetTable.findMany({
|
|
1488
|
+
const existing = current ?? await targetTable.findMany({
|
|
1414
1489
|
filter: { [fkField]: parentPK },
|
|
1415
1490
|
controls: childPKs.length > 0 ? { $select: [...childPKs] } : {}
|
|
1416
1491
|
});
|
|
@@ -1427,6 +1502,47 @@ async function fromReplace(target, children, parentPK) {
|
|
|
1427
1502
|
}));
|
|
1428
1503
|
}
|
|
1429
1504
|
/**
|
|
1505
|
+
* The current (keyed) children of several parents in ONE read — what
|
|
1506
|
+
* {@link fromReplace} reads per parent, grouped by parent key (since 0.1.151).
|
|
1507
|
+
* The writes stay per parent and in order; only this read is shared, which is
|
|
1508
|
+
* safe because each parent's writes are pinned to its own children (the
|
|
1509
|
+
* foreign key is filtered on and never SET) and no child entry of the batch
|
|
1510
|
+
* (`entries`) carries nested navigation data (no nested write of a child can
|
|
1511
|
+
* reach another parent's children); a row removed meanwhile by a delete cascade is a no-op orphan
|
|
1512
|
+
* delete or the same `CONFLICT` either way. Done only where grouping cannot
|
|
1513
|
+
* differ from the store's own matching: two or more DISTINCT integer parent
|
|
1514
|
+
* keys (no collation can merge two of them) and a child table with a primary
|
|
1515
|
+
* key; a fetched row that maps to no parent key (a representation the
|
|
1516
|
+
* grouping does not know) also falls back. `undefined` → read per parent.
|
|
1517
|
+
*/
|
|
1518
|
+
async function currentChildrenOf(target, parentPKs, entries) {
|
|
1519
|
+
const { targetTable, fkField, childPKs } = target;
|
|
1520
|
+
if (parentPKs.length < 2 || childPKs.length === 0) return void 0;
|
|
1521
|
+
const childNav = targetTable.getMetadata().navFields;
|
|
1522
|
+
if (childNav.size > 0) for (const entry of entries) for (const navField of childNav) {
|
|
1523
|
+
const value = entry?.[navField];
|
|
1524
|
+
if (value !== void 0 && value !== null) return void 0;
|
|
1525
|
+
}
|
|
1526
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1527
|
+
for (const pk of parentPKs) {
|
|
1528
|
+
if (!(typeof pk === "number" && Number.isInteger(pk)) && typeof pk !== "bigint") return;
|
|
1529
|
+
const key = keyString(pk);
|
|
1530
|
+
if (groups.has(key)) return void 0;
|
|
1531
|
+
groups.set(key, []);
|
|
1532
|
+
}
|
|
1533
|
+
const rows = await targetTable.findMany({
|
|
1534
|
+
filter: { [fkField]: { $in: parentPKs } },
|
|
1535
|
+
controls: { $select: [...new Set([...childPKs, fkField])] }
|
|
1536
|
+
});
|
|
1537
|
+
for (const row of rows) {
|
|
1538
|
+
const value = row[fkField];
|
|
1539
|
+
const group = value === null || value === void 0 ? void 0 : groups.get(keyString(value));
|
|
1540
|
+
if (!group) return void 0;
|
|
1541
|
+
group.push(row);
|
|
1542
|
+
}
|
|
1543
|
+
return groups;
|
|
1544
|
+
}
|
|
1545
|
+
/**
|
|
1430
1546
|
* Links `targets` to the parent: keyed entries by their key, unkeyed ones
|
|
1431
1547
|
* inserted first — then one junction insert.
|
|
1432
1548
|
*/
|
|
@@ -1471,4 +1587,4 @@ async function viaReplace(via, targets, parentPK, maxDepth, depth) {
|
|
|
1471
1587
|
await viaLinkTargets(via, targets, parentPK, maxDepth, depth);
|
|
1472
1588
|
}
|
|
1473
1589
|
//#endregion
|
|
1474
|
-
export {
|
|
1590
|
+
export { hasRelationOp as A, resolveRelationTargetTable as B, REL_FILTER_MAX_DEPTH as C, containsRelationFilter as D, andFilters as E, resolveRelationFilterTree as F, evaluateExpr as G, tableNameOf as H, compositeKey as I, viewExprNullable as J, isFieldRef as K, findFKEntryForRelation as L, noteRelationFilter as M, relGuardState as N, createRelationFilterHost as O, relationStaticFilter as P, findFKForRelation as R, uniqueKeyTuple as S, ResolvedRelationFilter as T, computeOf as U, slicePerGroup as V, computedOperands as W, walkViewExpr as Y, remapDeleteFkViolation as _, batchPatchNestedFrom as a, rowMatchesKey as b, batchReplaceNestedFrom as c, checkDepthOverflow as d, planNestedFromVia as f, enrichFkViolation as g, validateBatch as h, batchInsertNestedVia as i, isResolvedRelationFilter as j, forEachResolvedRelation as k, batchReplaceNestedTo as l, preValidateNestedFrom as m, batchInsertNestedFrom as n, batchPatchNestedTo as o, planPatchNestedTo as p, translateQueryTree as q, batchInsertNestedTo as r, batchPatchNestedVia as s, applyPatchNestedTo as t, batchReplaceNestedVia as u, findRowsByKeys as v, REL_FILTER_MAX_NODES as w, sameKey as x, pkTupleKey as y, findRemoteFK as z };
|
package/dist/rel.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_nested_writer = require("./nested-writer-
|
|
3
|
-
const require_relation_loader = require("./relation-loader-
|
|
2
|
+
const require_nested_writer = require("./nested-writer-BzbOPSUp.cjs");
|
|
3
|
+
const require_relation_loader = require("./relation-loader-fNjHgBMs.cjs");
|
|
4
4
|
exports.applyPatchNestedTo = require_nested_writer.applyPatchNestedTo;
|
|
5
5
|
exports.batchInsertNestedFrom = require_nested_writer.batchInsertNestedFrom;
|
|
6
6
|
exports.batchInsertNestedTo = require_nested_writer.batchInsertNestedTo;
|
package/dist/rel.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Hn as TGenericLogger, Pt as TTableResolver, U as TDbForeignKey, Wt as TableMetadata, Yt as BaseDbAdapter, et as TDbRelation, h as AtscriptDbWritable, m as AtscriptDbTableLike, zt as TWriteTableResolver } from "./buckets-
|
|
1
|
+
import { Hn as TGenericLogger, Pt as TTableResolver, U as TDbForeignKey, Wt as TableMetadata, Yt as BaseDbAdapter, et as TDbRelation, h as AtscriptDbWritable, m as AtscriptDbTableLike, zt as TWriteTableResolver } from "./buckets-tzd8iIM2.cjs";
|
|
2
2
|
import { t as DbValidationContext } from "./db-validator-plugin-BWy60OvG.cjs";
|
|
3
|
-
import { n as findRemoteFK, r as resolveRelationTargetTable, t as findFKForRelation } from "./relation-helpers-
|
|
3
|
+
import { n as findRemoteFK, r as resolveRelationTargetTable, t as findFKForRelation } from "./relation-helpers-DxIZKvnJ.cjs";
|
|
4
4
|
import { FilterExpr, WithRelation } from "@uniqu/core";
|
|
5
5
|
import { Validator } from "@atscript/typescript/utils";
|
|
6
6
|
|
package/dist/rel.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Hn as TGenericLogger, Pt as TTableResolver, U as TDbForeignKey, Wt as TableMetadata, Yt as BaseDbAdapter, et as TDbRelation, h as AtscriptDbWritable, m as AtscriptDbTableLike, zt as TWriteTableResolver } from "./buckets-
|
|
1
|
+
import { Hn as TGenericLogger, Pt as TTableResolver, U as TDbForeignKey, Wt as TableMetadata, Yt as BaseDbAdapter, et as TDbRelation, h as AtscriptDbWritable, m as AtscriptDbTableLike, zt as TWriteTableResolver } from "./buckets-Cb0zmhDc.mjs";
|
|
2
2
|
import { t as DbValidationContext } from "./db-validator-plugin-BWy60OvG.mjs";
|
|
3
|
-
import { n as findRemoteFK, r as resolveRelationTargetTable, t as findFKForRelation } from "./relation-helpers-
|
|
3
|
+
import { n as findRemoteFK, r as resolveRelationTargetTable, t as findFKForRelation } from "./relation-helpers-Bdo4NHPC.mjs";
|
|
4
4
|
import { Validator } from "@atscript/typescript/utils";
|
|
5
5
|
import { FilterExpr, WithRelation } from "@uniqu/core";
|
|
6
6
|
|
package/dist/rel.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as loadRelationsImpl } from "./relation-loader-
|
|
2
|
-
import {
|
|
1
|
+
import { t as loadRelationsImpl } from "./relation-loader-DYab07lw.mjs";
|
|
2
|
+
import { B as resolveRelationTargetTable, R as findFKForRelation, a as batchPatchNestedFrom, c as batchReplaceNestedFrom, d as checkDepthOverflow, f as planNestedFromVia, h as validateBatch, i as batchInsertNestedVia, l as batchReplaceNestedTo, m as preValidateNestedFrom, n as batchInsertNestedFrom, o as batchPatchNestedTo, p as planPatchNestedTo, r as batchInsertNestedTo, s as batchPatchNestedVia, t as applyPatchNestedTo, u as batchReplaceNestedVia, z as findRemoteFK } from "./nested-writer-cvbVAkNo.mjs";
|
|
3
3
|
export { applyPatchNestedTo, batchInsertNestedFrom, batchInsertNestedTo, batchInsertNestedVia, batchPatchNestedFrom, batchPatchNestedTo, batchPatchNestedVia, batchReplaceNestedFrom, batchReplaceNestedTo, batchReplaceNestedVia, checkDepthOverflow, findFKForRelation, findRemoteFK, loadRelationsImpl, planNestedFromVia, planPatchNestedTo, preValidateNestedFrom, resolveRelationTargetTable, validateBatch };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { U as TDbForeignKey, et as TDbRelation } from "./buckets-
|
|
1
|
+
import { U as TDbForeignKey, et as TDbRelation } from "./buckets-Cb0zmhDc.mjs";
|
|
2
2
|
import { TAtscriptAnnotatedType } from "@atscript/typescript/utils";
|
|
3
3
|
|
|
4
4
|
//#region src/rel/relation-helpers.d.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { U as TDbForeignKey, et as TDbRelation } from "./buckets-
|
|
1
|
+
import { U as TDbForeignKey, et as TDbRelation } from "./buckets-tzd8iIM2.cjs";
|
|
2
2
|
import { TAtscriptAnnotatedType } from "@atscript/typescript/utils";
|
|
3
3
|
|
|
4
4
|
//#region src/rel/relation-helpers.d.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as
|
|
1
|
+
import { B as resolveRelationTargetTable, E as andFilters, I as compositeKey, P as relationStaticFilter, R as findFKForRelation, V as slicePerGroup, z as findRemoteFK } from "./nested-writer-cvbVAkNo.mjs";
|
|
2
2
|
//#region \0rolldown/runtime.js
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __exportAll = (all, no_symbols) => {
|