@rvoh/dream 0.44.7 → 0.44.8
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/cjs/src/bin/index.js +7 -87
- package/dist/cjs/src/dream/LeftJoinLoadBuilder.js +1 -1
- package/dist/cjs/src/dream/LoadBuilder.js +1 -1
- package/dist/cjs/src/dream/Query.js +46 -1417
- package/dist/cjs/src/dream/QueryDriver/Base.js +311 -0
- package/dist/cjs/src/dream/QueryDriver/Kysely.js +1771 -0
- package/dist/cjs/src/dream/QueryDriver/Postgres.js +6 -0
- package/dist/cjs/src/dream/internal/saveDream.js +4 -17
- package/dist/esm/src/bin/index.js +7 -87
- package/dist/esm/src/dream/LeftJoinLoadBuilder.js +1 -1
- package/dist/esm/src/dream/LoadBuilder.js +1 -1
- package/dist/esm/src/dream/Query.js +46 -1417
- package/dist/esm/src/dream/QueryDriver/Base.js +308 -0
- package/dist/esm/src/dream/QueryDriver/Kysely.js +1768 -0
- package/dist/esm/src/dream/QueryDriver/Postgres.js +3 -0
- package/dist/esm/src/dream/internal/saveDream.js +4 -17
- package/dist/types/src/bin/index.d.ts +0 -2
- package/dist/types/src/dream/Query.d.ts +27 -155
- package/dist/types/src/dream/QueryDriver/Base.d.ts +242 -0
- package/dist/types/src/dream/QueryDriver/Kysely.d.ts +354 -0
- package/dist/types/src/dream/QueryDriver/Postgres.d.ts +4 -0
- package/dist/types/src/dream/internal/executeDatabaseQuery.d.ts +2 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/Benchmark.html +2 -2
- package/docs/classes/CalendarDate.html +2 -2
- package/docs/classes/CreateOrFindByFailedToCreateAndFind.html +3 -3
- package/docs/classes/Decorators.html +19 -19
- package/docs/classes/Dream.html +131 -131
- package/docs/classes/DreamApp.html +4 -4
- package/docs/classes/DreamBin.html +3 -4
- package/docs/classes/DreamCLI.html +4 -4
- package/docs/classes/DreamImporter.html +2 -2
- package/docs/classes/DreamLogos.html +2 -2
- package/docs/classes/DreamMigrationHelpers.html +7 -7
- package/docs/classes/DreamSerializerBuilder.html +2 -2
- package/docs/classes/DreamTransaction.html +2 -2
- package/docs/classes/Encrypt.html +2 -2
- package/docs/classes/Env.html +2 -2
- package/docs/classes/GlobalNameNotSet.html +3 -3
- package/docs/classes/NonLoadedAssociation.html +3 -3
- package/docs/classes/ObjectSerializerBuilder.html +2 -2
- package/docs/classes/Query.html +86 -57
- package/docs/classes/Range.html +2 -2
- package/docs/classes/RecordNotFound.html +3 -3
- package/docs/classes/ValidationError.html +3 -3
- package/docs/functions/DreamSerializer.html +1 -1
- package/docs/functions/ObjectSerializer.html +1 -1
- package/docs/functions/ReplicaSafe.html +1 -1
- package/docs/functions/STI.html +1 -1
- package/docs/functions/SoftDelete.html +1 -1
- package/docs/functions/camelize.html +1 -1
- package/docs/functions/capitalize.html +1 -1
- package/docs/functions/cloneDeepSafe.html +1 -1
- package/docs/functions/closeAllDbConnections.html +1 -1
- package/docs/functions/compact.html +1 -1
- package/docs/functions/dreamDbConnections.html +1 -1
- package/docs/functions/dreamPath.html +1 -1
- package/docs/functions/expandStiClasses.html +1 -1
- package/docs/functions/generateDream.html +1 -1
- package/docs/functions/globalClassNameFromFullyQualifiedModelName.html +1 -1
- package/docs/functions/groupBy.html +1 -1
- package/docs/functions/hyphenize.html +1 -1
- package/docs/functions/inferSerializerFromDreamOrViewModel.html +1 -1
- package/docs/functions/inferSerializersFromDreamClassOrViewModelClass.html +1 -1
- package/docs/functions/intersection.html +1 -1
- package/docs/functions/isDreamSerializer.html +1 -1
- package/docs/functions/isEmpty.html +1 -1
- package/docs/functions/loadRepl.html +1 -1
- package/docs/functions/lookupClassByGlobalName.html +1 -1
- package/docs/functions/normalizeUnicode.html +1 -1
- package/docs/functions/pascalize.html +1 -1
- package/docs/functions/pgErrorType.html +1 -1
- package/docs/functions/range-1.html +1 -1
- package/docs/functions/relativeDreamPath.html +1 -1
- package/docs/functions/round.html +1 -1
- package/docs/functions/serializerNameFromFullyQualifiedModelName.html +1 -1
- package/docs/functions/sharedPathPrefix.html +1 -1
- package/docs/functions/snakeify.html +1 -1
- package/docs/functions/sort.html +1 -1
- package/docs/functions/sortBy.html +1 -1
- package/docs/functions/sortObjectByKey.html +1 -1
- package/docs/functions/sortObjectByValue.html +1 -1
- package/docs/functions/standardizeFullyQualifiedModelName.html +1 -1
- package/docs/functions/uncapitalize.html +1 -1
- package/docs/functions/uniq.html +1 -1
- package/docs/functions/untypedDb.html +1 -1
- package/docs/functions/validateColumn.html +1 -1
- package/docs/functions/validateTable.html +1 -1
- package/docs/interfaces/BelongsToStatement.html +2 -2
- package/docs/interfaces/DecoratorContext.html +2 -2
- package/docs/interfaces/DreamAppInitOptions.html +2 -2
- package/docs/interfaces/DreamAppOpts.html +2 -2
- package/docs/interfaces/EncryptOptions.html +2 -2
- package/docs/interfaces/InternalAnyTypedSerializerRendersMany.html +2 -2
- package/docs/interfaces/InternalAnyTypedSerializerRendersOne.html +2 -2
- package/docs/interfaces/OpenapiDescription.html +2 -2
- package/docs/interfaces/OpenapiSchemaProperties.html +1 -1
- package/docs/interfaces/OpenapiSchemaPropertiesShorthand.html +1 -1
- package/docs/interfaces/OpenapiTypeFieldObject.html +1 -1
- package/docs/interfaces/SerializerRendererOpts.html +2 -2
- package/docs/types/Camelized.html +1 -1
- package/docs/types/CommonOpenapiSchemaObjectFields.html +1 -1
- package/docs/types/DateTime.html +1 -1
- package/docs/types/DbConnectionType.html +1 -1
- package/docs/types/DbTypes.html +1 -1
- package/docs/types/DreamAssociationMetadata.html +1 -1
- package/docs/types/DreamAttributes.html +1 -1
- package/docs/types/DreamClassColumn.html +1 -1
- package/docs/types/DreamColumn.html +1 -1
- package/docs/types/DreamColumnNames.html +1 -1
- package/docs/types/DreamLogLevel.html +1 -1
- package/docs/types/DreamLogger.html +1 -1
- package/docs/types/DreamModelSerializerType.html +1 -1
- package/docs/types/DreamOrViewModelClassSerializerKey.html +1 -1
- package/docs/types/DreamOrViewModelSerializerKey.html +1 -1
- package/docs/types/DreamParamSafeAttributes.html +1 -1
- package/docs/types/DreamParamSafeColumnNames.html +1 -1
- package/docs/types/DreamSerializable.html +1 -1
- package/docs/types/DreamSerializableArray.html +1 -1
- package/docs/types/DreamSerializerKey.html +1 -1
- package/docs/types/DreamSerializers.html +1 -1
- package/docs/types/DreamTableSchema.html +1 -1
- package/docs/types/DreamVirtualColumns.html +1 -1
- package/docs/types/EncryptAlgorithm.html +1 -1
- package/docs/types/HasManyStatement.html +1 -1
- package/docs/types/HasOneStatement.html +1 -1
- package/docs/types/Hyphenized.html +1 -1
- package/docs/types/IdType.html +1 -1
- package/docs/types/OpenapiAllTypes.html +1 -1
- package/docs/types/OpenapiFormats.html +1 -1
- package/docs/types/OpenapiNumberFormats.html +1 -1
- package/docs/types/OpenapiPrimitiveBaseTypes.html +1 -1
- package/docs/types/OpenapiPrimitiveTypes.html +1 -1
- package/docs/types/OpenapiSchemaArray.html +1 -1
- package/docs/types/OpenapiSchemaArrayShorthand.html +1 -1
- package/docs/types/OpenapiSchemaBase.html +1 -1
- package/docs/types/OpenapiSchemaBody.html +1 -1
- package/docs/types/OpenapiSchemaBodyShorthand.html +1 -1
- package/docs/types/OpenapiSchemaCommonFields.html +1 -1
- package/docs/types/OpenapiSchemaExpressionAllOf.html +1 -1
- package/docs/types/OpenapiSchemaExpressionAnyOf.html +1 -1
- package/docs/types/OpenapiSchemaExpressionOneOf.html +1 -1
- package/docs/types/OpenapiSchemaExpressionRef.html +1 -1
- package/docs/types/OpenapiSchemaExpressionRefSchemaShorthand.html +1 -1
- package/docs/types/OpenapiSchemaInteger.html +1 -1
- package/docs/types/OpenapiSchemaNull.html +1 -1
- package/docs/types/OpenapiSchemaNumber.html +1 -1
- package/docs/types/OpenapiSchemaObject.html +1 -1
- package/docs/types/OpenapiSchemaObjectAllOf.html +1 -1
- package/docs/types/OpenapiSchemaObjectAllOfShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectAnyOf.html +1 -1
- package/docs/types/OpenapiSchemaObjectAnyOfShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectBase.html +1 -1
- package/docs/types/OpenapiSchemaObjectBaseShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectOneOf.html +1 -1
- package/docs/types/OpenapiSchemaObjectOneOfShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectShorthand.html +1 -1
- package/docs/types/OpenapiSchemaPrimitiveGeneric.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionAllOf.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionOneOf.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionSerializableRef.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionSerializerRef.html +1 -1
- package/docs/types/OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
- package/docs/types/OpenapiSchemaString.html +1 -1
- package/docs/types/OpenapiShorthandAllTypes.html +1 -1
- package/docs/types/OpenapiShorthandPrimitiveBaseTypes.html +1 -1
- package/docs/types/OpenapiShorthandPrimitiveTypes.html +1 -1
- package/docs/types/OpenapiTypeField.html +1 -1
- package/docs/types/Pascalized.html +1 -1
- package/docs/types/PrimaryKeyType.html +1 -1
- package/docs/types/RoundingPrecision.html +1 -1
- package/docs/types/SerializerCasing.html +1 -1
- package/docs/types/SimpleObjectSerializerType.html +1 -1
- package/docs/types/Snakeified.html +1 -1
- package/docs/types/Timestamp.html +1 -1
- package/docs/types/UpdateableAssociationProperties.html +1 -1
- package/docs/types/UpdateableProperties.html +1 -1
- package/docs/types/ValidationType.html +1 -1
- package/docs/types/ViewModel.html +1 -1
- package/docs/types/ViewModelClass.html +1 -1
- package/docs/types/WhereStatementForDream.html +1 -1
- package/docs/types/WhereStatementForDreamClass.html +1 -1
- package/docs/variables/DateTime-1.html +1 -1
- package/docs/variables/DreamConst.html +1 -1
- package/docs/variables/TRIGRAM_OPERATORS.html +1 -1
- package/docs/variables/openapiPrimitiveTypes-1.html +1 -1
- package/docs/variables/openapiShorthandPrimitiveTypes-1.html +1 -1
- package/docs/variables/ops.html +1 -1
- package/docs/variables/primaryKeyTypes.html +1 -1
- package/package.json +2 -2
|
@@ -1,23 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const kysely_1 = require("kysely");
|
|
4
|
-
const pluralize_esm_1 = require("pluralize-esm");
|
|
5
|
-
const ConnectedToDB_js_1 = require("../db/ConnectedToDB.js");
|
|
6
3
|
const SoftDelete_js_1 = require("../decorators/class/SoftDelete.js");
|
|
7
|
-
const associationToGetterSetterProp_js_1 = require("../decorators/field/association/associationToGetterSetterProp.js");
|
|
8
4
|
const index_js_1 = require("../dream-app/index.js");
|
|
9
5
|
const AssociationDeclaredWithoutAssociatedDreamClass_js_1 = require("../errors/associations/AssociationDeclaredWithoutAssociatedDreamClass.js");
|
|
10
|
-
const CannotAssociateThroughPolymorphic_js_1 = require("../errors/associations/CannotAssociateThroughPolymorphic.js");
|
|
11
|
-
const CannotJoinPolymorphicBelongsToError_js_1 = require("../errors/associations/CannotJoinPolymorphicBelongsToError.js");
|
|
12
|
-
const JoinAttemptedOnMissingAssociation_js_1 = require("../errors/associations/JoinAttemptedOnMissingAssociation.js");
|
|
13
|
-
const MissingRequiredAssociationAndClause_js_1 = require("../errors/associations/MissingRequiredAssociationAndClause.js");
|
|
14
|
-
const MissingRequiredPassthroughForAssociationAndClause_js_1 = require("../errors/associations/MissingRequiredPassthroughForAssociationAndClause.js");
|
|
15
|
-
const MissingThroughAssociation_js_1 = require("../errors/associations/MissingThroughAssociation.js");
|
|
16
|
-
const MissingThroughAssociationSource_js_1 = require("../errors/associations/MissingThroughAssociationSource.js");
|
|
17
6
|
const CannotCallUndestroyOnANonSoftDeleteModel_js_1 = require("../errors/CannotCallUndestroyOnANonSoftDeleteModel.js");
|
|
18
|
-
const CannotNegateSimilarityClause_js_1 = require("../errors/CannotNegateSimilarityClause.js");
|
|
19
7
|
const CannotPassAdditionalFieldsToPluckEachAfterCallback_js_1 = require("../errors/CannotPassAdditionalFieldsToPluckEachAfterCallback.js");
|
|
20
|
-
const CannotPassUndefinedAsAValueToAWhereClause_js_1 = require("../errors/CannotPassUndefinedAsAValueToAWhereClause.js");
|
|
21
8
|
const LeftJoinPreloadIncompatibleWithFindEach_js_1 = require("../errors/LeftJoinPreloadIncompatibleWithFindEach.js");
|
|
22
9
|
const MissingRequiredCallbackFunctionToPluckEach_js_1 = require("../errors/MissingRequiredCallbackFunctionToPluckEach.js");
|
|
23
10
|
const NoUpdateAllOnJoins_js_1 = require("../errors/NoUpdateAllOnJoins.js");
|
|
@@ -25,33 +12,14 @@ const NoUpdateOnAssociationQuery_js_1 = require("../errors/NoUpdateOnAssociation
|
|
|
25
12
|
const CannotPaginateWithLimit_js_1 = require("../errors/pagination/CannotPaginateWithLimit.js");
|
|
26
13
|
const CannotPaginateWithOffset_js_1 = require("../errors/pagination/CannotPaginateWithOffset.js");
|
|
27
14
|
const RecordNotFound_js_1 = require("../errors/RecordNotFound.js");
|
|
28
|
-
const UnexpectedUndefined_js_1 = require("../errors/UnexpectedUndefined.js");
|
|
29
|
-
const CalendarDate_js_1 = require("../helpers/CalendarDate.js");
|
|
30
|
-
const camelize_js_1 = require("../helpers/camelize.js");
|
|
31
15
|
const cloneDeepSafe_js_1 = require("../helpers/cloneDeepSafe.js");
|
|
32
|
-
const compact_js_1 = require("../helpers/compact.js");
|
|
33
|
-
const DateTime_js_1 = require("../helpers/DateTime.js");
|
|
34
|
-
const isEmpty_js_1 = require("../helpers/isEmpty.js");
|
|
35
16
|
const isObject_js_1 = require("../helpers/isObject.js");
|
|
36
17
|
const namespaceColumn_js_1 = require("../helpers/namespaceColumn.js");
|
|
37
|
-
const normalizeUnicode_js_1 = require("../helpers/normalizeUnicode.js");
|
|
38
|
-
const objectPathsToArrays_js_1 = require("../helpers/objectPathsToArrays.js");
|
|
39
18
|
const protectAgainstPollutingAssignment_js_1 = require("../helpers/protectAgainstPollutingAssignment.js");
|
|
40
|
-
const range_js_1 = require("../helpers/range.js");
|
|
41
|
-
const snakeify_js_1 = require("../helpers/snakeify.js");
|
|
42
|
-
const uniq_js_1 = require("../helpers/uniq.js");
|
|
43
|
-
const curried_ops_statement_js_1 = require("../ops/curried-ops-statement.js");
|
|
44
19
|
const index_js_2 = require("../ops/index.js");
|
|
45
|
-
const ops_statement_js_1 = require("../ops/ops-statement.js");
|
|
46
|
-
const constants_js_1 = require("./constants.js");
|
|
47
20
|
const computedPaginatePage_js_1 = require("./internal/computedPaginatePage.js");
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
const orderByDirection_js_1 = require("./internal/orderByDirection.js");
|
|
51
|
-
const shouldBypassDefaultScope_js_1 = require("./internal/shouldBypassDefaultScope.js");
|
|
52
|
-
const SimilarityBuilder_js_1 = require("./internal/similarity/SimilarityBuilder.js");
|
|
53
|
-
const sqlResultToDreamInstance_js_1 = require("./internal/sqlResultToDreamInstance.js");
|
|
54
|
-
class Query extends ConnectedToDB_js_1.default {
|
|
21
|
+
const Postgres_js_1 = require("./QueryDriver/Postgres.js");
|
|
22
|
+
class Query {
|
|
55
23
|
/**
|
|
56
24
|
* @internal
|
|
57
25
|
*
|
|
@@ -230,8 +198,26 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
230
198
|
* baseSelectQuery.
|
|
231
199
|
*/
|
|
232
200
|
baseSelectQuery;
|
|
201
|
+
/*
|
|
202
|
+
* Store the original opts, so we can hand them off succinctly to the
|
|
203
|
+
* query executor. TODO: Should we do this?
|
|
204
|
+
* */
|
|
205
|
+
originalOpts;
|
|
206
|
+
dreamClass;
|
|
207
|
+
dreamInstance;
|
|
208
|
+
connectionOverride;
|
|
209
|
+
/**
|
|
210
|
+
* @internal
|
|
211
|
+
*
|
|
212
|
+
* stores the Dream models joined in this Query instance
|
|
213
|
+
*/
|
|
214
|
+
innerJoinDreamClasses = Object.freeze([]);
|
|
233
215
|
constructor(dreamInstance, opts = {}) {
|
|
234
|
-
|
|
216
|
+
this.dreamInstance = dreamInstance;
|
|
217
|
+
this.dreamClass = dreamInstance.constructor;
|
|
218
|
+
this.dreamTransaction = opts.transaction || null;
|
|
219
|
+
this.connectionOverride = opts.connection;
|
|
220
|
+
this.innerJoinDreamClasses = Object.freeze(opts.innerJoinDreamClasses || []);
|
|
235
221
|
this.passthroughOnStatement = Object.freeze(opts.passthroughOnStatement || {});
|
|
236
222
|
this.whereStatements = Object.freeze(opts.where || []);
|
|
237
223
|
this.whereNotStatements = Object.freeze(opts.whereNot || []);
|
|
@@ -256,6 +242,7 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
256
242
|
this.distinctColumn = opts.distinctColumn || null;
|
|
257
243
|
this.connectionOverride = opts.connection;
|
|
258
244
|
this.shouldReallyDestroy = opts.shouldReallyDestroy || false;
|
|
245
|
+
this.originalOpts = Object.freeze(opts);
|
|
259
246
|
}
|
|
260
247
|
/**
|
|
261
248
|
* Returns true. Useful for distinguishing Query instances
|
|
@@ -266,23 +253,6 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
266
253
|
get isDreamQuery() {
|
|
267
254
|
return true;
|
|
268
255
|
}
|
|
269
|
-
/**
|
|
270
|
-
* @internal
|
|
271
|
-
*
|
|
272
|
-
* Used for applying preload and load statements
|
|
273
|
-
*
|
|
274
|
-
* @returns An associated Query
|
|
275
|
-
*/
|
|
276
|
-
dreamClassQueryWithScopeBypasses(dreamClass, { bypassAllDefaultScopesExceptOnAssociations = false, defaultScopesToBypassExceptOnAssociations = [], } = {}) {
|
|
277
|
-
const associationQuery = dreamClass.query().clone({
|
|
278
|
-
passthroughOnStatement: this.passthroughOnStatement,
|
|
279
|
-
bypassAllDefaultScopes: this.bypassAllDefaultScopes,
|
|
280
|
-
bypassAllDefaultScopesExceptOnAssociations,
|
|
281
|
-
defaultScopesToBypass: this.defaultScopesToBypass,
|
|
282
|
-
defaultScopesToBypassExceptOnAssociations,
|
|
283
|
-
});
|
|
284
|
-
return (this.dreamTransaction ? associationQuery.txn(this.dreamTransaction) : associationQuery);
|
|
285
|
-
}
|
|
286
256
|
/**
|
|
287
257
|
* @internal
|
|
288
258
|
*
|
|
@@ -582,92 +552,6 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
582
552
|
this.fleshOutJoinStatements(innerJoinDreamClasses, joinStatements, joinAndStatements, previousAssociationName, associationStatements, previousDreamClass);
|
|
583
553
|
}
|
|
584
554
|
}
|
|
585
|
-
/**
|
|
586
|
-
* @internal
|
|
587
|
-
*
|
|
588
|
-
*
|
|
589
|
-
*/
|
|
590
|
-
associationNamesToDreamClassesMap(associationNames, associationsToDreamClassesMap = {}) {
|
|
591
|
-
const namesToAssociationsAndDreamClasses = this.associationNamesToAssociationDataAndDreamClassesMap(associationNames);
|
|
592
|
-
return Object.keys(namesToAssociationsAndDreamClasses).reduce((remap, associationName) => {
|
|
593
|
-
const associationAndDreamClass = namesToAssociationsAndDreamClasses[associationName];
|
|
594
|
-
if (associationAndDreamClass === undefined)
|
|
595
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
596
|
-
remap[associationName] = associationAndDreamClass.dreamClass;
|
|
597
|
-
return remap;
|
|
598
|
-
}, associationsToDreamClassesMap);
|
|
599
|
-
}
|
|
600
|
-
/**
|
|
601
|
-
* @internal
|
|
602
|
-
*
|
|
603
|
-
*
|
|
604
|
-
*/
|
|
605
|
-
associationNamesToAssociationsMap(associationNames, associationsToAssociations = {}) {
|
|
606
|
-
const namesToAssociationsAndDreamClasses = this.associationNamesToAssociationDataAndDreamClassesMap(associationNames);
|
|
607
|
-
return Object.keys(namesToAssociationsAndDreamClasses).reduce((remap, associationName) => {
|
|
608
|
-
const associationAndDreamClass = namesToAssociationsAndDreamClasses[associationName];
|
|
609
|
-
if (associationAndDreamClass === undefined)
|
|
610
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
611
|
-
remap[associationName] = associationAndDreamClass.association;
|
|
612
|
-
return remap;
|
|
613
|
-
}, associationsToAssociations);
|
|
614
|
-
}
|
|
615
|
-
/**
|
|
616
|
-
* @internal
|
|
617
|
-
*/
|
|
618
|
-
associationNamesToAssociationDataAndDreamClassesMap(associationNames) {
|
|
619
|
-
const associationsToDreamClassesMap = {};
|
|
620
|
-
associationNames.reduce((dreamClass, associationName) => {
|
|
621
|
-
const { name, alias } = (0, extractAssociationMetadataFromAssociationName_js_1.default)(associationName);
|
|
622
|
-
const association = dreamClass['getAssociationMetadata'](name);
|
|
623
|
-
if (association === undefined)
|
|
624
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
625
|
-
const through = association.through;
|
|
626
|
-
if (through) {
|
|
627
|
-
const { throughAssociation, throughAssociationDreamClass } = this.throughAssociationDetails(dreamClass, through);
|
|
628
|
-
associationsToDreamClassesMap[through] = {
|
|
629
|
-
association: throughAssociation,
|
|
630
|
-
dreamClass: throughAssociationDreamClass,
|
|
631
|
-
};
|
|
632
|
-
}
|
|
633
|
-
const nextDreamClass = association.modelCB();
|
|
634
|
-
if (alias === undefined)
|
|
635
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
636
|
-
associationsToDreamClassesMap[alias] = { association, dreamClass: nextDreamClass };
|
|
637
|
-
return nextDreamClass;
|
|
638
|
-
}, this.dreamClass);
|
|
639
|
-
return associationsToDreamClassesMap;
|
|
640
|
-
}
|
|
641
|
-
/**
|
|
642
|
-
* @internal
|
|
643
|
-
*/
|
|
644
|
-
throughAssociationDetails(dreamClass, through) {
|
|
645
|
-
const throughAssociation = dreamClass['getAssociationMetadata'](through);
|
|
646
|
-
if (throughAssociation === undefined)
|
|
647
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
648
|
-
const throughAssociationDreamClass = throughAssociation.modelCB();
|
|
649
|
-
return { throughAssociation, throughAssociationDreamClass };
|
|
650
|
-
}
|
|
651
|
-
/**
|
|
652
|
-
* @internal
|
|
653
|
-
*
|
|
654
|
-
*
|
|
655
|
-
*/
|
|
656
|
-
joinStatementsToDreamClassesMap(joinStatements) {
|
|
657
|
-
const associationsToDreamClassesMap = {};
|
|
658
|
-
(0, objectPathsToArrays_js_1.default)(joinStatements).forEach(associationChain => this.associationNamesToDreamClassesMap(associationChain, associationsToDreamClassesMap));
|
|
659
|
-
return associationsToDreamClassesMap;
|
|
660
|
-
}
|
|
661
|
-
/**
|
|
662
|
-
* @internal
|
|
663
|
-
*
|
|
664
|
-
*
|
|
665
|
-
*/
|
|
666
|
-
joinStatementsToAssociationsMap(joinStatements) {
|
|
667
|
-
const associationsToAssociationsMap = {};
|
|
668
|
-
(0, objectPathsToArrays_js_1.default)(joinStatements).forEach(associationChain => this.associationNamesToAssociationsMap(associationChain, associationsToAssociationsMap));
|
|
669
|
-
return associationsToAssociationsMap;
|
|
670
|
-
}
|
|
671
555
|
/**
|
|
672
556
|
* @internal
|
|
673
557
|
*
|
|
@@ -885,8 +769,7 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
885
769
|
* @returns A Kysely SelectQueryBuilder instance
|
|
886
770
|
*/
|
|
887
771
|
nestedSelect(selection) {
|
|
888
|
-
|
|
889
|
-
return query.select(this.namespaceColumn(selection));
|
|
772
|
+
return this.dbDriverInstance().nestedSelect(selection);
|
|
890
773
|
}
|
|
891
774
|
/**
|
|
892
775
|
* Returns a new Query instance, attaching the provided
|
|
@@ -979,8 +862,7 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
979
862
|
*
|
|
980
863
|
*/
|
|
981
864
|
sql() {
|
|
982
|
-
|
|
983
|
-
return kyselyQuery.compile();
|
|
865
|
+
return this.dbDriverInstance().sql();
|
|
984
866
|
}
|
|
985
867
|
/**
|
|
986
868
|
* Converts the given dream class into a Kysely query, enabling
|
|
@@ -994,21 +876,7 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
994
876
|
* @returns A Kysely query. Depending on the type passed, it will return either a SelectQueryBuilder, DeleteQueryBuilder, or an UpdateQueryBuilder
|
|
995
877
|
*/
|
|
996
878
|
toKysely(type) {
|
|
997
|
-
|
|
998
|
-
case 'select':
|
|
999
|
-
return this.buildSelect();
|
|
1000
|
-
case 'delete':
|
|
1001
|
-
return this.buildDelete();
|
|
1002
|
-
case 'update':
|
|
1003
|
-
return this.buildUpdate({});
|
|
1004
|
-
// TODO: in the future, we should support insert type, but don't yet, since inserts are done outside
|
|
1005
|
-
// the query class for some reason.
|
|
1006
|
-
default: {
|
|
1007
|
-
// protection so that if a new QueryType is ever added, this will throw a type error at build time
|
|
1008
|
-
const _never = type;
|
|
1009
|
-
throw new Error(`Unhandled QueryType: ${_never}`);
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
879
|
+
return this.dbDriverInstance().toKysely(type);
|
|
1012
880
|
}
|
|
1013
881
|
/**
|
|
1014
882
|
* Applies transaction to the Query instance
|
|
@@ -1036,17 +904,7 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
1036
904
|
* @returns The number of records in the database
|
|
1037
905
|
*/
|
|
1038
906
|
async count() {
|
|
1039
|
-
|
|
1040
|
-
const { count } = this.dbFor('select').fn;
|
|
1041
|
-
const distinctColumn = this.distinctColumn;
|
|
1042
|
-
const query = this.clone({ distinctColumn: null });
|
|
1043
|
-
let kyselyQuery = query.buildSelect({ bypassSelectAll: true, bypassOrder: true });
|
|
1044
|
-
const countClause = distinctColumn
|
|
1045
|
-
? count((0, kysely_1.sql) `DISTINCT ${distinctColumn}`)
|
|
1046
|
-
: count(query.namespaceColumn(query.dreamInstance.primaryKey));
|
|
1047
|
-
kyselyQuery = kyselyQuery.select(countClause.as('tablecount'));
|
|
1048
|
-
const data = await (0, executeDatabaseQuery_js_1.default)(kyselyQuery, 'executeTakeFirstOrThrow');
|
|
1049
|
-
return parseInt(data.tablecount.toString());
|
|
907
|
+
return await this.dbDriverInstance().count();
|
|
1050
908
|
}
|
|
1051
909
|
/**
|
|
1052
910
|
* Returns new Query with distinct clause applied
|
|
@@ -1094,12 +952,7 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
1094
952
|
*
|
|
1095
953
|
*/
|
|
1096
954
|
async max(columnName) {
|
|
1097
|
-
|
|
1098
|
-
const { max } = this.dbFor('select').fn;
|
|
1099
|
-
let kyselyQuery = this.buildSelect({ bypassSelectAll: true, bypassOrder: true });
|
|
1100
|
-
kyselyQuery = kyselyQuery.select(max(columnName));
|
|
1101
|
-
const data = await (0, executeDatabaseQuery_js_1.default)(kyselyQuery, 'executeTakeFirstOrThrow');
|
|
1102
|
-
return data.max;
|
|
955
|
+
return await this.dbDriverInstance().max(columnName);
|
|
1103
956
|
}
|
|
1104
957
|
/**
|
|
1105
958
|
* Retrieves the min value of the specified column
|
|
@@ -1114,218 +967,7 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
1114
967
|
* @returns the min value of the specified column for this Query
|
|
1115
968
|
*/
|
|
1116
969
|
async min(columnName) {
|
|
1117
|
-
|
|
1118
|
-
const { min } = this.dbFor('select').fn;
|
|
1119
|
-
let kyselyQuery = this.buildSelect({ bypassSelectAll: true, bypassOrder: true });
|
|
1120
|
-
kyselyQuery = kyselyQuery.select(min(columnName));
|
|
1121
|
-
const data = await (0, executeDatabaseQuery_js_1.default)(kyselyQuery, 'executeTakeFirstOrThrow');
|
|
1122
|
-
return data.min;
|
|
1123
|
-
}
|
|
1124
|
-
/**
|
|
1125
|
-
* @internal
|
|
1126
|
-
*
|
|
1127
|
-
* Runs the query and extracts plucked values
|
|
1128
|
-
*
|
|
1129
|
-
* @returns An array of plucked values
|
|
1130
|
-
*/
|
|
1131
|
-
async executePluck(...fields) {
|
|
1132
|
-
let kyselyQuery = this.removeAllDefaultScopesExceptOnAssociations().buildSelect({ bypassSelectAll: true });
|
|
1133
|
-
const aliases = [];
|
|
1134
|
-
fields.forEach((field) => {
|
|
1135
|
-
// field will already be namespaced in a join situation, but when the field to pluck is on the
|
|
1136
|
-
// base model, it will be underscored (to match the table name), but when the selected column
|
|
1137
|
-
// comes back from Kysely camelCased
|
|
1138
|
-
aliases.push(field.includes('_') ? (0, camelize_js_1.default)(field) : field);
|
|
1139
|
-
// namespace the selection so that when plucking the same column name from
|
|
1140
|
-
// multpile tables, they don't get saved as the same name (e.g. select results with two `id` columns,
|
|
1141
|
-
// which the pg package then returns in an object with a single `id` key)
|
|
1142
|
-
kyselyQuery = kyselyQuery.select(`${this.namespaceColumn(field)} as ${field}`);
|
|
1143
|
-
});
|
|
1144
|
-
return (await (0, executeDatabaseQuery_js_1.default)(kyselyQuery, 'execute')).map(singleResult => aliases.map(alias => singleResult[alias]));
|
|
1145
|
-
}
|
|
1146
|
-
/**
|
|
1147
|
-
* @internal
|
|
1148
|
-
*
|
|
1149
|
-
*/
|
|
1150
|
-
async executeJoinLoad(options = {}) {
|
|
1151
|
-
const query = this.limit(null).offset(null);
|
|
1152
|
-
let kyselyQuery = query.buildSelect({ bypassSelectAll: true });
|
|
1153
|
-
const aliasToDreamClassesMap = {
|
|
1154
|
-
[this.baseSqlAlias]: this.dreamClass,
|
|
1155
|
-
...this.joinStatementsToDreamClassesMap(this.leftJoinStatements),
|
|
1156
|
-
};
|
|
1157
|
-
const associationAliasToColumnAliasMap = {};
|
|
1158
|
-
const aliasToAssociationsMap = this.joinStatementsToAssociationsMap(this.leftJoinStatements);
|
|
1159
|
-
const aliases = Object.keys(aliasToDreamClassesMap);
|
|
1160
|
-
let nextColumnAliasCounter = 0;
|
|
1161
|
-
aliases.forEach((aliasOrExpression) => {
|
|
1162
|
-
const alias = (0, extractAssociationMetadataFromAssociationName_js_1.default)(aliasOrExpression).alias;
|
|
1163
|
-
if (alias === undefined)
|
|
1164
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
1165
|
-
associationAliasToColumnAliasMap[alias] ||= {};
|
|
1166
|
-
const aliasedDreamClass = aliasToDreamClassesMap[alias];
|
|
1167
|
-
if (aliasedDreamClass === undefined)
|
|
1168
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
1169
|
-
const association = aliasToAssociationsMap[alias];
|
|
1170
|
-
const columns = alias === this.baseSqlAlias
|
|
1171
|
-
? options.columns
|
|
1172
|
-
? this.columnsWithRequiredLoadColumns(options.columns)
|
|
1173
|
-
: this.dreamClass.columns()
|
|
1174
|
-
: aliasedDreamClass.columns();
|
|
1175
|
-
columns.forEach((column) => {
|
|
1176
|
-
const columnAlias = `dr${nextColumnAliasCounter++}`;
|
|
1177
|
-
kyselyQuery = kyselyQuery.select(`${this.namespaceColumn(column, alias)} as ${columnAlias}`);
|
|
1178
|
-
const columnAliasMap = associationAliasToColumnAliasMap[alias];
|
|
1179
|
-
if (columnAliasMap === undefined)
|
|
1180
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
1181
|
-
columnAliasMap[column] = columnAlias;
|
|
1182
|
-
});
|
|
1183
|
-
if (association?.type === 'HasOne' || association?.type === 'HasMany') {
|
|
1184
|
-
const setupPreloadData = (dbColumnName) => {
|
|
1185
|
-
const columnAlias = `dr${nextColumnAliasCounter++}`;
|
|
1186
|
-
const columnAliasMap = associationAliasToColumnAliasMap[association.through];
|
|
1187
|
-
if (columnAliasMap === undefined)
|
|
1188
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
1189
|
-
columnAliasMap[dbColumnName] = columnAlias;
|
|
1190
|
-
kyselyQuery = kyselyQuery.select(`${this.namespaceColumn(dbColumnName, association.through)} as ${columnAlias}`);
|
|
1191
|
-
};
|
|
1192
|
-
if (association.through && association.preloadThroughColumns) {
|
|
1193
|
-
if ((0, isObject_js_1.default)(association.preloadThroughColumns)) {
|
|
1194
|
-
const preloadMap = association.preloadThroughColumns;
|
|
1195
|
-
Object.keys(preloadMap).forEach(columnName => setupPreloadData(columnName));
|
|
1196
|
-
}
|
|
1197
|
-
else {
|
|
1198
|
-
const preloadArray = association.preloadThroughColumns;
|
|
1199
|
-
preloadArray.forEach(columnName => setupPreloadData(columnName));
|
|
1200
|
-
}
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
|
-
});
|
|
1204
|
-
const queryResults = await (0, executeDatabaseQuery_js_1.default)(kyselyQuery, 'execute');
|
|
1205
|
-
const aliasToDreamIdMap = queryResults.reduce((aliasToDreamIdMap, singleSqlResult) => {
|
|
1206
|
-
this.fleshOutJoinLoadExecutionResults({
|
|
1207
|
-
currentAlias: this.baseSqlAlias,
|
|
1208
|
-
singleSqlResult,
|
|
1209
|
-
aliasToDreamIdMap,
|
|
1210
|
-
associationAliasToColumnAliasMap,
|
|
1211
|
-
aliasToAssociationsMap,
|
|
1212
|
-
aliasToDreamClassesMap,
|
|
1213
|
-
leftJoinStatements: this.leftJoinStatements,
|
|
1214
|
-
});
|
|
1215
|
-
return aliasToDreamIdMap;
|
|
1216
|
-
}, {});
|
|
1217
|
-
const baseModelIdToDreamMap = aliasToDreamIdMap[this.baseSqlAlias] || new Map();
|
|
1218
|
-
return (0, compact_js_1.default)(Array.from(baseModelIdToDreamMap.values()));
|
|
1219
|
-
}
|
|
1220
|
-
fleshOutJoinLoadExecutionResults({ currentAlias, singleSqlResult, aliasToDreamIdMap, associationAliasToColumnAliasMap, aliasToAssociationsMap, aliasToDreamClassesMap, leftJoinStatements, }) {
|
|
1221
|
-
const dreamClass = aliasToDreamClassesMap[currentAlias];
|
|
1222
|
-
if (dreamClass === undefined)
|
|
1223
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
1224
|
-
const columnToColumnAliasMap = associationAliasToColumnAliasMap[currentAlias];
|
|
1225
|
-
if (columnToColumnAliasMap === undefined)
|
|
1226
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
1227
|
-
const primaryKeyName = dreamClass.primaryKey;
|
|
1228
|
-
if (primaryKeyName === undefined)
|
|
1229
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
1230
|
-
const columnAlias = columnToColumnAliasMap[primaryKeyName];
|
|
1231
|
-
if (columnAlias === undefined)
|
|
1232
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
1233
|
-
const primaryKeyValue = singleSqlResult[columnAlias];
|
|
1234
|
-
if (!primaryKeyValue)
|
|
1235
|
-
return null;
|
|
1236
|
-
aliasToDreamIdMap[currentAlias] ||= new Map();
|
|
1237
|
-
if (!aliasToDreamIdMap[currentAlias].get(primaryKeyValue)) {
|
|
1238
|
-
const columnValueMap = Object.keys(columnToColumnAliasMap).reduce((columnNameValueMap, columnName) => {
|
|
1239
|
-
const columnAlias = columnToColumnAliasMap[columnName];
|
|
1240
|
-
if (columnAlias === undefined)
|
|
1241
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
1242
|
-
columnNameValueMap[columnName] = singleSqlResult[columnAlias];
|
|
1243
|
-
return columnNameValueMap;
|
|
1244
|
-
}, {});
|
|
1245
|
-
const dream = (0, sqlResultToDreamInstance_js_1.default)(dreamClass, columnValueMap);
|
|
1246
|
-
const association = aliasToAssociationsMap[currentAlias];
|
|
1247
|
-
if (association && association.through && association.preloadThroughColumns) {
|
|
1248
|
-
const throughAssociationColumnToColumnAliasMap = associationAliasToColumnAliasMap[association.through];
|
|
1249
|
-
if (throughAssociationColumnToColumnAliasMap === undefined)
|
|
1250
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
1251
|
-
this.hydratePreloadedThroughColumns({
|
|
1252
|
-
association,
|
|
1253
|
-
columnToColumnAliasMap: throughAssociationColumnToColumnAliasMap,
|
|
1254
|
-
dream,
|
|
1255
|
-
singleSqlResult,
|
|
1256
|
-
});
|
|
1257
|
-
}
|
|
1258
|
-
aliasToDreamIdMap[(0, protectAgainstPollutingAssignment_js_1.default)(currentAlias)]?.set(primaryKeyValue, dream);
|
|
1259
|
-
}
|
|
1260
|
-
const dream = aliasToDreamIdMap[currentAlias].get(primaryKeyValue);
|
|
1261
|
-
Object.keys(leftJoinStatements).forEach(nextAlias => {
|
|
1262
|
-
const { name: associationName, alias } = (0, extractAssociationMetadataFromAssociationName_js_1.default)(nextAlias);
|
|
1263
|
-
const association = dreamClass['getAssociationMetadata'](associationName);
|
|
1264
|
-
if (association === undefined)
|
|
1265
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
1266
|
-
const associatedDream = this.fleshOutJoinLoadExecutionResults({
|
|
1267
|
-
currentAlias: alias,
|
|
1268
|
-
singleSqlResult,
|
|
1269
|
-
aliasToDreamIdMap,
|
|
1270
|
-
associationAliasToColumnAliasMap,
|
|
1271
|
-
aliasToAssociationsMap,
|
|
1272
|
-
aliasToDreamClassesMap,
|
|
1273
|
-
leftJoinStatements: leftJoinStatements[nextAlias],
|
|
1274
|
-
});
|
|
1275
|
-
const hasMany = association.type === 'HasMany';
|
|
1276
|
-
// initialize by trying to access the association, which throws an exception if not yet initialized
|
|
1277
|
-
try {
|
|
1278
|
-
;
|
|
1279
|
-
dream[association.as];
|
|
1280
|
-
}
|
|
1281
|
-
catch {
|
|
1282
|
-
if (hasMany)
|
|
1283
|
-
dream[association.as] = [];
|
|
1284
|
-
else
|
|
1285
|
-
dream[(0, associationToGetterSetterProp_js_1.default)(association)] = null;
|
|
1286
|
-
}
|
|
1287
|
-
if (!associatedDream)
|
|
1288
|
-
return;
|
|
1289
|
-
if (hasMany) {
|
|
1290
|
-
if (!dream[association.as].includes(associatedDream))
|
|
1291
|
-
dream[association.as].push(associatedDream);
|
|
1292
|
-
}
|
|
1293
|
-
else
|
|
1294
|
-
dream[(0, associationToGetterSetterProp_js_1.default)(association)] = associatedDream;
|
|
1295
|
-
});
|
|
1296
|
-
return dream;
|
|
1297
|
-
}
|
|
1298
|
-
hydratePreloadedThroughColumns({ association, columnToColumnAliasMap, dream, singleSqlResult, }) {
|
|
1299
|
-
if (!association.through)
|
|
1300
|
-
return;
|
|
1301
|
-
if (!dream.preloadedThroughColumns)
|
|
1302
|
-
return;
|
|
1303
|
-
let columnNames = [];
|
|
1304
|
-
const columnNameToPreloadedThroughColumnNameMap = {};
|
|
1305
|
-
if ((0, isObject_js_1.default)(association.preloadThroughColumns)) {
|
|
1306
|
-
const preloadMap = association.preloadThroughColumns;
|
|
1307
|
-
columnNames = Object.keys(preloadMap).map(columnName => {
|
|
1308
|
-
columnNameToPreloadedThroughColumnNameMap[columnName] = preloadMap[columnName];
|
|
1309
|
-
return columnName;
|
|
1310
|
-
});
|
|
1311
|
-
}
|
|
1312
|
-
else if (Array.isArray(association.preloadThroughColumns)) {
|
|
1313
|
-
columnNames = association.preloadThroughColumns.map(columnName => {
|
|
1314
|
-
columnNameToPreloadedThroughColumnNameMap[columnName] = columnName;
|
|
1315
|
-
return columnName;
|
|
1316
|
-
});
|
|
1317
|
-
}
|
|
1318
|
-
columnNames.forEach(columnName => {
|
|
1319
|
-
const preloadedThroughColumnName = columnNameToPreloadedThroughColumnNameMap[columnName];
|
|
1320
|
-
if (preloadedThroughColumnName === undefined)
|
|
1321
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
1322
|
-
const columnAlias = columnToColumnAliasMap[columnName];
|
|
1323
|
-
if (columnAlias === undefined) {
|
|
1324
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
1325
|
-
}
|
|
1326
|
-
;
|
|
1327
|
-
dream.preloadedThroughColumns[preloadedThroughColumnName] = singleSqlResult[columnAlias];
|
|
1328
|
-
});
|
|
970
|
+
return await this.dbDriverInstance().min(columnName);
|
|
1329
971
|
}
|
|
1330
972
|
/**
|
|
1331
973
|
* Plucks the provided fields from the given dream class table
|
|
@@ -1347,7 +989,7 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
1347
989
|
* @returns An array of pluck results
|
|
1348
990
|
*/
|
|
1349
991
|
async pluck(...columnNames) {
|
|
1350
|
-
const vals = await this.
|
|
992
|
+
const vals = await this.dbDriverInstance().pluck(...columnNames);
|
|
1351
993
|
return (columnNames.length > 1 ? vals : vals.flat());
|
|
1352
994
|
}
|
|
1353
995
|
/**
|
|
@@ -1384,11 +1026,11 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
1384
1026
|
const columnsIncludingPrimaryKey = onlyIncludesPrimaryKey
|
|
1385
1027
|
? onlyColumns
|
|
1386
1028
|
: [this.namespacedPrimaryKey, ...onlyColumns];
|
|
1387
|
-
|
|
1029
|
+
const query = this.offset(offset)
|
|
1388
1030
|
.order(null)
|
|
1389
1031
|
.order(this.namespacedPrimaryKey)
|
|
1390
|
-
.limit(batchSize)
|
|
1391
|
-
|
|
1032
|
+
.limit(batchSize);
|
|
1033
|
+
records = await this.dbDriverInstance(query).pluck(...columnsIncludingPrimaryKey);
|
|
1392
1034
|
// In order to batch, we need to order by primary key, so the primary key must be plucked.
|
|
1393
1035
|
// If the developer did not include the primary key in the columns to pluck, then we prepended it above
|
|
1394
1036
|
// and need to remove it from each group of plucked columns prior to passing them into the callback functions
|
|
@@ -1413,13 +1055,14 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
1413
1055
|
* @returns an array of dreams
|
|
1414
1056
|
*/
|
|
1415
1057
|
async all(options = {}) {
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1058
|
+
return await this.dbDriverInstance().takeAll(options);
|
|
1059
|
+
}
|
|
1060
|
+
static dbDriverClass() {
|
|
1061
|
+
return Postgres_js_1.default;
|
|
1062
|
+
}
|
|
1063
|
+
dbDriverInstance(query = this) {
|
|
1064
|
+
const driverClass = Query.dbDriverClass();
|
|
1065
|
+
return new driverClass(query);
|
|
1423
1066
|
}
|
|
1424
1067
|
/**
|
|
1425
1068
|
* Paginates the results of your query, accepting a pageSize and page argument,
|
|
@@ -1524,7 +1167,8 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
1524
1167
|
const query = this.orderStatements.length
|
|
1525
1168
|
? this
|
|
1526
1169
|
: this.order({ [this.namespacedPrimaryKey]: 'asc' });
|
|
1527
|
-
|
|
1170
|
+
const dbDriverClass = Query.dbDriverClass();
|
|
1171
|
+
return await new dbDriverClass(query).takeOne();
|
|
1528
1172
|
}
|
|
1529
1173
|
/**
|
|
1530
1174
|
* Returns the first record in the database
|
|
@@ -1563,7 +1207,8 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
1563
1207
|
const query = this.orderStatements.length
|
|
1564
1208
|
? this.invertOrder()
|
|
1565
1209
|
: this.order({ [this.namespacedPrimaryKey]: 'desc' });
|
|
1566
|
-
|
|
1210
|
+
const dbDriverClass = Query.dbDriverClass();
|
|
1211
|
+
return await new dbDriverClass(query).takeOne();
|
|
1567
1212
|
}
|
|
1568
1213
|
/**
|
|
1569
1214
|
* Returns the last record in the database
|
|
@@ -1713,8 +1358,7 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
1713
1358
|
* @returns The number of records that were removed
|
|
1714
1359
|
*/
|
|
1715
1360
|
async delete() {
|
|
1716
|
-
|
|
1717
|
-
return Number(deletionResult?.numDeletedRows || 0);
|
|
1361
|
+
return await this.dbDriverInstance().delete();
|
|
1718
1362
|
}
|
|
1719
1363
|
/**
|
|
1720
1364
|
* Updates all records matching the Query
|
|
@@ -1748,1014 +1392,7 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
1748
1392
|
return counter;
|
|
1749
1393
|
}
|
|
1750
1394
|
async updateWithoutCallingModelHooks(attributes) {
|
|
1751
|
-
|
|
1752
|
-
const res = await (0, executeDatabaseQuery_js_1.default)(kyselyQuery, 'execute');
|
|
1753
|
-
const resultData = Array.from(res.entries())?.[0]?.[1];
|
|
1754
|
-
return Number(resultData?.numUpdatedRows || 0);
|
|
1755
|
-
}
|
|
1756
|
-
/**
|
|
1757
|
-
* @internal
|
|
1758
|
-
*
|
|
1759
|
-
* Used for applying first and last queries
|
|
1760
|
-
*
|
|
1761
|
-
* @returns A dream instance or null
|
|
1762
|
-
*/
|
|
1763
|
-
async takeOne() {
|
|
1764
|
-
if (this.joinLoadActivated) {
|
|
1765
|
-
let query;
|
|
1766
|
-
if (this.whereStatements.find(whereStatement => whereStatement[this.dreamClass.primaryKey] ||
|
|
1767
|
-
whereStatement[this.namespacedPrimaryKey])) {
|
|
1768
|
-
// the query already includes a primary key where statement
|
|
1769
|
-
query = this;
|
|
1770
|
-
}
|
|
1771
|
-
else {
|
|
1772
|
-
// otherwise find the primary key and apply it to the query
|
|
1773
|
-
const primaryKeyValue = (await this.limit(1).pluck(this.namespacedPrimaryKey))[0];
|
|
1774
|
-
if (primaryKeyValue === undefined)
|
|
1775
|
-
return null;
|
|
1776
|
-
query = this.where({ [this.namespacedPrimaryKey]: primaryKeyValue });
|
|
1777
|
-
}
|
|
1778
|
-
return (await query.executeJoinLoad())[0] || null;
|
|
1779
|
-
}
|
|
1780
|
-
const kyselyQuery = this.limit(1).buildSelect();
|
|
1781
|
-
const results = await (0, executeDatabaseQuery_js_1.default)(kyselyQuery, 'executeTakeFirst');
|
|
1782
|
-
if (results) {
|
|
1783
|
-
const theFirst = (0, sqlResultToDreamInstance_js_1.default)(this.dreamClass, results);
|
|
1784
|
-
if (theFirst)
|
|
1785
|
-
await this.applyPreload(this.preloadStatements, this.preloadOnStatements, [theFirst]);
|
|
1786
|
-
return theFirst;
|
|
1787
|
-
}
|
|
1788
|
-
else
|
|
1789
|
-
return null;
|
|
1790
|
-
}
|
|
1791
|
-
/**
|
|
1792
|
-
* @internal
|
|
1793
|
-
*
|
|
1794
|
-
* Used to hydrate dreams with the provided associations
|
|
1795
|
-
*/
|
|
1796
|
-
hydrateAssociation(dreams, association, preloadedDreamsAndWhatTheyPointTo) {
|
|
1797
|
-
switch (association.type) {
|
|
1798
|
-
case 'HasMany':
|
|
1799
|
-
dreams.forEach((dream) => {
|
|
1800
|
-
dream[association.as] = [];
|
|
1801
|
-
});
|
|
1802
|
-
break;
|
|
1803
|
-
default:
|
|
1804
|
-
dreams.forEach((dream) => {
|
|
1805
|
-
dream[(0, associationToGetterSetterProp_js_1.default)(association)] = null;
|
|
1806
|
-
});
|
|
1807
|
-
}
|
|
1808
|
-
// dreams is a Rating
|
|
1809
|
-
// Rating belongs to: rateables (Posts / Compositions)
|
|
1810
|
-
// loadedAssociations is an array of Posts and Compositions
|
|
1811
|
-
// if rating.rateable_id === loadedAssociation.primaryKeyvalue
|
|
1812
|
-
// rating.rateable = loadedAssociation
|
|
1813
|
-
preloadedDreamsAndWhatTheyPointTo.forEach(preloadedDreamAndWhatItPointsTo => {
|
|
1814
|
-
dreams
|
|
1815
|
-
.filter(dream => dream.primaryKeyValue === preloadedDreamAndWhatItPointsTo.pointsToPrimaryKey)
|
|
1816
|
-
.forEach((dream) => {
|
|
1817
|
-
if (association.type === 'HasMany') {
|
|
1818
|
-
dream[association.as].push(preloadedDreamAndWhatItPointsTo.dream);
|
|
1819
|
-
}
|
|
1820
|
-
else {
|
|
1821
|
-
// in a HasOne context, order clauses will be applied in advance,
|
|
1822
|
-
// prior to hydration. Considering, we only want to set the first
|
|
1823
|
-
// result and ignore other results, so we will use ||= to set.
|
|
1824
|
-
dream[association.as] ||= preloadedDreamAndWhatItPointsTo.dream;
|
|
1825
|
-
}
|
|
1826
|
-
});
|
|
1827
|
-
});
|
|
1828
|
-
if (association.type === 'HasMany') {
|
|
1829
|
-
dreams.forEach((dream) => Object.freeze(dream[association.as]));
|
|
1830
|
-
}
|
|
1831
|
-
}
|
|
1832
|
-
/**
|
|
1833
|
-
* @internal
|
|
1834
|
-
*
|
|
1835
|
-
* Used to bridge through associations
|
|
1836
|
-
*/
|
|
1837
|
-
followThroughAssociation(dreamClass, association) {
|
|
1838
|
-
const throughAssociation = association.through && dreamClass['getAssociationMetadata'](association.through);
|
|
1839
|
-
if (!throughAssociation)
|
|
1840
|
-
throw new MissingThroughAssociation_js_1.default({
|
|
1841
|
-
dreamClass,
|
|
1842
|
-
association,
|
|
1843
|
-
});
|
|
1844
|
-
const throughClass = throughAssociation.modelCB();
|
|
1845
|
-
if (Array.isArray(throughClass))
|
|
1846
|
-
throw new CannotAssociateThroughPolymorphic_js_1.default({
|
|
1847
|
-
dreamClass,
|
|
1848
|
-
association,
|
|
1849
|
-
});
|
|
1850
|
-
const newAssociation = getSourceAssociation(throughClass, association.source);
|
|
1851
|
-
if (!newAssociation)
|
|
1852
|
-
throw new MissingThroughAssociationSource_js_1.default({
|
|
1853
|
-
dreamClass,
|
|
1854
|
-
throughClass,
|
|
1855
|
-
association,
|
|
1856
|
-
});
|
|
1857
|
-
return { throughAssociation, throughClass, newAssociation };
|
|
1858
|
-
}
|
|
1859
|
-
/**
|
|
1860
|
-
* @internal
|
|
1861
|
-
*
|
|
1862
|
-
* Polymorphic BelongsTo. Since polymorphic associations may point to multiple tables,
|
|
1863
|
-
* preload by loading each target class separately.
|
|
1864
|
-
*
|
|
1865
|
-
* Used to preload polymorphic belongs to associations
|
|
1866
|
-
*/
|
|
1867
|
-
async preloadPolymorphicBelongsTo(association, dreams) {
|
|
1868
|
-
if (!association.polymorphic)
|
|
1869
|
-
throw new Error(`Association ${association.as} points to an array of models but is not designated polymorphic`);
|
|
1870
|
-
if (association.type !== 'BelongsTo')
|
|
1871
|
-
throw new Error(`Polymorphic association ${association.as} points to an array of models but is ${association.type}. Only BelongsTo associations may point to an array of models.`);
|
|
1872
|
-
const associatedDreams = [];
|
|
1873
|
-
for (const associatedModel of association.modelCB()) {
|
|
1874
|
-
await this.preloadPolymorphicAssociationModel(dreams, association, associatedModel, associatedDreams);
|
|
1875
|
-
}
|
|
1876
|
-
return associatedDreams;
|
|
1877
|
-
}
|
|
1878
|
-
async preloadPolymorphicAssociationModel(dreams, association, associatedDreamClass, associatedDreams) {
|
|
1879
|
-
const relevantAssociatedModels = dreams.filter((dream) => {
|
|
1880
|
-
const field = association.foreignKeyTypeField();
|
|
1881
|
-
return dream[field] === associatedDreamClass['stiBaseClassOrOwnClassName'] || dream[field] === null;
|
|
1882
|
-
});
|
|
1883
|
-
if (relevantAssociatedModels.length) {
|
|
1884
|
-
dreams.forEach((dream) => {
|
|
1885
|
-
dream[(0, associationToGetterSetterProp_js_1.default)(association)] = null;
|
|
1886
|
-
});
|
|
1887
|
-
// Load all models of type associated that are associated with any of the already loaded Dream models
|
|
1888
|
-
const loadedAssociations = await this.dreamClassQueryWithScopeBypasses(associatedDreamClass, {
|
|
1889
|
-
// The association may remove specific default scopes that would otherwise preclude
|
|
1890
|
-
// certain instances of the associated class from being found.
|
|
1891
|
-
defaultScopesToBypassExceptOnAssociations: association.withoutDefaultScopes,
|
|
1892
|
-
})
|
|
1893
|
-
.where({
|
|
1894
|
-
[associatedDreamClass.primaryKey]: relevantAssociatedModels.map((dream) => dream[association.foreignKey()]),
|
|
1895
|
-
})
|
|
1896
|
-
.all();
|
|
1897
|
-
loadedAssociations.forEach((loadedAssociation) => associatedDreams.push(loadedAssociation));
|
|
1898
|
-
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
1899
|
-
// Associate each loaded association with each dream based on primary key and foreign key type
|
|
1900
|
-
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
1901
|
-
for (const loadedAssociation of loadedAssociations) {
|
|
1902
|
-
dreams
|
|
1903
|
-
.filter((dream) => {
|
|
1904
|
-
return (dream[association.foreignKeyTypeField()] === loadedAssociation['stiBaseClassOrOwnClassName'] &&
|
|
1905
|
-
dream[association.foreignKey()] === association.primaryKeyValue(loadedAssociation));
|
|
1906
|
-
})
|
|
1907
|
-
.forEach((dream) => {
|
|
1908
|
-
dream[association.as] = loadedAssociation;
|
|
1909
|
-
});
|
|
1910
|
-
}
|
|
1911
|
-
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
1912
|
-
// end: Associate each loaded association with each dream based on primary key and foreign key type
|
|
1913
|
-
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
1914
|
-
}
|
|
1915
|
-
}
|
|
1916
|
-
/**
|
|
1917
|
-
* @internal
|
|
1918
|
-
*
|
|
1919
|
-
* Applies a preload statement
|
|
1920
|
-
*/
|
|
1921
|
-
async applyOnePreload(associationName, dreams, onStatement = {}) {
|
|
1922
|
-
if (!Array.isArray(dreams))
|
|
1923
|
-
dreams = [dreams];
|
|
1924
|
-
const dream = dreams.find(dream => dream['getAssociationMetadata'](associationName));
|
|
1925
|
-
if (!dream)
|
|
1926
|
-
return;
|
|
1927
|
-
const { name, alias } = (0, extractAssociationMetadataFromAssociationName_js_1.default)(associationName);
|
|
1928
|
-
const association = dream['getAssociationMetadata'](name);
|
|
1929
|
-
if (association === undefined)
|
|
1930
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
1931
|
-
const dreamClass = dream.constructor;
|
|
1932
|
-
const dreamClassToHydrate = association.modelCB();
|
|
1933
|
-
if ((association.polymorphic && association.type === 'BelongsTo') || Array.isArray(dreamClassToHydrate))
|
|
1934
|
-
return this.preloadPolymorphicBelongsTo(association, dreams);
|
|
1935
|
-
const dreamClassToHydrateColumns = [...dreamClassToHydrate.columns()];
|
|
1936
|
-
const throughColumnsToHydrate = [];
|
|
1937
|
-
const columnsToPluck = dreamClassToHydrateColumns.map(column => this.namespaceColumn(column.toString(), alias));
|
|
1938
|
-
const asHasAssociation = association;
|
|
1939
|
-
if (asHasAssociation.through && asHasAssociation.preloadThroughColumns) {
|
|
1940
|
-
if ((0, isObject_js_1.default)(asHasAssociation.preloadThroughColumns)) {
|
|
1941
|
-
const preloadMap = asHasAssociation.preloadThroughColumns;
|
|
1942
|
-
Object.keys(preloadMap).forEach(preloadThroughColumn => {
|
|
1943
|
-
throughColumnsToHydrate.push(preloadMap[preloadThroughColumn]);
|
|
1944
|
-
columnsToPluck.push(this.namespaceColumn(preloadThroughColumn, asHasAssociation.through));
|
|
1945
|
-
});
|
|
1946
|
-
}
|
|
1947
|
-
else {
|
|
1948
|
-
const preloadArray = asHasAssociation.preloadThroughColumns;
|
|
1949
|
-
preloadArray.forEach(preloadThroughColumn => {
|
|
1950
|
-
throughColumnsToHydrate.push(preloadThroughColumn);
|
|
1951
|
-
columnsToPluck.push(this.namespaceColumn(preloadThroughColumn, asHasAssociation.through));
|
|
1952
|
-
});
|
|
1953
|
-
}
|
|
1954
|
-
}
|
|
1955
|
-
columnsToPluck.push(this.namespaceColumn(dreamClass.primaryKey, dreamClass.table));
|
|
1956
|
-
const baseClass = dreamClass['stiBaseClassOrOwnClass']['getAssociationMetadata'](associationName)
|
|
1957
|
-
? dreamClass['stiBaseClassOrOwnClass']
|
|
1958
|
-
: dreamClass;
|
|
1959
|
-
const associationDataScope = this.dreamClassQueryWithScopeBypasses(baseClass, {
|
|
1960
|
-
// In order to stay DRY, preloading leverages the association logic built into
|
|
1961
|
-
// `joins` (by using `pluck`, which calls `joins`). However, baseClass may have
|
|
1962
|
-
// default scopes that would preclude finding that instance. We remove all
|
|
1963
|
-
// default scopes on baseClass, but not subsequent associations, so that the
|
|
1964
|
-
// single query will be able to find each row corresponding to a Dream in `dreams`,
|
|
1965
|
-
// regardless of default scopes on that Dream's class.
|
|
1966
|
-
bypassAllDefaultScopesExceptOnAssociations: true,
|
|
1967
|
-
}).where({
|
|
1968
|
-
[dreamClass.primaryKey]: dreams.map(obj => obj.primaryKeyValue),
|
|
1969
|
-
});
|
|
1970
|
-
const hydrationData = await associationDataScope
|
|
1971
|
-
._connection(this.connectionOverride)
|
|
1972
|
-
.innerJoin(associationName, (onStatement || {}))
|
|
1973
|
-
.pluck(...columnsToPluck);
|
|
1974
|
-
const preloadedDreamsAndWhatTheyPointTo = hydrationData.map(pluckedData => {
|
|
1975
|
-
const attributes = {};
|
|
1976
|
-
dreamClassToHydrateColumns.forEach((columnName, index) => (attributes[(0, protectAgainstPollutingAssignment_js_1.default)(columnName)] = pluckedData[index]));
|
|
1977
|
-
const hydratedDream = (0, sqlResultToDreamInstance_js_1.default)(dreamClassToHydrate, attributes);
|
|
1978
|
-
throughColumnsToHydrate.forEach((throughAssociationColumn, index) => (hydratedDream.preloadedThroughColumns[throughAssociationColumn] =
|
|
1979
|
-
pluckedData[dreamClassToHydrateColumns.length + index]));
|
|
1980
|
-
return {
|
|
1981
|
-
dream: hydratedDream,
|
|
1982
|
-
pointsToPrimaryKey: pluckedData.at(-1),
|
|
1983
|
-
};
|
|
1984
|
-
});
|
|
1985
|
-
this.hydrateAssociation(dreams, association, preloadedDreamsAndWhatTheyPointTo);
|
|
1986
|
-
return preloadedDreamsAndWhatTheyPointTo.map(obj => obj.dream);
|
|
1987
|
-
}
|
|
1988
|
-
/**
|
|
1989
|
-
* @internal
|
|
1990
|
-
*
|
|
1991
|
-
* Used by loadBuider
|
|
1992
|
-
*/
|
|
1993
|
-
async hydratePreload(dream) {
|
|
1994
|
-
await this.applyPreload(this.preloadStatements, this.preloadOnStatements, dream);
|
|
1995
|
-
}
|
|
1996
|
-
/**
|
|
1997
|
-
* @internal
|
|
1998
|
-
*
|
|
1999
|
-
* Applies a preload statement
|
|
2000
|
-
*/
|
|
2001
|
-
async applyPreload(preloadStatement, preloadOnStatements, dream) {
|
|
2002
|
-
const keys = Object.keys(preloadStatement);
|
|
2003
|
-
for (const key of keys) {
|
|
2004
|
-
const nestedDreams = await this.applyOnePreload(key, dream, this.applyablePreloadOnStatements(preloadOnStatements[key]));
|
|
2005
|
-
if (nestedDreams) {
|
|
2006
|
-
await this.applyPreload(preloadStatement[key], preloadOnStatements[key], nestedDreams);
|
|
2007
|
-
}
|
|
2008
|
-
}
|
|
2009
|
-
}
|
|
2010
|
-
/**
|
|
2011
|
-
* @internal
|
|
2012
|
-
*
|
|
2013
|
-
* retrieves on statements that can be applied to a preload
|
|
2014
|
-
*/
|
|
2015
|
-
applyablePreloadOnStatements(preloadOnStatements) {
|
|
2016
|
-
if (preloadOnStatements === undefined)
|
|
2017
|
-
return undefined;
|
|
2018
|
-
return Object.keys(preloadOnStatements).reduce((agg, key) => {
|
|
2019
|
-
const value = preloadOnStatements[key];
|
|
2020
|
-
if (value === undefined)
|
|
2021
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
2022
|
-
// filter out plain objects, but not ops and not and/andNot/andAny statements
|
|
2023
|
-
// because plain objects are just the next level of nested preload
|
|
2024
|
-
if (key === 'and' ||
|
|
2025
|
-
key === 'andNot' ||
|
|
2026
|
-
key === 'andAny' ||
|
|
2027
|
-
value === null ||
|
|
2028
|
-
value.constructor !== Object) {
|
|
2029
|
-
agg[key] = value;
|
|
2030
|
-
}
|
|
2031
|
-
return agg;
|
|
2032
|
-
}, {});
|
|
2033
|
-
}
|
|
2034
|
-
conditionallyApplyDefaultScopes() {
|
|
2035
|
-
if (this.bypassAllDefaultScopes || this.bypassAllDefaultScopesExceptOnAssociations)
|
|
2036
|
-
return this;
|
|
2037
|
-
const thisScopes = this.dreamClass['scopes'].default;
|
|
2038
|
-
let query = this;
|
|
2039
|
-
for (const scope of thisScopes) {
|
|
2040
|
-
if (!(0, shouldBypassDefaultScope_js_1.default)(scope.method, {
|
|
2041
|
-
defaultScopesToBypass: [
|
|
2042
|
-
...this.defaultScopesToBypass,
|
|
2043
|
-
...this.defaultScopesToBypassExceptOnAssociations,
|
|
2044
|
-
],
|
|
2045
|
-
})) {
|
|
2046
|
-
query = this.dreamClass[scope.method](query);
|
|
2047
|
-
}
|
|
2048
|
-
}
|
|
2049
|
-
return query;
|
|
2050
|
-
}
|
|
2051
|
-
/**
|
|
2052
|
-
* Each association in the chain is pushed onto `throughAssociations`
|
|
2053
|
-
* and `applyOneJoin` is recursively called. The trick is that the
|
|
2054
|
-
* through associations don't get written into the SQL; they
|
|
2055
|
-
* locate the next association we need to build into the SQL,
|
|
2056
|
-
* which is only run by the association that started the `through`
|
|
2057
|
-
* chain. The final association at the end of the `through` chain _is_
|
|
2058
|
-
* written into the SQL as a full association, but the modifications from
|
|
2059
|
-
* the `through` association are only added when the recursion returns
|
|
2060
|
-
* back to the association that kicked off the through associations.
|
|
2061
|
-
*/
|
|
2062
|
-
joinsBridgeThroughAssociations({ query, dreamClass, association, previousAssociationTableOrAlias, throughAssociations, joinType, }) {
|
|
2063
|
-
if (association.type === 'BelongsTo' || !association.through) {
|
|
2064
|
-
return {
|
|
2065
|
-
query,
|
|
2066
|
-
dreamClass,
|
|
2067
|
-
association,
|
|
2068
|
-
previousAssociationTableOrAlias,
|
|
2069
|
-
};
|
|
2070
|
-
}
|
|
2071
|
-
else {
|
|
2072
|
-
throughAssociations.push(association);
|
|
2073
|
-
// We have entered joinsBridgeThroughAssociations with the
|
|
2074
|
-
// CompositionAssetAudits HasOne User association, which
|
|
2075
|
-
// is through compositionAsset
|
|
2076
|
-
// We now apply the compositionAsset association (a BelongsTo)
|
|
2077
|
-
// to the query
|
|
2078
|
-
const { query: queryWithThroughAssociationApplied } = this.applyOneJoin({
|
|
2079
|
-
query,
|
|
2080
|
-
dreamClass,
|
|
2081
|
-
previousAssociationTableOrAlias,
|
|
2082
|
-
currentAssociationTableOrAlias: association.through,
|
|
2083
|
-
throughAssociations,
|
|
2084
|
-
joinType,
|
|
2085
|
-
});
|
|
2086
|
-
// The through association has both a `through` and a `source`. The `source`
|
|
2087
|
-
// is the association on the model that has now been joined. In our example,
|
|
2088
|
-
// the `source` is the `user` association on the CompositionAsset model
|
|
2089
|
-
const { newAssociation, throughAssociation, throughClass } = this.followThroughAssociation(dreamClass, association);
|
|
2090
|
-
if (newAssociation.through) {
|
|
2091
|
-
// This new association is itself a through association, so we recursively
|
|
2092
|
-
// call joinsBridgeThroughAssociations
|
|
2093
|
-
return this.joinsBridgeThroughAssociations({
|
|
2094
|
-
query: queryWithThroughAssociationApplied,
|
|
2095
|
-
dreamClass: throughClass,
|
|
2096
|
-
association: newAssociation,
|
|
2097
|
-
previousAssociationTableOrAlias: throughAssociation.as,
|
|
2098
|
-
throughAssociations,
|
|
2099
|
-
joinType,
|
|
2100
|
-
});
|
|
2101
|
-
}
|
|
2102
|
-
else {
|
|
2103
|
-
// This new association is not a through association, so
|
|
2104
|
-
// this is the target association we were looking for
|
|
2105
|
-
return {
|
|
2106
|
-
query: queryWithThroughAssociationApplied,
|
|
2107
|
-
dreamClass: association.modelCB(),
|
|
2108
|
-
association: newAssociation,
|
|
2109
|
-
throughClass,
|
|
2110
|
-
previousAssociationTableOrAlias: association.through,
|
|
2111
|
-
};
|
|
2112
|
-
}
|
|
2113
|
-
}
|
|
2114
|
-
}
|
|
2115
|
-
applyOneJoin({ query, dreamClass, previousAssociationTableOrAlias, currentAssociationTableOrAlias, joinAndStatements = {}, throughAssociations = [], joinType, }) {
|
|
2116
|
-
const { name, alias } = (0, extractAssociationMetadataFromAssociationName_js_1.default)(currentAssociationTableOrAlias);
|
|
2117
|
-
const joinAndStatement = joinAndStatements[currentAssociationTableOrAlias];
|
|
2118
|
-
previousAssociationTableOrAlias = (0, extractAssociationMetadataFromAssociationName_js_1.default)(previousAssociationTableOrAlias).alias;
|
|
2119
|
-
currentAssociationTableOrAlias = alias;
|
|
2120
|
-
let association = dreamClass['getAssociationMetadata'](name);
|
|
2121
|
-
if (!association) {
|
|
2122
|
-
throw new JoinAttemptedOnMissingAssociation_js_1.default({
|
|
2123
|
-
dreamClass,
|
|
2124
|
-
associationName: currentAssociationTableOrAlias,
|
|
2125
|
-
});
|
|
2126
|
-
}
|
|
2127
|
-
const results = this.joinsBridgeThroughAssociations({
|
|
2128
|
-
query,
|
|
2129
|
-
dreamClass,
|
|
2130
|
-
association,
|
|
2131
|
-
previousAssociationTableOrAlias,
|
|
2132
|
-
throughAssociations,
|
|
2133
|
-
joinType,
|
|
2134
|
-
});
|
|
2135
|
-
query = results.query;
|
|
2136
|
-
dreamClass = results.dreamClass;
|
|
2137
|
-
association = results.association;
|
|
2138
|
-
const timeToApplyThroughAssociations = throughAssociations.length && throughAssociations[0]?.source === association.as;
|
|
2139
|
-
const originalPreviousAssociationTableOrAlias = previousAssociationTableOrAlias;
|
|
2140
|
-
previousAssociationTableOrAlias = results.previousAssociationTableOrAlias;
|
|
2141
|
-
const throughClass = results.throughClass;
|
|
2142
|
-
if (timeToApplyThroughAssociations) {
|
|
2143
|
-
/**
|
|
2144
|
-
* Each association in the chain is pushed onto `throughAssociations`
|
|
2145
|
-
* and `applyOneJoin` is recursively called. The trick is that the
|
|
2146
|
-
* through associations don't get written into the SQL; they
|
|
2147
|
-
* locate the next association we need to build into the SQL,
|
|
2148
|
-
* which is only run by the association that started the `through`
|
|
2149
|
-
* chain (thus the
|
|
2150
|
-
* `throughAssociations.length && throughAssociations[0].source === association.as`
|
|
2151
|
-
* above). The final association at the end of the `through` chain _is_
|
|
2152
|
-
* written into the SQL as a full association, but the modifications from
|
|
2153
|
-
* the `through` association are only added when the recursion returns
|
|
2154
|
-
* back to the association that kicked off the through associations.
|
|
2155
|
-
*/
|
|
2156
|
-
throughAssociations.forEach((throughAssociation) => {
|
|
2157
|
-
if (throughAssociation.type === 'HasMany') {
|
|
2158
|
-
if (query?.distinctOn && throughAssociation.distinct) {
|
|
2159
|
-
query = query.distinctOn(this.distinctColumnNameForAssociation({
|
|
2160
|
-
association: throughAssociation,
|
|
2161
|
-
tableNameOrAlias: currentAssociationTableOrAlias,
|
|
2162
|
-
foreignKey: throughAssociation.primaryKey(),
|
|
2163
|
-
}));
|
|
2164
|
-
}
|
|
2165
|
-
if (throughAssociation.order) {
|
|
2166
|
-
query = this.applyOrderStatementForAssociation({
|
|
2167
|
-
query,
|
|
2168
|
-
association: throughAssociation,
|
|
2169
|
-
tableNameOrAlias: currentAssociationTableOrAlias,
|
|
2170
|
-
});
|
|
2171
|
-
}
|
|
2172
|
-
}
|
|
2173
|
-
});
|
|
2174
|
-
}
|
|
2175
|
-
if (association.type === 'BelongsTo') {
|
|
2176
|
-
if (Array.isArray(association.modelCB()))
|
|
2177
|
-
throw new CannotJoinPolymorphicBelongsToError_js_1.default({
|
|
2178
|
-
dreamClass,
|
|
2179
|
-
association,
|
|
2180
|
-
innerJoinStatements: this.innerJoinStatements,
|
|
2181
|
-
leftJoinStatements: this.leftJoinStatements,
|
|
2182
|
-
});
|
|
2183
|
-
const to = association.modelCB().table;
|
|
2184
|
-
const joinTableExpression = currentAssociationTableOrAlias === to
|
|
2185
|
-
? currentAssociationTableOrAlias
|
|
2186
|
-
: `${to} as ${currentAssociationTableOrAlias}`;
|
|
2187
|
-
query = query[(joinType === 'inner' ? 'innerJoin' : 'leftJoin')](joinTableExpression, (join) => {
|
|
2188
|
-
join = join.onRef(this.namespaceColumn(association.foreignKey(), previousAssociationTableOrAlias), '=', this.namespaceColumn(association.primaryKey(), currentAssociationTableOrAlias));
|
|
2189
|
-
if (timeToApplyThroughAssociations) {
|
|
2190
|
-
throughAssociations.forEach((throughAssociation) => {
|
|
2191
|
-
join = this.applyAssociationAndStatementsToJoinStatement({
|
|
2192
|
-
join,
|
|
2193
|
-
association: throughAssociation,
|
|
2194
|
-
currentAssociationTableOrAlias,
|
|
2195
|
-
previousAssociationTableOrAlias: originalPreviousAssociationTableOrAlias,
|
|
2196
|
-
joinAndStatements,
|
|
2197
|
-
});
|
|
2198
|
-
});
|
|
2199
|
-
}
|
|
2200
|
-
join = this.conditionallyApplyDefaultScopesDependentOnAssociation({
|
|
2201
|
-
join,
|
|
2202
|
-
tableNameOrAlias: currentAssociationTableOrAlias,
|
|
2203
|
-
association,
|
|
2204
|
-
});
|
|
2205
|
-
join = this.applyJoinAndStatement(join, joinAndStatement, currentAssociationTableOrAlias);
|
|
2206
|
-
return join;
|
|
2207
|
-
});
|
|
2208
|
-
}
|
|
2209
|
-
else {
|
|
2210
|
-
const to = association.modelCB().table;
|
|
2211
|
-
const joinTableExpression = currentAssociationTableOrAlias === to
|
|
2212
|
-
? currentAssociationTableOrAlias
|
|
2213
|
-
: `${to} as ${currentAssociationTableOrAlias}`;
|
|
2214
|
-
query = query[(joinType === 'inner' ? 'innerJoin' : 'leftJoin')](joinTableExpression, (join) => {
|
|
2215
|
-
join = join.onRef(this.namespaceColumn(association.primaryKey(), previousAssociationTableOrAlias), '=', this.namespaceColumn(association.foreignKey(), currentAssociationTableOrAlias));
|
|
2216
|
-
if (association.polymorphic) {
|
|
2217
|
-
join = join.on((eb) => this.whereStatementToExpressionWrapper(eb, this.aliasWhereStatement({
|
|
2218
|
-
[association.foreignKeyTypeField()]: throughClass
|
|
2219
|
-
? throughClass['stiBaseClassOrOwnClassName']
|
|
2220
|
-
: dreamClass['stiBaseClassOrOwnClassName'],
|
|
2221
|
-
}, currentAssociationTableOrAlias)));
|
|
2222
|
-
}
|
|
2223
|
-
if (timeToApplyThroughAssociations) {
|
|
2224
|
-
throughAssociations.forEach((throughAssociation) => {
|
|
2225
|
-
join = this.applyAssociationAndStatementsToJoinStatement({
|
|
2226
|
-
join,
|
|
2227
|
-
association: throughAssociation,
|
|
2228
|
-
currentAssociationTableOrAlias,
|
|
2229
|
-
previousAssociationTableOrAlias: originalPreviousAssociationTableOrAlias,
|
|
2230
|
-
joinAndStatements,
|
|
2231
|
-
});
|
|
2232
|
-
});
|
|
2233
|
-
}
|
|
2234
|
-
join = this.applyAssociationAndStatementsToJoinStatement({
|
|
2235
|
-
join,
|
|
2236
|
-
association,
|
|
2237
|
-
currentAssociationTableOrAlias,
|
|
2238
|
-
previousAssociationTableOrAlias,
|
|
2239
|
-
joinAndStatements,
|
|
2240
|
-
});
|
|
2241
|
-
join = this.conditionallyApplyDefaultScopesDependentOnAssociation({
|
|
2242
|
-
join,
|
|
2243
|
-
tableNameOrAlias: currentAssociationTableOrAlias,
|
|
2244
|
-
association,
|
|
2245
|
-
});
|
|
2246
|
-
join = this.applyJoinAndStatement(join, joinAndStatement, currentAssociationTableOrAlias);
|
|
2247
|
-
return join;
|
|
2248
|
-
});
|
|
2249
|
-
if (association.type === 'HasMany') {
|
|
2250
|
-
if (association.order) {
|
|
2251
|
-
query = this.applyOrderStatementForAssociation({
|
|
2252
|
-
query,
|
|
2253
|
-
tableNameOrAlias: currentAssociationTableOrAlias,
|
|
2254
|
-
association,
|
|
2255
|
-
});
|
|
2256
|
-
}
|
|
2257
|
-
if (query.distinctOn && association.distinct) {
|
|
2258
|
-
query = query.distinctOn(this.distinctColumnNameForAssociation({
|
|
2259
|
-
association,
|
|
2260
|
-
tableNameOrAlias: currentAssociationTableOrAlias,
|
|
2261
|
-
foreignKey: association.foreignKey(),
|
|
2262
|
-
}));
|
|
2263
|
-
}
|
|
2264
|
-
}
|
|
2265
|
-
}
|
|
2266
|
-
return {
|
|
2267
|
-
query,
|
|
2268
|
-
association,
|
|
2269
|
-
previousAssociationTableOrAlias,
|
|
2270
|
-
currentAssociationTableOrAlias,
|
|
2271
|
-
};
|
|
2272
|
-
}
|
|
2273
|
-
applyAssociationAndStatementsToJoinStatement({ join, currentAssociationTableOrAlias, previousAssociationTableOrAlias, association, joinAndStatements, }) {
|
|
2274
|
-
if (association.and) {
|
|
2275
|
-
this.throwUnlessAllRequiredWhereClausesProvided(association, currentAssociationTableOrAlias, joinAndStatements);
|
|
2276
|
-
join = join.on((eb) => this.whereStatementToExpressionWrapper(eb, this.aliasWhereStatement(association.and, currentAssociationTableOrAlias), { disallowSimilarityOperator: false }));
|
|
2277
|
-
}
|
|
2278
|
-
if (association.andNot) {
|
|
2279
|
-
join = join.on((eb) => this.whereStatementToExpressionWrapper(eb, this.aliasWhereStatement(association.andNot, currentAssociationTableOrAlias), { negate: true }));
|
|
2280
|
-
}
|
|
2281
|
-
if (association.andAny) {
|
|
2282
|
-
join = join.on((eb) => eb.or(association.andAny.map(whereAnyStatement => this.whereStatementToExpressionWrapper(eb, this.aliasWhereStatement(whereAnyStatement, currentAssociationTableOrAlias), { disallowSimilarityOperator: false }))));
|
|
2283
|
-
}
|
|
2284
|
-
if (association.selfAnd) {
|
|
2285
|
-
join = join.on((eb) => this.whereStatementToExpressionWrapper(eb, this.rawifiedSelfOnClause({
|
|
2286
|
-
associationAlias: association.as,
|
|
2287
|
-
selfAlias: previousAssociationTableOrAlias,
|
|
2288
|
-
selfAndClause: association.selfAnd,
|
|
2289
|
-
})));
|
|
2290
|
-
}
|
|
2291
|
-
if (association.selfAndNot) {
|
|
2292
|
-
join = join.on((eb) => this.whereStatementToExpressionWrapper(eb, this.rawifiedSelfOnClause({
|
|
2293
|
-
associationAlias: association.as,
|
|
2294
|
-
selfAlias: previousAssociationTableOrAlias,
|
|
2295
|
-
selfAndClause: association.selfAndNot,
|
|
2296
|
-
}), { negate: true }));
|
|
2297
|
-
}
|
|
2298
|
-
return join;
|
|
2299
|
-
}
|
|
2300
|
-
conditionallyApplyDefaultScopesDependentOnAssociation({ join, tableNameOrAlias, association, }) {
|
|
2301
|
-
let scopesQuery = new Query(this.dreamInstance);
|
|
2302
|
-
const associationClass = association.modelCB();
|
|
2303
|
-
const associationScopes = associationClass['scopes'].default;
|
|
2304
|
-
for (const scope of associationScopes) {
|
|
2305
|
-
if (!(0, shouldBypassDefaultScope_js_1.default)(scope.method, {
|
|
2306
|
-
bypassAllDefaultScopes: this.bypassAllDefaultScopes,
|
|
2307
|
-
defaultScopesToBypass: [...this.defaultScopesToBypass, ...(association.withoutDefaultScopes || [])],
|
|
2308
|
-
})) {
|
|
2309
|
-
const tempQuery = associationClass[scope.method](scopesQuery);
|
|
2310
|
-
// The scope method on a Dream model should return a clone of the Query it receives
|
|
2311
|
-
// (e.g. by returning `scope.where(...)`), but in case the function doesn't return,
|
|
2312
|
-
// or returns the wrong thing, we check before overriding `scopesQuery` with what the
|
|
2313
|
-
// method returned.
|
|
2314
|
-
if (tempQuery && tempQuery.constructor === scopesQuery.constructor)
|
|
2315
|
-
scopesQuery = tempQuery;
|
|
2316
|
-
}
|
|
2317
|
-
}
|
|
2318
|
-
if (scopesQuery.whereStatements.length) {
|
|
2319
|
-
join = join.on((eb) => eb.and(scopesQuery.whereStatements.flatMap(whereStatement => this.whereStatementToExpressionWrapper(eb, this.aliasWhereStatement(whereStatement, tableNameOrAlias), { disallowSimilarityOperator: false }))));
|
|
2320
|
-
}
|
|
2321
|
-
return join;
|
|
2322
|
-
}
|
|
2323
|
-
distinctColumnNameForAssociation({ association, tableNameOrAlias, foreignKey, }) {
|
|
2324
|
-
if (!association.distinct)
|
|
2325
|
-
return null;
|
|
2326
|
-
if (association.distinct === true)
|
|
2327
|
-
return this.namespaceColumn(foreignKey, tableNameOrAlias);
|
|
2328
|
-
return this.namespaceColumn(association.distinct, tableNameOrAlias);
|
|
2329
|
-
}
|
|
2330
|
-
recursivelyJoin({ query, joinStatement, joinAndStatements, dreamClass, previousAssociationTableOrAlias, joinType, }) {
|
|
2331
|
-
for (const currentAssociationTableOrAlias of Object.keys(joinStatement)) {
|
|
2332
|
-
const results = this.applyOneJoin({
|
|
2333
|
-
query,
|
|
2334
|
-
dreamClass,
|
|
2335
|
-
previousAssociationTableOrAlias,
|
|
2336
|
-
currentAssociationTableOrAlias,
|
|
2337
|
-
joinAndStatements,
|
|
2338
|
-
joinType,
|
|
2339
|
-
});
|
|
2340
|
-
query = results.query;
|
|
2341
|
-
const association = results.association;
|
|
2342
|
-
query = this.recursivelyJoin({
|
|
2343
|
-
query,
|
|
2344
|
-
joinStatement: joinStatement[currentAssociationTableOrAlias],
|
|
2345
|
-
joinAndStatements: joinAndStatements[currentAssociationTableOrAlias],
|
|
2346
|
-
dreamClass: association.modelCB(),
|
|
2347
|
-
previousAssociationTableOrAlias: currentAssociationTableOrAlias,
|
|
2348
|
-
joinType,
|
|
2349
|
-
});
|
|
2350
|
-
}
|
|
2351
|
-
return query;
|
|
2352
|
-
}
|
|
2353
|
-
throwUnlessAllRequiredWhereClausesProvided(association, namespace, joinAndStatements) {
|
|
2354
|
-
const andClause = association.and;
|
|
2355
|
-
const columnsRequiringAndStatements = Object.keys(andClause).reduce((agg, column) => {
|
|
2356
|
-
if (andClause[column] === constants_js_1.DreamConst.required)
|
|
2357
|
-
agg.push(column);
|
|
2358
|
-
return agg;
|
|
2359
|
-
}, []);
|
|
2360
|
-
const missingRequiredWhereStatements = columnsRequiringAndStatements.filter(column => joinAndStatements[namespace]?.and?.[column] === undefined);
|
|
2361
|
-
if (missingRequiredWhereStatements.length)
|
|
2362
|
-
throw new MissingRequiredAssociationAndClause_js_1.default(association, missingRequiredWhereStatements[0]);
|
|
2363
|
-
}
|
|
2364
|
-
applyOrderStatementForAssociation({ query, tableNameOrAlias, association, }) {
|
|
2365
|
-
if (!query.orderBy)
|
|
2366
|
-
return query;
|
|
2367
|
-
let selectQuery = query;
|
|
2368
|
-
const orderStatement = association.order;
|
|
2369
|
-
if (typeof orderStatement === 'string') {
|
|
2370
|
-
selectQuery = selectQuery.orderBy(this.namespaceColumn(orderStatement, tableNameOrAlias), 'asc');
|
|
2371
|
-
}
|
|
2372
|
-
else {
|
|
2373
|
-
Object.keys(orderStatement).forEach(column => {
|
|
2374
|
-
const direction = orderStatement[column];
|
|
2375
|
-
selectQuery = selectQuery.orderBy(this.namespaceColumn(column, tableNameOrAlias), direction);
|
|
2376
|
-
});
|
|
2377
|
-
}
|
|
2378
|
-
return selectQuery;
|
|
2379
|
-
}
|
|
2380
|
-
inArrayWithNull_or_notInArrayWithoutNull_ExpressionBuilder(eb, a, b, c) {
|
|
2381
|
-
const isNullStatement = eb(a, 'is', null);
|
|
2382
|
-
const compactedC = (0, compact_js_1.default)(c);
|
|
2383
|
-
if (compactedC.length)
|
|
2384
|
-
return eb.or([eb(a, b, compactedC), isNullStatement]);
|
|
2385
|
-
// not in an empty array means match everything
|
|
2386
|
-
if (b === 'not in')
|
|
2387
|
-
return (0, kysely_1.sql) `TRUE`;
|
|
2388
|
-
return isNullStatement;
|
|
2389
|
-
}
|
|
2390
|
-
inArrayWithoutNullExpressionBuilder(eb, a, b, c) {
|
|
2391
|
-
const isNotNullStatement = eb(a, 'is not', null);
|
|
2392
|
-
const compactedC = (0, compact_js_1.default)(c);
|
|
2393
|
-
if (compactedC.length)
|
|
2394
|
-
return eb.and([eb(a, 'in', compactedC), isNotNullStatement]);
|
|
2395
|
-
// in an empty array means match nothing
|
|
2396
|
-
return (0, kysely_1.sql) `FALSE`;
|
|
2397
|
-
}
|
|
2398
|
-
notInArrayWithNullExpressionBuilder(eb, a, b, c) {
|
|
2399
|
-
const isNullStatement = eb(a, 'is not', null);
|
|
2400
|
-
const compactedC = (0, compact_js_1.default)(c);
|
|
2401
|
-
if (compactedC.length)
|
|
2402
|
-
return eb.and([eb(a, 'not in', compactedC), isNullStatement]);
|
|
2403
|
-
return isNullStatement;
|
|
2404
|
-
}
|
|
2405
|
-
whereStatementToExpressionWrapper(eb, whereStatement, { negate = false, disallowSimilarityOperator = true, } = {}) {
|
|
2406
|
-
const clauses = (0, compact_js_1.default)(Object.keys(whereStatement)
|
|
2407
|
-
.filter(key => whereStatement[key] !== constants_js_1.DreamConst.required)
|
|
2408
|
-
.map(attr => {
|
|
2409
|
-
const val = whereStatement[attr];
|
|
2410
|
-
if (val?.isOpsStatement &&
|
|
2411
|
-
val.shouldBypassWhereStatement) {
|
|
2412
|
-
if (disallowSimilarityOperator)
|
|
2413
|
-
throw new Error('Similarity operator may not be used in whereAny');
|
|
2414
|
-
// some ops statements are handled specifically in the select portion of the query,
|
|
2415
|
-
// and should be ommited from the where clause directly
|
|
2416
|
-
return;
|
|
2417
|
-
}
|
|
2418
|
-
const { a, b, c, a2, b2, c2 } = this.dreamWhereStatementToExpressionBuilderParts(attr, val);
|
|
2419
|
-
// postgres is unable to handle WHERE IN statements with blank arrays, such as in
|
|
2420
|
-
// "WHERE id IN ()", meaning that:
|
|
2421
|
-
// 1. If we receive a blank array during an IN comparison,
|
|
2422
|
-
// then we need to simply regurgitate a where statement which
|
|
2423
|
-
// guarantees no records.
|
|
2424
|
-
// 2. If we receive a blank array during a NOT IN comparison,
|
|
2425
|
-
// then it is the same as the where statement not being present at all,
|
|
2426
|
-
// resulting in a noop on our end
|
|
2427
|
-
//
|
|
2428
|
-
if (Array.isArray(c)) {
|
|
2429
|
-
if ((b === 'in' && c.includes(null)) || (b === 'not in' && !c.includes(null))) {
|
|
2430
|
-
return this.inArrayWithNull_or_notInArrayWithoutNull_ExpressionBuilder(eb, a, b, c);
|
|
2431
|
-
}
|
|
2432
|
-
else if (negate && b === 'in' && !c.includes(null)) {
|
|
2433
|
-
return this.inArrayWithoutNullExpressionBuilder(eb, a, b, c);
|
|
2434
|
-
}
|
|
2435
|
-
else if (b === 'not in' && c.includes(null)) {
|
|
2436
|
-
return this.notInArrayWithNullExpressionBuilder(eb, a, b, c);
|
|
2437
|
-
}
|
|
2438
|
-
const compactedC = (0, compact_js_1.default)(c);
|
|
2439
|
-
if (b === 'in' && compactedC.length === 0) {
|
|
2440
|
-
// in an empty array means match nothing
|
|
2441
|
-
return (0, kysely_1.sql) `FALSE`;
|
|
2442
|
-
}
|
|
2443
|
-
else if (b === 'not in' && compactedC.length === 0) {
|
|
2444
|
-
// not in an empty array means match everything
|
|
2445
|
-
return (0, kysely_1.sql) `TRUE`;
|
|
2446
|
-
}
|
|
2447
|
-
else {
|
|
2448
|
-
return eb(a, b, compactedC);
|
|
2449
|
-
}
|
|
2450
|
-
//
|
|
2451
|
-
}
|
|
2452
|
-
else if (b === '=' && c === null) {
|
|
2453
|
-
return eb(a, 'is', null);
|
|
2454
|
-
//
|
|
2455
|
-
}
|
|
2456
|
-
else if (b === '!=' && c === null) {
|
|
2457
|
-
return eb(a, 'is not', null);
|
|
2458
|
-
//
|
|
2459
|
-
}
|
|
2460
|
-
else if (b === '=' && negate) {
|
|
2461
|
-
return eb.and([eb(a, '=', c), eb(a, 'is not', null)]);
|
|
2462
|
-
//
|
|
2463
|
-
}
|
|
2464
|
-
else if (b === '!=' && c !== null) {
|
|
2465
|
-
return eb.or([eb(a, '!=', c), eb(a, 'is', null)]);
|
|
2466
|
-
//
|
|
2467
|
-
}
|
|
2468
|
-
else {
|
|
2469
|
-
const expression = eb(a, b, c);
|
|
2470
|
-
if (b2)
|
|
2471
|
-
return expression.and(eb(a2, b2, c2));
|
|
2472
|
-
return expression;
|
|
2473
|
-
}
|
|
2474
|
-
}));
|
|
2475
|
-
return negate ? eb.not(eb.parens(eb.and(clauses))) : eb.and(clauses);
|
|
2476
|
-
}
|
|
2477
|
-
dreamWhereStatementToExpressionBuilderParts(attr, val) {
|
|
2478
|
-
let a;
|
|
2479
|
-
let b;
|
|
2480
|
-
let c;
|
|
2481
|
-
let a2 = null;
|
|
2482
|
-
let b2 = null;
|
|
2483
|
-
let c2 = null;
|
|
2484
|
-
if (val instanceof Function && val !== constants_js_1.DreamConst.passthrough) {
|
|
2485
|
-
val = val();
|
|
2486
|
-
}
|
|
2487
|
-
else if (val === constants_js_1.DreamConst.passthrough) {
|
|
2488
|
-
const column = attr.split('.').at(-1);
|
|
2489
|
-
if (this.passthroughOnStatement[column] === undefined)
|
|
2490
|
-
throw new MissingRequiredPassthroughForAssociationAndClause_js_1.default(column);
|
|
2491
|
-
val = this.passthroughOnStatement[column];
|
|
2492
|
-
}
|
|
2493
|
-
if (val === null) {
|
|
2494
|
-
a = attr;
|
|
2495
|
-
b = 'is';
|
|
2496
|
-
c = val;
|
|
2497
|
-
}
|
|
2498
|
-
else if (['SelectQueryBuilder', 'SelectQueryBuilderImpl'].includes(val?.constructor?.name)) {
|
|
2499
|
-
a = attr;
|
|
2500
|
-
b = 'in';
|
|
2501
|
-
c = val;
|
|
2502
|
-
}
|
|
2503
|
-
else if (Array.isArray(val)) {
|
|
2504
|
-
a = attr;
|
|
2505
|
-
b = 'in';
|
|
2506
|
-
c = val.map(v => v instanceof DateTime_js_1.DateTime || v instanceof CalendarDate_js_1.default
|
|
2507
|
-
? v.toSQL()
|
|
2508
|
-
: typeof v === 'string'
|
|
2509
|
-
? (0, normalizeUnicode_js_1.default)(v)
|
|
2510
|
-
: v);
|
|
2511
|
-
}
|
|
2512
|
-
else if (val instanceof curried_ops_statement_js_1.default) {
|
|
2513
|
-
val = val.toOpsStatement(this.dreamClass, attr);
|
|
2514
|
-
a = attr;
|
|
2515
|
-
b = val.operator;
|
|
2516
|
-
c = val.value;
|
|
2517
|
-
}
|
|
2518
|
-
else if (val instanceof ops_statement_js_1.default) {
|
|
2519
|
-
a = attr;
|
|
2520
|
-
b = val.operator;
|
|
2521
|
-
c = val.value;
|
|
2522
|
-
}
|
|
2523
|
-
else if (val instanceof range_js_1.Range) {
|
|
2524
|
-
const rangeStart = val.begin;
|
|
2525
|
-
const rangeEnd = val.end;
|
|
2526
|
-
const excludeEnd = val.excludeEnd;
|
|
2527
|
-
if (rangeStart && rangeEnd) {
|
|
2528
|
-
a = attr;
|
|
2529
|
-
b = '>=';
|
|
2530
|
-
c = rangeStart;
|
|
2531
|
-
a2 = attr;
|
|
2532
|
-
b2 = excludeEnd ? '<' : '<=';
|
|
2533
|
-
c2 = rangeEnd;
|
|
2534
|
-
}
|
|
2535
|
-
else if (rangeStart) {
|
|
2536
|
-
a = attr;
|
|
2537
|
-
b = '>=';
|
|
2538
|
-
c = rangeStart;
|
|
2539
|
-
}
|
|
2540
|
-
else {
|
|
2541
|
-
a = attr;
|
|
2542
|
-
b = excludeEnd ? '<' : '<=';
|
|
2543
|
-
c = rangeEnd;
|
|
2544
|
-
}
|
|
2545
|
-
}
|
|
2546
|
-
else {
|
|
2547
|
-
a = attr;
|
|
2548
|
-
b = '=';
|
|
2549
|
-
c = val;
|
|
2550
|
-
}
|
|
2551
|
-
if (c instanceof DateTime_js_1.DateTime || c instanceof CalendarDate_js_1.default)
|
|
2552
|
-
c = c.toSQL();
|
|
2553
|
-
else if (typeof c === 'string')
|
|
2554
|
-
c = (0, normalizeUnicode_js_1.default)(c);
|
|
2555
|
-
if (c2 instanceof DateTime_js_1.DateTime || c2 instanceof CalendarDate_js_1.default)
|
|
2556
|
-
c2 = c2.toSQL();
|
|
2557
|
-
else if (typeof c2 === 'string')
|
|
2558
|
-
c2 = (0, normalizeUnicode_js_1.default)(c2);
|
|
2559
|
-
if (a && c === undefined)
|
|
2560
|
-
throw new CannotPassUndefinedAsAValueToAWhereClause_js_1.default(this.dreamClass, a);
|
|
2561
|
-
if (a2 && c2 === undefined)
|
|
2562
|
-
throw new CannotPassUndefinedAsAValueToAWhereClause_js_1.default(this.dreamClass, a2);
|
|
2563
|
-
return { a, b, c, a2, b2, c2 };
|
|
2564
|
-
}
|
|
2565
|
-
applyJoinAndStatement(join, joinAndStatement, rootTableOrAssociationAlias) {
|
|
2566
|
-
if (!joinAndStatement)
|
|
2567
|
-
return join;
|
|
2568
|
-
join = this._applyJoinAndStatements(join, joinAndStatement.and, rootTableOrAssociationAlias);
|
|
2569
|
-
join = this._applyJoinAndStatements(join, joinAndStatement.andNot, rootTableOrAssociationAlias, {
|
|
2570
|
-
negate: true,
|
|
2571
|
-
});
|
|
2572
|
-
join = this._applyJoinAndAnyStatements(join, joinAndStatement.andAny, rootTableOrAssociationAlias);
|
|
2573
|
-
return join;
|
|
2574
|
-
}
|
|
2575
|
-
_applyJoinAndStatements(join, joinAndStatement, rootTableOrAssociationAlias, { negate = false, } = {}) {
|
|
2576
|
-
if (!joinAndStatement)
|
|
2577
|
-
return join;
|
|
2578
|
-
return join.on((eb) => this.joinAndStatementToExpressionWrapper(joinAndStatement, rootTableOrAssociationAlias, eb, {
|
|
2579
|
-
negate,
|
|
2580
|
-
disallowSimilarityOperator: negate,
|
|
2581
|
-
}));
|
|
2582
|
-
}
|
|
2583
|
-
_applyJoinAndAnyStatements(join, joinAndAnyStatement, rootTableOrAssociationAlias) {
|
|
2584
|
-
if (!joinAndAnyStatement)
|
|
2585
|
-
return join;
|
|
2586
|
-
if (!joinAndAnyStatement.length)
|
|
2587
|
-
return join;
|
|
2588
|
-
return join.on((eb) => {
|
|
2589
|
-
return eb.or(joinAndAnyStatement.map(joinAndStatement => this.joinAndStatementToExpressionWrapper(joinAndStatement, rootTableOrAssociationAlias, eb)));
|
|
2590
|
-
});
|
|
2591
|
-
}
|
|
2592
|
-
joinAndStatementToExpressionWrapper(joinAndStatement, rootTableOrAssociationAlias, eb, { negate = false, disallowSimilarityOperator = true, } = {}) {
|
|
2593
|
-
return this.whereStatementToExpressionWrapper(eb, Object.keys(joinAndStatement).reduce((agg, key) => {
|
|
2594
|
-
agg[this.namespaceColumn(key.toString(), rootTableOrAssociationAlias)] = joinAndStatement[key];
|
|
2595
|
-
return agg;
|
|
2596
|
-
}, {}), {
|
|
2597
|
-
negate,
|
|
2598
|
-
disallowSimilarityOperator,
|
|
2599
|
-
});
|
|
2600
|
-
}
|
|
2601
|
-
buildCommon(kyselyQuery) {
|
|
2602
|
-
this.checkForQueryViolations();
|
|
2603
|
-
const query = this.conditionallyApplyDefaultScopes();
|
|
2604
|
-
if (!(0, isEmpty_js_1.default)(query.innerJoinStatements)) {
|
|
2605
|
-
kyselyQuery = query.recursivelyJoin({
|
|
2606
|
-
query: kyselyQuery,
|
|
2607
|
-
joinStatement: query.innerJoinStatements,
|
|
2608
|
-
joinAndStatements: query.innerJoinAndStatements,
|
|
2609
|
-
dreamClass: query.dreamClass,
|
|
2610
|
-
previousAssociationTableOrAlias: this.baseSqlAlias,
|
|
2611
|
-
joinType: 'inner',
|
|
2612
|
-
});
|
|
2613
|
-
}
|
|
2614
|
-
if (!(0, isEmpty_js_1.default)(query.leftJoinStatements)) {
|
|
2615
|
-
kyselyQuery = query.recursivelyJoin({
|
|
2616
|
-
query: kyselyQuery,
|
|
2617
|
-
joinStatement: query.leftJoinStatements,
|
|
2618
|
-
joinAndStatements: query.leftJoinAndStatements,
|
|
2619
|
-
dreamClass: query.dreamClass,
|
|
2620
|
-
previousAssociationTableOrAlias: this.baseSqlAlias,
|
|
2621
|
-
joinType: 'left',
|
|
2622
|
-
});
|
|
2623
|
-
}
|
|
2624
|
-
if (query.whereStatements.length || query.whereNotStatements.length || query.whereAnyStatements.length) {
|
|
2625
|
-
kyselyQuery = kyselyQuery.where((eb) => eb.and([
|
|
2626
|
-
...this.aliasWhereStatements(query.whereStatements, query.baseSqlAlias).map(whereStatement => this.whereStatementToExpressionWrapper(eb, whereStatement, {
|
|
2627
|
-
disallowSimilarityOperator: false,
|
|
2628
|
-
})),
|
|
2629
|
-
...this.aliasWhereStatements(query.whereNotStatements, query.baseSqlAlias).map(whereNotStatement => this.whereStatementToExpressionWrapper(eb, whereNotStatement, { negate: true })),
|
|
2630
|
-
...query.whereAnyStatements.map(whereAnyStatements => eb.or(this.aliasWhereStatements(whereAnyStatements, query.baseSqlAlias).map(whereAnyStatement => this.whereStatementToExpressionWrapper(eb, whereAnyStatement)))),
|
|
2631
|
-
]));
|
|
2632
|
-
}
|
|
2633
|
-
return kyselyQuery;
|
|
2634
|
-
}
|
|
2635
|
-
checkForQueryViolations() {
|
|
2636
|
-
const invalidWhereNotClauses = this.similarityStatementBuilder().whereNotStatementsWithSimilarityClauses();
|
|
2637
|
-
if (invalidWhereNotClauses.length) {
|
|
2638
|
-
const invalidWhereNotClause = invalidWhereNotClauses[0];
|
|
2639
|
-
if (invalidWhereNotClause === undefined)
|
|
2640
|
-
throw new UnexpectedUndefined_js_1.default();
|
|
2641
|
-
const { tableName, columnName, opsStatement } = invalidWhereNotClause;
|
|
2642
|
-
throw new CannotNegateSimilarityClause_js_1.default(tableName, columnName, opsStatement.value);
|
|
2643
|
-
}
|
|
2644
|
-
}
|
|
2645
|
-
aliasWhereStatements(whereStatements, alias) {
|
|
2646
|
-
return whereStatements.map(whereStatement => this.aliasWhereStatement(whereStatement, alias));
|
|
2647
|
-
}
|
|
2648
|
-
aliasWhereStatement(whereStatement, alias) {
|
|
2649
|
-
return Object.keys(whereStatement).reduce((aliasedWhere, key) => {
|
|
2650
|
-
aliasedWhere[this.namespaceColumn(key, alias)] = whereStatement[key];
|
|
2651
|
-
return aliasedWhere;
|
|
2652
|
-
}, {});
|
|
2653
|
-
}
|
|
2654
|
-
rawifiedSelfOnClause({ associationAlias, selfAlias, selfAndClause, }) {
|
|
2655
|
-
const alphanumericUnderscoreRegexp = /[^a-zA-Z0-9_]/g;
|
|
2656
|
-
selfAlias = selfAlias.replace(alphanumericUnderscoreRegexp, '');
|
|
2657
|
-
return Object.keys(selfAndClause).reduce((acc, key) => {
|
|
2658
|
-
const selfColumn = selfAndClause[key]?.replace(alphanumericUnderscoreRegexp, '');
|
|
2659
|
-
if (!selfColumn)
|
|
2660
|
-
return acc;
|
|
2661
|
-
acc[this.namespaceColumn(key, associationAlias)] = kysely_1.sql.raw(`"${(0, snakeify_js_1.default)(selfAlias)}"."${(0, snakeify_js_1.default)(selfColumn)}"`);
|
|
2662
|
-
return acc;
|
|
2663
|
-
}, {});
|
|
2664
|
-
}
|
|
2665
|
-
buildDelete() {
|
|
2666
|
-
const kyselyQuery = this.dbFor('delete').deleteFrom(this.baseSqlAlias);
|
|
2667
|
-
const results = this.attachLimitAndOrderStatementsToNonSelectQuery(kyselyQuery);
|
|
2668
|
-
return results.clone.buildCommon(results.kyselyQuery);
|
|
2669
|
-
}
|
|
2670
|
-
buildSelect({ bypassSelectAll = false, bypassOrder = false, columns, } = {}) {
|
|
2671
|
-
let kyselyQuery;
|
|
2672
|
-
if (this.baseSelectQuery) {
|
|
2673
|
-
kyselyQuery = (this.connectionOverride
|
|
2674
|
-
? this.baseSelectQuery.connection(this.connectionOverride)
|
|
2675
|
-
: this.baseSelectQuery).buildSelect({ bypassSelectAll: true });
|
|
2676
|
-
}
|
|
2677
|
-
else {
|
|
2678
|
-
const from = this.baseSqlAlias === this.tableName ? this.tableName : `${this.tableName} as ${this.baseSqlAlias}`;
|
|
2679
|
-
kyselyQuery = this.dbFor('select').selectFrom(from);
|
|
2680
|
-
}
|
|
2681
|
-
if (this.distinctColumn) {
|
|
2682
|
-
kyselyQuery = kyselyQuery.distinctOn(this.distinctColumn);
|
|
2683
|
-
}
|
|
2684
|
-
kyselyQuery = this.buildCommon(kyselyQuery);
|
|
2685
|
-
kyselyQuery = this.conditionallyAttachSimilarityColumnsToSelect(kyselyQuery, {
|
|
2686
|
-
bypassOrder: bypassOrder || !!this.distinctColumn,
|
|
2687
|
-
});
|
|
2688
|
-
if (this.orderStatements.length && !bypassOrder) {
|
|
2689
|
-
this.orderStatements.forEach(orderStatement => {
|
|
2690
|
-
kyselyQuery = kyselyQuery.orderBy(this.namespaceColumn(orderStatement.column), (0, orderByDirection_js_1.default)(orderStatement.direction));
|
|
2691
|
-
});
|
|
2692
|
-
}
|
|
2693
|
-
if (this.limitStatement)
|
|
2694
|
-
kyselyQuery = kyselyQuery.limit(this.limitStatement);
|
|
2695
|
-
if (this.offsetStatement)
|
|
2696
|
-
kyselyQuery = kyselyQuery.offset(this.offsetStatement);
|
|
2697
|
-
if (columns) {
|
|
2698
|
-
kyselyQuery = kyselyQuery.select(this.columnsWithRequiredLoadColumns(columns).map(column => this.namespaceColumn(column)));
|
|
2699
|
-
}
|
|
2700
|
-
else if (!bypassSelectAll) {
|
|
2701
|
-
kyselyQuery = kyselyQuery.selectAll(this.baseSqlAlias);
|
|
2702
|
-
}
|
|
2703
|
-
// even though we manually bypass explicit order statements above,
|
|
2704
|
-
// associations can contain their own ordering systems. If we do not
|
|
2705
|
-
// escape all orders, we can mistakenly allow an order clause to sneak in.
|
|
2706
|
-
if (bypassOrder)
|
|
2707
|
-
kyselyQuery = kyselyQuery.clearOrderBy();
|
|
2708
|
-
return kyselyQuery;
|
|
2709
|
-
}
|
|
2710
|
-
columnsWithRequiredLoadColumns(columns) {
|
|
2711
|
-
return (0, uniq_js_1.default)((0, compact_js_1.default)([this.dreamClass.primaryKey, this.dreamClass['isSTIBase'] ? 'type' : null, ...columns]));
|
|
2712
|
-
}
|
|
2713
|
-
buildUpdate(attributes) {
|
|
2714
|
-
let kyselyQuery = this.dbFor('update')
|
|
2715
|
-
.updateTable(this.tableName)
|
|
2716
|
-
.set(attributes);
|
|
2717
|
-
kyselyQuery = this.conditionallyAttachSimilarityColumnsToUpdate(kyselyQuery);
|
|
2718
|
-
const results = this.attachLimitAndOrderStatementsToNonSelectQuery(kyselyQuery);
|
|
2719
|
-
return results.clone.buildCommon(results.kyselyQuery);
|
|
2720
|
-
}
|
|
2721
|
-
attachLimitAndOrderStatementsToNonSelectQuery(kyselyQuery) {
|
|
2722
|
-
if (this.limitStatement || this.orderStatements.length) {
|
|
2723
|
-
kyselyQuery = kyselyQuery.where((eb) => {
|
|
2724
|
-
const subquery = this.nestedSelect(this.dreamInstance.primaryKey);
|
|
2725
|
-
return eb(this.dreamInstance.primaryKey, 'in', subquery);
|
|
2726
|
-
});
|
|
2727
|
-
return {
|
|
2728
|
-
kyselyQuery,
|
|
2729
|
-
clone: this.clone({ where: null, whereNot: null, order: null, limit: null }),
|
|
2730
|
-
};
|
|
2731
|
-
}
|
|
2732
|
-
return { kyselyQuery, clone: this };
|
|
2733
|
-
}
|
|
2734
|
-
get hasSimilarityClauses() {
|
|
2735
|
-
return this.similarityStatementBuilder().hasSimilarityClauses;
|
|
2736
|
-
}
|
|
2737
|
-
similarityStatementBuilder() {
|
|
2738
|
-
return new SimilarityBuilder_js_1.default(this.dreamInstance, {
|
|
2739
|
-
where: [...this.whereStatements],
|
|
2740
|
-
whereNot: [...this.whereNotStatements],
|
|
2741
|
-
joinAndStatements: this.innerJoinAndStatements,
|
|
2742
|
-
transaction: this.dreamTransaction,
|
|
2743
|
-
connection: this.connectionOverride,
|
|
2744
|
-
});
|
|
2745
|
-
}
|
|
2746
|
-
conditionallyAttachSimilarityColumnsToSelect(kyselyQuery, { bypassOrder = false } = {}) {
|
|
2747
|
-
const similarityBuilder = this.similarityStatementBuilder();
|
|
2748
|
-
if (similarityBuilder.hasSimilarityClauses) {
|
|
2749
|
-
kyselyQuery = similarityBuilder.select(kyselyQuery, { bypassOrder });
|
|
2750
|
-
}
|
|
2751
|
-
return kyselyQuery;
|
|
2752
|
-
}
|
|
2753
|
-
conditionallyAttachSimilarityColumnsToUpdate(kyselyQuery) {
|
|
2754
|
-
const similarityBuilder = this.similarityStatementBuilder();
|
|
2755
|
-
if (similarityBuilder.hasSimilarityClauses) {
|
|
2756
|
-
kyselyQuery = similarityBuilder.update(kyselyQuery);
|
|
2757
|
-
}
|
|
2758
|
-
return kyselyQuery;
|
|
1395
|
+
return await this.dbDriverInstance().update(attributes);
|
|
2759
1396
|
}
|
|
2760
1397
|
invertOrder() {
|
|
2761
1398
|
let query = this.clone({ order: null });
|
|
@@ -2768,11 +1405,3 @@ class Query extends ConnectedToDB_js_1.default {
|
|
|
2768
1405
|
}
|
|
2769
1406
|
}
|
|
2770
1407
|
exports.default = Query;
|
|
2771
|
-
function getSourceAssociation(dream, sourceName) {
|
|
2772
|
-
if (!dream)
|
|
2773
|
-
return;
|
|
2774
|
-
if (!sourceName)
|
|
2775
|
-
return;
|
|
2776
|
-
return (dream['getAssociationMetadata'](sourceName) ||
|
|
2777
|
-
dream['getAssociationMetadata'](pluralize_esm_1.default.singular(sourceName)));
|
|
2778
|
-
}
|