@strapi/database 5.0.0-beta.8 → 5.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -3
- package/dist/entity-manager/regular-relations.d.ts.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +361 -133
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +361 -133
- package/dist/index.mjs.map +1 -1
- package/dist/migrations/internal-migrations/5.0.0-03-locale.d.ts +3 -0
- package/dist/migrations/internal-migrations/5.0.0-03-locale.d.ts.map +1 -0
- package/dist/migrations/internal-migrations/5.0.0-04-published-at.d.ts +3 -0
- package/dist/migrations/internal-migrations/5.0.0-04-published-at.d.ts.map +1 -0
- package/dist/migrations/internal-migrations/5.0.0-05-drop-slug-unique-index.d.ts +3 -0
- package/dist/migrations/internal-migrations/5.0.0-05-drop-slug-unique-index.d.ts.map +1 -0
- package/dist/migrations/internal-migrations/index.d.ts.map +1 -1
- package/dist/migrations/internal.d.ts.map +1 -1
- package/dist/migrations/logger.d.ts +10 -0
- package/dist/migrations/logger.d.ts.map +1 -0
- package/dist/migrations/users.d.ts.map +1 -1
- package/dist/query/helpers/order-by.d.ts +9 -1
- package/dist/query/helpers/order-by.d.ts.map +1 -1
- package/dist/query/helpers/populate/apply.d.ts.map +1 -1
- package/dist/query/helpers/streams/readable.d.ts +1 -1
- package/dist/query/helpers/where.d.ts.map +1 -1
- package/dist/query/query-builder.d.ts +3 -2
- package/dist/query/query-builder.d.ts.map +1 -1
- package/package.json +7 -6
package/dist/index.js
CHANGED
|
@@ -7,11 +7,11 @@ const _ = require("lodash/fp");
|
|
|
7
7
|
const crypto = require("crypto");
|
|
8
8
|
const crypto$1 = require("node:crypto");
|
|
9
9
|
const dateFns = require("date-fns");
|
|
10
|
-
const
|
|
10
|
+
const node_async_hooks = require("node:async_hooks");
|
|
11
11
|
const KnexBuilder = require("knex/lib/query/querybuilder");
|
|
12
12
|
const KnexRaw = require("knex/lib/raw");
|
|
13
|
+
const utils = require("@strapi/utils");
|
|
13
14
|
const stream = require("stream");
|
|
14
|
-
const node_async_hooks = require("node:async_hooks");
|
|
15
15
|
const _$1 = require("lodash");
|
|
16
16
|
const umzug = require("umzug");
|
|
17
17
|
const cuid2 = require("@paralleldrive/cuid2");
|
|
@@ -1119,7 +1119,7 @@ const createHelpers = (db) => {
|
|
|
1119
1119
|
}
|
|
1120
1120
|
}
|
|
1121
1121
|
};
|
|
1122
|
-
const
|
|
1122
|
+
const dropIndex2 = (tableBuilder, index2) => {
|
|
1123
1123
|
if (!db.config.settings?.forceMigration) {
|
|
1124
1124
|
return;
|
|
1125
1125
|
}
|
|
@@ -1196,13 +1196,13 @@ const createHelpers = (db) => {
|
|
|
1196
1196
|
for (const removedIndex of table.indexes.removed) {
|
|
1197
1197
|
if (!ignoreForeignKeyNames.includes(removedIndex.name)) {
|
|
1198
1198
|
debug$2(`Dropping index ${removedIndex.name} on ${table.name}`);
|
|
1199
|
-
|
|
1199
|
+
dropIndex2(tableBuilder, removedIndex);
|
|
1200
1200
|
}
|
|
1201
1201
|
}
|
|
1202
1202
|
for (const updatedIndex of table.indexes.updated) {
|
|
1203
1203
|
if (!ignoreForeignKeyNames.includes(updatedIndex.name)) {
|
|
1204
1204
|
debug$2(`Dropping updated index ${updatedIndex.name} on ${table.name}`);
|
|
1205
|
-
|
|
1205
|
+
dropIndex2(tableBuilder, updatedIndex.object);
|
|
1206
1206
|
}
|
|
1207
1207
|
}
|
|
1208
1208
|
for (const updatedColumn of table.columns.updated) {
|
|
@@ -2927,6 +2927,68 @@ const createField = (attribute) => {
|
|
|
2927
2927
|
}
|
|
2928
2928
|
throw new Error(`Undefined field for type ${type}`);
|
|
2929
2929
|
};
|
|
2930
|
+
const storage = new node_async_hooks.AsyncLocalStorage();
|
|
2931
|
+
const transactionCtx = {
|
|
2932
|
+
async run(trx, cb) {
|
|
2933
|
+
const store = storage.getStore();
|
|
2934
|
+
return storage.run(
|
|
2935
|
+
{
|
|
2936
|
+
trx,
|
|
2937
|
+
// Fill with existing callbacks if nesting transactions
|
|
2938
|
+
commitCallbacks: store?.commitCallbacks || [],
|
|
2939
|
+
rollbackCallbacks: store?.rollbackCallbacks || []
|
|
2940
|
+
},
|
|
2941
|
+
cb
|
|
2942
|
+
);
|
|
2943
|
+
},
|
|
2944
|
+
get() {
|
|
2945
|
+
const store = storage.getStore();
|
|
2946
|
+
return store?.trx;
|
|
2947
|
+
},
|
|
2948
|
+
async commit(trx) {
|
|
2949
|
+
const store = storage.getStore();
|
|
2950
|
+
if (store?.trx) {
|
|
2951
|
+
store.trx = null;
|
|
2952
|
+
}
|
|
2953
|
+
await trx.commit();
|
|
2954
|
+
if (!store?.commitCallbacks.length) {
|
|
2955
|
+
return;
|
|
2956
|
+
}
|
|
2957
|
+
store.commitCallbacks.forEach((cb) => cb());
|
|
2958
|
+
store.commitCallbacks = [];
|
|
2959
|
+
},
|
|
2960
|
+
async rollback(trx) {
|
|
2961
|
+
const store = storage.getStore();
|
|
2962
|
+
if (store?.trx) {
|
|
2963
|
+
store.trx = null;
|
|
2964
|
+
}
|
|
2965
|
+
await trx.rollback();
|
|
2966
|
+
if (!store?.rollbackCallbacks.length) {
|
|
2967
|
+
return;
|
|
2968
|
+
}
|
|
2969
|
+
store.rollbackCallbacks.forEach((cb) => cb());
|
|
2970
|
+
store.rollbackCallbacks = [];
|
|
2971
|
+
},
|
|
2972
|
+
onCommit(cb) {
|
|
2973
|
+
const store = storage.getStore();
|
|
2974
|
+
if (store?.commitCallbacks) {
|
|
2975
|
+
store.commitCallbacks.push(cb);
|
|
2976
|
+
}
|
|
2977
|
+
},
|
|
2978
|
+
onRollback(cb) {
|
|
2979
|
+
const store = storage.getStore();
|
|
2980
|
+
if (store?.rollbackCallbacks) {
|
|
2981
|
+
store.rollbackCallbacks.push(cb);
|
|
2982
|
+
}
|
|
2983
|
+
}
|
|
2984
|
+
};
|
|
2985
|
+
function isKnexQuery(value) {
|
|
2986
|
+
return value instanceof KnexBuilder__default.default || value instanceof KnexRaw__default.default;
|
|
2987
|
+
}
|
|
2988
|
+
const addSchema = (db, tableName) => {
|
|
2989
|
+
const schemaName = db.getSchemaName();
|
|
2990
|
+
return schemaName ? `${schemaName}.${tableName}` : tableName;
|
|
2991
|
+
};
|
|
2930
2992
|
const fromSingleRow = (meta, row) => {
|
|
2931
2993
|
const { attributes } = meta;
|
|
2932
2994
|
if (___default.default.isNil(row)) {
|
|
@@ -3049,7 +3111,7 @@ const escapeQuery = (query, charsToEscape, escapeChar = "\\") => {
|
|
|
3049
3111
|
""
|
|
3050
3112
|
);
|
|
3051
3113
|
};
|
|
3052
|
-
const createPivotJoin = (ctx, { alias, refAlias, joinTable, targetMeta }) => {
|
|
3114
|
+
const createPivotJoin = (ctx, { alias: alias2, refAlias, joinTable, targetMeta }) => {
|
|
3053
3115
|
const { qb } = ctx;
|
|
3054
3116
|
const joinAlias = qb.getAlias();
|
|
3055
3117
|
qb.join({
|
|
@@ -3057,7 +3119,7 @@ const createPivotJoin = (ctx, { alias, refAlias, joinTable, targetMeta }) => {
|
|
|
3057
3119
|
referencedTable: joinTable.name,
|
|
3058
3120
|
referencedColumn: joinTable.joinColumn.name,
|
|
3059
3121
|
rootColumn: joinTable.joinColumn.referencedColumn,
|
|
3060
|
-
rootTable:
|
|
3122
|
+
rootTable: alias2,
|
|
3061
3123
|
on: joinTable.on
|
|
3062
3124
|
});
|
|
3063
3125
|
const subAlias = refAlias || qb.getAlias();
|
|
@@ -3070,7 +3132,7 @@ const createPivotJoin = (ctx, { alias, refAlias, joinTable, targetMeta }) => {
|
|
|
3070
3132
|
});
|
|
3071
3133
|
return subAlias;
|
|
3072
3134
|
};
|
|
3073
|
-
const createJoin = (ctx, { alias, refAlias, attributeName, attribute }) => {
|
|
3135
|
+
const createJoin = (ctx, { alias: alias2, refAlias, attributeName, attribute }) => {
|
|
3074
3136
|
const { db, qb, uid } = ctx;
|
|
3075
3137
|
if (attribute.type !== "relation") {
|
|
3076
3138
|
throw new Error(`Cannot join on non relational field ${attributeName}`);
|
|
@@ -3086,7 +3148,7 @@ const createJoin = (ctx, { alias, refAlias, attributeName, attribute }) => {
|
|
|
3086
3148
|
referencedTable: targetMeta.tableName,
|
|
3087
3149
|
referencedColumn: morphColumn.idColumn.name,
|
|
3088
3150
|
rootColumn: morphColumn.idColumn.referencedColumn,
|
|
3089
|
-
rootTable:
|
|
3151
|
+
rootTable: alias2,
|
|
3090
3152
|
on: {
|
|
3091
3153
|
[morphColumn.typeColumn.name]: uid,
|
|
3092
3154
|
...morphColumn.on
|
|
@@ -3101,7 +3163,7 @@ const createJoin = (ctx, { alias, refAlias, attributeName, attribute }) => {
|
|
|
3101
3163
|
referencedTable: joinTable2.name,
|
|
3102
3164
|
referencedColumn: joinTable2.morphColumn.idColumn.name,
|
|
3103
3165
|
rootColumn: joinTable2.morphColumn.idColumn.referencedColumn,
|
|
3104
|
-
rootTable:
|
|
3166
|
+
rootTable: alias2,
|
|
3105
3167
|
on: {
|
|
3106
3168
|
[joinTable2.morphColumn.typeColumn.name]: uid,
|
|
3107
3169
|
field: attributeName
|
|
@@ -3117,7 +3179,7 @@ const createJoin = (ctx, { alias, refAlias, attributeName, attribute }) => {
|
|
|
3117
3179
|
});
|
|
3118
3180
|
return subAlias;
|
|
3119
3181
|
}
|
|
3120
|
-
return
|
|
3182
|
+
return alias2;
|
|
3121
3183
|
}
|
|
3122
3184
|
const { joinColumn } = attribute;
|
|
3123
3185
|
if (joinColumn) {
|
|
@@ -3127,20 +3189,20 @@ const createJoin = (ctx, { alias, refAlias, attributeName, attribute }) => {
|
|
|
3127
3189
|
referencedTable: targetMeta.tableName,
|
|
3128
3190
|
referencedColumn: joinColumn.referencedColumn,
|
|
3129
3191
|
rootColumn: joinColumn.name,
|
|
3130
|
-
rootTable:
|
|
3192
|
+
rootTable: alias2
|
|
3131
3193
|
});
|
|
3132
3194
|
return subAlias;
|
|
3133
3195
|
}
|
|
3134
3196
|
const { joinTable } = attribute;
|
|
3135
3197
|
if (joinTable) {
|
|
3136
|
-
return createPivotJoin(ctx, { alias, refAlias, joinTable, targetMeta });
|
|
3198
|
+
return createPivotJoin(ctx, { alias: alias2, refAlias, joinTable, targetMeta });
|
|
3137
3199
|
}
|
|
3138
|
-
return
|
|
3200
|
+
return alias2;
|
|
3139
3201
|
};
|
|
3140
3202
|
const applyJoin = (qb, join) => {
|
|
3141
3203
|
const {
|
|
3142
3204
|
method = "leftJoin",
|
|
3143
|
-
alias,
|
|
3205
|
+
alias: alias2,
|
|
3144
3206
|
referencedTable,
|
|
3145
3207
|
referencedColumn,
|
|
3146
3208
|
rootColumn,
|
|
@@ -3150,26 +3212,28 @@ const applyJoin = (qb, join) => {
|
|
|
3150
3212
|
on,
|
|
3151
3213
|
orderBy
|
|
3152
3214
|
} = join;
|
|
3153
|
-
qb[method](`${referencedTable} as ${
|
|
3154
|
-
inner.on(`${rootTable}.${rootColumn}`, `${
|
|
3215
|
+
qb[method](`${referencedTable} as ${alias2}`, (inner) => {
|
|
3216
|
+
inner.on(`${rootTable}.${rootColumn}`, `${alias2}.${referencedColumn}`);
|
|
3155
3217
|
if (on) {
|
|
3156
3218
|
for (const key of Object.keys(on)) {
|
|
3157
|
-
inner.onVal(`${
|
|
3219
|
+
inner.onVal(`${alias2}.${key}`, on[key]);
|
|
3158
3220
|
}
|
|
3159
3221
|
}
|
|
3160
3222
|
});
|
|
3161
3223
|
if (orderBy) {
|
|
3162
3224
|
Object.keys(orderBy).forEach((column) => {
|
|
3163
3225
|
const direction = orderBy[column];
|
|
3164
|
-
qb.orderBy(`${
|
|
3226
|
+
qb.orderBy(`${alias2}.${column}`, direction);
|
|
3165
3227
|
});
|
|
3166
3228
|
}
|
|
3167
3229
|
};
|
|
3168
3230
|
const applyJoins = (qb, joins) => {
|
|
3169
3231
|
return joins.forEach((join) => applyJoin(qb, join));
|
|
3170
3232
|
};
|
|
3233
|
+
const COL_STRAPI_ROW_NUMBER = "__strapi_row_number";
|
|
3234
|
+
const COL_STRAPI_ORDER_BY_PREFIX = "__strapi_order_by";
|
|
3171
3235
|
const processOrderBy = (orderBy, ctx) => {
|
|
3172
|
-
const { db, uid, qb, alias } = ctx;
|
|
3236
|
+
const { db, uid, qb, alias: alias2 } = ctx;
|
|
3173
3237
|
const meta = db.metadata.get(uid);
|
|
3174
3238
|
const { attributes } = meta;
|
|
3175
3239
|
if (typeof orderBy === "string") {
|
|
@@ -3178,7 +3242,7 @@ const processOrderBy = (orderBy, ctx) => {
|
|
|
3178
3242
|
throw new Error(`Attribute ${orderBy} not found on model ${uid}`);
|
|
3179
3243
|
}
|
|
3180
3244
|
const columnName = toColumnName(meta, orderBy);
|
|
3181
|
-
return [{ column: qb.aliasColumn(columnName,
|
|
3245
|
+
return [{ column: qb.aliasColumn(columnName, alias2) }];
|
|
3182
3246
|
}
|
|
3183
3247
|
if (Array.isArray(orderBy)) {
|
|
3184
3248
|
return orderBy.flatMap((value) => processOrderBy(value, ctx));
|
|
@@ -3192,11 +3256,11 @@ const processOrderBy = (orderBy, ctx) => {
|
|
|
3192
3256
|
}
|
|
3193
3257
|
if (isScalar(attribute.type)) {
|
|
3194
3258
|
const columnName = toColumnName(meta, key);
|
|
3195
|
-
return { column: qb.aliasColumn(columnName,
|
|
3259
|
+
return { column: qb.aliasColumn(columnName, alias2), order: direction };
|
|
3196
3260
|
}
|
|
3197
3261
|
if (attribute.type === "relation" && "target" in attribute) {
|
|
3198
3262
|
const subAlias = createJoin(ctx, {
|
|
3199
|
-
alias:
|
|
3263
|
+
alias: alias2 || qb.alias,
|
|
3200
3264
|
attributeName: key,
|
|
3201
3265
|
attribute
|
|
3202
3266
|
});
|
|
@@ -3212,6 +3276,76 @@ const processOrderBy = (orderBy, ctx) => {
|
|
|
3212
3276
|
}
|
|
3213
3277
|
throw new Error("Invalid orderBy syntax");
|
|
3214
3278
|
};
|
|
3279
|
+
const getStrapiOrderColumnAlias = (column) => {
|
|
3280
|
+
const trimmedColumnName = column.replaceAll(".", "_");
|
|
3281
|
+
return `${COL_STRAPI_ORDER_BY_PREFIX}__${trimmedColumnName}`;
|
|
3282
|
+
};
|
|
3283
|
+
const wrapWithDeepSort = (originalQuery, ctx) => {
|
|
3284
|
+
const { db, qb, uid } = ctx;
|
|
3285
|
+
const { tableName } = db.metadata.get(uid);
|
|
3286
|
+
const orderBy = ___default.default.cloneDeep(qb.state.orderBy);
|
|
3287
|
+
const resultQueryAlias = qb.getAlias();
|
|
3288
|
+
const aliasedTableName = qb.mustUseAlias() ? alias(resultQueryAlias, tableName) : tableName;
|
|
3289
|
+
const resultQuery = db.getConnection(aliasedTableName);
|
|
3290
|
+
const baseQuery = originalQuery.clone();
|
|
3291
|
+
const baseQueryAlias = qb.getAlias();
|
|
3292
|
+
baseQuery.clear("select").clear("order").clear("limit").clear("offset");
|
|
3293
|
+
baseQuery.select(
|
|
3294
|
+
// Always select the row id for future manipulation
|
|
3295
|
+
prefix(qb.alias, "id"),
|
|
3296
|
+
...orderBy.map(
|
|
3297
|
+
(orderByClause) => alias(getStrapiOrderColumnAlias(orderByClause.column), orderByClause.column)
|
|
3298
|
+
)
|
|
3299
|
+
);
|
|
3300
|
+
const partitionedQueryAlias = qb.getAlias();
|
|
3301
|
+
const selectRowsAsNumberedPartitions = (partitionedQuery) => {
|
|
3302
|
+
const prefixedOrderBy = orderBy.map((orderByClause) => ({
|
|
3303
|
+
column: prefix(baseQueryAlias, getStrapiOrderColumnAlias(orderByClause.column)),
|
|
3304
|
+
order: orderByClause.order
|
|
3305
|
+
}));
|
|
3306
|
+
const orderByColumns = prefixedOrderBy.map(___default.default.prop("column"));
|
|
3307
|
+
partitionedQuery.select(
|
|
3308
|
+
// Always select baseQuery.id
|
|
3309
|
+
prefix(baseQueryAlias, "id"),
|
|
3310
|
+
...orderByColumns
|
|
3311
|
+
).rowNumber(COL_STRAPI_ROW_NUMBER, (subQuery) => {
|
|
3312
|
+
for (const orderByClause of prefixedOrderBy) {
|
|
3313
|
+
subQuery.orderBy(orderByClause.column, orderByClause.order, "last");
|
|
3314
|
+
}
|
|
3315
|
+
subQuery.partitionBy(`${baseQueryAlias}.id`);
|
|
3316
|
+
}).from(baseQuery.as(baseQueryAlias)).as(partitionedQueryAlias);
|
|
3317
|
+
};
|
|
3318
|
+
const originalSelect = ___default.default.difference(
|
|
3319
|
+
qb.state.select,
|
|
3320
|
+
// Remove order by columns from the initial select
|
|
3321
|
+
qb.state.orderBy.map(___default.default.prop("column"))
|
|
3322
|
+
).map(prefix(resultQueryAlias));
|
|
3323
|
+
resultQuery.select(originalSelect).innerJoin(selectRowsAsNumberedPartitions, function() {
|
|
3324
|
+
this.on(`${partitionedQueryAlias}.id`, `${resultQueryAlias}.id`).andOnVal(`${partitionedQueryAlias}.${COL_STRAPI_ROW_NUMBER}`, "=", 1);
|
|
3325
|
+
});
|
|
3326
|
+
if (qb.state.limit) {
|
|
3327
|
+
resultQuery.limit(qb.state.limit);
|
|
3328
|
+
}
|
|
3329
|
+
if (qb.state.offset) {
|
|
3330
|
+
resultQuery.offset(qb.state.offset);
|
|
3331
|
+
}
|
|
3332
|
+
if (qb.state.first) {
|
|
3333
|
+
resultQuery.first();
|
|
3334
|
+
}
|
|
3335
|
+
resultQuery.orderBy([
|
|
3336
|
+
// Transform "order by" clause to their T alias and prefix them with T alias
|
|
3337
|
+
...orderBy.map((orderByClause) => ({
|
|
3338
|
+
column: prefix(partitionedQueryAlias, getStrapiOrderColumnAlias(orderByClause.column)),
|
|
3339
|
+
order: orderByClause.order
|
|
3340
|
+
})),
|
|
3341
|
+
// Add T.id to the order by clause to get consistent results in case several rows have the exact same order
|
|
3342
|
+
{ column: `${partitionedQueryAlias}.id`, order: "asc" }
|
|
3343
|
+
]);
|
|
3344
|
+
return resultQuery;
|
|
3345
|
+
};
|
|
3346
|
+
const alias = ___default.default.curry((alias2, value) => `${value} as ${alias2}`);
|
|
3347
|
+
const prefix = ___default.default.curry((prefix2, value) => `${prefix2}.${value}`);
|
|
3348
|
+
const joinColPrefix = "__strapi";
|
|
3215
3349
|
const XtoOne = async (input, ctx) => {
|
|
3216
3350
|
const { attribute, attributeName, results, populateValue, targetMeta, isCount } = input;
|
|
3217
3351
|
const { db, qb } = ctx;
|
|
@@ -3238,8 +3372,10 @@ const XtoOne = async (input, ctx) => {
|
|
|
3238
3372
|
const { joinTable } = attribute;
|
|
3239
3373
|
const qb2 = db.entityManager.createQueryBuilder(targetMeta.uid);
|
|
3240
3374
|
const { name: joinColumnName, referencedColumn: referencedColumnName } = joinTable.joinColumn;
|
|
3241
|
-
const
|
|
3242
|
-
const joinColAlias = `${
|
|
3375
|
+
const alias2 = qb2.getAlias();
|
|
3376
|
+
const joinColAlias = `${alias2}.${joinColumnName}`;
|
|
3377
|
+
const joinColRenameAs = `${joinColPrefix}${joinColumnName}`;
|
|
3378
|
+
const joinColSelect = `${joinColAlias} as ${joinColRenameAs}`;
|
|
3243
3379
|
const referencedValues = ___default.default.uniq(
|
|
3244
3380
|
results.map((r) => r[referencedColumnName]).filter((value) => !___default.default.isNil(value))
|
|
3245
3381
|
);
|
|
@@ -3251,7 +3387,7 @@ const XtoOne = async (input, ctx) => {
|
|
|
3251
3387
|
return;
|
|
3252
3388
|
}
|
|
3253
3389
|
const rows2 = await qb2.init(populateValue).join({
|
|
3254
|
-
alias,
|
|
3390
|
+
alias: alias2,
|
|
3255
3391
|
referencedTable: joinTable.name,
|
|
3256
3392
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3257
3393
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
@@ -3277,15 +3413,15 @@ const XtoOne = async (input, ctx) => {
|
|
|
3277
3413
|
return;
|
|
3278
3414
|
}
|
|
3279
3415
|
const rows = await qb2.init(populateValue).join({
|
|
3280
|
-
alias,
|
|
3416
|
+
alias: alias2,
|
|
3281
3417
|
referencedTable: joinTable.name,
|
|
3282
3418
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3283
3419
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
3284
3420
|
rootTable: qb2.alias,
|
|
3285
3421
|
on: joinTable.on,
|
|
3286
3422
|
orderBy: joinTable.orderBy
|
|
3287
|
-
}).addSelect(
|
|
3288
|
-
const map = ___default.default.groupBy(
|
|
3423
|
+
}).addSelect(joinColSelect).where({ [joinColAlias]: referencedValues }).execute({ mapResults: false });
|
|
3424
|
+
const map = ___default.default.groupBy(joinColRenameAs)(rows);
|
|
3289
3425
|
results.forEach((result) => {
|
|
3290
3426
|
result[attributeName] = fromTargetRow(___default.default.first(map[result[referencedColumnName]]));
|
|
3291
3427
|
});
|
|
@@ -3317,8 +3453,10 @@ const oneToMany = async (input, ctx) => {
|
|
|
3317
3453
|
const { joinTable } = attribute;
|
|
3318
3454
|
const qb2 = db.entityManager.createQueryBuilder(targetMeta.uid);
|
|
3319
3455
|
const { name: joinColumnName, referencedColumn: referencedColumnName } = joinTable.joinColumn;
|
|
3320
|
-
const
|
|
3321
|
-
const joinColAlias = `${
|
|
3456
|
+
const alias2 = qb2.getAlias();
|
|
3457
|
+
const joinColAlias = `${alias2}.${joinColumnName}`;
|
|
3458
|
+
const joinColRenameAs = `${joinColPrefix}${joinColumnName}`;
|
|
3459
|
+
const joinColSelect = `${joinColAlias} as ${joinColRenameAs}`;
|
|
3322
3460
|
const referencedValues = ___default.default.uniq(
|
|
3323
3461
|
results.map((r) => r[referencedColumnName]).filter((value) => !___default.default.isNil(value))
|
|
3324
3462
|
);
|
|
@@ -3330,16 +3468,16 @@ const oneToMany = async (input, ctx) => {
|
|
|
3330
3468
|
return;
|
|
3331
3469
|
}
|
|
3332
3470
|
const rows2 = await qb2.init(populateValue).join({
|
|
3333
|
-
alias,
|
|
3471
|
+
alias: alias2,
|
|
3334
3472
|
referencedTable: joinTable.name,
|
|
3335
3473
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3336
3474
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
3337
3475
|
rootTable: qb2.alias,
|
|
3338
3476
|
on: joinTable.on
|
|
3339
|
-
}).select([
|
|
3477
|
+
}).select([joinColSelect, qb2.raw("count(*) AS count")]).where({ [joinColAlias]: referencedValues }).groupBy(joinColAlias).execute({ mapResults: false });
|
|
3340
3478
|
const map2 = rows2.reduce(
|
|
3341
3479
|
(map3, row) => {
|
|
3342
|
-
map3[row[
|
|
3480
|
+
map3[row[joinColRenameAs]] = { count: Number(row.count) };
|
|
3343
3481
|
return map3;
|
|
3344
3482
|
},
|
|
3345
3483
|
{}
|
|
@@ -3356,15 +3494,15 @@ const oneToMany = async (input, ctx) => {
|
|
|
3356
3494
|
return;
|
|
3357
3495
|
}
|
|
3358
3496
|
const rows = await qb2.init(populateValue).join({
|
|
3359
|
-
alias,
|
|
3497
|
+
alias: alias2,
|
|
3360
3498
|
referencedTable: joinTable.name,
|
|
3361
3499
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3362
3500
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
3363
3501
|
rootTable: qb2.alias,
|
|
3364
3502
|
on: joinTable.on,
|
|
3365
3503
|
orderBy: ___default.default.mapValues((v) => populateValue.ordering || v, joinTable.orderBy)
|
|
3366
|
-
}).addSelect(
|
|
3367
|
-
const map = ___default.default.groupBy(
|
|
3504
|
+
}).addSelect(joinColSelect).where({ [joinColAlias]: referencedValues }).execute({ mapResults: false });
|
|
3505
|
+
const map = ___default.default.groupBy(joinColRenameAs)(rows);
|
|
3368
3506
|
results.forEach((r) => {
|
|
3369
3507
|
r[attributeName] = fromTargetRow(map[r[referencedColumnName]] || []);
|
|
3370
3508
|
});
|
|
@@ -3377,8 +3515,10 @@ const manyToMany = async (input, ctx) => {
|
|
|
3377
3515
|
const { joinTable } = attribute;
|
|
3378
3516
|
const populateQb = db.entityManager.createQueryBuilder(targetMeta.uid);
|
|
3379
3517
|
const { name: joinColumnName, referencedColumn: referencedColumnName } = joinTable.joinColumn;
|
|
3380
|
-
const
|
|
3381
|
-
const joinColAlias = `${
|
|
3518
|
+
const alias2 = populateQb.getAlias();
|
|
3519
|
+
const joinColAlias = `${alias2}.${joinColumnName}`;
|
|
3520
|
+
const joinColRenameAs = `${joinColPrefix}${joinColumnName}`;
|
|
3521
|
+
const joinColSelect = `${joinColAlias} as ${joinColRenameAs}`;
|
|
3382
3522
|
const referencedValues = ___default.default.uniq(
|
|
3383
3523
|
results.map((r) => r[referencedColumnName]).filter((value) => !___default.default.isNil(value))
|
|
3384
3524
|
);
|
|
@@ -3390,7 +3530,7 @@ const manyToMany = async (input, ctx) => {
|
|
|
3390
3530
|
return;
|
|
3391
3531
|
}
|
|
3392
3532
|
const rows2 = await populateQb.init(populateValue).join({
|
|
3393
|
-
alias,
|
|
3533
|
+
alias: alias2,
|
|
3394
3534
|
referencedTable: joinTable.name,
|
|
3395
3535
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3396
3536
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
@@ -3416,15 +3556,15 @@ const manyToMany = async (input, ctx) => {
|
|
|
3416
3556
|
return;
|
|
3417
3557
|
}
|
|
3418
3558
|
const rows = await populateQb.init(populateValue).join({
|
|
3419
|
-
alias,
|
|
3559
|
+
alias: alias2,
|
|
3420
3560
|
referencedTable: joinTable.name,
|
|
3421
3561
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3422
3562
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
3423
3563
|
rootTable: populateQb.alias,
|
|
3424
3564
|
on: joinTable.on,
|
|
3425
3565
|
orderBy: ___default.default.mapValues((v) => populateValue.ordering || v, joinTable.orderBy)
|
|
3426
|
-
}).addSelect(
|
|
3427
|
-
const map = ___default.default.groupBy(
|
|
3566
|
+
}).addSelect(joinColSelect).where({ [joinColAlias]: referencedValues }).execute({ mapResults: false });
|
|
3567
|
+
const map = ___default.default.groupBy(joinColRenameAs)(rows);
|
|
3428
3568
|
results.forEach((result) => {
|
|
3429
3569
|
result[attributeName] = fromTargetRow(map[result[referencedColumnName]] || []);
|
|
3430
3570
|
});
|
|
@@ -3467,9 +3607,9 @@ const morphX = async (input, ctx) => {
|
|
|
3467
3607
|
return;
|
|
3468
3608
|
}
|
|
3469
3609
|
const qb = db.entityManager.createQueryBuilder(target);
|
|
3470
|
-
const
|
|
3610
|
+
const alias2 = qb.getAlias();
|
|
3471
3611
|
const rows = await qb.init(populateValue).join({
|
|
3472
|
-
alias,
|
|
3612
|
+
alias: alias2,
|
|
3473
3613
|
referencedTable: joinTable.name,
|
|
3474
3614
|
referencedColumn: joinColumn.name,
|
|
3475
3615
|
rootColumn: joinColumn.referencedColumn,
|
|
@@ -3479,9 +3619,9 @@ const morphX = async (input, ctx) => {
|
|
|
3479
3619
|
field: attributeName
|
|
3480
3620
|
},
|
|
3481
3621
|
orderBy: ___default.default.mapValues((v) => populateValue.ordering || v, joinTable.orderBy)
|
|
3482
|
-
}).addSelect([`${
|
|
3483
|
-
[`${
|
|
3484
|
-
[`${
|
|
3622
|
+
}).addSelect([`${alias2}.${idColumn.name}`, `${alias2}.${typeColumn.name}`]).where({
|
|
3623
|
+
[`${alias2}.${idColumn.name}`]: referencedValues,
|
|
3624
|
+
[`${alias2}.${typeColumn.name}`]: uid
|
|
3485
3625
|
}).execute({ mapResults: false });
|
|
3486
3626
|
const map = ___default.default.groupBy(idColumn.name)(rows);
|
|
3487
3627
|
results.forEach((result) => {
|
|
@@ -3730,13 +3870,6 @@ const processPopulate = (populate, ctx) => {
|
|
|
3730
3870
|
}
|
|
3731
3871
|
return finalPopulate;
|
|
3732
3872
|
};
|
|
3733
|
-
function isKnexQuery(value) {
|
|
3734
|
-
return value instanceof KnexBuilder__default.default || value instanceof KnexRaw__default.default;
|
|
3735
|
-
}
|
|
3736
|
-
const addSchema = (db, tableName) => {
|
|
3737
|
-
const schemaName = db.getSchemaName();
|
|
3738
|
-
return schemaName ? `${schemaName}.${tableName}` : tableName;
|
|
3739
|
-
};
|
|
3740
3873
|
const isRecord$1 = (value) => _.isPlainObject(value);
|
|
3741
3874
|
const castValue = (value, attribute) => {
|
|
3742
3875
|
if (!attribute) {
|
|
@@ -3778,8 +3911,8 @@ const processNested = (where, ctx) => {
|
|
|
3778
3911
|
return processWhere(where, ctx);
|
|
3779
3912
|
};
|
|
3780
3913
|
const processRelationWhere = (where, ctx) => {
|
|
3781
|
-
const { qb, alias } = ctx;
|
|
3782
|
-
const idAlias = qb.aliasColumn("id",
|
|
3914
|
+
const { qb, alias: alias2 } = ctx;
|
|
3915
|
+
const idAlias = qb.aliasColumn("id", alias2);
|
|
3783
3916
|
if (!isRecord$1(where)) {
|
|
3784
3917
|
return { [idAlias]: where };
|
|
3785
3918
|
}
|
|
@@ -3795,6 +3928,9 @@ const processRelationWhere = (where, ctx) => {
|
|
|
3795
3928
|
}
|
|
3796
3929
|
if (operatorKeys.length === 1) {
|
|
3797
3930
|
const operator = operatorKeys[0];
|
|
3931
|
+
if (utils.isOperatorOfType("group", operator)) {
|
|
3932
|
+
return processWhere(where, ctx);
|
|
3933
|
+
}
|
|
3798
3934
|
return { [idAlias]: { [operator]: processNested(where[operator], ctx) } };
|
|
3799
3935
|
}
|
|
3800
3936
|
return processWhere(where, ctx);
|
|
@@ -3806,7 +3942,7 @@ function processWhere(where, ctx) {
|
|
|
3806
3942
|
if (_.isArray(where)) {
|
|
3807
3943
|
return where.map((sub) => processWhere(sub, ctx));
|
|
3808
3944
|
}
|
|
3809
|
-
const { db, uid, qb, alias } = ctx;
|
|
3945
|
+
const { db, uid, qb, alias: alias2 } = ctx;
|
|
3810
3946
|
const meta = db.metadata.get(uid);
|
|
3811
3947
|
const filters = {};
|
|
3812
3948
|
for (const key of Object.keys(where)) {
|
|
@@ -3829,12 +3965,12 @@ function processWhere(where, ctx) {
|
|
|
3829
3965
|
}
|
|
3830
3966
|
const attribute = meta.attributes[key];
|
|
3831
3967
|
if (!attribute) {
|
|
3832
|
-
filters[qb.aliasColumn(key,
|
|
3968
|
+
filters[qb.aliasColumn(key, alias2)] = processAttributeWhere(null, value);
|
|
3833
3969
|
continue;
|
|
3834
3970
|
}
|
|
3835
3971
|
if (isRelation(attribute.type) && "target" in attribute) {
|
|
3836
3972
|
const subAlias = createJoin(ctx, {
|
|
3837
|
-
alias:
|
|
3973
|
+
alias: alias2 || qb.alias,
|
|
3838
3974
|
attributeName: key,
|
|
3839
3975
|
attribute
|
|
3840
3976
|
});
|
|
@@ -3849,7 +3985,7 @@ function processWhere(where, ctx) {
|
|
|
3849
3985
|
}
|
|
3850
3986
|
if (isScalar(attribute.type)) {
|
|
3851
3987
|
const columnName = toColumnName(meta, key);
|
|
3852
|
-
const aliasedColumnName = qb.aliasColumn(columnName,
|
|
3988
|
+
const aliasedColumnName = qb.aliasColumn(columnName, alias2);
|
|
3853
3989
|
filters[aliasedColumnName] = processAttributeWhere(attribute, value);
|
|
3854
3990
|
continue;
|
|
3855
3991
|
}
|
|
@@ -4077,7 +4213,7 @@ class ReadableStrapiQuery extends stream.Readable {
|
|
|
4077
4213
|
* Custom ._read() implementation
|
|
4078
4214
|
*
|
|
4079
4215
|
* NOTE: Here "size" means the number of entities to be read from the database.
|
|
4080
|
-
* Not the actual byte size, as it would
|
|
4216
|
+
* Not the actual byte size, as it would mean that we need to return partial entities.
|
|
4081
4217
|
*
|
|
4082
4218
|
*/
|
|
4083
4219
|
async _read(size) {
|
|
@@ -4140,61 +4276,6 @@ class ReadableStrapiQuery extends stream.Readable {
|
|
|
4140
4276
|
}
|
|
4141
4277
|
}
|
|
4142
4278
|
}
|
|
4143
|
-
const storage = new node_async_hooks.AsyncLocalStorage();
|
|
4144
|
-
const transactionCtx = {
|
|
4145
|
-
async run(trx, cb) {
|
|
4146
|
-
const store = storage.getStore();
|
|
4147
|
-
return storage.run(
|
|
4148
|
-
{
|
|
4149
|
-
trx,
|
|
4150
|
-
// Fill with existing callbacks if nesting transactions
|
|
4151
|
-
commitCallbacks: store?.commitCallbacks || [],
|
|
4152
|
-
rollbackCallbacks: store?.rollbackCallbacks || []
|
|
4153
|
-
},
|
|
4154
|
-
cb
|
|
4155
|
-
);
|
|
4156
|
-
},
|
|
4157
|
-
get() {
|
|
4158
|
-
const store = storage.getStore();
|
|
4159
|
-
return store?.trx;
|
|
4160
|
-
},
|
|
4161
|
-
async commit(trx) {
|
|
4162
|
-
const store = storage.getStore();
|
|
4163
|
-
if (store?.trx) {
|
|
4164
|
-
store.trx = null;
|
|
4165
|
-
}
|
|
4166
|
-
await trx.commit();
|
|
4167
|
-
if (!store?.commitCallbacks.length) {
|
|
4168
|
-
return;
|
|
4169
|
-
}
|
|
4170
|
-
store.commitCallbacks.forEach((cb) => cb());
|
|
4171
|
-
store.commitCallbacks = [];
|
|
4172
|
-
},
|
|
4173
|
-
async rollback(trx) {
|
|
4174
|
-
const store = storage.getStore();
|
|
4175
|
-
if (store?.trx) {
|
|
4176
|
-
store.trx = null;
|
|
4177
|
-
}
|
|
4178
|
-
await trx.rollback();
|
|
4179
|
-
if (!store?.rollbackCallbacks.length) {
|
|
4180
|
-
return;
|
|
4181
|
-
}
|
|
4182
|
-
store.rollbackCallbacks.forEach((cb) => cb());
|
|
4183
|
-
store.rollbackCallbacks = [];
|
|
4184
|
-
},
|
|
4185
|
-
onCommit(cb) {
|
|
4186
|
-
const store = storage.getStore();
|
|
4187
|
-
if (store?.commitCallbacks) {
|
|
4188
|
-
store.commitCallbacks.push(cb);
|
|
4189
|
-
}
|
|
4190
|
-
},
|
|
4191
|
-
onRollback(cb) {
|
|
4192
|
-
const store = storage.getStore();
|
|
4193
|
-
if (store?.rollbackCallbacks) {
|
|
4194
|
-
store.rollbackCallbacks.push(cb);
|
|
4195
|
-
}
|
|
4196
|
-
}
|
|
4197
|
-
};
|
|
4198
4279
|
const createQueryBuilder = (uid, db, initialState = {}) => {
|
|
4199
4280
|
const meta = db.metadata.get(uid);
|
|
4200
4281
|
const { tableName } = meta;
|
|
@@ -4227,9 +4308,9 @@ const createQueryBuilder = (uid, db, initialState = {}) => {
|
|
|
4227
4308
|
initialState
|
|
4228
4309
|
);
|
|
4229
4310
|
const getAlias = () => {
|
|
4230
|
-
const
|
|
4311
|
+
const alias2 = `t${state.aliasCounter}`;
|
|
4231
4312
|
state.aliasCounter += 1;
|
|
4232
|
-
return
|
|
4313
|
+
return alias2;
|
|
4233
4314
|
};
|
|
4234
4315
|
return {
|
|
4235
4316
|
alias: getAlias(),
|
|
@@ -4396,15 +4477,15 @@ const createQueryBuilder = (uid, db, initialState = {}) => {
|
|
|
4396
4477
|
mustUseAlias() {
|
|
4397
4478
|
return ["select", "count"].includes(state.type);
|
|
4398
4479
|
},
|
|
4399
|
-
aliasColumn(key,
|
|
4480
|
+
aliasColumn(key, alias2) {
|
|
4400
4481
|
if (typeof key !== "string") {
|
|
4401
4482
|
return key;
|
|
4402
4483
|
}
|
|
4403
4484
|
if (key.indexOf(".") >= 0) {
|
|
4404
4485
|
return key;
|
|
4405
4486
|
}
|
|
4406
|
-
if (!___default.default.isNil(
|
|
4407
|
-
return `${
|
|
4487
|
+
if (!___default.default.isNil(alias2)) {
|
|
4488
|
+
return `${alias2}.${key}`;
|
|
4408
4489
|
}
|
|
4409
4490
|
return this.mustUseAlias() ? `${this.alias}.${key}` : key;
|
|
4410
4491
|
},
|
|
@@ -4439,6 +4520,20 @@ const createQueryBuilder = (uid, db, initialState = {}) => {
|
|
|
4439
4520
|
shouldUseDistinct() {
|
|
4440
4521
|
return state.joins.length > 0 && ___default.default.isEmpty(state.groupBy);
|
|
4441
4522
|
},
|
|
4523
|
+
shouldUseDeepSort() {
|
|
4524
|
+
return state.orderBy.filter(({ column }) => column.indexOf(".") >= 0).filter(({ column }) => {
|
|
4525
|
+
const col = column.split(".");
|
|
4526
|
+
for (let i = 0; i < col.length - 1; i += 1) {
|
|
4527
|
+
const el = col[i];
|
|
4528
|
+
const isRelationAttribute = meta.attributes[el]?.type === "relation";
|
|
4529
|
+
const isAliasedRelation = Object.values(state.joins).map((join) => join.alias).includes(el);
|
|
4530
|
+
if (isRelationAttribute || isAliasedRelation) {
|
|
4531
|
+
return true;
|
|
4532
|
+
}
|
|
4533
|
+
}
|
|
4534
|
+
return false;
|
|
4535
|
+
}).length > 0;
|
|
4536
|
+
},
|
|
4442
4537
|
processSelect() {
|
|
4443
4538
|
state.select = state.select.map((field) => {
|
|
4444
4539
|
if (isKnexQuery(field)) {
|
|
@@ -4556,6 +4651,9 @@ const createQueryBuilder = (uid, db, initialState = {}) => {
|
|
|
4556
4651
|
if (state.joins.length > 0) {
|
|
4557
4652
|
applyJoins(qb, state.joins);
|
|
4558
4653
|
}
|
|
4654
|
+
if (this.shouldUseDeepSort()) {
|
|
4655
|
+
return wrapWithDeepSort(qb, { qb: this, db, uid });
|
|
4656
|
+
}
|
|
4559
4657
|
return qb;
|
|
4560
4658
|
},
|
|
4561
4659
|
async execute({ mapResults = true } = {}) {
|
|
@@ -4757,7 +4855,7 @@ const deleteRelatedMorphOneRelationsAfterMorphToManyUpdate = async (rows, {
|
|
|
4757
4855
|
await createQueryBuilder(joinTable.name, db).delete().where({ $or: orWhere }).transacting(trx).execute();
|
|
4758
4856
|
}
|
|
4759
4857
|
};
|
|
4760
|
-
const getDocumentSiblingIdsQuery = (
|
|
4858
|
+
const getDocumentSiblingIdsQuery = (tableName, id) => {
|
|
4761
4859
|
const models = Array.from(strapi.db.metadata.values());
|
|
4762
4860
|
const isContentType = models.find((model) => {
|
|
4763
4861
|
return model.tableName === tableName && model.attributes.documentId;
|
|
@@ -4765,10 +4863,11 @@ const getDocumentSiblingIdsQuery = (con, tableName, id) => {
|
|
|
4765
4863
|
if (!isContentType) {
|
|
4766
4864
|
return [id];
|
|
4767
4865
|
}
|
|
4768
|
-
return
|
|
4769
|
-
"document_id",
|
|
4770
|
-
|
|
4771
|
-
|
|
4866
|
+
return function(query) {
|
|
4867
|
+
query.select("id").from(tableName).whereIn("document_id", (documentIDSubQuery) => {
|
|
4868
|
+
documentIDSubQuery.from(tableName).select("document_id").where("id", id);
|
|
4869
|
+
});
|
|
4870
|
+
};
|
|
4772
4871
|
};
|
|
4773
4872
|
const deletePreviousOneToAnyRelations = async ({
|
|
4774
4873
|
id,
|
|
@@ -4785,7 +4884,7 @@ const deletePreviousOneToAnyRelations = async ({
|
|
|
4785
4884
|
const { joinTable } = attribute;
|
|
4786
4885
|
const { joinColumn, inverseJoinColumn } = joinTable;
|
|
4787
4886
|
const con = db.getConnection();
|
|
4788
|
-
await con.delete().from(joinTable.name).whereNotIn(joinColumn.name, getDocumentSiblingIdsQuery(
|
|
4887
|
+
await con.delete().from(joinTable.name).whereNotIn(joinColumn.name, getDocumentSiblingIdsQuery(joinColumn.referencedTable, id)).whereIn(inverseJoinColumn.name, relIdsToadd).where(joinTable.on || {}).transacting(trx);
|
|
4789
4888
|
await cleanOrderColumns({ attribute, db, inverseRelIds: relIdsToadd, transaction: trx });
|
|
4790
4889
|
};
|
|
4791
4890
|
const deletePreviousAnyToOneRelations = async ({
|
|
@@ -4804,7 +4903,7 @@ const deletePreviousAnyToOneRelations = async ({
|
|
|
4804
4903
|
if (isManyToAny(attribute)) {
|
|
4805
4904
|
const relsToDelete = await con.select(inverseJoinColumn.name).from(joinTable.name).where(joinColumn.name, id).whereNotIn(
|
|
4806
4905
|
inverseJoinColumn.name,
|
|
4807
|
-
getDocumentSiblingIdsQuery(
|
|
4906
|
+
getDocumentSiblingIdsQuery(inverseJoinColumn.referencedTable, relIdToadd)
|
|
4808
4907
|
).where(joinTable.on || {}).transacting(trx);
|
|
4809
4908
|
const relIdsToDelete = _.map(inverseJoinColumn.name, relsToDelete);
|
|
4810
4909
|
await createQueryBuilder(joinTable.name, db).delete().where({
|
|
@@ -4815,7 +4914,7 @@ const deletePreviousAnyToOneRelations = async ({
|
|
|
4815
4914
|
} else {
|
|
4816
4915
|
await con.delete().from(joinTable.name).where(joinColumn.name, id).whereNotIn(
|
|
4817
4916
|
inverseJoinColumn.name,
|
|
4818
|
-
getDocumentSiblingIdsQuery(
|
|
4917
|
+
getDocumentSiblingIdsQuery(inverseJoinColumn.referencedTable, relIdToadd)
|
|
4819
4918
|
).where(joinTable.on || {}).transacting(trx);
|
|
4820
4919
|
}
|
|
4821
4920
|
};
|
|
@@ -5899,6 +5998,21 @@ const createStorage = (opts) => {
|
|
|
5899
5998
|
const wrapTransaction = (db) => (fn) => () => {
|
|
5900
5999
|
return db.transaction(({ trx }) => Promise.resolve(fn(trx, db)));
|
|
5901
6000
|
};
|
|
6001
|
+
const transformLogMessage = (level, message) => {
|
|
6002
|
+
if (typeof message === "string") {
|
|
6003
|
+
return { level, message };
|
|
6004
|
+
}
|
|
6005
|
+
if (typeof message === "object" && message !== null) {
|
|
6006
|
+
if ("event" in message && "name" in message) {
|
|
6007
|
+
return {
|
|
6008
|
+
level,
|
|
6009
|
+
message: `[internal migration]: ${message.event} ${message?.name}`,
|
|
6010
|
+
timestamp: Date.now()
|
|
6011
|
+
};
|
|
6012
|
+
}
|
|
6013
|
+
}
|
|
6014
|
+
return "";
|
|
6015
|
+
};
|
|
5902
6016
|
const migrationResolver = ({ name, path: path2, context }) => {
|
|
5903
6017
|
const { db } = context;
|
|
5904
6018
|
if (!path2) {
|
|
@@ -5927,7 +6041,20 @@ const createUserMigrationProvider = (db) => {
|
|
|
5927
6041
|
const context = { db };
|
|
5928
6042
|
const umzugProvider = new umzug.Umzug({
|
|
5929
6043
|
storage: createStorage({ db, tableName: "strapi_migrations" }),
|
|
5930
|
-
logger:
|
|
6044
|
+
logger: {
|
|
6045
|
+
info(message) {
|
|
6046
|
+
db.logger.info(transformLogMessage("info", message));
|
|
6047
|
+
},
|
|
6048
|
+
warn(message) {
|
|
6049
|
+
db.logger.warn(transformLogMessage("warn", message));
|
|
6050
|
+
},
|
|
6051
|
+
error(message) {
|
|
6052
|
+
db.logger.error(transformLogMessage("error", message));
|
|
6053
|
+
},
|
|
6054
|
+
debug(message) {
|
|
6055
|
+
db.logger.debug(transformLogMessage("debug", message));
|
|
6056
|
+
}
|
|
6057
|
+
},
|
|
5931
6058
|
context,
|
|
5932
6059
|
migrations: {
|
|
5933
6060
|
glob: ["*.{js,sql}", { cwd: dir }],
|
|
@@ -6215,16 +6342,115 @@ const findDiffs = (shortMap) => {
|
|
|
6215
6342
|
});
|
|
6216
6343
|
return diffs;
|
|
6217
6344
|
};
|
|
6345
|
+
const createLocaleColumn = async (db, tableName) => {
|
|
6346
|
+
await db.schema.alterTable(tableName, (table) => {
|
|
6347
|
+
table.string("locale");
|
|
6348
|
+
});
|
|
6349
|
+
};
|
|
6350
|
+
const createdLocale = {
|
|
6351
|
+
name: "5.0.0-03-created-locale",
|
|
6352
|
+
async up(knex2, db) {
|
|
6353
|
+
for (const meta of db.metadata.values()) {
|
|
6354
|
+
const hasTable = await knex2.schema.hasTable(meta.tableName);
|
|
6355
|
+
if (!hasTable) {
|
|
6356
|
+
continue;
|
|
6357
|
+
}
|
|
6358
|
+
const uid = meta.uid;
|
|
6359
|
+
const model = strapi.getModel(uid);
|
|
6360
|
+
if (!model) {
|
|
6361
|
+
continue;
|
|
6362
|
+
}
|
|
6363
|
+
const hasLocaleColumn = await knex2.schema.hasColumn(meta.tableName, "locale");
|
|
6364
|
+
if (meta.attributes.locale && !hasLocaleColumn) {
|
|
6365
|
+
await createLocaleColumn(knex2, meta.tableName);
|
|
6366
|
+
}
|
|
6367
|
+
}
|
|
6368
|
+
},
|
|
6369
|
+
async down() {
|
|
6370
|
+
throw new Error("not implemented");
|
|
6371
|
+
}
|
|
6372
|
+
};
|
|
6373
|
+
const createPublishedAtColumn = async (db, tableName) => {
|
|
6374
|
+
await db.schema.alterTable(tableName, (table) => {
|
|
6375
|
+
table.string("published_at");
|
|
6376
|
+
});
|
|
6377
|
+
};
|
|
6378
|
+
const createdPublishedAt = {
|
|
6379
|
+
name: "5.0.0-04-created-published-at",
|
|
6380
|
+
async up(knex2, db) {
|
|
6381
|
+
for (const meta of db.metadata.values()) {
|
|
6382
|
+
const hasTable = await knex2.schema.hasTable(meta.tableName);
|
|
6383
|
+
if (!hasTable) {
|
|
6384
|
+
continue;
|
|
6385
|
+
}
|
|
6386
|
+
const uid = meta.uid;
|
|
6387
|
+
const model = strapi.getModel(uid);
|
|
6388
|
+
if (!model) {
|
|
6389
|
+
continue;
|
|
6390
|
+
}
|
|
6391
|
+
const hasPublishedAtColumn = await knex2.schema.hasColumn(meta.tableName, "published_at");
|
|
6392
|
+
if (meta.attributes.publishedAt && !hasPublishedAtColumn) {
|
|
6393
|
+
await createPublishedAtColumn(knex2, meta.tableName);
|
|
6394
|
+
}
|
|
6395
|
+
}
|
|
6396
|
+
},
|
|
6397
|
+
async down() {
|
|
6398
|
+
throw new Error("not implemented");
|
|
6399
|
+
}
|
|
6400
|
+
};
|
|
6401
|
+
const dropIndex = async (knex2, tableName, columnName) => {
|
|
6402
|
+
try {
|
|
6403
|
+
await knex2.schema.alterTable(tableName, (table) => {
|
|
6404
|
+
table.dropUnique([columnName], `${tableName}_${columnName}_unique`);
|
|
6405
|
+
});
|
|
6406
|
+
} catch (error) {
|
|
6407
|
+
}
|
|
6408
|
+
};
|
|
6409
|
+
const dropSlugFieldsIndex = {
|
|
6410
|
+
name: "5.0.0-05-drop-slug-fields-index",
|
|
6411
|
+
async up(knex2, db) {
|
|
6412
|
+
for (const meta of db.metadata.values()) {
|
|
6413
|
+
const hasTable = await knex2.schema.hasTable(meta.tableName);
|
|
6414
|
+
if (!hasTable) {
|
|
6415
|
+
continue;
|
|
6416
|
+
}
|
|
6417
|
+
for (const attribute of Object.values(meta.attributes)) {
|
|
6418
|
+
if (attribute.type === "uid" && attribute.columnName) {
|
|
6419
|
+
await dropIndex(knex2, meta.tableName, attribute.columnName);
|
|
6420
|
+
}
|
|
6421
|
+
}
|
|
6422
|
+
}
|
|
6423
|
+
},
|
|
6424
|
+
async down() {
|
|
6425
|
+
throw new Error("not implemented");
|
|
6426
|
+
}
|
|
6427
|
+
};
|
|
6218
6428
|
const internalMigrations = [
|
|
6219
6429
|
renameIdentifiersLongerThanMaxLength,
|
|
6220
|
-
createdDocumentId
|
|
6430
|
+
createdDocumentId,
|
|
6431
|
+
createdLocale,
|
|
6432
|
+
createdPublishedAt,
|
|
6433
|
+
dropSlugFieldsIndex
|
|
6221
6434
|
];
|
|
6222
6435
|
const createInternalMigrationProvider = (db) => {
|
|
6223
6436
|
const context = { db };
|
|
6224
6437
|
const migrations = [...internalMigrations];
|
|
6225
6438
|
const umzugProvider = new umzug.Umzug({
|
|
6226
6439
|
storage: createStorage({ db, tableName: "strapi_migrations_internal" }),
|
|
6227
|
-
logger:
|
|
6440
|
+
logger: {
|
|
6441
|
+
info(message) {
|
|
6442
|
+
db.logger.debug(transformLogMessage("info", message));
|
|
6443
|
+
},
|
|
6444
|
+
warn(message) {
|
|
6445
|
+
db.logger.warn(transformLogMessage("warn", message));
|
|
6446
|
+
},
|
|
6447
|
+
error(message) {
|
|
6448
|
+
db.logger.error(transformLogMessage("error", message));
|
|
6449
|
+
},
|
|
6450
|
+
debug(message) {
|
|
6451
|
+
db.logger.debug(transformLogMessage("debug", message));
|
|
6452
|
+
}
|
|
6453
|
+
},
|
|
6228
6454
|
context,
|
|
6229
6455
|
migrations: () => migrations.map((migration) => {
|
|
6230
6456
|
return {
|
|
@@ -6495,6 +6721,7 @@ class Database {
|
|
|
6495
6721
|
migrations;
|
|
6496
6722
|
lifecycles;
|
|
6497
6723
|
entityManager;
|
|
6724
|
+
logger;
|
|
6498
6725
|
constructor(config) {
|
|
6499
6726
|
this.config = {
|
|
6500
6727
|
...config,
|
|
@@ -6514,6 +6741,7 @@ class Database {
|
|
|
6514
6741
|
this.migrations = createMigrationsProvider(this);
|
|
6515
6742
|
this.lifecycles = createLifecyclesProvider(this);
|
|
6516
6743
|
this.entityManager = createEntityManager(this);
|
|
6744
|
+
this.logger = config.logger ?? console;
|
|
6517
6745
|
}
|
|
6518
6746
|
async init({ models }) {
|
|
6519
6747
|
this.metadata.loadModels(models);
|