@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.mjs
CHANGED
|
@@ -5,11 +5,11 @@ import _, { isNil, castArray, prop, omit, isInteger, snakeCase, partition, sumBy
|
|
|
5
5
|
import crypto from "crypto";
|
|
6
6
|
import crypto$1 from "node:crypto";
|
|
7
7
|
import * as dateFns from "date-fns";
|
|
8
|
-
import {
|
|
8
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
9
9
|
import KnexBuilder from "knex/lib/query/querybuilder";
|
|
10
10
|
import KnexRaw from "knex/lib/raw";
|
|
11
|
+
import { isOperatorOfType, isOperator } from "@strapi/utils";
|
|
11
12
|
import { Readable } from "stream";
|
|
12
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
13
13
|
import _$1 from "lodash";
|
|
14
14
|
import { Umzug } from "umzug";
|
|
15
15
|
import { createId } from "@paralleldrive/cuid2";
|
|
@@ -1087,7 +1087,7 @@ const createHelpers = (db) => {
|
|
|
1087
1087
|
}
|
|
1088
1088
|
}
|
|
1089
1089
|
};
|
|
1090
|
-
const
|
|
1090
|
+
const dropIndex2 = (tableBuilder, index2) => {
|
|
1091
1091
|
if (!db.config.settings?.forceMigration) {
|
|
1092
1092
|
return;
|
|
1093
1093
|
}
|
|
@@ -1164,13 +1164,13 @@ const createHelpers = (db) => {
|
|
|
1164
1164
|
for (const removedIndex of table.indexes.removed) {
|
|
1165
1165
|
if (!ignoreForeignKeyNames.includes(removedIndex.name)) {
|
|
1166
1166
|
debug$2(`Dropping index ${removedIndex.name} on ${table.name}`);
|
|
1167
|
-
|
|
1167
|
+
dropIndex2(tableBuilder, removedIndex);
|
|
1168
1168
|
}
|
|
1169
1169
|
}
|
|
1170
1170
|
for (const updatedIndex of table.indexes.updated) {
|
|
1171
1171
|
if (!ignoreForeignKeyNames.includes(updatedIndex.name)) {
|
|
1172
1172
|
debug$2(`Dropping updated index ${updatedIndex.name} on ${table.name}`);
|
|
1173
|
-
|
|
1173
|
+
dropIndex2(tableBuilder, updatedIndex.object);
|
|
1174
1174
|
}
|
|
1175
1175
|
}
|
|
1176
1176
|
for (const updatedColumn of table.columns.updated) {
|
|
@@ -2895,6 +2895,68 @@ const createField = (attribute) => {
|
|
|
2895
2895
|
}
|
|
2896
2896
|
throw new Error(`Undefined field for type ${type}`);
|
|
2897
2897
|
};
|
|
2898
|
+
const storage = new AsyncLocalStorage();
|
|
2899
|
+
const transactionCtx = {
|
|
2900
|
+
async run(trx, cb) {
|
|
2901
|
+
const store = storage.getStore();
|
|
2902
|
+
return storage.run(
|
|
2903
|
+
{
|
|
2904
|
+
trx,
|
|
2905
|
+
// Fill with existing callbacks if nesting transactions
|
|
2906
|
+
commitCallbacks: store?.commitCallbacks || [],
|
|
2907
|
+
rollbackCallbacks: store?.rollbackCallbacks || []
|
|
2908
|
+
},
|
|
2909
|
+
cb
|
|
2910
|
+
);
|
|
2911
|
+
},
|
|
2912
|
+
get() {
|
|
2913
|
+
const store = storage.getStore();
|
|
2914
|
+
return store?.trx;
|
|
2915
|
+
},
|
|
2916
|
+
async commit(trx) {
|
|
2917
|
+
const store = storage.getStore();
|
|
2918
|
+
if (store?.trx) {
|
|
2919
|
+
store.trx = null;
|
|
2920
|
+
}
|
|
2921
|
+
await trx.commit();
|
|
2922
|
+
if (!store?.commitCallbacks.length) {
|
|
2923
|
+
return;
|
|
2924
|
+
}
|
|
2925
|
+
store.commitCallbacks.forEach((cb) => cb());
|
|
2926
|
+
store.commitCallbacks = [];
|
|
2927
|
+
},
|
|
2928
|
+
async rollback(trx) {
|
|
2929
|
+
const store = storage.getStore();
|
|
2930
|
+
if (store?.trx) {
|
|
2931
|
+
store.trx = null;
|
|
2932
|
+
}
|
|
2933
|
+
await trx.rollback();
|
|
2934
|
+
if (!store?.rollbackCallbacks.length) {
|
|
2935
|
+
return;
|
|
2936
|
+
}
|
|
2937
|
+
store.rollbackCallbacks.forEach((cb) => cb());
|
|
2938
|
+
store.rollbackCallbacks = [];
|
|
2939
|
+
},
|
|
2940
|
+
onCommit(cb) {
|
|
2941
|
+
const store = storage.getStore();
|
|
2942
|
+
if (store?.commitCallbacks) {
|
|
2943
|
+
store.commitCallbacks.push(cb);
|
|
2944
|
+
}
|
|
2945
|
+
},
|
|
2946
|
+
onRollback(cb) {
|
|
2947
|
+
const store = storage.getStore();
|
|
2948
|
+
if (store?.rollbackCallbacks) {
|
|
2949
|
+
store.rollbackCallbacks.push(cb);
|
|
2950
|
+
}
|
|
2951
|
+
}
|
|
2952
|
+
};
|
|
2953
|
+
function isKnexQuery(value) {
|
|
2954
|
+
return value instanceof KnexBuilder || value instanceof KnexRaw;
|
|
2955
|
+
}
|
|
2956
|
+
const addSchema = (db, tableName) => {
|
|
2957
|
+
const schemaName = db.getSchemaName();
|
|
2958
|
+
return schemaName ? `${schemaName}.${tableName}` : tableName;
|
|
2959
|
+
};
|
|
2898
2960
|
const fromSingleRow = (meta, row) => {
|
|
2899
2961
|
const { attributes } = meta;
|
|
2900
2962
|
if (_.isNil(row)) {
|
|
@@ -3017,7 +3079,7 @@ const escapeQuery = (query, charsToEscape, escapeChar = "\\") => {
|
|
|
3017
3079
|
""
|
|
3018
3080
|
);
|
|
3019
3081
|
};
|
|
3020
|
-
const createPivotJoin = (ctx, { alias, refAlias, joinTable, targetMeta }) => {
|
|
3082
|
+
const createPivotJoin = (ctx, { alias: alias2, refAlias, joinTable, targetMeta }) => {
|
|
3021
3083
|
const { qb } = ctx;
|
|
3022
3084
|
const joinAlias = qb.getAlias();
|
|
3023
3085
|
qb.join({
|
|
@@ -3025,7 +3087,7 @@ const createPivotJoin = (ctx, { alias, refAlias, joinTable, targetMeta }) => {
|
|
|
3025
3087
|
referencedTable: joinTable.name,
|
|
3026
3088
|
referencedColumn: joinTable.joinColumn.name,
|
|
3027
3089
|
rootColumn: joinTable.joinColumn.referencedColumn,
|
|
3028
|
-
rootTable:
|
|
3090
|
+
rootTable: alias2,
|
|
3029
3091
|
on: joinTable.on
|
|
3030
3092
|
});
|
|
3031
3093
|
const subAlias = refAlias || qb.getAlias();
|
|
@@ -3038,7 +3100,7 @@ const createPivotJoin = (ctx, { alias, refAlias, joinTable, targetMeta }) => {
|
|
|
3038
3100
|
});
|
|
3039
3101
|
return subAlias;
|
|
3040
3102
|
};
|
|
3041
|
-
const createJoin = (ctx, { alias, refAlias, attributeName, attribute }) => {
|
|
3103
|
+
const createJoin = (ctx, { alias: alias2, refAlias, attributeName, attribute }) => {
|
|
3042
3104
|
const { db, qb, uid } = ctx;
|
|
3043
3105
|
if (attribute.type !== "relation") {
|
|
3044
3106
|
throw new Error(`Cannot join on non relational field ${attributeName}`);
|
|
@@ -3054,7 +3116,7 @@ const createJoin = (ctx, { alias, refAlias, attributeName, attribute }) => {
|
|
|
3054
3116
|
referencedTable: targetMeta.tableName,
|
|
3055
3117
|
referencedColumn: morphColumn.idColumn.name,
|
|
3056
3118
|
rootColumn: morphColumn.idColumn.referencedColumn,
|
|
3057
|
-
rootTable:
|
|
3119
|
+
rootTable: alias2,
|
|
3058
3120
|
on: {
|
|
3059
3121
|
[morphColumn.typeColumn.name]: uid,
|
|
3060
3122
|
...morphColumn.on
|
|
@@ -3069,7 +3131,7 @@ const createJoin = (ctx, { alias, refAlias, attributeName, attribute }) => {
|
|
|
3069
3131
|
referencedTable: joinTable2.name,
|
|
3070
3132
|
referencedColumn: joinTable2.morphColumn.idColumn.name,
|
|
3071
3133
|
rootColumn: joinTable2.morphColumn.idColumn.referencedColumn,
|
|
3072
|
-
rootTable:
|
|
3134
|
+
rootTable: alias2,
|
|
3073
3135
|
on: {
|
|
3074
3136
|
[joinTable2.morphColumn.typeColumn.name]: uid,
|
|
3075
3137
|
field: attributeName
|
|
@@ -3085,7 +3147,7 @@ const createJoin = (ctx, { alias, refAlias, attributeName, attribute }) => {
|
|
|
3085
3147
|
});
|
|
3086
3148
|
return subAlias;
|
|
3087
3149
|
}
|
|
3088
|
-
return
|
|
3150
|
+
return alias2;
|
|
3089
3151
|
}
|
|
3090
3152
|
const { joinColumn } = attribute;
|
|
3091
3153
|
if (joinColumn) {
|
|
@@ -3095,20 +3157,20 @@ const createJoin = (ctx, { alias, refAlias, attributeName, attribute }) => {
|
|
|
3095
3157
|
referencedTable: targetMeta.tableName,
|
|
3096
3158
|
referencedColumn: joinColumn.referencedColumn,
|
|
3097
3159
|
rootColumn: joinColumn.name,
|
|
3098
|
-
rootTable:
|
|
3160
|
+
rootTable: alias2
|
|
3099
3161
|
});
|
|
3100
3162
|
return subAlias;
|
|
3101
3163
|
}
|
|
3102
3164
|
const { joinTable } = attribute;
|
|
3103
3165
|
if (joinTable) {
|
|
3104
|
-
return createPivotJoin(ctx, { alias, refAlias, joinTable, targetMeta });
|
|
3166
|
+
return createPivotJoin(ctx, { alias: alias2, refAlias, joinTable, targetMeta });
|
|
3105
3167
|
}
|
|
3106
|
-
return
|
|
3168
|
+
return alias2;
|
|
3107
3169
|
};
|
|
3108
3170
|
const applyJoin = (qb, join) => {
|
|
3109
3171
|
const {
|
|
3110
3172
|
method = "leftJoin",
|
|
3111
|
-
alias,
|
|
3173
|
+
alias: alias2,
|
|
3112
3174
|
referencedTable,
|
|
3113
3175
|
referencedColumn,
|
|
3114
3176
|
rootColumn,
|
|
@@ -3118,26 +3180,28 @@ const applyJoin = (qb, join) => {
|
|
|
3118
3180
|
on,
|
|
3119
3181
|
orderBy
|
|
3120
3182
|
} = join;
|
|
3121
|
-
qb[method](`${referencedTable} as ${
|
|
3122
|
-
inner.on(`${rootTable}.${rootColumn}`, `${
|
|
3183
|
+
qb[method](`${referencedTable} as ${alias2}`, (inner) => {
|
|
3184
|
+
inner.on(`${rootTable}.${rootColumn}`, `${alias2}.${referencedColumn}`);
|
|
3123
3185
|
if (on) {
|
|
3124
3186
|
for (const key of Object.keys(on)) {
|
|
3125
|
-
inner.onVal(`${
|
|
3187
|
+
inner.onVal(`${alias2}.${key}`, on[key]);
|
|
3126
3188
|
}
|
|
3127
3189
|
}
|
|
3128
3190
|
});
|
|
3129
3191
|
if (orderBy) {
|
|
3130
3192
|
Object.keys(orderBy).forEach((column) => {
|
|
3131
3193
|
const direction = orderBy[column];
|
|
3132
|
-
qb.orderBy(`${
|
|
3194
|
+
qb.orderBy(`${alias2}.${column}`, direction);
|
|
3133
3195
|
});
|
|
3134
3196
|
}
|
|
3135
3197
|
};
|
|
3136
3198
|
const applyJoins = (qb, joins) => {
|
|
3137
3199
|
return joins.forEach((join) => applyJoin(qb, join));
|
|
3138
3200
|
};
|
|
3201
|
+
const COL_STRAPI_ROW_NUMBER = "__strapi_row_number";
|
|
3202
|
+
const COL_STRAPI_ORDER_BY_PREFIX = "__strapi_order_by";
|
|
3139
3203
|
const processOrderBy = (orderBy, ctx) => {
|
|
3140
|
-
const { db, uid, qb, alias } = ctx;
|
|
3204
|
+
const { db, uid, qb, alias: alias2 } = ctx;
|
|
3141
3205
|
const meta = db.metadata.get(uid);
|
|
3142
3206
|
const { attributes } = meta;
|
|
3143
3207
|
if (typeof orderBy === "string") {
|
|
@@ -3146,7 +3210,7 @@ const processOrderBy = (orderBy, ctx) => {
|
|
|
3146
3210
|
throw new Error(`Attribute ${orderBy} not found on model ${uid}`);
|
|
3147
3211
|
}
|
|
3148
3212
|
const columnName = toColumnName(meta, orderBy);
|
|
3149
|
-
return [{ column: qb.aliasColumn(columnName,
|
|
3213
|
+
return [{ column: qb.aliasColumn(columnName, alias2) }];
|
|
3150
3214
|
}
|
|
3151
3215
|
if (Array.isArray(orderBy)) {
|
|
3152
3216
|
return orderBy.flatMap((value) => processOrderBy(value, ctx));
|
|
@@ -3160,11 +3224,11 @@ const processOrderBy = (orderBy, ctx) => {
|
|
|
3160
3224
|
}
|
|
3161
3225
|
if (isScalar(attribute.type)) {
|
|
3162
3226
|
const columnName = toColumnName(meta, key);
|
|
3163
|
-
return { column: qb.aliasColumn(columnName,
|
|
3227
|
+
return { column: qb.aliasColumn(columnName, alias2), order: direction };
|
|
3164
3228
|
}
|
|
3165
3229
|
if (attribute.type === "relation" && "target" in attribute) {
|
|
3166
3230
|
const subAlias = createJoin(ctx, {
|
|
3167
|
-
alias:
|
|
3231
|
+
alias: alias2 || qb.alias,
|
|
3168
3232
|
attributeName: key,
|
|
3169
3233
|
attribute
|
|
3170
3234
|
});
|
|
@@ -3180,6 +3244,76 @@ const processOrderBy = (orderBy, ctx) => {
|
|
|
3180
3244
|
}
|
|
3181
3245
|
throw new Error("Invalid orderBy syntax");
|
|
3182
3246
|
};
|
|
3247
|
+
const getStrapiOrderColumnAlias = (column) => {
|
|
3248
|
+
const trimmedColumnName = column.replaceAll(".", "_");
|
|
3249
|
+
return `${COL_STRAPI_ORDER_BY_PREFIX}__${trimmedColumnName}`;
|
|
3250
|
+
};
|
|
3251
|
+
const wrapWithDeepSort = (originalQuery, ctx) => {
|
|
3252
|
+
const { db, qb, uid } = ctx;
|
|
3253
|
+
const { tableName } = db.metadata.get(uid);
|
|
3254
|
+
const orderBy = _.cloneDeep(qb.state.orderBy);
|
|
3255
|
+
const resultQueryAlias = qb.getAlias();
|
|
3256
|
+
const aliasedTableName = qb.mustUseAlias() ? alias(resultQueryAlias, tableName) : tableName;
|
|
3257
|
+
const resultQuery = db.getConnection(aliasedTableName);
|
|
3258
|
+
const baseQuery = originalQuery.clone();
|
|
3259
|
+
const baseQueryAlias = qb.getAlias();
|
|
3260
|
+
baseQuery.clear("select").clear("order").clear("limit").clear("offset");
|
|
3261
|
+
baseQuery.select(
|
|
3262
|
+
// Always select the row id for future manipulation
|
|
3263
|
+
prefix(qb.alias, "id"),
|
|
3264
|
+
...orderBy.map(
|
|
3265
|
+
(orderByClause) => alias(getStrapiOrderColumnAlias(orderByClause.column), orderByClause.column)
|
|
3266
|
+
)
|
|
3267
|
+
);
|
|
3268
|
+
const partitionedQueryAlias = qb.getAlias();
|
|
3269
|
+
const selectRowsAsNumberedPartitions = (partitionedQuery) => {
|
|
3270
|
+
const prefixedOrderBy = orderBy.map((orderByClause) => ({
|
|
3271
|
+
column: prefix(baseQueryAlias, getStrapiOrderColumnAlias(orderByClause.column)),
|
|
3272
|
+
order: orderByClause.order
|
|
3273
|
+
}));
|
|
3274
|
+
const orderByColumns = prefixedOrderBy.map(_.prop("column"));
|
|
3275
|
+
partitionedQuery.select(
|
|
3276
|
+
// Always select baseQuery.id
|
|
3277
|
+
prefix(baseQueryAlias, "id"),
|
|
3278
|
+
...orderByColumns
|
|
3279
|
+
).rowNumber(COL_STRAPI_ROW_NUMBER, (subQuery) => {
|
|
3280
|
+
for (const orderByClause of prefixedOrderBy) {
|
|
3281
|
+
subQuery.orderBy(orderByClause.column, orderByClause.order, "last");
|
|
3282
|
+
}
|
|
3283
|
+
subQuery.partitionBy(`${baseQueryAlias}.id`);
|
|
3284
|
+
}).from(baseQuery.as(baseQueryAlias)).as(partitionedQueryAlias);
|
|
3285
|
+
};
|
|
3286
|
+
const originalSelect = _.difference(
|
|
3287
|
+
qb.state.select,
|
|
3288
|
+
// Remove order by columns from the initial select
|
|
3289
|
+
qb.state.orderBy.map(_.prop("column"))
|
|
3290
|
+
).map(prefix(resultQueryAlias));
|
|
3291
|
+
resultQuery.select(originalSelect).innerJoin(selectRowsAsNumberedPartitions, function() {
|
|
3292
|
+
this.on(`${partitionedQueryAlias}.id`, `${resultQueryAlias}.id`).andOnVal(`${partitionedQueryAlias}.${COL_STRAPI_ROW_NUMBER}`, "=", 1);
|
|
3293
|
+
});
|
|
3294
|
+
if (qb.state.limit) {
|
|
3295
|
+
resultQuery.limit(qb.state.limit);
|
|
3296
|
+
}
|
|
3297
|
+
if (qb.state.offset) {
|
|
3298
|
+
resultQuery.offset(qb.state.offset);
|
|
3299
|
+
}
|
|
3300
|
+
if (qb.state.first) {
|
|
3301
|
+
resultQuery.first();
|
|
3302
|
+
}
|
|
3303
|
+
resultQuery.orderBy([
|
|
3304
|
+
// Transform "order by" clause to their T alias and prefix them with T alias
|
|
3305
|
+
...orderBy.map((orderByClause) => ({
|
|
3306
|
+
column: prefix(partitionedQueryAlias, getStrapiOrderColumnAlias(orderByClause.column)),
|
|
3307
|
+
order: orderByClause.order
|
|
3308
|
+
})),
|
|
3309
|
+
// Add T.id to the order by clause to get consistent results in case several rows have the exact same order
|
|
3310
|
+
{ column: `${partitionedQueryAlias}.id`, order: "asc" }
|
|
3311
|
+
]);
|
|
3312
|
+
return resultQuery;
|
|
3313
|
+
};
|
|
3314
|
+
const alias = _.curry((alias2, value) => `${value} as ${alias2}`);
|
|
3315
|
+
const prefix = _.curry((prefix2, value) => `${prefix2}.${value}`);
|
|
3316
|
+
const joinColPrefix = "__strapi";
|
|
3183
3317
|
const XtoOne = async (input, ctx) => {
|
|
3184
3318
|
const { attribute, attributeName, results, populateValue, targetMeta, isCount } = input;
|
|
3185
3319
|
const { db, qb } = ctx;
|
|
@@ -3206,8 +3340,10 @@ const XtoOne = async (input, ctx) => {
|
|
|
3206
3340
|
const { joinTable } = attribute;
|
|
3207
3341
|
const qb2 = db.entityManager.createQueryBuilder(targetMeta.uid);
|
|
3208
3342
|
const { name: joinColumnName, referencedColumn: referencedColumnName } = joinTable.joinColumn;
|
|
3209
|
-
const
|
|
3210
|
-
const joinColAlias = `${
|
|
3343
|
+
const alias2 = qb2.getAlias();
|
|
3344
|
+
const joinColAlias = `${alias2}.${joinColumnName}`;
|
|
3345
|
+
const joinColRenameAs = `${joinColPrefix}${joinColumnName}`;
|
|
3346
|
+
const joinColSelect = `${joinColAlias} as ${joinColRenameAs}`;
|
|
3211
3347
|
const referencedValues = _.uniq(
|
|
3212
3348
|
results.map((r) => r[referencedColumnName]).filter((value) => !_.isNil(value))
|
|
3213
3349
|
);
|
|
@@ -3219,7 +3355,7 @@ const XtoOne = async (input, ctx) => {
|
|
|
3219
3355
|
return;
|
|
3220
3356
|
}
|
|
3221
3357
|
const rows2 = await qb2.init(populateValue).join({
|
|
3222
|
-
alias,
|
|
3358
|
+
alias: alias2,
|
|
3223
3359
|
referencedTable: joinTable.name,
|
|
3224
3360
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3225
3361
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
@@ -3245,15 +3381,15 @@ const XtoOne = async (input, ctx) => {
|
|
|
3245
3381
|
return;
|
|
3246
3382
|
}
|
|
3247
3383
|
const rows = await qb2.init(populateValue).join({
|
|
3248
|
-
alias,
|
|
3384
|
+
alias: alias2,
|
|
3249
3385
|
referencedTable: joinTable.name,
|
|
3250
3386
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3251
3387
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
3252
3388
|
rootTable: qb2.alias,
|
|
3253
3389
|
on: joinTable.on,
|
|
3254
3390
|
orderBy: joinTable.orderBy
|
|
3255
|
-
}).addSelect(
|
|
3256
|
-
const map2 = _.groupBy(
|
|
3391
|
+
}).addSelect(joinColSelect).where({ [joinColAlias]: referencedValues }).execute({ mapResults: false });
|
|
3392
|
+
const map2 = _.groupBy(joinColRenameAs)(rows);
|
|
3257
3393
|
results.forEach((result) => {
|
|
3258
3394
|
result[attributeName] = fromTargetRow(_.first(map2[result[referencedColumnName]]));
|
|
3259
3395
|
});
|
|
@@ -3285,8 +3421,10 @@ const oneToMany = async (input, ctx) => {
|
|
|
3285
3421
|
const { joinTable } = attribute;
|
|
3286
3422
|
const qb2 = db.entityManager.createQueryBuilder(targetMeta.uid);
|
|
3287
3423
|
const { name: joinColumnName, referencedColumn: referencedColumnName } = joinTable.joinColumn;
|
|
3288
|
-
const
|
|
3289
|
-
const joinColAlias = `${
|
|
3424
|
+
const alias2 = qb2.getAlias();
|
|
3425
|
+
const joinColAlias = `${alias2}.${joinColumnName}`;
|
|
3426
|
+
const joinColRenameAs = `${joinColPrefix}${joinColumnName}`;
|
|
3427
|
+
const joinColSelect = `${joinColAlias} as ${joinColRenameAs}`;
|
|
3290
3428
|
const referencedValues = _.uniq(
|
|
3291
3429
|
results.map((r) => r[referencedColumnName]).filter((value) => !_.isNil(value))
|
|
3292
3430
|
);
|
|
@@ -3298,16 +3436,16 @@ const oneToMany = async (input, ctx) => {
|
|
|
3298
3436
|
return;
|
|
3299
3437
|
}
|
|
3300
3438
|
const rows2 = await qb2.init(populateValue).join({
|
|
3301
|
-
alias,
|
|
3439
|
+
alias: alias2,
|
|
3302
3440
|
referencedTable: joinTable.name,
|
|
3303
3441
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3304
3442
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
3305
3443
|
rootTable: qb2.alias,
|
|
3306
3444
|
on: joinTable.on
|
|
3307
|
-
}).select([
|
|
3445
|
+
}).select([joinColSelect, qb2.raw("count(*) AS count")]).where({ [joinColAlias]: referencedValues }).groupBy(joinColAlias).execute({ mapResults: false });
|
|
3308
3446
|
const map22 = rows2.reduce(
|
|
3309
3447
|
(map3, row) => {
|
|
3310
|
-
map3[row[
|
|
3448
|
+
map3[row[joinColRenameAs]] = { count: Number(row.count) };
|
|
3311
3449
|
return map3;
|
|
3312
3450
|
},
|
|
3313
3451
|
{}
|
|
@@ -3324,15 +3462,15 @@ const oneToMany = async (input, ctx) => {
|
|
|
3324
3462
|
return;
|
|
3325
3463
|
}
|
|
3326
3464
|
const rows = await qb2.init(populateValue).join({
|
|
3327
|
-
alias,
|
|
3465
|
+
alias: alias2,
|
|
3328
3466
|
referencedTable: joinTable.name,
|
|
3329
3467
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3330
3468
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
3331
3469
|
rootTable: qb2.alias,
|
|
3332
3470
|
on: joinTable.on,
|
|
3333
3471
|
orderBy: _.mapValues((v) => populateValue.ordering || v, joinTable.orderBy)
|
|
3334
|
-
}).addSelect(
|
|
3335
|
-
const map2 = _.groupBy(
|
|
3472
|
+
}).addSelect(joinColSelect).where({ [joinColAlias]: referencedValues }).execute({ mapResults: false });
|
|
3473
|
+
const map2 = _.groupBy(joinColRenameAs)(rows);
|
|
3336
3474
|
results.forEach((r) => {
|
|
3337
3475
|
r[attributeName] = fromTargetRow(map2[r[referencedColumnName]] || []);
|
|
3338
3476
|
});
|
|
@@ -3345,8 +3483,10 @@ const manyToMany = async (input, ctx) => {
|
|
|
3345
3483
|
const { joinTable } = attribute;
|
|
3346
3484
|
const populateQb = db.entityManager.createQueryBuilder(targetMeta.uid);
|
|
3347
3485
|
const { name: joinColumnName, referencedColumn: referencedColumnName } = joinTable.joinColumn;
|
|
3348
|
-
const
|
|
3349
|
-
const joinColAlias = `${
|
|
3486
|
+
const alias2 = populateQb.getAlias();
|
|
3487
|
+
const joinColAlias = `${alias2}.${joinColumnName}`;
|
|
3488
|
+
const joinColRenameAs = `${joinColPrefix}${joinColumnName}`;
|
|
3489
|
+
const joinColSelect = `${joinColAlias} as ${joinColRenameAs}`;
|
|
3350
3490
|
const referencedValues = _.uniq(
|
|
3351
3491
|
results.map((r) => r[referencedColumnName]).filter((value) => !_.isNil(value))
|
|
3352
3492
|
);
|
|
@@ -3358,7 +3498,7 @@ const manyToMany = async (input, ctx) => {
|
|
|
3358
3498
|
return;
|
|
3359
3499
|
}
|
|
3360
3500
|
const rows2 = await populateQb.init(populateValue).join({
|
|
3361
|
-
alias,
|
|
3501
|
+
alias: alias2,
|
|
3362
3502
|
referencedTable: joinTable.name,
|
|
3363
3503
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3364
3504
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
@@ -3384,15 +3524,15 @@ const manyToMany = async (input, ctx) => {
|
|
|
3384
3524
|
return;
|
|
3385
3525
|
}
|
|
3386
3526
|
const rows = await populateQb.init(populateValue).join({
|
|
3387
|
-
alias,
|
|
3527
|
+
alias: alias2,
|
|
3388
3528
|
referencedTable: joinTable.name,
|
|
3389
3529
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3390
3530
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
3391
3531
|
rootTable: populateQb.alias,
|
|
3392
3532
|
on: joinTable.on,
|
|
3393
3533
|
orderBy: _.mapValues((v) => populateValue.ordering || v, joinTable.orderBy)
|
|
3394
|
-
}).addSelect(
|
|
3395
|
-
const map2 = _.groupBy(
|
|
3534
|
+
}).addSelect(joinColSelect).where({ [joinColAlias]: referencedValues }).execute({ mapResults: false });
|
|
3535
|
+
const map2 = _.groupBy(joinColRenameAs)(rows);
|
|
3396
3536
|
results.forEach((result) => {
|
|
3397
3537
|
result[attributeName] = fromTargetRow(map2[result[referencedColumnName]] || []);
|
|
3398
3538
|
});
|
|
@@ -3435,9 +3575,9 @@ const morphX = async (input, ctx) => {
|
|
|
3435
3575
|
return;
|
|
3436
3576
|
}
|
|
3437
3577
|
const qb = db.entityManager.createQueryBuilder(target);
|
|
3438
|
-
const
|
|
3578
|
+
const alias2 = qb.getAlias();
|
|
3439
3579
|
const rows = await qb.init(populateValue).join({
|
|
3440
|
-
alias,
|
|
3580
|
+
alias: alias2,
|
|
3441
3581
|
referencedTable: joinTable.name,
|
|
3442
3582
|
referencedColumn: joinColumn.name,
|
|
3443
3583
|
rootColumn: joinColumn.referencedColumn,
|
|
@@ -3447,9 +3587,9 @@ const morphX = async (input, ctx) => {
|
|
|
3447
3587
|
field: attributeName
|
|
3448
3588
|
},
|
|
3449
3589
|
orderBy: _.mapValues((v) => populateValue.ordering || v, joinTable.orderBy)
|
|
3450
|
-
}).addSelect([`${
|
|
3451
|
-
[`${
|
|
3452
|
-
[`${
|
|
3590
|
+
}).addSelect([`${alias2}.${idColumn.name}`, `${alias2}.${typeColumn.name}`]).where({
|
|
3591
|
+
[`${alias2}.${idColumn.name}`]: referencedValues,
|
|
3592
|
+
[`${alias2}.${typeColumn.name}`]: uid
|
|
3453
3593
|
}).execute({ mapResults: false });
|
|
3454
3594
|
const map2 = _.groupBy(idColumn.name)(rows);
|
|
3455
3595
|
results.forEach((result) => {
|
|
@@ -3698,13 +3838,6 @@ const processPopulate = (populate, ctx) => {
|
|
|
3698
3838
|
}
|
|
3699
3839
|
return finalPopulate;
|
|
3700
3840
|
};
|
|
3701
|
-
function isKnexQuery(value) {
|
|
3702
|
-
return value instanceof KnexBuilder || value instanceof KnexRaw;
|
|
3703
|
-
}
|
|
3704
|
-
const addSchema = (db, tableName) => {
|
|
3705
|
-
const schemaName = db.getSchemaName();
|
|
3706
|
-
return schemaName ? `${schemaName}.${tableName}` : tableName;
|
|
3707
|
-
};
|
|
3708
3841
|
const isRecord$1 = (value) => isPlainObject(value);
|
|
3709
3842
|
const castValue = (value, attribute) => {
|
|
3710
3843
|
if (!attribute) {
|
|
@@ -3746,8 +3879,8 @@ const processNested = (where, ctx) => {
|
|
|
3746
3879
|
return processWhere(where, ctx);
|
|
3747
3880
|
};
|
|
3748
3881
|
const processRelationWhere = (where, ctx) => {
|
|
3749
|
-
const { qb, alias } = ctx;
|
|
3750
|
-
const idAlias = qb.aliasColumn("id",
|
|
3882
|
+
const { qb, alias: alias2 } = ctx;
|
|
3883
|
+
const idAlias = qb.aliasColumn("id", alias2);
|
|
3751
3884
|
if (!isRecord$1(where)) {
|
|
3752
3885
|
return { [idAlias]: where };
|
|
3753
3886
|
}
|
|
@@ -3763,6 +3896,9 @@ const processRelationWhere = (where, ctx) => {
|
|
|
3763
3896
|
}
|
|
3764
3897
|
if (operatorKeys.length === 1) {
|
|
3765
3898
|
const operator = operatorKeys[0];
|
|
3899
|
+
if (isOperatorOfType("group", operator)) {
|
|
3900
|
+
return processWhere(where, ctx);
|
|
3901
|
+
}
|
|
3766
3902
|
return { [idAlias]: { [operator]: processNested(where[operator], ctx) } };
|
|
3767
3903
|
}
|
|
3768
3904
|
return processWhere(where, ctx);
|
|
@@ -3774,7 +3910,7 @@ function processWhere(where, ctx) {
|
|
|
3774
3910
|
if (isArray(where)) {
|
|
3775
3911
|
return where.map((sub) => processWhere(sub, ctx));
|
|
3776
3912
|
}
|
|
3777
|
-
const { db, uid, qb, alias } = ctx;
|
|
3913
|
+
const { db, uid, qb, alias: alias2 } = ctx;
|
|
3778
3914
|
const meta = db.metadata.get(uid);
|
|
3779
3915
|
const filters = {};
|
|
3780
3916
|
for (const key of Object.keys(where)) {
|
|
@@ -3797,12 +3933,12 @@ function processWhere(where, ctx) {
|
|
|
3797
3933
|
}
|
|
3798
3934
|
const attribute = meta.attributes[key];
|
|
3799
3935
|
if (!attribute) {
|
|
3800
|
-
filters[qb.aliasColumn(key,
|
|
3936
|
+
filters[qb.aliasColumn(key, alias2)] = processAttributeWhere(null, value);
|
|
3801
3937
|
continue;
|
|
3802
3938
|
}
|
|
3803
3939
|
if (isRelation(attribute.type) && "target" in attribute) {
|
|
3804
3940
|
const subAlias = createJoin(ctx, {
|
|
3805
|
-
alias:
|
|
3941
|
+
alias: alias2 || qb.alias,
|
|
3806
3942
|
attributeName: key,
|
|
3807
3943
|
attribute
|
|
3808
3944
|
});
|
|
@@ -3817,7 +3953,7 @@ function processWhere(where, ctx) {
|
|
|
3817
3953
|
}
|
|
3818
3954
|
if (isScalar(attribute.type)) {
|
|
3819
3955
|
const columnName = toColumnName(meta, key);
|
|
3820
|
-
const aliasedColumnName = qb.aliasColumn(columnName,
|
|
3956
|
+
const aliasedColumnName = qb.aliasColumn(columnName, alias2);
|
|
3821
3957
|
filters[aliasedColumnName] = processAttributeWhere(attribute, value);
|
|
3822
3958
|
continue;
|
|
3823
3959
|
}
|
|
@@ -4045,7 +4181,7 @@ class ReadableStrapiQuery extends Readable {
|
|
|
4045
4181
|
* Custom ._read() implementation
|
|
4046
4182
|
*
|
|
4047
4183
|
* NOTE: Here "size" means the number of entities to be read from the database.
|
|
4048
|
-
* Not the actual byte size, as it would
|
|
4184
|
+
* Not the actual byte size, as it would mean that we need to return partial entities.
|
|
4049
4185
|
*
|
|
4050
4186
|
*/
|
|
4051
4187
|
async _read(size) {
|
|
@@ -4108,61 +4244,6 @@ class ReadableStrapiQuery extends Readable {
|
|
|
4108
4244
|
}
|
|
4109
4245
|
}
|
|
4110
4246
|
}
|
|
4111
|
-
const storage = new AsyncLocalStorage();
|
|
4112
|
-
const transactionCtx = {
|
|
4113
|
-
async run(trx, cb) {
|
|
4114
|
-
const store = storage.getStore();
|
|
4115
|
-
return storage.run(
|
|
4116
|
-
{
|
|
4117
|
-
trx,
|
|
4118
|
-
// Fill with existing callbacks if nesting transactions
|
|
4119
|
-
commitCallbacks: store?.commitCallbacks || [],
|
|
4120
|
-
rollbackCallbacks: store?.rollbackCallbacks || []
|
|
4121
|
-
},
|
|
4122
|
-
cb
|
|
4123
|
-
);
|
|
4124
|
-
},
|
|
4125
|
-
get() {
|
|
4126
|
-
const store = storage.getStore();
|
|
4127
|
-
return store?.trx;
|
|
4128
|
-
},
|
|
4129
|
-
async commit(trx) {
|
|
4130
|
-
const store = storage.getStore();
|
|
4131
|
-
if (store?.trx) {
|
|
4132
|
-
store.trx = null;
|
|
4133
|
-
}
|
|
4134
|
-
await trx.commit();
|
|
4135
|
-
if (!store?.commitCallbacks.length) {
|
|
4136
|
-
return;
|
|
4137
|
-
}
|
|
4138
|
-
store.commitCallbacks.forEach((cb) => cb());
|
|
4139
|
-
store.commitCallbacks = [];
|
|
4140
|
-
},
|
|
4141
|
-
async rollback(trx) {
|
|
4142
|
-
const store = storage.getStore();
|
|
4143
|
-
if (store?.trx) {
|
|
4144
|
-
store.trx = null;
|
|
4145
|
-
}
|
|
4146
|
-
await trx.rollback();
|
|
4147
|
-
if (!store?.rollbackCallbacks.length) {
|
|
4148
|
-
return;
|
|
4149
|
-
}
|
|
4150
|
-
store.rollbackCallbacks.forEach((cb) => cb());
|
|
4151
|
-
store.rollbackCallbacks = [];
|
|
4152
|
-
},
|
|
4153
|
-
onCommit(cb) {
|
|
4154
|
-
const store = storage.getStore();
|
|
4155
|
-
if (store?.commitCallbacks) {
|
|
4156
|
-
store.commitCallbacks.push(cb);
|
|
4157
|
-
}
|
|
4158
|
-
},
|
|
4159
|
-
onRollback(cb) {
|
|
4160
|
-
const store = storage.getStore();
|
|
4161
|
-
if (store?.rollbackCallbacks) {
|
|
4162
|
-
store.rollbackCallbacks.push(cb);
|
|
4163
|
-
}
|
|
4164
|
-
}
|
|
4165
|
-
};
|
|
4166
4247
|
const createQueryBuilder = (uid, db, initialState = {}) => {
|
|
4167
4248
|
const meta = db.metadata.get(uid);
|
|
4168
4249
|
const { tableName } = meta;
|
|
@@ -4195,9 +4276,9 @@ const createQueryBuilder = (uid, db, initialState = {}) => {
|
|
|
4195
4276
|
initialState
|
|
4196
4277
|
);
|
|
4197
4278
|
const getAlias = () => {
|
|
4198
|
-
const
|
|
4279
|
+
const alias2 = `t${state.aliasCounter}`;
|
|
4199
4280
|
state.aliasCounter += 1;
|
|
4200
|
-
return
|
|
4281
|
+
return alias2;
|
|
4201
4282
|
};
|
|
4202
4283
|
return {
|
|
4203
4284
|
alias: getAlias(),
|
|
@@ -4364,15 +4445,15 @@ const createQueryBuilder = (uid, db, initialState = {}) => {
|
|
|
4364
4445
|
mustUseAlias() {
|
|
4365
4446
|
return ["select", "count"].includes(state.type);
|
|
4366
4447
|
},
|
|
4367
|
-
aliasColumn(key,
|
|
4448
|
+
aliasColumn(key, alias2) {
|
|
4368
4449
|
if (typeof key !== "string") {
|
|
4369
4450
|
return key;
|
|
4370
4451
|
}
|
|
4371
4452
|
if (key.indexOf(".") >= 0) {
|
|
4372
4453
|
return key;
|
|
4373
4454
|
}
|
|
4374
|
-
if (!_.isNil(
|
|
4375
|
-
return `${
|
|
4455
|
+
if (!_.isNil(alias2)) {
|
|
4456
|
+
return `${alias2}.${key}`;
|
|
4376
4457
|
}
|
|
4377
4458
|
return this.mustUseAlias() ? `${this.alias}.${key}` : key;
|
|
4378
4459
|
},
|
|
@@ -4407,6 +4488,20 @@ const createQueryBuilder = (uid, db, initialState = {}) => {
|
|
|
4407
4488
|
shouldUseDistinct() {
|
|
4408
4489
|
return state.joins.length > 0 && _.isEmpty(state.groupBy);
|
|
4409
4490
|
},
|
|
4491
|
+
shouldUseDeepSort() {
|
|
4492
|
+
return state.orderBy.filter(({ column }) => column.indexOf(".") >= 0).filter(({ column }) => {
|
|
4493
|
+
const col = column.split(".");
|
|
4494
|
+
for (let i = 0; i < col.length - 1; i += 1) {
|
|
4495
|
+
const el = col[i];
|
|
4496
|
+
const isRelationAttribute = meta.attributes[el]?.type === "relation";
|
|
4497
|
+
const isAliasedRelation = Object.values(state.joins).map((join) => join.alias).includes(el);
|
|
4498
|
+
if (isRelationAttribute || isAliasedRelation) {
|
|
4499
|
+
return true;
|
|
4500
|
+
}
|
|
4501
|
+
}
|
|
4502
|
+
return false;
|
|
4503
|
+
}).length > 0;
|
|
4504
|
+
},
|
|
4410
4505
|
processSelect() {
|
|
4411
4506
|
state.select = state.select.map((field) => {
|
|
4412
4507
|
if (isKnexQuery(field)) {
|
|
@@ -4524,6 +4619,9 @@ const createQueryBuilder = (uid, db, initialState = {}) => {
|
|
|
4524
4619
|
if (state.joins.length > 0) {
|
|
4525
4620
|
applyJoins(qb, state.joins);
|
|
4526
4621
|
}
|
|
4622
|
+
if (this.shouldUseDeepSort()) {
|
|
4623
|
+
return wrapWithDeepSort(qb, { qb: this, db, uid });
|
|
4624
|
+
}
|
|
4527
4625
|
return qb;
|
|
4528
4626
|
},
|
|
4529
4627
|
async execute({ mapResults = true } = {}) {
|
|
@@ -4725,7 +4823,7 @@ const deleteRelatedMorphOneRelationsAfterMorphToManyUpdate = async (rows, {
|
|
|
4725
4823
|
await createQueryBuilder(joinTable.name, db).delete().where({ $or: orWhere }).transacting(trx).execute();
|
|
4726
4824
|
}
|
|
4727
4825
|
};
|
|
4728
|
-
const getDocumentSiblingIdsQuery = (
|
|
4826
|
+
const getDocumentSiblingIdsQuery = (tableName, id) => {
|
|
4729
4827
|
const models = Array.from(strapi.db.metadata.values());
|
|
4730
4828
|
const isContentType = models.find((model) => {
|
|
4731
4829
|
return model.tableName === tableName && model.attributes.documentId;
|
|
@@ -4733,10 +4831,11 @@ const getDocumentSiblingIdsQuery = (con, tableName, id) => {
|
|
|
4733
4831
|
if (!isContentType) {
|
|
4734
4832
|
return [id];
|
|
4735
4833
|
}
|
|
4736
|
-
return
|
|
4737
|
-
"document_id",
|
|
4738
|
-
|
|
4739
|
-
|
|
4834
|
+
return function(query) {
|
|
4835
|
+
query.select("id").from(tableName).whereIn("document_id", (documentIDSubQuery) => {
|
|
4836
|
+
documentIDSubQuery.from(tableName).select("document_id").where("id", id);
|
|
4837
|
+
});
|
|
4838
|
+
};
|
|
4740
4839
|
};
|
|
4741
4840
|
const deletePreviousOneToAnyRelations = async ({
|
|
4742
4841
|
id,
|
|
@@ -4753,7 +4852,7 @@ const deletePreviousOneToAnyRelations = async ({
|
|
|
4753
4852
|
const { joinTable } = attribute;
|
|
4754
4853
|
const { joinColumn, inverseJoinColumn } = joinTable;
|
|
4755
4854
|
const con = db.getConnection();
|
|
4756
|
-
await con.delete().from(joinTable.name).whereNotIn(joinColumn.name, getDocumentSiblingIdsQuery(
|
|
4855
|
+
await con.delete().from(joinTable.name).whereNotIn(joinColumn.name, getDocumentSiblingIdsQuery(joinColumn.referencedTable, id)).whereIn(inverseJoinColumn.name, relIdsToadd).where(joinTable.on || {}).transacting(trx);
|
|
4757
4856
|
await cleanOrderColumns({ attribute, db, inverseRelIds: relIdsToadd, transaction: trx });
|
|
4758
4857
|
};
|
|
4759
4858
|
const deletePreviousAnyToOneRelations = async ({
|
|
@@ -4772,7 +4871,7 @@ const deletePreviousAnyToOneRelations = async ({
|
|
|
4772
4871
|
if (isManyToAny(attribute)) {
|
|
4773
4872
|
const relsToDelete = await con.select(inverseJoinColumn.name).from(joinTable.name).where(joinColumn.name, id).whereNotIn(
|
|
4774
4873
|
inverseJoinColumn.name,
|
|
4775
|
-
getDocumentSiblingIdsQuery(
|
|
4874
|
+
getDocumentSiblingIdsQuery(inverseJoinColumn.referencedTable, relIdToadd)
|
|
4776
4875
|
).where(joinTable.on || {}).transacting(trx);
|
|
4777
4876
|
const relIdsToDelete = map(inverseJoinColumn.name, relsToDelete);
|
|
4778
4877
|
await createQueryBuilder(joinTable.name, db).delete().where({
|
|
@@ -4783,7 +4882,7 @@ const deletePreviousAnyToOneRelations = async ({
|
|
|
4783
4882
|
} else {
|
|
4784
4883
|
await con.delete().from(joinTable.name).where(joinColumn.name, id).whereNotIn(
|
|
4785
4884
|
inverseJoinColumn.name,
|
|
4786
|
-
getDocumentSiblingIdsQuery(
|
|
4885
|
+
getDocumentSiblingIdsQuery(inverseJoinColumn.referencedTable, relIdToadd)
|
|
4787
4886
|
).where(joinTable.on || {}).transacting(trx);
|
|
4788
4887
|
}
|
|
4789
4888
|
};
|
|
@@ -5867,6 +5966,21 @@ const createStorage = (opts) => {
|
|
|
5867
5966
|
const wrapTransaction = (db) => (fn) => () => {
|
|
5868
5967
|
return db.transaction(({ trx }) => Promise.resolve(fn(trx, db)));
|
|
5869
5968
|
};
|
|
5969
|
+
const transformLogMessage = (level, message) => {
|
|
5970
|
+
if (typeof message === "string") {
|
|
5971
|
+
return { level, message };
|
|
5972
|
+
}
|
|
5973
|
+
if (typeof message === "object" && message !== null) {
|
|
5974
|
+
if ("event" in message && "name" in message) {
|
|
5975
|
+
return {
|
|
5976
|
+
level,
|
|
5977
|
+
message: `[internal migration]: ${message.event} ${message?.name}`,
|
|
5978
|
+
timestamp: Date.now()
|
|
5979
|
+
};
|
|
5980
|
+
}
|
|
5981
|
+
}
|
|
5982
|
+
return "";
|
|
5983
|
+
};
|
|
5870
5984
|
const migrationResolver = ({ name, path: path2, context }) => {
|
|
5871
5985
|
const { db } = context;
|
|
5872
5986
|
if (!path2) {
|
|
@@ -5895,7 +6009,20 @@ const createUserMigrationProvider = (db) => {
|
|
|
5895
6009
|
const context = { db };
|
|
5896
6010
|
const umzugProvider = new Umzug({
|
|
5897
6011
|
storage: createStorage({ db, tableName: "strapi_migrations" }),
|
|
5898
|
-
logger:
|
|
6012
|
+
logger: {
|
|
6013
|
+
info(message) {
|
|
6014
|
+
db.logger.info(transformLogMessage("info", message));
|
|
6015
|
+
},
|
|
6016
|
+
warn(message) {
|
|
6017
|
+
db.logger.warn(transformLogMessage("warn", message));
|
|
6018
|
+
},
|
|
6019
|
+
error(message) {
|
|
6020
|
+
db.logger.error(transformLogMessage("error", message));
|
|
6021
|
+
},
|
|
6022
|
+
debug(message) {
|
|
6023
|
+
db.logger.debug(transformLogMessage("debug", message));
|
|
6024
|
+
}
|
|
6025
|
+
},
|
|
5899
6026
|
context,
|
|
5900
6027
|
migrations: {
|
|
5901
6028
|
glob: ["*.{js,sql}", { cwd: dir }],
|
|
@@ -6183,16 +6310,115 @@ const findDiffs = (shortMap) => {
|
|
|
6183
6310
|
});
|
|
6184
6311
|
return diffs;
|
|
6185
6312
|
};
|
|
6313
|
+
const createLocaleColumn = async (db, tableName) => {
|
|
6314
|
+
await db.schema.alterTable(tableName, (table) => {
|
|
6315
|
+
table.string("locale");
|
|
6316
|
+
});
|
|
6317
|
+
};
|
|
6318
|
+
const createdLocale = {
|
|
6319
|
+
name: "5.0.0-03-created-locale",
|
|
6320
|
+
async up(knex2, db) {
|
|
6321
|
+
for (const meta of db.metadata.values()) {
|
|
6322
|
+
const hasTable = await knex2.schema.hasTable(meta.tableName);
|
|
6323
|
+
if (!hasTable) {
|
|
6324
|
+
continue;
|
|
6325
|
+
}
|
|
6326
|
+
const uid = meta.uid;
|
|
6327
|
+
const model = strapi.getModel(uid);
|
|
6328
|
+
if (!model) {
|
|
6329
|
+
continue;
|
|
6330
|
+
}
|
|
6331
|
+
const hasLocaleColumn = await knex2.schema.hasColumn(meta.tableName, "locale");
|
|
6332
|
+
if (meta.attributes.locale && !hasLocaleColumn) {
|
|
6333
|
+
await createLocaleColumn(knex2, meta.tableName);
|
|
6334
|
+
}
|
|
6335
|
+
}
|
|
6336
|
+
},
|
|
6337
|
+
async down() {
|
|
6338
|
+
throw new Error("not implemented");
|
|
6339
|
+
}
|
|
6340
|
+
};
|
|
6341
|
+
const createPublishedAtColumn = async (db, tableName) => {
|
|
6342
|
+
await db.schema.alterTable(tableName, (table) => {
|
|
6343
|
+
table.string("published_at");
|
|
6344
|
+
});
|
|
6345
|
+
};
|
|
6346
|
+
const createdPublishedAt = {
|
|
6347
|
+
name: "5.0.0-04-created-published-at",
|
|
6348
|
+
async up(knex2, db) {
|
|
6349
|
+
for (const meta of db.metadata.values()) {
|
|
6350
|
+
const hasTable = await knex2.schema.hasTable(meta.tableName);
|
|
6351
|
+
if (!hasTable) {
|
|
6352
|
+
continue;
|
|
6353
|
+
}
|
|
6354
|
+
const uid = meta.uid;
|
|
6355
|
+
const model = strapi.getModel(uid);
|
|
6356
|
+
if (!model) {
|
|
6357
|
+
continue;
|
|
6358
|
+
}
|
|
6359
|
+
const hasPublishedAtColumn = await knex2.schema.hasColumn(meta.tableName, "published_at");
|
|
6360
|
+
if (meta.attributes.publishedAt && !hasPublishedAtColumn) {
|
|
6361
|
+
await createPublishedAtColumn(knex2, meta.tableName);
|
|
6362
|
+
}
|
|
6363
|
+
}
|
|
6364
|
+
},
|
|
6365
|
+
async down() {
|
|
6366
|
+
throw new Error("not implemented");
|
|
6367
|
+
}
|
|
6368
|
+
};
|
|
6369
|
+
const dropIndex = async (knex2, tableName, columnName) => {
|
|
6370
|
+
try {
|
|
6371
|
+
await knex2.schema.alterTable(tableName, (table) => {
|
|
6372
|
+
table.dropUnique([columnName], `${tableName}_${columnName}_unique`);
|
|
6373
|
+
});
|
|
6374
|
+
} catch (error) {
|
|
6375
|
+
}
|
|
6376
|
+
};
|
|
6377
|
+
const dropSlugFieldsIndex = {
|
|
6378
|
+
name: "5.0.0-05-drop-slug-fields-index",
|
|
6379
|
+
async up(knex2, db) {
|
|
6380
|
+
for (const meta of db.metadata.values()) {
|
|
6381
|
+
const hasTable = await knex2.schema.hasTable(meta.tableName);
|
|
6382
|
+
if (!hasTable) {
|
|
6383
|
+
continue;
|
|
6384
|
+
}
|
|
6385
|
+
for (const attribute of Object.values(meta.attributes)) {
|
|
6386
|
+
if (attribute.type === "uid" && attribute.columnName) {
|
|
6387
|
+
await dropIndex(knex2, meta.tableName, attribute.columnName);
|
|
6388
|
+
}
|
|
6389
|
+
}
|
|
6390
|
+
}
|
|
6391
|
+
},
|
|
6392
|
+
async down() {
|
|
6393
|
+
throw new Error("not implemented");
|
|
6394
|
+
}
|
|
6395
|
+
};
|
|
6186
6396
|
const internalMigrations = [
|
|
6187
6397
|
renameIdentifiersLongerThanMaxLength,
|
|
6188
|
-
createdDocumentId
|
|
6398
|
+
createdDocumentId,
|
|
6399
|
+
createdLocale,
|
|
6400
|
+
createdPublishedAt,
|
|
6401
|
+
dropSlugFieldsIndex
|
|
6189
6402
|
];
|
|
6190
6403
|
const createInternalMigrationProvider = (db) => {
|
|
6191
6404
|
const context = { db };
|
|
6192
6405
|
const migrations = [...internalMigrations];
|
|
6193
6406
|
const umzugProvider = new Umzug({
|
|
6194
6407
|
storage: createStorage({ db, tableName: "strapi_migrations_internal" }),
|
|
6195
|
-
logger:
|
|
6408
|
+
logger: {
|
|
6409
|
+
info(message) {
|
|
6410
|
+
db.logger.debug(transformLogMessage("info", message));
|
|
6411
|
+
},
|
|
6412
|
+
warn(message) {
|
|
6413
|
+
db.logger.warn(transformLogMessage("warn", message));
|
|
6414
|
+
},
|
|
6415
|
+
error(message) {
|
|
6416
|
+
db.logger.error(transformLogMessage("error", message));
|
|
6417
|
+
},
|
|
6418
|
+
debug(message) {
|
|
6419
|
+
db.logger.debug(transformLogMessage("debug", message));
|
|
6420
|
+
}
|
|
6421
|
+
},
|
|
6196
6422
|
context,
|
|
6197
6423
|
migrations: () => migrations.map((migration) => {
|
|
6198
6424
|
return {
|
|
@@ -6463,6 +6689,7 @@ class Database {
|
|
|
6463
6689
|
migrations;
|
|
6464
6690
|
lifecycles;
|
|
6465
6691
|
entityManager;
|
|
6692
|
+
logger;
|
|
6466
6693
|
constructor(config) {
|
|
6467
6694
|
this.config = {
|
|
6468
6695
|
...config,
|
|
@@ -6482,6 +6709,7 @@ class Database {
|
|
|
6482
6709
|
this.migrations = createMigrationsProvider(this);
|
|
6483
6710
|
this.lifecycles = createLifecyclesProvider(this);
|
|
6484
6711
|
this.entityManager = createEntityManager(this);
|
|
6712
|
+
this.logger = config.logger ?? console;
|
|
6485
6713
|
}
|
|
6486
6714
|
async init({ models }) {
|
|
6487
6715
|
this.metadata.loadModels(models);
|