kitcn 0.18.0 → 0.19.0
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/aggregate/index.d.ts +1 -1
- package/dist/auth/index.js +1 -1
- package/dist/orm/index.d.ts +1 -1
- package/dist/orm/index.js +66 -10
- package/dist/{query-context-CJE_hYA3.js → query-context-BzihIpnM.js} +208 -102
- package/dist/{where-clause-compiler-B1weGkP4.d.ts → where-clause-compiler-CmBz9CWA.d.ts} +44 -34
- package/package.json +1 -1
- package/skills/kitcn/references/features/orm.md +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ConvexNumberBuilderInitial, E as ConvexIdBuilderInitial, N as ConvexCustomBuilderInitial, dn as ConvexTableWithColumns, tr as ConvexTextBuilderInitial } from "../where-clause-compiler-
|
|
1
|
+
import { C as ConvexNumberBuilderInitial, E as ConvexIdBuilderInitial, N as ConvexCustomBuilderInitial, dn as ConvexTableWithColumns, tr as ConvexTextBuilderInitial } from "../where-clause-compiler-CmBz9CWA.js";
|
|
2
2
|
import * as convex_values0 from "convex/values";
|
|
3
3
|
import { GenericId, Infer, Value } from "convex/values";
|
|
4
4
|
import { DocumentByName, GenericDataModel, GenericDatabaseReader, GenericDatabaseWriter, TableNamesInDataModel } from "convex/server";
|
package/dist/auth/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { r as partial } from "../validators-C7LelqTN.js";
|
|
|
3
3
|
import { i as defineAuth, n as createDisabledAuthRuntime, r as getGeneratedAuthDisabledReason, t as DEFAULT_AUTH_DEFINITION_PATH } from "../generated-contract-disabled-BXaz7JCE.js";
|
|
4
4
|
import { n as createGeneratedFunctionReference, o as isQueryCtx, s as isRunMutationCtx } from "../api-entry-N3nBOlI2.js";
|
|
5
5
|
import { n as customCtx, r as customMutation } from "../customFunctions-DxEEO4Dq.js";
|
|
6
|
-
import { o as mergedStream, s as stream, t as getByIdWithOrmQueryFallback, u as unsetToken, y as eq } from "../query-context-
|
|
6
|
+
import { o as mergedStream, s as stream, t as getByIdWithOrmQueryFallback, u as unsetToken, y as eq } from "../query-context-BzihIpnM.js";
|
|
7
7
|
import { n as convex } from "../convex-plugin-BHVCqWTH.js";
|
|
8
8
|
import { v } from "convex/values";
|
|
9
9
|
import { internalActionGeneric, internalMutationGeneric, internalQueryGeneric, paginationOptsValidator } from "convex/server";
|
package/dist/orm/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as GenericOrmCtx$1, $n as unique, $r as endsWith, $t as ManyConfig, A as ConvexDateMode, An as ConvexRankIndexBuilder, Ar as ReturningResult, At as MigrationManifestEntry, B as ConvexBytesBuilderInitial, Bn as rankIndex, Br as OrmSchemaRelations, Bt as defineMigration, C as ConvexNumberBuilderInitial, Ci as ColumnBuilderWithTableName, Cn as RlsRole, Cr as MutationReturning, Ct as MigrationStatusArgs, D as id, Di as IsPrimaryKey, Dn as ConvexAggregateIndexBuilderOn, Dr as PaginatedResult, Dt as MigrationDoc, E as ConvexIdBuilderInitial, Ei as HasDefault, En as ConvexAggregateIndexBuilder, Er as OrderDirection, Et as MigrationDirection, F as custom, Fn as ConvexVectorIndexBuilder, Fr as unsetToken, Ft as MigrationStateMap, G as ConvexBigIntBuilder, Gn as ConvexCheckConfig, Gr as ExpressionVisitor, Gt as OrmReader$1, H as ConvexBooleanBuilder, Hn as uniqueIndex, Hr as TableName, Ht as detectMigrationDrift, I as json, In as ConvexVectorIndexBuilderOn, Ir as Brand, It as MigrationStep, J as CountBackfillChunkArgs, Jn as ConvexUniqueConstraintBuilder, Jr as LogicalExpression, Jt as RlsMode, K as ConvexBigIntBuilderInitial, Kn as ConvexForeignKeyBuilder, Kr as FieldReference, Kt as OrmWriter$1, L as objectOf, Ln as ConvexVectorIndexConfig, Lr as Columns, Lt as MigrationTableName, M as ConvexCustomBuilder, Mn as ConvexSearchIndexBuilder, Mr as UpdateSet, Mt as MigrationPlan, N as ConvexCustomBuilderInitial, Nn as ConvexSearchIndexBuilderOn, Nr as VectorQueryConfig, Nt as MigrationRunStatus, O as ConvexDateBuilder, Oi as IsUnique, On as ConvexIndexBuilder, Or as PredicateWhereIndexConfig, Ot as MigrationDocContext, P as arrayOf, Pn as ConvexSearchIndexConfig, Pr as VectorSearchProvider, Pt as MigrationSet, Q as GenericOrm$1, Qn as foreignKey, Qr as contains, Qt as ExtractTablesWithRelations, R as unionOf, Rn as aggregateIndex, Rr as OrmSchemaExtensionTables, Rt as MigrationWriteMode, S as ConvexNumberBuilder, Si as ColumnBuilderTypeConfig, Sn as rlsPolicy, Sr as MutationResult, St as MigrationRunChunkArgs, T as ConvexIdBuilder, Ti as DrizzleEntity, Tn as rlsRole, Tr as OrderByClause, Tt as MigrationDefinition, U as ConvexBooleanBuilderInitial, Un as vectorIndex, Ur as SystemFields, Ut as DatabaseWithMutations, V as bytes, Vn as searchIndex, Vr as OrmSchemaTriggers, Vt as defineMigrationSet, W as boolean, Wn as ConvexCheckBuilder, Wr as BinaryExpression, Wt as DatabaseWithQuery, X as CountBackfillStatusArgs, Xn as ConvexUniqueConstraintConfig, Xr as and, Xt as extractRelationsConfig, Y as CountBackfillKickoffArgs, Yn as ConvexUniqueConstraintBuilderOn, Yr as UnaryExpression, Yt as EdgeMetadata, Z as CreateOrmOptions, Zn as check, Zr as between, Zt as ExtractTablesFromSchema, _ as ConvexTimestampMode, _i as startsWith, _n as deletion, _r as MutationExecuteConfig, _t as OrmTriggerContext, a as requireSchemaRelations, ai as inArray, an as TablesRelationalConfig, ar as AggregateResult, at as OrmWriterCtx, b as ConvexTextEnumBuilderInitial, bi as ColumnBuilderBaseConfig, bn as RlsPolicyConfig, br as MutationPaginateConfig, bt as MigrationCancelArgs, c as TableConfigResult, ci as isNull, cn as ConvexDeletionBuilder, cr as CountConfig, ct as ScheduledMutationBatchArgs, d as OrmNotFoundError, di as lte, dn as ConvexTableWithColumns, dr as FilterOperators, dt as scheduledDeleteFactory, ei as eq, en as OneConfig, er as ConvexTextBuilder, et as OrmApiResult, f as ConvexVectorBuilder, fi as ne, fn as DiscriminatorBuilderConfig, fr as GetColumnData, ft as SchemaExtension, g as ConvexTimestampBuilderInitial, gi as or, gn as convexTable, gr as InsertValue, gt as OrmTriggerChange, h as ConvexTimestampBuilder, hi as notInArray, hn as TableConfig, hr as InferSelectModel, ht as OrmTableTriggers, i as getSchemaTriggers, ii as ilike, in as TableRelationalConfig, ir as AggregateFieldValue, it as OrmReaderCtx, j as date, jn as ConvexRankIndexBuilderOn, jr as ReturningSelection, jt as MigrationMigrateOne, k as ConvexDateBuilderInitial, ki as NotNull, kn as ConvexIndexBuilderOn, kr as ReturningAll, kt as MigrationDriftIssue, l as getTableColumns, li as like, ln as ConvexDeletionConfig, lr as CountResult, lt as scheduledMutationBatchFactory, m as vector, mi as notBetween, mn as OrmLifecycleOperation, mr as InferModelFromColumns, mt as OrmBeforeResult, n as defineSchema, ni as gt, nn as RelationsBuilderColumnBase, nr as text, nt as OrmClientWithApi$1, o as asc, oi as isFieldReference, on as defineRelations, or as BuildQueryResult, ot as ResolveOrmSchema, p as ConvexVectorBuilderInitial, pi as not, pn as OrmLifecycleChange, pr as InferInsertModel, pt as defineSchemaExtension, q as bigint, qn as ConvexForeignKeyConfig, qr as FilterExpression, qt as RlsContext, r as getSchemaRelations, ri as gte, rn as RelationsBuilderColumnConfig, rr as AggregateConfig, rt as OrmFunctions, s as desc, si as isNotNull, sn as defineRelationsPart, sr as BuildRelationResult, st as createOrm, t as WhereClauseResult, ti as fieldRef, tn as RelationsBuilder, tr as ConvexTextBuilderInitial, tt as OrmClientBase$1, u as getTableConfig, ui as lt, un as ConvexTable, ur as DBQueryConfig, ut as ScheduledDeleteArgs, v as timestamp, vi as AnyColumn, vn as discriminator, vr as MutationExecuteResult, vt as OrmTriggers, w as integer, wi as ColumnDataType, wn as RlsRoleConfig, wr as MutationRunMode, wt as MigrationAppliedState, x as textEnum, xi as ColumnBuilderRuntimeConfig, xn as RlsPolicyToOption, xr as MutationPaginatedResult, xt as MigrationRunArgs, y as ConvexTextEnumBuilder, yi as ColumnBuilder, yn as RlsPolicy, yr as MutationExecutionMode, yt as defineTriggers, z as ConvexBytesBuilder, zn as index, zr as OrmSchemaExtensions, zt as buildMigrationPlan } from "../where-clause-compiler-
|
|
1
|
+
import { $ as GenericOrmCtx$1, $n as unique, $r as endsWith, $t as ManyConfig, A as ConvexDateMode, An as ConvexRankIndexBuilder, Ar as ReturningResult, At as MigrationManifestEntry, B as ConvexBytesBuilderInitial, Bn as rankIndex, Br as OrmSchemaRelations, Bt as defineMigration, C as ConvexNumberBuilderInitial, Ci as ColumnBuilderWithTableName, Cn as RlsRole, Cr as MutationReturning, Ct as MigrationStatusArgs, D as id, Di as IsPrimaryKey, Dn as ConvexAggregateIndexBuilderOn, Dr as PaginatedResult, Dt as MigrationDoc, E as ConvexIdBuilderInitial, Ei as HasDefault, En as ConvexAggregateIndexBuilder, Er as OrderDirection, Et as MigrationDirection, F as custom, Fn as ConvexVectorIndexBuilder, Fr as unsetToken, Ft as MigrationStateMap, G as ConvexBigIntBuilder, Gn as ConvexCheckConfig, Gr as ExpressionVisitor, Gt as OrmReader$1, H as ConvexBooleanBuilder, Hn as uniqueIndex, Hr as TableName, Ht as detectMigrationDrift, I as json, In as ConvexVectorIndexBuilderOn, Ir as Brand, It as MigrationStep, J as CountBackfillChunkArgs, Jn as ConvexUniqueConstraintBuilder, Jr as LogicalExpression, Jt as RlsMode, K as ConvexBigIntBuilderInitial, Kn as ConvexForeignKeyBuilder, Kr as FieldReference, Kt as OrmWriter$1, L as objectOf, Ln as ConvexVectorIndexConfig, Lr as Columns, Lt as MigrationTableName, M as ConvexCustomBuilder, Mn as ConvexSearchIndexBuilder, Mr as UpdateSet, Mt as MigrationPlan, N as ConvexCustomBuilderInitial, Nn as ConvexSearchIndexBuilderOn, Nr as VectorQueryConfig, Nt as MigrationRunStatus, O as ConvexDateBuilder, Oi as IsUnique, On as ConvexIndexBuilder, Or as PredicateWhereIndexConfig, Ot as MigrationDocContext, P as arrayOf, Pn as ConvexSearchIndexConfig, Pr as VectorSearchProvider, Pt as MigrationSet, Q as GenericOrm$1, Qn as foreignKey, Qr as contains, Qt as ExtractTablesWithRelations, R as unionOf, Rn as aggregateIndex, Rr as OrmSchemaExtensionTables, Rt as MigrationWriteMode, S as ConvexNumberBuilder, Si as ColumnBuilderTypeConfig, Sn as rlsPolicy, Sr as MutationResult, St as MigrationRunChunkArgs, T as ConvexIdBuilder, Ti as DrizzleEntity, Tn as rlsRole, Tr as OrderByClause, Tt as MigrationDefinition, U as ConvexBooleanBuilderInitial, Un as vectorIndex, Ur as SystemFields, Ut as DatabaseWithMutations, V as bytes, Vn as searchIndex, Vr as OrmSchemaTriggers, Vt as defineMigrationSet, W as boolean, Wn as ConvexCheckBuilder, Wr as BinaryExpression, Wt as DatabaseWithQuery, X as CountBackfillStatusArgs, Xn as ConvexUniqueConstraintConfig, Xr as and, Xt as extractRelationsConfig, Y as CountBackfillKickoffArgs, Yn as ConvexUniqueConstraintBuilderOn, Yr as UnaryExpression, Yt as EdgeMetadata, Z as CreateOrmOptions, Zn as check, Zr as between, Zt as ExtractTablesFromSchema, _ as ConvexTimestampMode, _i as startsWith, _n as deletion, _r as MutationExecuteConfig, _t as OrmTriggerContext, a as requireSchemaRelations, ai as inArray, an as TablesRelationalConfig, ar as AggregateResult, at as OrmWriterCtx, b as ConvexTextEnumBuilderInitial, bi as ColumnBuilderBaseConfig, bn as RlsPolicyConfig, br as MutationPaginateConfig, bt as MigrationCancelArgs, c as TableConfigResult, ci as isNull, cn as ConvexDeletionBuilder, cr as CountConfig, ct as ScheduledMutationBatchArgs, d as OrmNotFoundError, di as lte, dn as ConvexTableWithColumns, dr as FilterOperators, dt as scheduledDeleteFactory, ei as eq, en as OneConfig, er as ConvexTextBuilder, et as OrmApiResult, f as ConvexVectorBuilder, fi as ne, fn as DiscriminatorBuilderConfig, fr as GetColumnData, ft as SchemaExtension, g as ConvexTimestampBuilderInitial, gi as or, gn as convexTable, gr as InsertValue, gt as OrmTriggerChange, h as ConvexTimestampBuilder, hi as notInArray, hn as TableConfig, hr as InferSelectModel, ht as OrmTableTriggers, i as getSchemaTriggers, ii as ilike, in as TableRelationalConfig, ir as AggregateFieldValue, it as OrmReaderCtx, j as date, jn as ConvexRankIndexBuilderOn, jr as ReturningSelection, jt as MigrationMigrateOne, k as ConvexDateBuilderInitial, ki as NotNull, kn as ConvexIndexBuilderOn, kr as ReturningAll, kt as MigrationDriftIssue, l as getTableColumns, li as like, ln as ConvexDeletionConfig, lr as CountResult, lt as scheduledMutationBatchFactory, m as vector, mi as notBetween, mn as OrmLifecycleOperation, mr as InferModelFromColumns, mt as OrmBeforeResult, n as defineSchema, ni as gt, nn as RelationsBuilderColumnBase, nr as text, nt as OrmClientWithApi$1, o as asc, oi as isFieldReference, on as defineRelations, or as BuildQueryResult, ot as ResolveOrmSchema, p as ConvexVectorBuilderInitial, pi as not, pn as OrmLifecycleChange, pr as InferInsertModel, pt as defineSchemaExtension, q as bigint, qn as ConvexForeignKeyConfig, qr as FilterExpression, qt as RlsContext, r as getSchemaRelations, ri as gte, rn as RelationsBuilderColumnConfig, rr as AggregateConfig, rt as OrmFunctions, s as desc, si as isNotNull, sn as defineRelationsPart, sr as BuildRelationResult, st as createOrm, t as WhereClauseResult, ti as fieldRef, tn as RelationsBuilder, tr as ConvexTextBuilderInitial, tt as OrmClientBase$1, u as getTableConfig, ui as lt, un as ConvexTable, ur as DBQueryConfig, ut as ScheduledDeleteArgs, v as timestamp, vi as AnyColumn, vn as discriminator, vr as MutationExecuteResult, vt as OrmTriggers, w as integer, wi as ColumnDataType, wn as RlsRoleConfig, wr as MutationRunMode, wt as MigrationAppliedState, x as textEnum, xi as ColumnBuilderRuntimeConfig, xn as RlsPolicyToOption, xr as MutationPaginatedResult, xt as MigrationRunArgs, y as ConvexTextEnumBuilder, yi as ColumnBuilder, yn as RlsPolicy, yr as MutationExecutionMode, yt as defineTriggers, z as ConvexBytesBuilder, zn as index, zr as OrmSchemaExtensions, zt as buildMigrationPlan } from "../where-clause-compiler-CmBz9CWA.js";
|
|
2
2
|
import { i as pretendRequired, n as deprecated, r as pretend } from "../validators-BhsByJeg.js";
|
|
3
3
|
import { a as QueryCtxWithPreferredOrmQueryTable, i as QueryCtxWithOrmQueryTable, n as LookupByIdResultByCtx, o as getByIdWithOrmQueryFallback, r as QueryCtxWithOptionalOrmQueryTable, t as DocByCtx } from "../query-context-CNo9ffvI.js";
|
|
4
4
|
import { DefineSchemaOptions, GenericDatabaseReader, GenericDatabaseWriter, GenericSchema, SchemaDefinition } from "convex/server";
|
package/dist/orm/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { A as vectorIndex, B as ConvexColumnBuilder, C as RlsPolicy, D as rankIndex, E as index, F as arrayOf, I as custom, L as json, M as createSystemFields, N as integer, O as searchIndex, P as id, R as objectOf, S as TablePolymorphic, T as aggregateIndex, V as entityKind, _ as OrmSchemaRelations, a as deletion, b as TableDeleteConfig, c as Columns, d as OrmSchemaDefinition, f as OrmSchemaExtensionRelations, g as OrmSchemaOptions, h as OrmSchemaExtensions, i as convexTable, j as text, k as uniqueIndex, l as EnableRLS, m as OrmSchemaExtensionTriggers, o as discriminator, p as OrmSchemaExtensionTables, s as Brand, t as DirectAggregate, u as OrmContext, v as OrmSchemaTriggers, w as rlsPolicy, x as TableName, y as RlsPolicies, z as unionOf } from "../runtime-DmVSOe24.js";
|
|
2
2
|
import { a as pretendRequired, i as pretend, n as deprecated } from "../validators-C7LelqTN.js";
|
|
3
|
-
import { A as like, B as or, C as gt, D as isFieldReference, E as inArray, F as not, I as notBetween, L as notIlike, M as lte, N as matchLikePattern, O as isNotNull, P as ne, R as notInArray, S as filterValuesEqual, T as ilike, V as startsWith, _ as contains, a as indexKeyWithinBounds, b as fieldRef, c as streamIndexRange, d as and, f as arrayContained, g as column, h as between, i as getIndexFields, j as lt, k as isNull, l as isUnsetToken, m as arrayOverlaps, n as EmptyStream, o as mergedStream, p as arrayContains, r as QueryStream, s as stream, t as getByIdWithOrmQueryFallback, u as unsetToken, v as endsWith, w as gte, x as filterValueInList, y as eq, z as notLike } from "../query-context-
|
|
3
|
+
import { A as like, B as or, C as gt, D as isFieldReference, E as inArray, F as not, I as notBetween, L as notIlike, M as lte, N as matchLikePattern, O as isNotNull, P as ne, R as notInArray, S as filterValuesEqual, T as ilike, V as startsWith, _ as contains, a as indexKeyWithinBounds, b as fieldRef, c as streamIndexRange, d as and, f as arrayContained, g as column, h as between, i as getIndexFields, j as lt, k as isNull, l as isUnsetToken, m as arrayOverlaps, n as EmptyStream, o as mergedStream, p as arrayContains, r as QueryStream, s as stream, t as getByIdWithOrmQueryFallback, u as unsetToken, v as endsWith, w as gte, x as filterValueInList, y as eq, z as notLike } from "../query-context-BzihIpnM.js";
|
|
4
4
|
import { compareValues, v } from "convex/values";
|
|
5
5
|
import { defineSchema as defineSchema$1, internalActionGeneric, internalMutationGeneric } from "convex/server";
|
|
6
6
|
|
|
@@ -4585,6 +4585,42 @@ var BufferedQueryStream = class BufferedQueryStream extends QueryStream {
|
|
|
4585
4585
|
return this.equalityIndexFilter;
|
|
4586
4586
|
}
|
|
4587
4587
|
};
|
|
4588
|
+
const ID_LIST_POSITION_FIELD = "__kitcn_id_list_position";
|
|
4589
|
+
/**
|
|
4590
|
+
* Reads an `id` / `id in [...]` where one document at a time, in the order the
|
|
4591
|
+
* ids were given.
|
|
4592
|
+
*
|
|
4593
|
+
* The index key is the position in the de-duplicated id list, so a cursor names
|
|
4594
|
+
* a position and `narrow` drops entries without reading them. A page reads only
|
|
4595
|
+
* the listed positions it visits, not every id in the list on every page.
|
|
4596
|
+
*/
|
|
4597
|
+
var LazyIdListQueryStream = class LazyIdListQueryStream extends QueryStream {
|
|
4598
|
+
constructor(readId, entries, order) {
|
|
4599
|
+
super();
|
|
4600
|
+
this.readId = readId;
|
|
4601
|
+
this.entries = entries;
|
|
4602
|
+
this.order = order;
|
|
4603
|
+
}
|
|
4604
|
+
iterWithKeys() {
|
|
4605
|
+
const entries = this.entries;
|
|
4606
|
+
const readId = this.readId;
|
|
4607
|
+
return { async *[Symbol.asyncIterator]() {
|
|
4608
|
+
for (const [position, id] of entries) yield [await readId(id), [position]];
|
|
4609
|
+
} };
|
|
4610
|
+
}
|
|
4611
|
+
narrow(indexBounds) {
|
|
4612
|
+
return new LazyIdListQueryStream(this.readId, this.entries.filter(([position]) => indexKeyWithinBounds([position], indexBounds)), this.order);
|
|
4613
|
+
}
|
|
4614
|
+
getOrder() {
|
|
4615
|
+
return this.order;
|
|
4616
|
+
}
|
|
4617
|
+
getIndexFields() {
|
|
4618
|
+
return [ID_LIST_POSITION_FIELD];
|
|
4619
|
+
}
|
|
4620
|
+
getEqualityIndexFilter() {
|
|
4621
|
+
return [];
|
|
4622
|
+
}
|
|
4623
|
+
};
|
|
4588
4624
|
const PIPELINE_LIMIT_ORDINAL_FIELD = "__kitcn_limit_ordinal";
|
|
4589
4625
|
/** Cap a stream at its first `limit` matching documents without eager reads. */
|
|
4590
4626
|
var LimitedMatchesQueryStream = class LimitedMatchesQueryStream extends QueryStream {
|
|
@@ -5787,9 +5823,12 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
|
|
|
5787
5823
|
* The where-clause compiler is built from declared indexes only, and `_id` is
|
|
5788
5824
|
* never one of them, so an `id` filter can never be index-selected: it lands
|
|
5789
5825
|
* in the post-filters and the stream walks the creation-time index until it
|
|
5790
|
-
* happens on the row. `db.get()` reads exactly the rows asked for
|
|
5791
|
-
*
|
|
5792
|
-
*
|
|
5826
|
+
* happens on the row. `db.get()` reads exactly the rows asked for.
|
|
5827
|
+
*
|
|
5828
|
+
* Rows come back in the order the ids were given, one read at a time. Missing
|
|
5829
|
+
* or policy-filtered ids still cost a read, but a page does not reread the
|
|
5830
|
+
* complete list. An `orderBy` on creation time is the exception: an id carries
|
|
5831
|
+
* no creation time, so every id must be read before the first row is placed.
|
|
5793
5832
|
*
|
|
5794
5833
|
* Returns null when something else already owns the read: a pinned index, an
|
|
5795
5834
|
* index the compiler did select, a `where(predicate)`, or an `orderBy` that
|
|
@@ -5801,13 +5840,26 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
|
|
|
5801
5840
|
const primaryOrder = queryConfig.order?.[0];
|
|
5802
5841
|
if (primaryOrder && primaryOrder.field !== INTERNAL_CREATION_TIME_FIELD) return null;
|
|
5803
5842
|
const ids = idLookup.kind === "in" ? Array.from(new Map(idLookup.ids.map((id) => [String(id), id])).values()) : [idLookup.id];
|
|
5804
|
-
const
|
|
5805
|
-
|
|
5806
|
-
|
|
5843
|
+
const readId = (id) => this._getById(this.tableConfig.name, id);
|
|
5844
|
+
if (!primaryOrder) {
|
|
5845
|
+
const entries = ids.map((id, position) => [position, id]);
|
|
5846
|
+
if (order === "desc") entries.reverse();
|
|
5847
|
+
return new LazyIdListQueryStream(readId, entries, order);
|
|
5848
|
+
}
|
|
5849
|
+
const rows = (await this._mapWithConcurrency(ids, readId)).filter((row) => !!row);
|
|
5807
5850
|
rows.sort((a, b) => compareValues(a[INTERNAL_CREATION_TIME_FIELD], b[INTERNAL_CREATION_TIME_FIELD]) || compareValues(a[INTERNAL_ID_FIELD], b[INTERNAL_ID_FIELD]));
|
|
5808
5851
|
if (order === "desc") rows.reverse();
|
|
5809
5852
|
return new BufferedQueryStream(rows.map((row) => [row, [row[INTERNAL_CREATION_TIME_FIELD], row[INTERNAL_ID_FIELD]]]), order, [INTERNAL_CREATION_TIME_FIELD, INTERNAL_ID_FIELD], []);
|
|
5810
5853
|
}
|
|
5854
|
+
/**
|
|
5855
|
+
* The declared index a stream read can walk to emit `field` in order.
|
|
5856
|
+
*
|
|
5857
|
+
* A stream orders by the index it scans, so only an index that leads with
|
|
5858
|
+
* the field produces that order.
|
|
5859
|
+
*/
|
|
5860
|
+
_findStreamOrderIndex(field) {
|
|
5861
|
+
return getIndexes(this.tableConfig.table).find((index) => index.fields[0] === field);
|
|
5862
|
+
}
|
|
5811
5863
|
_buildBasePipelineStream(queryConfig, wherePredicate, configuredIndex) {
|
|
5812
5864
|
const schemaDefinition = this._getSchemaDefinitionOrThrow();
|
|
5813
5865
|
let streamQuery = stream(this.db, schemaDefinition).query(this.tableConfig.name);
|
|
@@ -5819,8 +5871,8 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
|
|
|
5819
5871
|
return indexQuery;
|
|
5820
5872
|
});
|
|
5821
5873
|
else if (configuredIndex?.name) streamQuery = streamQuery.withIndex(configuredIndex.name, configuredIndex.range ? configuredIndex.range : (q) => q);
|
|
5822
|
-
else if (primaryOrder && primaryOrder.field !==
|
|
5823
|
-
const orderIndex =
|
|
5874
|
+
else if (primaryOrder && primaryOrder.field !== INTERNAL_CREATION_TIME_FIELD) {
|
|
5875
|
+
const orderIndex = this._findStreamOrderIndex(primaryOrder.field);
|
|
5824
5876
|
if (orderIndex) streamQuery = streamQuery.withIndex(orderIndex.name, (q) => q);
|
|
5825
5877
|
}
|
|
5826
5878
|
streamQuery = streamQuery.order(primaryOrderDirection);
|
|
@@ -6978,7 +7030,11 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
|
|
|
6978
7030
|
streamQuery = mergedStream(streams, pipeline.interleaveBy.map((field) => this._normalizePublicFieldName(field)));
|
|
6979
7031
|
}
|
|
6980
7032
|
} else {
|
|
6981
|
-
|
|
7033
|
+
const orderedIdList = isCursorPaginated && maxScan !== void 0 && idLookup?.kind === "in" ? queryConfig.order?.[0] : void 0;
|
|
7034
|
+
if (orderedIdList) {
|
|
7035
|
+
if (orderedIdList.field === INTERNAL_CREATION_TIME_FIELD) throw new Error("An id IN pipeline cannot combine orderBy on createdAt with maxScan, because ordering an id list by creation time requires reading every id in the list. Drop maxScan, or drop orderBy to page in id-list order at one read per row.");
|
|
7036
|
+
if (queryConfig.order?.length !== 1 || configuredIndex?.name || queryConfig.index || !this._findStreamOrderIndex(orderedIdList.field)) throw new Error(`An id IN pipeline cannot combine orderBy on ${this._toPublicFilterFieldName(orderedIdList.field)} with maxScan, because the scan cannot produce that order. It needs a single orderBy field that an index leads with, and no index pinned by withIndex().`);
|
|
7037
|
+
}
|
|
6982
7038
|
streamQuery = await this._buildIdLookupStream({
|
|
6983
7039
|
configuredIndex,
|
|
6984
7040
|
idLookup,
|
|
@@ -528,11 +528,19 @@ function getIndexFields(table, index, schema) {
|
|
|
528
528
|
fields.push("_id");
|
|
529
529
|
return fields;
|
|
530
530
|
}
|
|
531
|
-
|
|
531
|
+
/**
|
|
532
|
+
* Read the index key out of a document.
|
|
533
|
+
*
|
|
534
|
+
* Takes field paths already split on `.` rather than the field names: the field
|
|
535
|
+
* list is fixed for the life of a query, so splitting it once at `withIndex`
|
|
536
|
+
* time saves an array allocation per field per document pulled through the
|
|
537
|
+
* stream.
|
|
538
|
+
*/
|
|
539
|
+
function getIndexKey(doc, indexFieldPaths) {
|
|
532
540
|
const key = [];
|
|
533
|
-
for (const
|
|
541
|
+
for (const path of indexFieldPaths) {
|
|
534
542
|
let obj = doc;
|
|
535
|
-
for (const subfield of
|
|
543
|
+
for (const subfield of path) obj = obj[subfield];
|
|
536
544
|
key.push(obj);
|
|
537
545
|
}
|
|
538
546
|
return key;
|
|
@@ -729,17 +737,26 @@ var QueryStream = class {
|
|
|
729
737
|
}
|
|
730
738
|
[Symbol.asyncIterator]() {
|
|
731
739
|
const iterator = this.iterWithKeys()[Symbol.asyncIterator]();
|
|
732
|
-
return {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
done
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
740
|
+
return {
|
|
741
|
+
async next() {
|
|
742
|
+
const result = await iterator.next();
|
|
743
|
+
if (result.done) return {
|
|
744
|
+
done: true,
|
|
745
|
+
value: void 0
|
|
746
|
+
};
|
|
747
|
+
return {
|
|
748
|
+
done: false,
|
|
749
|
+
value: result.value[0]
|
|
750
|
+
};
|
|
751
|
+
},
|
|
752
|
+
async return() {
|
|
753
|
+
await iterator.return?.();
|
|
754
|
+
return {
|
|
755
|
+
done: true,
|
|
756
|
+
value: void 0
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
};
|
|
743
760
|
}
|
|
744
761
|
};
|
|
745
762
|
var StreamDatabaseReader = class {
|
|
@@ -858,6 +875,7 @@ var OrderedStreamQuery = class extends StreamableQuery {
|
|
|
858
875
|
table: this.parent.parent.table,
|
|
859
876
|
index: this.parent.index,
|
|
860
877
|
indexFields: this.parent.q.indexFields,
|
|
878
|
+
indexFieldPaths: this.parent.q.indexFieldPaths,
|
|
861
879
|
order: this.order,
|
|
862
880
|
bounds: {
|
|
863
881
|
lowerBound: this.parent.q.lowerBoundIndexKey ?? [],
|
|
@@ -876,7 +894,7 @@ var OrderedStreamQuery = class extends StreamableQuery {
|
|
|
876
894
|
return db.query(table).withIndex(index, indexRange).order(order);
|
|
877
895
|
}
|
|
878
896
|
iterWithKeys() {
|
|
879
|
-
const {
|
|
897
|
+
const { indexFieldPaths } = this.reflect();
|
|
880
898
|
const iterable = this.inner();
|
|
881
899
|
return { [Symbol.asyncIterator]() {
|
|
882
900
|
const iterator = iterable[Symbol.asyncIterator]();
|
|
@@ -888,7 +906,7 @@ var OrderedStreamQuery = class extends StreamableQuery {
|
|
|
888
906
|
};
|
|
889
907
|
return {
|
|
890
908
|
done: false,
|
|
891
|
-
value: [result.value, getIndexKey(result.value,
|
|
909
|
+
value: [result.value, getIndexKey(result.value, indexFieldPaths)]
|
|
892
910
|
};
|
|
893
911
|
} };
|
|
894
912
|
} };
|
|
@@ -950,8 +968,11 @@ var ReflectIndexRange = class {
|
|
|
950
968
|
upperBoundInclusive = true;
|
|
951
969
|
equalityIndexFilter = [];
|
|
952
970
|
indexFields;
|
|
971
|
+
/** `indexFields`, each split on `.` once, for `getIndexKey`. */
|
|
972
|
+
indexFieldPaths;
|
|
953
973
|
constructor(indexFields) {
|
|
954
974
|
this.indexFields = indexFields;
|
|
975
|
+
this.indexFieldPaths = indexFields.map((field) => field.split("."));
|
|
955
976
|
}
|
|
956
977
|
eq(field, value) {
|
|
957
978
|
if (!this.#canLowerBound(field) || !this.#canUpperBound(field)) throw new Error(`Cannot use eq on field '${field}'`);
|
|
@@ -1043,16 +1064,24 @@ var ReflectIndexRange = class {
|
|
|
1043
1064
|
function mergedStream(streams, orderByIndexFields) {
|
|
1044
1065
|
return new MergedStream(streams, orderByIndexFields);
|
|
1045
1066
|
}
|
|
1067
|
+
/**
|
|
1068
|
+
* Marks sources that are already `OrderByStream`s, so `narrow` reuses them
|
|
1069
|
+
* instead of adding a redundant delegation layer per call.
|
|
1070
|
+
*
|
|
1071
|
+
* Module-private on purpose: wrapping is also where the ordering invariant is
|
|
1072
|
+
* checked, so no caller outside this file can skip it.
|
|
1073
|
+
*/
|
|
1074
|
+
const PRE_ORDERED_STREAMS = Symbol("preOrderedStreams");
|
|
1046
1075
|
var MergedStream = class MergedStream extends QueryStream {
|
|
1047
1076
|
#order;
|
|
1048
1077
|
#streams;
|
|
1049
1078
|
#equalityIndexFilter;
|
|
1050
1079
|
#indexFields;
|
|
1051
|
-
constructor(streams, orderByIndexFields) {
|
|
1080
|
+
constructor(streams, orderByIndexFields, preOrdered) {
|
|
1052
1081
|
super();
|
|
1053
1082
|
if (streams.length === 0) throw new Error("Cannot union empty array of streams");
|
|
1054
1083
|
this.#order = allSame(streams.map((stream) => stream.getOrder()), "Cannot merge streams with different orders");
|
|
1055
|
-
this.#streams = streams.map((stream) => new OrderByStream(stream, orderByIndexFields));
|
|
1084
|
+
this.#streams = preOrdered === PRE_ORDERED_STREAMS ? streams : streams.map((stream) => new OrderByStream(stream, orderByIndexFields.slice()));
|
|
1056
1085
|
this.#indexFields = allSame(this.#streams.map((stream) => stream.getIndexFields()), "Cannot merge streams with different index fields. Consider using .orderBy()");
|
|
1057
1086
|
this.#equalityIndexFilter = commonPrefix(this.#streams.map((stream) => stream.getEqualityIndexFilter()));
|
|
1058
1087
|
}
|
|
@@ -1065,40 +1094,60 @@ var MergedStream = class MergedStream extends QueryStream {
|
|
|
1065
1094
|
done: false,
|
|
1066
1095
|
value: void 0
|
|
1067
1096
|
}));
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1097
|
+
let started = false;
|
|
1098
|
+
let refillIndex;
|
|
1099
|
+
return {
|
|
1100
|
+
async next() {
|
|
1101
|
+
if (started) {
|
|
1102
|
+
if (refillIndex !== void 0) {
|
|
1103
|
+
results[refillIndex] = await iterators[refillIndex].next();
|
|
1104
|
+
refillIndex = void 0;
|
|
1105
|
+
}
|
|
1106
|
+
} else {
|
|
1107
|
+
started = true;
|
|
1108
|
+
await Promise.all(iterators.map(async (iterator, i) => {
|
|
1109
|
+
results[i] = await iterator.next();
|
|
1110
|
+
}));
|
|
1080
1111
|
}
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1112
|
+
let minIndexKeyAndIndex;
|
|
1113
|
+
for (let i = 0; i < results.length; i++) {
|
|
1114
|
+
const result = results[i];
|
|
1115
|
+
if (result.done || !result.value) continue;
|
|
1116
|
+
const [_, resultIndexKey] = result.value;
|
|
1117
|
+
if (minIndexKeyAndIndex === void 0) {
|
|
1118
|
+
minIndexKeyAndIndex = [resultIndexKey, i];
|
|
1119
|
+
continue;
|
|
1120
|
+
}
|
|
1121
|
+
const [prevMin, _prevMinIndex] = minIndexKeyAndIndex;
|
|
1122
|
+
if (compareKeys({
|
|
1123
|
+
value: resultIndexKey,
|
|
1124
|
+
kind: "exact"
|
|
1125
|
+
}, {
|
|
1126
|
+
value: prevMin,
|
|
1127
|
+
kind: "exact"
|
|
1128
|
+
}) * comparisonInversion < 0) minIndexKeyAndIndex = [resultIndexKey, i];
|
|
1129
|
+
}
|
|
1130
|
+
if (minIndexKeyAndIndex === void 0) return {
|
|
1131
|
+
done: true,
|
|
1132
|
+
value: void 0
|
|
1133
|
+
};
|
|
1134
|
+
const [_, minIndex] = minIndexKeyAndIndex;
|
|
1135
|
+
const result = results[minIndex].value;
|
|
1136
|
+
results[minIndex].value = void 0;
|
|
1137
|
+
refillIndex = minIndex;
|
|
1138
|
+
return {
|
|
1139
|
+
done: false,
|
|
1140
|
+
value: result
|
|
1141
|
+
};
|
|
1142
|
+
},
|
|
1143
|
+
async return() {
|
|
1144
|
+
await Promise.all(iterators.map((iterator) => iterator.return?.()));
|
|
1145
|
+
return {
|
|
1146
|
+
done: true,
|
|
1147
|
+
value: void 0
|
|
1148
|
+
};
|
|
1089
1149
|
}
|
|
1090
|
-
|
|
1091
|
-
done: true,
|
|
1092
|
-
value: void 0
|
|
1093
|
-
};
|
|
1094
|
-
const [_, minIndex] = minIndexKeyAndIndex;
|
|
1095
|
-
const result = results[minIndex].value;
|
|
1096
|
-
results[minIndex].value = void 0;
|
|
1097
|
-
return {
|
|
1098
|
-
done: false,
|
|
1099
|
-
value: result
|
|
1100
|
-
};
|
|
1101
|
-
} };
|
|
1150
|
+
};
|
|
1102
1151
|
} };
|
|
1103
1152
|
}
|
|
1104
1153
|
getOrder() {
|
|
@@ -1111,7 +1160,7 @@ var MergedStream = class MergedStream extends QueryStream {
|
|
|
1111
1160
|
return this.#indexFields;
|
|
1112
1161
|
}
|
|
1113
1162
|
narrow(indexBounds) {
|
|
1114
|
-
return new MergedStream(this.#streams.map((stream) => stream.narrow(indexBounds)), this.#indexFields);
|
|
1163
|
+
return new MergedStream(this.#streams.map((stream) => stream.narrow(indexBounds)), this.#indexFields, PRE_ORDERED_STREAMS);
|
|
1115
1164
|
}
|
|
1116
1165
|
};
|
|
1117
1166
|
function allSame(values, errorMessage) {
|
|
@@ -1159,16 +1208,22 @@ var ConcatStreams = class ConcatStreams extends QueryStream {
|
|
|
1159
1208
|
this.#equalityIndexFilter = commonPrefix(streams.map((stream) => stream.getEqualityIndexFilter()));
|
|
1160
1209
|
}
|
|
1161
1210
|
iterWithKeys() {
|
|
1162
|
-
const
|
|
1211
|
+
const streams = this.#streams;
|
|
1163
1212
|
const comparisonInversion = this.#order === "asc" ? 1 : -1;
|
|
1164
|
-
let previousIndexKey;
|
|
1165
1213
|
return { [Symbol.asyncIterator]() {
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1214
|
+
let index = 0;
|
|
1215
|
+
let iterator;
|
|
1216
|
+
let previousIndexKey;
|
|
1217
|
+
return {
|
|
1218
|
+
async next() {
|
|
1219
|
+
while (index < streams.length) {
|
|
1220
|
+
iterator ??= streams[index].iterWithKeys()[Symbol.asyncIterator]();
|
|
1221
|
+
const result = await iterator.next();
|
|
1222
|
+
if (result.done) {
|
|
1223
|
+
index++;
|
|
1224
|
+
iterator = void 0;
|
|
1225
|
+
continue;
|
|
1226
|
+
}
|
|
1172
1227
|
const [_, indexKey] = result.value;
|
|
1173
1228
|
if (previousIndexKey !== void 0 && compareKeys({
|
|
1174
1229
|
value: previousIndexKey,
|
|
@@ -1180,12 +1235,21 @@ var ConcatStreams = class ConcatStreams extends QueryStream {
|
|
|
1180
1235
|
previousIndexKey = indexKey;
|
|
1181
1236
|
return result;
|
|
1182
1237
|
}
|
|
1238
|
+
return {
|
|
1239
|
+
done: true,
|
|
1240
|
+
value: void 0
|
|
1241
|
+
};
|
|
1242
|
+
},
|
|
1243
|
+
async return() {
|
|
1244
|
+
await iterator?.return?.();
|
|
1245
|
+
index = streams.length;
|
|
1246
|
+
iterator = void 0;
|
|
1247
|
+
return {
|
|
1248
|
+
done: true,
|
|
1249
|
+
value: void 0
|
|
1250
|
+
};
|
|
1183
1251
|
}
|
|
1184
|
-
|
|
1185
|
-
done: true,
|
|
1186
|
-
value: void 0
|
|
1187
|
-
};
|
|
1188
|
-
} };
|
|
1252
|
+
};
|
|
1189
1253
|
} };
|
|
1190
1254
|
}
|
|
1191
1255
|
getOrder() {
|
|
@@ -1258,6 +1322,18 @@ var FlatMapStreamIterator = class {
|
|
|
1258
1322
|
value: [u, [...this.#currentOuterItem.indexKey, ...indexKey]]
|
|
1259
1323
|
};
|
|
1260
1324
|
}
|
|
1325
|
+
async return() {
|
|
1326
|
+
try {
|
|
1327
|
+
await this.#currentOuterItem?.innerIterator.return?.();
|
|
1328
|
+
} finally {
|
|
1329
|
+
this.#currentOuterItem = null;
|
|
1330
|
+
await this.#outerIterator.return?.();
|
|
1331
|
+
}
|
|
1332
|
+
return {
|
|
1333
|
+
done: true,
|
|
1334
|
+
value: void 0
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1261
1337
|
};
|
|
1262
1338
|
var FlatMapStream = class FlatMapStream extends QueryStream {
|
|
1263
1339
|
#stream;
|
|
@@ -1477,15 +1553,24 @@ var OrderByStream = class OrderByStream extends QueryStream {
|
|
|
1477
1553
|
const staticFilter = this.#staticFilter;
|
|
1478
1554
|
return { [Symbol.asyncIterator]() {
|
|
1479
1555
|
const iterator = iterable[Symbol.asyncIterator]();
|
|
1480
|
-
return {
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1556
|
+
return {
|
|
1557
|
+
async next() {
|
|
1558
|
+
const result = await iterator.next();
|
|
1559
|
+
if (result.done) return result;
|
|
1560
|
+
const [doc, indexKey] = result.value;
|
|
1561
|
+
return {
|
|
1562
|
+
done: false,
|
|
1563
|
+
value: [doc, indexKey.slice(staticFilter.length)]
|
|
1564
|
+
};
|
|
1565
|
+
},
|
|
1566
|
+
async return() {
|
|
1567
|
+
await iterator.return?.();
|
|
1568
|
+
return {
|
|
1569
|
+
done: true,
|
|
1570
|
+
value: void 0
|
|
1571
|
+
};
|
|
1572
|
+
}
|
|
1573
|
+
};
|
|
1489
1574
|
} };
|
|
1490
1575
|
}
|
|
1491
1576
|
narrow(indexBounds) {
|
|
@@ -1516,36 +1601,57 @@ var DistinctStream = class DistinctStream extends QueryStream {
|
|
|
1516
1601
|
iterWithKeys() {
|
|
1517
1602
|
const stream = this.#stream;
|
|
1518
1603
|
const distinctIndexFieldsLength = this.#distinctIndexFieldsLength;
|
|
1604
|
+
const order = stream.getOrder();
|
|
1605
|
+
const comparisonInversion = order === "asc" ? 1 : -1;
|
|
1519
1606
|
return { [Symbol.asyncIterator]() {
|
|
1520
|
-
let
|
|
1521
|
-
let
|
|
1522
|
-
return {
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
done
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1607
|
+
let currentIterator = stream.iterWithKeys()[Symbol.asyncIterator]();
|
|
1608
|
+
let previousDistinctIndexKey;
|
|
1609
|
+
return {
|
|
1610
|
+
async next() {
|
|
1611
|
+
const result = await currentIterator.next();
|
|
1612
|
+
if (result.done) return {
|
|
1613
|
+
done: true,
|
|
1614
|
+
value: void 0
|
|
1615
|
+
};
|
|
1616
|
+
const [doc, indexKey] = result.value;
|
|
1617
|
+
if (doc === null) return {
|
|
1618
|
+
done: false,
|
|
1619
|
+
value: [null, indexKey]
|
|
1620
|
+
};
|
|
1621
|
+
const distinctIndexKey = indexKey.slice(0, distinctIndexFieldsLength);
|
|
1622
|
+
if (previousDistinctIndexKey !== void 0 && compareKeys({
|
|
1623
|
+
value: previousDistinctIndexKey,
|
|
1624
|
+
kind: "exact"
|
|
1625
|
+
}, {
|
|
1626
|
+
value: distinctIndexKey,
|
|
1627
|
+
kind: "exact"
|
|
1628
|
+
}) * comparisonInversion >= 0) throw new Error(`DistinctStream in wrong order: ${JSON.stringify(previousDistinctIndexKey)}, ${JSON.stringify(distinctIndexKey)}`);
|
|
1629
|
+
previousDistinctIndexKey = distinctIndexKey;
|
|
1630
|
+
let narrowed;
|
|
1631
|
+
if (order === "asc") narrowed = stream.narrow({
|
|
1632
|
+
lowerBound: distinctIndexKey,
|
|
1633
|
+
lowerBoundInclusive: false,
|
|
1634
|
+
upperBound: [],
|
|
1635
|
+
upperBoundInclusive: true
|
|
1636
|
+
});
|
|
1637
|
+
else narrowed = stream.narrow({
|
|
1638
|
+
lowerBound: [],
|
|
1639
|
+
lowerBoundInclusive: true,
|
|
1640
|
+
upperBound: distinctIndexKey,
|
|
1641
|
+
upperBoundInclusive: false
|
|
1642
|
+
});
|
|
1643
|
+
await currentIterator.return?.();
|
|
1644
|
+
currentIterator = narrowed.iterWithKeys()[Symbol.asyncIterator]();
|
|
1645
|
+
return result;
|
|
1646
|
+
},
|
|
1647
|
+
async return() {
|
|
1648
|
+
await currentIterator.return?.();
|
|
1649
|
+
return {
|
|
1650
|
+
done: true,
|
|
1651
|
+
value: void 0
|
|
1652
|
+
};
|
|
1653
|
+
}
|
|
1654
|
+
};
|
|
1549
1655
|
} };
|
|
1550
1656
|
}
|
|
1551
1657
|
narrow(indexBounds) {
|
|
@@ -2539,15 +2539,25 @@ declare class GelRelationalQuery<TSchema extends TablesRelationalConfig, TTableC
|
|
|
2539
2539
|
* The where-clause compiler is built from declared indexes only, and `_id` is
|
|
2540
2540
|
* never one of them, so an `id` filter can never be index-selected: it lands
|
|
2541
2541
|
* in the post-filters and the stream walks the creation-time index until it
|
|
2542
|
-
* happens on the row. `db.get()` reads exactly the rows asked for
|
|
2543
|
-
*
|
|
2544
|
-
*
|
|
2542
|
+
* happens on the row. `db.get()` reads exactly the rows asked for.
|
|
2543
|
+
*
|
|
2544
|
+
* Rows come back in the order the ids were given, one read at a time. Missing
|
|
2545
|
+
* or policy-filtered ids still cost a read, but a page does not reread the
|
|
2546
|
+
* complete list. An `orderBy` on creation time is the exception: an id carries
|
|
2547
|
+
* no creation time, so every id must be read before the first row is placed.
|
|
2545
2548
|
*
|
|
2546
2549
|
* Returns null when something else already owns the read: a pinned index, an
|
|
2547
2550
|
* index the compiler did select, a `where(predicate)`, or an `orderBy` that
|
|
2548
2551
|
* walks a different index.
|
|
2549
2552
|
*/
|
|
2550
2553
|
private _buildIdLookupStream;
|
|
2554
|
+
/**
|
|
2555
|
+
* The declared index a stream read can walk to emit `field` in order.
|
|
2556
|
+
*
|
|
2557
|
+
* A stream orders by the index it scans, so only an index that leads with
|
|
2558
|
+
* the field produces that order.
|
|
2559
|
+
*/
|
|
2560
|
+
private _findStreamOrderIndex;
|
|
2551
2561
|
private _buildBasePipelineStream;
|
|
2552
2562
|
/**
|
|
2553
2563
|
* Stream equivalent of the `db.query(...)` chain, used when a post-fetch
|
|
@@ -4367,6 +4377,19 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
4367
4377
|
readonly aggregate_state: ConvexTableWithColumns<{
|
|
4368
4378
|
name: "aggregate_state";
|
|
4369
4379
|
columns: {
|
|
4380
|
+
status: ConvexTextBuilderInitial<""> & {
|
|
4381
|
+
_: {
|
|
4382
|
+
notNull: true;
|
|
4383
|
+
};
|
|
4384
|
+
} & {
|
|
4385
|
+
_: {
|
|
4386
|
+
tableName: "aggregate_state";
|
|
4387
|
+
};
|
|
4388
|
+
} & {
|
|
4389
|
+
_: {
|
|
4390
|
+
fieldName: "status";
|
|
4391
|
+
};
|
|
4392
|
+
};
|
|
4370
4393
|
kind: ConvexTextBuilderInitial<""> & {
|
|
4371
4394
|
_: {
|
|
4372
4395
|
notNull: true;
|
|
@@ -4454,19 +4477,6 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
4454
4477
|
fieldName: "metricDefinitionHash";
|
|
4455
4478
|
};
|
|
4456
4479
|
};
|
|
4457
|
-
status: ConvexTextBuilderInitial<""> & {
|
|
4458
|
-
_: {
|
|
4459
|
-
notNull: true;
|
|
4460
|
-
};
|
|
4461
|
-
} & {
|
|
4462
|
-
_: {
|
|
4463
|
-
tableName: "aggregate_state";
|
|
4464
|
-
};
|
|
4465
|
-
} & {
|
|
4466
|
-
_: {
|
|
4467
|
-
fieldName: "status";
|
|
4468
|
-
};
|
|
4469
|
-
};
|
|
4470
4480
|
processed: ConvexNumberBuilderInitial<""> & {
|
|
4471
4481
|
_: {
|
|
4472
4482
|
notNull: true;
|
|
@@ -4521,38 +4531,38 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
4521
4531
|
readonly migration_state: ConvexTableWithColumns<{
|
|
4522
4532
|
name: "migration_state";
|
|
4523
4533
|
columns: {
|
|
4524
|
-
|
|
4534
|
+
status: ConvexTextBuilderInitial<""> & {
|
|
4535
|
+
_: {
|
|
4536
|
+
notNull: true;
|
|
4537
|
+
};
|
|
4538
|
+
} & {
|
|
4525
4539
|
_: {
|
|
4526
4540
|
tableName: "migration_state";
|
|
4527
4541
|
};
|
|
4528
4542
|
} & {
|
|
4529
4543
|
_: {
|
|
4530
|
-
fieldName: "
|
|
4544
|
+
fieldName: "status";
|
|
4531
4545
|
};
|
|
4532
4546
|
};
|
|
4533
|
-
|
|
4547
|
+
cursor: ConvexTextBuilderInitial<""> & {
|
|
4534
4548
|
_: {
|
|
4535
4549
|
tableName: "migration_state";
|
|
4536
4550
|
};
|
|
4537
4551
|
} & {
|
|
4538
4552
|
_: {
|
|
4539
|
-
fieldName: "
|
|
4553
|
+
fieldName: "cursor";
|
|
4540
4554
|
};
|
|
4541
4555
|
};
|
|
4542
|
-
|
|
4543
|
-
_: {
|
|
4544
|
-
notNull: true;
|
|
4545
|
-
};
|
|
4546
|
-
} & {
|
|
4556
|
+
direction: ConvexTextBuilderInitial<""> & {
|
|
4547
4557
|
_: {
|
|
4548
4558
|
tableName: "migration_state";
|
|
4549
4559
|
};
|
|
4550
4560
|
} & {
|
|
4551
4561
|
_: {
|
|
4552
|
-
fieldName: "
|
|
4562
|
+
fieldName: "direction";
|
|
4553
4563
|
};
|
|
4554
4564
|
};
|
|
4555
|
-
|
|
4565
|
+
updatedAt: ConvexNumberBuilderInitial<""> & {
|
|
4556
4566
|
_: {
|
|
4557
4567
|
notNull: true;
|
|
4558
4568
|
};
|
|
@@ -4562,7 +4572,7 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
4562
4572
|
};
|
|
4563
4573
|
} & {
|
|
4564
4574
|
_: {
|
|
4565
|
-
fieldName: "
|
|
4575
|
+
fieldName: "updatedAt";
|
|
4566
4576
|
};
|
|
4567
4577
|
};
|
|
4568
4578
|
processed: ConvexNumberBuilderInitial<""> & {
|
|
@@ -4675,7 +4685,7 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
4675
4685
|
readonly migration_run: ConvexTableWithColumns<{
|
|
4676
4686
|
name: "migration_run";
|
|
4677
4687
|
columns: {
|
|
4678
|
-
|
|
4688
|
+
status: ConvexTextBuilderInitial<""> & {
|
|
4679
4689
|
_: {
|
|
4680
4690
|
notNull: true;
|
|
4681
4691
|
};
|
|
@@ -4685,10 +4695,10 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
4685
4695
|
};
|
|
4686
4696
|
} & {
|
|
4687
4697
|
_: {
|
|
4688
|
-
fieldName: "
|
|
4698
|
+
fieldName: "status";
|
|
4689
4699
|
};
|
|
4690
4700
|
};
|
|
4691
|
-
|
|
4701
|
+
direction: ConvexTextBuilderInitial<""> & {
|
|
4692
4702
|
_: {
|
|
4693
4703
|
notNull: true;
|
|
4694
4704
|
};
|
|
@@ -4698,10 +4708,10 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
4698
4708
|
};
|
|
4699
4709
|
} & {
|
|
4700
4710
|
_: {
|
|
4701
|
-
fieldName: "
|
|
4711
|
+
fieldName: "direction";
|
|
4702
4712
|
};
|
|
4703
4713
|
};
|
|
4704
|
-
|
|
4714
|
+
updatedAt: ConvexNumberBuilderInitial<""> & {
|
|
4705
4715
|
_: {
|
|
4706
4716
|
notNull: true;
|
|
4707
4717
|
};
|
|
@@ -4711,7 +4721,7 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
4711
4721
|
};
|
|
4712
4722
|
} & {
|
|
4713
4723
|
_: {
|
|
4714
|
-
fieldName: "
|
|
4724
|
+
fieldName: "updatedAt";
|
|
4715
4725
|
};
|
|
4716
4726
|
};
|
|
4717
4727
|
startedAt: ConvexNumberBuilderInitial<""> & {
|
package/package.json
CHANGED
|
@@ -721,7 +721,7 @@ const filtered = results.filter((a) => a.publishedAt >= startDate);
|
|
|
721
721
|
### Performance
|
|
722
722
|
|
|
723
723
|
1. **Index first** — constrain leading index fields. Compound indexes follow prefix rules. Put the `orderBy` column right after the constrained prefix so the scan is already sorted and `limit` bounds the read.
|
|
724
|
-
2. **Bound scans** — use `maxScan` for predicate `where` (cursor mode only).
|
|
724
|
+
2. **Bound scans** — use `maxScan` for predicate `where` (cursor mode only). A `.select()` ID-list query with `orderBy` needs a single field that an index leads with.
|
|
725
725
|
3. **Limit results** — always use `limit` or cursor pagination.
|
|
726
726
|
4. **Cursor stability** — keep same `where`/`orderBy` between page requests.
|
|
727
727
|
5. **`allowFullScan`** — non-cursor only. Cursor mode uses `maxScan` instead.
|