@strapi/database 5.0.0-beta.9 → 5.0.0-rc.1
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 +395 -179
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +395 -179
- package/dist/index.mjs.map +1 -1
- package/dist/migrations/internal-migrations/5.0.0-03-locale.d.ts.map +1 -1
- 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/streams/readable.d.ts +1 -1
- package/dist/query/query-builder.d.ts +3 -2
- package/dist/query/query-builder.d.ts.map +1 -1
- package/dist/schema/diff.d.ts +6 -1
- package/dist/schema/diff.d.ts.map +1 -1
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/storage.d.ts +6 -1
- package/dist/schema/storage.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) {
|
|
@@ -1388,27 +1388,28 @@ const createSchemaDiff = (db) => {
|
|
|
1388
1388
|
}
|
|
1389
1389
|
};
|
|
1390
1390
|
};
|
|
1391
|
-
const diffTableColumns = (
|
|
1391
|
+
const diffTableColumns = (diffCtx) => {
|
|
1392
|
+
const { databaseTable, userSchemaTable, previousTable } = diffCtx;
|
|
1392
1393
|
const addedColumns = [];
|
|
1393
1394
|
const updatedColumns = [];
|
|
1394
1395
|
const unchangedColumns = [];
|
|
1395
1396
|
const removedColumns = [];
|
|
1396
|
-
for (const
|
|
1397
|
-
const
|
|
1398
|
-
if (
|
|
1399
|
-
const { status, diff } = diffColumns(
|
|
1397
|
+
for (const userSchemaColumn of userSchemaTable.columns) {
|
|
1398
|
+
const databaseColumn = helpers.findColumn(databaseTable, userSchemaColumn.name);
|
|
1399
|
+
if (databaseColumn) {
|
|
1400
|
+
const { status, diff } = diffColumns(databaseColumn, userSchemaColumn);
|
|
1400
1401
|
if (status === statuses.CHANGED) {
|
|
1401
1402
|
updatedColumns.push(diff);
|
|
1402
1403
|
} else {
|
|
1403
|
-
unchangedColumns.push(
|
|
1404
|
+
unchangedColumns.push(databaseColumn);
|
|
1404
1405
|
}
|
|
1405
1406
|
} else {
|
|
1406
|
-
addedColumns.push(
|
|
1407
|
+
addedColumns.push(userSchemaColumn);
|
|
1407
1408
|
}
|
|
1408
1409
|
}
|
|
1409
|
-
for (const
|
|
1410
|
-
if (!helpers.hasColumn(
|
|
1411
|
-
removedColumns.push(
|
|
1410
|
+
for (const databaseColumn of databaseTable.columns) {
|
|
1411
|
+
if (!helpers.hasColumn(userSchemaTable, databaseColumn.name) && previousTable && helpers.hasColumn(previousTable, databaseColumn.name)) {
|
|
1412
|
+
removedColumns.push(databaseColumn);
|
|
1412
1413
|
}
|
|
1413
1414
|
}
|
|
1414
1415
|
const hasChanged = [addedColumns, updatedColumns, removedColumns].some((arr) => arr.length > 0);
|
|
@@ -1422,27 +1423,28 @@ const createSchemaDiff = (db) => {
|
|
|
1422
1423
|
}
|
|
1423
1424
|
};
|
|
1424
1425
|
};
|
|
1425
|
-
const diffTableIndexes = (
|
|
1426
|
+
const diffTableIndexes = (diffCtx) => {
|
|
1427
|
+
const { databaseTable, userSchemaTable, previousTable } = diffCtx;
|
|
1426
1428
|
const addedIndexes = [];
|
|
1427
1429
|
const updatedIndexes = [];
|
|
1428
1430
|
const unchangedIndexes = [];
|
|
1429
1431
|
const removedIndexes = [];
|
|
1430
|
-
for (const
|
|
1431
|
-
const
|
|
1432
|
-
if (
|
|
1433
|
-
const { status, diff } = diffIndexes(
|
|
1432
|
+
for (const userSchemaIndex of userSchemaTable.indexes) {
|
|
1433
|
+
const databaseIndex = helpers.findIndex(databaseTable, userSchemaIndex.name);
|
|
1434
|
+
if (databaseIndex) {
|
|
1435
|
+
const { status, diff } = diffIndexes(databaseIndex, userSchemaIndex);
|
|
1434
1436
|
if (status === statuses.CHANGED) {
|
|
1435
1437
|
updatedIndexes.push(diff);
|
|
1436
1438
|
} else {
|
|
1437
|
-
unchangedIndexes.push(
|
|
1439
|
+
unchangedIndexes.push(databaseIndex);
|
|
1438
1440
|
}
|
|
1439
1441
|
} else {
|
|
1440
|
-
addedIndexes.push(
|
|
1442
|
+
addedIndexes.push(userSchemaIndex);
|
|
1441
1443
|
}
|
|
1442
1444
|
}
|
|
1443
|
-
for (const
|
|
1444
|
-
if (!helpers.hasIndex(
|
|
1445
|
-
removedIndexes.push(
|
|
1445
|
+
for (const databaseIndex of databaseTable.indexes) {
|
|
1446
|
+
if (!helpers.hasIndex(userSchemaTable, databaseIndex.name) && previousTable && helpers.hasIndex(previousTable, databaseIndex.name)) {
|
|
1447
|
+
removedIndexes.push(databaseIndex);
|
|
1446
1448
|
}
|
|
1447
1449
|
}
|
|
1448
1450
|
const hasChanged = [addedIndexes, updatedIndexes, removedIndexes].some((arr) => arr.length > 0);
|
|
@@ -1456,7 +1458,8 @@ const createSchemaDiff = (db) => {
|
|
|
1456
1458
|
}
|
|
1457
1459
|
};
|
|
1458
1460
|
};
|
|
1459
|
-
const diffTableForeignKeys = (
|
|
1461
|
+
const diffTableForeignKeys = (diffCtx) => {
|
|
1462
|
+
const { databaseTable, userSchemaTable, previousTable } = diffCtx;
|
|
1460
1463
|
const addedForeignKeys = [];
|
|
1461
1464
|
const updatedForeignKeys = [];
|
|
1462
1465
|
const unchangedForeignKeys = [];
|
|
@@ -1472,22 +1475,22 @@ const createSchemaDiff = (db) => {
|
|
|
1472
1475
|
}
|
|
1473
1476
|
};
|
|
1474
1477
|
}
|
|
1475
|
-
for (const
|
|
1476
|
-
const
|
|
1477
|
-
if (
|
|
1478
|
-
const { status, diff } = diffForeignKeys(
|
|
1478
|
+
for (const userSchemaForeignKeys of userSchemaTable.foreignKeys) {
|
|
1479
|
+
const databaseForeignKeys = helpers.findForeignKey(databaseTable, userSchemaForeignKeys.name);
|
|
1480
|
+
if (databaseForeignKeys) {
|
|
1481
|
+
const { status, diff } = diffForeignKeys(databaseForeignKeys, userSchemaForeignKeys);
|
|
1479
1482
|
if (status === statuses.CHANGED) {
|
|
1480
1483
|
updatedForeignKeys.push(diff);
|
|
1481
1484
|
} else {
|
|
1482
|
-
unchangedForeignKeys.push(
|
|
1485
|
+
unchangedForeignKeys.push(databaseForeignKeys);
|
|
1483
1486
|
}
|
|
1484
1487
|
} else {
|
|
1485
|
-
addedForeignKeys.push(
|
|
1488
|
+
addedForeignKeys.push(userSchemaForeignKeys);
|
|
1486
1489
|
}
|
|
1487
1490
|
}
|
|
1488
|
-
for (const
|
|
1489
|
-
if (!helpers.hasForeignKey(
|
|
1490
|
-
removedForeignKeys.push(
|
|
1491
|
+
for (const databaseForeignKeys of databaseTable.foreignKeys) {
|
|
1492
|
+
if (!helpers.hasForeignKey(userSchemaTable, databaseForeignKeys.name) && previousTable && helpers.hasForeignKey(previousTable, databaseForeignKeys.name)) {
|
|
1493
|
+
removedForeignKeys.push(databaseForeignKeys);
|
|
1491
1494
|
}
|
|
1492
1495
|
}
|
|
1493
1496
|
const hasChanged = [addedForeignKeys, updatedForeignKeys, removedForeignKeys].some(
|
|
@@ -1503,37 +1506,44 @@ const createSchemaDiff = (db) => {
|
|
|
1503
1506
|
}
|
|
1504
1507
|
};
|
|
1505
1508
|
};
|
|
1506
|
-
const diffTables = (
|
|
1507
|
-
const
|
|
1508
|
-
const
|
|
1509
|
-
const
|
|
1509
|
+
const diffTables = (diffCtx) => {
|
|
1510
|
+
const { databaseTable } = diffCtx;
|
|
1511
|
+
const columnsDiff = diffTableColumns(diffCtx);
|
|
1512
|
+
const indexesDiff = diffTableIndexes(diffCtx);
|
|
1513
|
+
const foreignKeysDiff = diffTableForeignKeys(diffCtx);
|
|
1510
1514
|
const hasChanged = [columnsDiff, indexesDiff, foreignKeysDiff].some(hasChangedStatus);
|
|
1511
1515
|
return {
|
|
1512
1516
|
status: hasChanged ? statuses.CHANGED : statuses.UNCHANGED,
|
|
1513
1517
|
diff: {
|
|
1514
|
-
name:
|
|
1518
|
+
name: databaseTable.name,
|
|
1515
1519
|
indexes: indexesDiff.diff,
|
|
1516
1520
|
foreignKeys: foreignKeysDiff.diff,
|
|
1517
1521
|
columns: columnsDiff.diff
|
|
1518
1522
|
}
|
|
1519
1523
|
};
|
|
1520
1524
|
};
|
|
1521
|
-
const diffSchemas = async (
|
|
1525
|
+
const diffSchemas = async (schemaDiffCtx) => {
|
|
1526
|
+
const { previousSchema, databaseSchema, userSchema } = schemaDiffCtx;
|
|
1522
1527
|
const addedTables = [];
|
|
1523
1528
|
const updatedTables = [];
|
|
1524
1529
|
const unchangedTables = [];
|
|
1525
1530
|
const removedTables = [];
|
|
1526
|
-
for (const
|
|
1527
|
-
const
|
|
1528
|
-
|
|
1529
|
-
|
|
1531
|
+
for (const userSchemaTable of userSchema.tables) {
|
|
1532
|
+
const databaseTable = helpers.findTable(databaseSchema, userSchemaTable.name);
|
|
1533
|
+
const previousTable = previousSchema && helpers.findTable(previousSchema, userSchemaTable.name);
|
|
1534
|
+
if (databaseTable) {
|
|
1535
|
+
const { status, diff } = diffTables({
|
|
1536
|
+
previousTable,
|
|
1537
|
+
databaseTable,
|
|
1538
|
+
userSchemaTable
|
|
1539
|
+
});
|
|
1530
1540
|
if (status === statuses.CHANGED) {
|
|
1531
1541
|
updatedTables.push(diff);
|
|
1532
1542
|
} else {
|
|
1533
|
-
unchangedTables.push(
|
|
1543
|
+
unchangedTables.push(databaseTable);
|
|
1534
1544
|
}
|
|
1535
1545
|
} else {
|
|
1536
|
-
addedTables.push(
|
|
1546
|
+
addedTables.push(userSchemaTable);
|
|
1537
1547
|
}
|
|
1538
1548
|
}
|
|
1539
1549
|
const parsePersistedTable = (persistedTable) => {
|
|
@@ -1542,23 +1552,34 @@ const createSchemaDiff = (db) => {
|
|
|
1542
1552
|
}
|
|
1543
1553
|
return persistedTable.name;
|
|
1544
1554
|
};
|
|
1545
|
-
const persistedTables = helpers.hasTable(
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1555
|
+
const persistedTables = helpers.hasTable(databaseSchema, "strapi_core_store_settings") ? (
|
|
1556
|
+
// TODO: replace with low level db query instead
|
|
1557
|
+
await strapi.store.get({
|
|
1558
|
+
type: "core",
|
|
1559
|
+
key: "persisted_tables"
|
|
1560
|
+
}) ?? []
|
|
1561
|
+
) : [];
|
|
1549
1562
|
const reservedTables = [...RESERVED_TABLE_NAMES, ...persistedTables.map(parsePersistedTable)];
|
|
1550
|
-
for (const
|
|
1551
|
-
|
|
1563
|
+
for (const databaseTable of databaseSchema.tables) {
|
|
1564
|
+
const isInUserSchema = helpers.hasTable(userSchema, databaseTable.name);
|
|
1565
|
+
const wasTracked = previousSchema && helpers.hasTable(previousSchema, databaseTable.name);
|
|
1566
|
+
const isReserved = reservedTables.includes(databaseTable.name);
|
|
1567
|
+
if (!isInUserSchema && !wasTracked) {
|
|
1568
|
+
continue;
|
|
1569
|
+
}
|
|
1570
|
+
if (!isInUserSchema && wasTracked && !isReserved) {
|
|
1552
1571
|
const dependencies = persistedTables.filter((table) => {
|
|
1553
1572
|
const dependsOn = table?.dependsOn;
|
|
1554
1573
|
if (!___default.default.isArray(dependsOn)) {
|
|
1555
1574
|
return;
|
|
1556
1575
|
}
|
|
1557
|
-
return dependsOn.some((table2) => table2.name ===
|
|
1576
|
+
return dependsOn.some((table2) => table2.name === databaseTable.name);
|
|
1558
1577
|
}).map((dependsOnTable) => {
|
|
1559
|
-
return
|
|
1578
|
+
return databaseSchema.tables.find(
|
|
1579
|
+
(databaseTable2) => databaseTable2.name === dependsOnTable.name
|
|
1580
|
+
);
|
|
1560
1581
|
}).filter((table) => !___default.default.isNil(table));
|
|
1561
|
-
removedTables.push(
|
|
1582
|
+
removedTables.push(databaseTable, ...dependencies);
|
|
1562
1583
|
}
|
|
1563
1584
|
}
|
|
1564
1585
|
const hasChanged = [addedTables, updatedTables, removedTables].some((arr) => arr.length > 0);
|
|
@@ -2204,8 +2225,13 @@ const createSchemaProvider = (db) => {
|
|
|
2204
2225
|
},
|
|
2205
2226
|
async syncSchema() {
|
|
2206
2227
|
debug$1("Synchronizing database schema");
|
|
2207
|
-
const
|
|
2208
|
-
const
|
|
2228
|
+
const databaseSchema = await db.dialect.schemaInspector.getSchema();
|
|
2229
|
+
const storedSchema = await this.schemaStorage.read();
|
|
2230
|
+
const { status, diff } = await this.schemaDiff.diff({
|
|
2231
|
+
previousSchema: storedSchema?.schema,
|
|
2232
|
+
databaseSchema,
|
|
2233
|
+
userSchema: this.schema
|
|
2234
|
+
});
|
|
2209
2235
|
if (status === "CHANGED") {
|
|
2210
2236
|
await this.builder.updateSchema(diff);
|
|
2211
2237
|
}
|
|
@@ -2927,6 +2953,68 @@ const createField = (attribute) => {
|
|
|
2927
2953
|
}
|
|
2928
2954
|
throw new Error(`Undefined field for type ${type}`);
|
|
2929
2955
|
};
|
|
2956
|
+
const storage = new node_async_hooks.AsyncLocalStorage();
|
|
2957
|
+
const transactionCtx = {
|
|
2958
|
+
async run(trx, cb) {
|
|
2959
|
+
const store = storage.getStore();
|
|
2960
|
+
return storage.run(
|
|
2961
|
+
{
|
|
2962
|
+
trx,
|
|
2963
|
+
// Fill with existing callbacks if nesting transactions
|
|
2964
|
+
commitCallbacks: store?.commitCallbacks || [],
|
|
2965
|
+
rollbackCallbacks: store?.rollbackCallbacks || []
|
|
2966
|
+
},
|
|
2967
|
+
cb
|
|
2968
|
+
);
|
|
2969
|
+
},
|
|
2970
|
+
get() {
|
|
2971
|
+
const store = storage.getStore();
|
|
2972
|
+
return store?.trx;
|
|
2973
|
+
},
|
|
2974
|
+
async commit(trx) {
|
|
2975
|
+
const store = storage.getStore();
|
|
2976
|
+
if (store?.trx) {
|
|
2977
|
+
store.trx = null;
|
|
2978
|
+
}
|
|
2979
|
+
await trx.commit();
|
|
2980
|
+
if (!store?.commitCallbacks.length) {
|
|
2981
|
+
return;
|
|
2982
|
+
}
|
|
2983
|
+
store.commitCallbacks.forEach((cb) => cb());
|
|
2984
|
+
store.commitCallbacks = [];
|
|
2985
|
+
},
|
|
2986
|
+
async rollback(trx) {
|
|
2987
|
+
const store = storage.getStore();
|
|
2988
|
+
if (store?.trx) {
|
|
2989
|
+
store.trx = null;
|
|
2990
|
+
}
|
|
2991
|
+
await trx.rollback();
|
|
2992
|
+
if (!store?.rollbackCallbacks.length) {
|
|
2993
|
+
return;
|
|
2994
|
+
}
|
|
2995
|
+
store.rollbackCallbacks.forEach((cb) => cb());
|
|
2996
|
+
store.rollbackCallbacks = [];
|
|
2997
|
+
},
|
|
2998
|
+
onCommit(cb) {
|
|
2999
|
+
const store = storage.getStore();
|
|
3000
|
+
if (store?.commitCallbacks) {
|
|
3001
|
+
store.commitCallbacks.push(cb);
|
|
3002
|
+
}
|
|
3003
|
+
},
|
|
3004
|
+
onRollback(cb) {
|
|
3005
|
+
const store = storage.getStore();
|
|
3006
|
+
if (store?.rollbackCallbacks) {
|
|
3007
|
+
store.rollbackCallbacks.push(cb);
|
|
3008
|
+
}
|
|
3009
|
+
}
|
|
3010
|
+
};
|
|
3011
|
+
function isKnexQuery(value) {
|
|
3012
|
+
return value instanceof KnexBuilder__default.default || value instanceof KnexRaw__default.default;
|
|
3013
|
+
}
|
|
3014
|
+
const addSchema = (db, tableName) => {
|
|
3015
|
+
const schemaName = db.getSchemaName();
|
|
3016
|
+
return schemaName ? `${schemaName}.${tableName}` : tableName;
|
|
3017
|
+
};
|
|
2930
3018
|
const fromSingleRow = (meta, row) => {
|
|
2931
3019
|
const { attributes } = meta;
|
|
2932
3020
|
if (___default.default.isNil(row)) {
|
|
@@ -3049,7 +3137,7 @@ const escapeQuery = (query, charsToEscape, escapeChar = "\\") => {
|
|
|
3049
3137
|
""
|
|
3050
3138
|
);
|
|
3051
3139
|
};
|
|
3052
|
-
const createPivotJoin = (ctx, { alias, refAlias, joinTable, targetMeta }) => {
|
|
3140
|
+
const createPivotJoin = (ctx, { alias: alias2, refAlias, joinTable, targetMeta }) => {
|
|
3053
3141
|
const { qb } = ctx;
|
|
3054
3142
|
const joinAlias = qb.getAlias();
|
|
3055
3143
|
qb.join({
|
|
@@ -3057,7 +3145,7 @@ const createPivotJoin = (ctx, { alias, refAlias, joinTable, targetMeta }) => {
|
|
|
3057
3145
|
referencedTable: joinTable.name,
|
|
3058
3146
|
referencedColumn: joinTable.joinColumn.name,
|
|
3059
3147
|
rootColumn: joinTable.joinColumn.referencedColumn,
|
|
3060
|
-
rootTable:
|
|
3148
|
+
rootTable: alias2,
|
|
3061
3149
|
on: joinTable.on
|
|
3062
3150
|
});
|
|
3063
3151
|
const subAlias = refAlias || qb.getAlias();
|
|
@@ -3070,7 +3158,7 @@ const createPivotJoin = (ctx, { alias, refAlias, joinTable, targetMeta }) => {
|
|
|
3070
3158
|
});
|
|
3071
3159
|
return subAlias;
|
|
3072
3160
|
};
|
|
3073
|
-
const createJoin = (ctx, { alias, refAlias, attributeName, attribute }) => {
|
|
3161
|
+
const createJoin = (ctx, { alias: alias2, refAlias, attributeName, attribute }) => {
|
|
3074
3162
|
const { db, qb, uid } = ctx;
|
|
3075
3163
|
if (attribute.type !== "relation") {
|
|
3076
3164
|
throw new Error(`Cannot join on non relational field ${attributeName}`);
|
|
@@ -3086,7 +3174,7 @@ const createJoin = (ctx, { alias, refAlias, attributeName, attribute }) => {
|
|
|
3086
3174
|
referencedTable: targetMeta.tableName,
|
|
3087
3175
|
referencedColumn: morphColumn.idColumn.name,
|
|
3088
3176
|
rootColumn: morphColumn.idColumn.referencedColumn,
|
|
3089
|
-
rootTable:
|
|
3177
|
+
rootTable: alias2,
|
|
3090
3178
|
on: {
|
|
3091
3179
|
[morphColumn.typeColumn.name]: uid,
|
|
3092
3180
|
...morphColumn.on
|
|
@@ -3101,7 +3189,7 @@ const createJoin = (ctx, { alias, refAlias, attributeName, attribute }) => {
|
|
|
3101
3189
|
referencedTable: joinTable2.name,
|
|
3102
3190
|
referencedColumn: joinTable2.morphColumn.idColumn.name,
|
|
3103
3191
|
rootColumn: joinTable2.morphColumn.idColumn.referencedColumn,
|
|
3104
|
-
rootTable:
|
|
3192
|
+
rootTable: alias2,
|
|
3105
3193
|
on: {
|
|
3106
3194
|
[joinTable2.morphColumn.typeColumn.name]: uid,
|
|
3107
3195
|
field: attributeName
|
|
@@ -3117,7 +3205,7 @@ const createJoin = (ctx, { alias, refAlias, attributeName, attribute }) => {
|
|
|
3117
3205
|
});
|
|
3118
3206
|
return subAlias;
|
|
3119
3207
|
}
|
|
3120
|
-
return
|
|
3208
|
+
return alias2;
|
|
3121
3209
|
}
|
|
3122
3210
|
const { joinColumn } = attribute;
|
|
3123
3211
|
if (joinColumn) {
|
|
@@ -3127,20 +3215,20 @@ const createJoin = (ctx, { alias, refAlias, attributeName, attribute }) => {
|
|
|
3127
3215
|
referencedTable: targetMeta.tableName,
|
|
3128
3216
|
referencedColumn: joinColumn.referencedColumn,
|
|
3129
3217
|
rootColumn: joinColumn.name,
|
|
3130
|
-
rootTable:
|
|
3218
|
+
rootTable: alias2
|
|
3131
3219
|
});
|
|
3132
3220
|
return subAlias;
|
|
3133
3221
|
}
|
|
3134
3222
|
const { joinTable } = attribute;
|
|
3135
3223
|
if (joinTable) {
|
|
3136
|
-
return createPivotJoin(ctx, { alias, refAlias, joinTable, targetMeta });
|
|
3224
|
+
return createPivotJoin(ctx, { alias: alias2, refAlias, joinTable, targetMeta });
|
|
3137
3225
|
}
|
|
3138
|
-
return
|
|
3226
|
+
return alias2;
|
|
3139
3227
|
};
|
|
3140
3228
|
const applyJoin = (qb, join) => {
|
|
3141
3229
|
const {
|
|
3142
3230
|
method = "leftJoin",
|
|
3143
|
-
alias,
|
|
3231
|
+
alias: alias2,
|
|
3144
3232
|
referencedTable,
|
|
3145
3233
|
referencedColumn,
|
|
3146
3234
|
rootColumn,
|
|
@@ -3150,26 +3238,28 @@ const applyJoin = (qb, join) => {
|
|
|
3150
3238
|
on,
|
|
3151
3239
|
orderBy
|
|
3152
3240
|
} = join;
|
|
3153
|
-
qb[method](`${referencedTable} as ${
|
|
3154
|
-
inner.on(`${rootTable}.${rootColumn}`, `${
|
|
3241
|
+
qb[method](`${referencedTable} as ${alias2}`, (inner) => {
|
|
3242
|
+
inner.on(`${rootTable}.${rootColumn}`, `${alias2}.${referencedColumn}`);
|
|
3155
3243
|
if (on) {
|
|
3156
3244
|
for (const key of Object.keys(on)) {
|
|
3157
|
-
inner.onVal(`${
|
|
3245
|
+
inner.onVal(`${alias2}.${key}`, on[key]);
|
|
3158
3246
|
}
|
|
3159
3247
|
}
|
|
3160
3248
|
});
|
|
3161
3249
|
if (orderBy) {
|
|
3162
3250
|
Object.keys(orderBy).forEach((column) => {
|
|
3163
3251
|
const direction = orderBy[column];
|
|
3164
|
-
qb.orderBy(`${
|
|
3252
|
+
qb.orderBy(`${alias2}.${column}`, direction);
|
|
3165
3253
|
});
|
|
3166
3254
|
}
|
|
3167
3255
|
};
|
|
3168
3256
|
const applyJoins = (qb, joins) => {
|
|
3169
3257
|
return joins.forEach((join) => applyJoin(qb, join));
|
|
3170
3258
|
};
|
|
3259
|
+
const COL_STRAPI_ROW_NUMBER = "__strapi_row_number";
|
|
3260
|
+
const COL_STRAPI_ORDER_BY_PREFIX = "__strapi_order_by";
|
|
3171
3261
|
const processOrderBy = (orderBy, ctx) => {
|
|
3172
|
-
const { db, uid, qb, alias } = ctx;
|
|
3262
|
+
const { db, uid, qb, alias: alias2 } = ctx;
|
|
3173
3263
|
const meta = db.metadata.get(uid);
|
|
3174
3264
|
const { attributes } = meta;
|
|
3175
3265
|
if (typeof orderBy === "string") {
|
|
@@ -3178,7 +3268,7 @@ const processOrderBy = (orderBy, ctx) => {
|
|
|
3178
3268
|
throw new Error(`Attribute ${orderBy} not found on model ${uid}`);
|
|
3179
3269
|
}
|
|
3180
3270
|
const columnName = toColumnName(meta, orderBy);
|
|
3181
|
-
return [{ column: qb.aliasColumn(columnName,
|
|
3271
|
+
return [{ column: qb.aliasColumn(columnName, alias2) }];
|
|
3182
3272
|
}
|
|
3183
3273
|
if (Array.isArray(orderBy)) {
|
|
3184
3274
|
return orderBy.flatMap((value) => processOrderBy(value, ctx));
|
|
@@ -3192,11 +3282,11 @@ const processOrderBy = (orderBy, ctx) => {
|
|
|
3192
3282
|
}
|
|
3193
3283
|
if (isScalar(attribute.type)) {
|
|
3194
3284
|
const columnName = toColumnName(meta, key);
|
|
3195
|
-
return { column: qb.aliasColumn(columnName,
|
|
3285
|
+
return { column: qb.aliasColumn(columnName, alias2), order: direction };
|
|
3196
3286
|
}
|
|
3197
3287
|
if (attribute.type === "relation" && "target" in attribute) {
|
|
3198
3288
|
const subAlias = createJoin(ctx, {
|
|
3199
|
-
alias:
|
|
3289
|
+
alias: alias2 || qb.alias,
|
|
3200
3290
|
attributeName: key,
|
|
3201
3291
|
attribute
|
|
3202
3292
|
});
|
|
@@ -3212,6 +3302,75 @@ const processOrderBy = (orderBy, ctx) => {
|
|
|
3212
3302
|
}
|
|
3213
3303
|
throw new Error("Invalid orderBy syntax");
|
|
3214
3304
|
};
|
|
3305
|
+
const getStrapiOrderColumnAlias = (column) => {
|
|
3306
|
+
const trimmedColumnName = column.replaceAll(".", "_");
|
|
3307
|
+
return `${COL_STRAPI_ORDER_BY_PREFIX}__${trimmedColumnName}`;
|
|
3308
|
+
};
|
|
3309
|
+
const wrapWithDeepSort = (originalQuery, ctx) => {
|
|
3310
|
+
const { db, qb, uid } = ctx;
|
|
3311
|
+
const { tableName } = db.metadata.get(uid);
|
|
3312
|
+
const orderBy = ___default.default.cloneDeep(qb.state.orderBy);
|
|
3313
|
+
const resultQueryAlias = qb.getAlias();
|
|
3314
|
+
const aliasedTableName = qb.mustUseAlias() ? alias(resultQueryAlias, tableName) : tableName;
|
|
3315
|
+
const resultQuery = db.getConnection(aliasedTableName);
|
|
3316
|
+
const baseQuery = originalQuery.clone();
|
|
3317
|
+
const baseQueryAlias = qb.getAlias();
|
|
3318
|
+
baseQuery.clear("select").clear("order").clear("limit").clear("offset");
|
|
3319
|
+
baseQuery.select(
|
|
3320
|
+
// Always select the row id for future manipulation
|
|
3321
|
+
prefix(qb.alias, "id"),
|
|
3322
|
+
...orderBy.map(
|
|
3323
|
+
(orderByClause) => alias(getStrapiOrderColumnAlias(orderByClause.column), orderByClause.column)
|
|
3324
|
+
)
|
|
3325
|
+
);
|
|
3326
|
+
const partitionedQueryAlias = qb.getAlias();
|
|
3327
|
+
const selectRowsAsNumberedPartitions = (partitionedQuery) => {
|
|
3328
|
+
const prefixedOrderBy = orderBy.map((orderByClause) => ({
|
|
3329
|
+
column: prefix(baseQueryAlias, getStrapiOrderColumnAlias(orderByClause.column)),
|
|
3330
|
+
order: orderByClause.order
|
|
3331
|
+
}));
|
|
3332
|
+
const orderByColumns = prefixedOrderBy.map(___default.default.prop("column"));
|
|
3333
|
+
partitionedQuery.select(
|
|
3334
|
+
// Always select baseQuery.id
|
|
3335
|
+
prefix(baseQueryAlias, "id"),
|
|
3336
|
+
...orderByColumns
|
|
3337
|
+
).rowNumber(COL_STRAPI_ROW_NUMBER, (subQuery) => {
|
|
3338
|
+
for (const orderByClause of prefixedOrderBy) {
|
|
3339
|
+
subQuery.orderBy(orderByClause.column, orderByClause.order, "last");
|
|
3340
|
+
}
|
|
3341
|
+
subQuery.partitionBy(`${baseQueryAlias}.id`);
|
|
3342
|
+
}).from(baseQuery.as(baseQueryAlias)).as(partitionedQueryAlias);
|
|
3343
|
+
};
|
|
3344
|
+
const originalSelect = ___default.default.difference(
|
|
3345
|
+
qb.state.select,
|
|
3346
|
+
// Remove order by columns from the initial select
|
|
3347
|
+
qb.state.orderBy.map(___default.default.prop("column"))
|
|
3348
|
+
).map(prefix(resultQueryAlias));
|
|
3349
|
+
resultQuery.select(originalSelect).innerJoin(selectRowsAsNumberedPartitions, function() {
|
|
3350
|
+
this.on(`${partitionedQueryAlias}.id`, `${resultQueryAlias}.id`).andOnVal(`${partitionedQueryAlias}.${COL_STRAPI_ROW_NUMBER}`, "=", 1);
|
|
3351
|
+
});
|
|
3352
|
+
if (qb.state.limit) {
|
|
3353
|
+
resultQuery.limit(qb.state.limit);
|
|
3354
|
+
}
|
|
3355
|
+
if (qb.state.offset) {
|
|
3356
|
+
resultQuery.offset(qb.state.offset);
|
|
3357
|
+
}
|
|
3358
|
+
if (qb.state.first) {
|
|
3359
|
+
resultQuery.first();
|
|
3360
|
+
}
|
|
3361
|
+
resultQuery.orderBy([
|
|
3362
|
+
// Transform "order by" clause to their T alias and prefix them with T alias
|
|
3363
|
+
...orderBy.map((orderByClause) => ({
|
|
3364
|
+
column: prefix(partitionedQueryAlias, getStrapiOrderColumnAlias(orderByClause.column)),
|
|
3365
|
+
order: orderByClause.order
|
|
3366
|
+
})),
|
|
3367
|
+
// Add T.id to the order by clause to get consistent results in case several rows have the exact same order
|
|
3368
|
+
{ column: `${partitionedQueryAlias}.id`, order: "asc" }
|
|
3369
|
+
]);
|
|
3370
|
+
return resultQuery;
|
|
3371
|
+
};
|
|
3372
|
+
const alias = ___default.default.curry((alias2, value) => `${value} as ${alias2}`);
|
|
3373
|
+
const prefix = ___default.default.curry((prefix2, value) => `${prefix2}.${value}`);
|
|
3215
3374
|
const joinColPrefix = "__strapi";
|
|
3216
3375
|
const XtoOne = async (input, ctx) => {
|
|
3217
3376
|
const { attribute, attributeName, results, populateValue, targetMeta, isCount } = input;
|
|
@@ -3239,8 +3398,8 @@ const XtoOne = async (input, ctx) => {
|
|
|
3239
3398
|
const { joinTable } = attribute;
|
|
3240
3399
|
const qb2 = db.entityManager.createQueryBuilder(targetMeta.uid);
|
|
3241
3400
|
const { name: joinColumnName, referencedColumn: referencedColumnName } = joinTable.joinColumn;
|
|
3242
|
-
const
|
|
3243
|
-
const joinColAlias = `${
|
|
3401
|
+
const alias2 = qb2.getAlias();
|
|
3402
|
+
const joinColAlias = `${alias2}.${joinColumnName}`;
|
|
3244
3403
|
const joinColRenameAs = `${joinColPrefix}${joinColumnName}`;
|
|
3245
3404
|
const joinColSelect = `${joinColAlias} as ${joinColRenameAs}`;
|
|
3246
3405
|
const referencedValues = ___default.default.uniq(
|
|
@@ -3254,7 +3413,7 @@ const XtoOne = async (input, ctx) => {
|
|
|
3254
3413
|
return;
|
|
3255
3414
|
}
|
|
3256
3415
|
const rows2 = await qb2.init(populateValue).join({
|
|
3257
|
-
alias,
|
|
3416
|
+
alias: alias2,
|
|
3258
3417
|
referencedTable: joinTable.name,
|
|
3259
3418
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3260
3419
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
@@ -3280,7 +3439,7 @@ const XtoOne = async (input, ctx) => {
|
|
|
3280
3439
|
return;
|
|
3281
3440
|
}
|
|
3282
3441
|
const rows = await qb2.init(populateValue).join({
|
|
3283
|
-
alias,
|
|
3442
|
+
alias: alias2,
|
|
3284
3443
|
referencedTable: joinTable.name,
|
|
3285
3444
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3286
3445
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
@@ -3320,8 +3479,8 @@ const oneToMany = async (input, ctx) => {
|
|
|
3320
3479
|
const { joinTable } = attribute;
|
|
3321
3480
|
const qb2 = db.entityManager.createQueryBuilder(targetMeta.uid);
|
|
3322
3481
|
const { name: joinColumnName, referencedColumn: referencedColumnName } = joinTable.joinColumn;
|
|
3323
|
-
const
|
|
3324
|
-
const joinColAlias = `${
|
|
3482
|
+
const alias2 = qb2.getAlias();
|
|
3483
|
+
const joinColAlias = `${alias2}.${joinColumnName}`;
|
|
3325
3484
|
const joinColRenameAs = `${joinColPrefix}${joinColumnName}`;
|
|
3326
3485
|
const joinColSelect = `${joinColAlias} as ${joinColRenameAs}`;
|
|
3327
3486
|
const referencedValues = ___default.default.uniq(
|
|
@@ -3335,7 +3494,7 @@ const oneToMany = async (input, ctx) => {
|
|
|
3335
3494
|
return;
|
|
3336
3495
|
}
|
|
3337
3496
|
const rows2 = await qb2.init(populateValue).join({
|
|
3338
|
-
alias,
|
|
3497
|
+
alias: alias2,
|
|
3339
3498
|
referencedTable: joinTable.name,
|
|
3340
3499
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3341
3500
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
@@ -3361,7 +3520,7 @@ const oneToMany = async (input, ctx) => {
|
|
|
3361
3520
|
return;
|
|
3362
3521
|
}
|
|
3363
3522
|
const rows = await qb2.init(populateValue).join({
|
|
3364
|
-
alias,
|
|
3523
|
+
alias: alias2,
|
|
3365
3524
|
referencedTable: joinTable.name,
|
|
3366
3525
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3367
3526
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
@@ -3382,8 +3541,8 @@ const manyToMany = async (input, ctx) => {
|
|
|
3382
3541
|
const { joinTable } = attribute;
|
|
3383
3542
|
const populateQb = db.entityManager.createQueryBuilder(targetMeta.uid);
|
|
3384
3543
|
const { name: joinColumnName, referencedColumn: referencedColumnName } = joinTable.joinColumn;
|
|
3385
|
-
const
|
|
3386
|
-
const joinColAlias = `${
|
|
3544
|
+
const alias2 = populateQb.getAlias();
|
|
3545
|
+
const joinColAlias = `${alias2}.${joinColumnName}`;
|
|
3387
3546
|
const joinColRenameAs = `${joinColPrefix}${joinColumnName}`;
|
|
3388
3547
|
const joinColSelect = `${joinColAlias} as ${joinColRenameAs}`;
|
|
3389
3548
|
const referencedValues = ___default.default.uniq(
|
|
@@ -3397,7 +3556,7 @@ const manyToMany = async (input, ctx) => {
|
|
|
3397
3556
|
return;
|
|
3398
3557
|
}
|
|
3399
3558
|
const rows2 = await populateQb.init(populateValue).join({
|
|
3400
|
-
alias,
|
|
3559
|
+
alias: alias2,
|
|
3401
3560
|
referencedTable: joinTable.name,
|
|
3402
3561
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3403
3562
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
@@ -3423,7 +3582,7 @@ const manyToMany = async (input, ctx) => {
|
|
|
3423
3582
|
return;
|
|
3424
3583
|
}
|
|
3425
3584
|
const rows = await populateQb.init(populateValue).join({
|
|
3426
|
-
alias,
|
|
3585
|
+
alias: alias2,
|
|
3427
3586
|
referencedTable: joinTable.name,
|
|
3428
3587
|
referencedColumn: joinTable.inverseJoinColumn.name,
|
|
3429
3588
|
rootColumn: joinTable.inverseJoinColumn.referencedColumn,
|
|
@@ -3474,9 +3633,9 @@ const morphX = async (input, ctx) => {
|
|
|
3474
3633
|
return;
|
|
3475
3634
|
}
|
|
3476
3635
|
const qb = db.entityManager.createQueryBuilder(target);
|
|
3477
|
-
const
|
|
3636
|
+
const alias2 = qb.getAlias();
|
|
3478
3637
|
const rows = await qb.init(populateValue).join({
|
|
3479
|
-
alias,
|
|
3638
|
+
alias: alias2,
|
|
3480
3639
|
referencedTable: joinTable.name,
|
|
3481
3640
|
referencedColumn: joinColumn.name,
|
|
3482
3641
|
rootColumn: joinColumn.referencedColumn,
|
|
@@ -3486,9 +3645,9 @@ const morphX = async (input, ctx) => {
|
|
|
3486
3645
|
field: attributeName
|
|
3487
3646
|
},
|
|
3488
3647
|
orderBy: ___default.default.mapValues((v) => populateValue.ordering || v, joinTable.orderBy)
|
|
3489
|
-
}).addSelect([`${
|
|
3490
|
-
[`${
|
|
3491
|
-
[`${
|
|
3648
|
+
}).addSelect([`${alias2}.${idColumn.name}`, `${alias2}.${typeColumn.name}`]).where({
|
|
3649
|
+
[`${alias2}.${idColumn.name}`]: referencedValues,
|
|
3650
|
+
[`${alias2}.${typeColumn.name}`]: uid
|
|
3492
3651
|
}).execute({ mapResults: false });
|
|
3493
3652
|
const map = ___default.default.groupBy(idColumn.name)(rows);
|
|
3494
3653
|
results.forEach((result) => {
|
|
@@ -3737,13 +3896,6 @@ const processPopulate = (populate, ctx) => {
|
|
|
3737
3896
|
}
|
|
3738
3897
|
return finalPopulate;
|
|
3739
3898
|
};
|
|
3740
|
-
function isKnexQuery(value) {
|
|
3741
|
-
return value instanceof KnexBuilder__default.default || value instanceof KnexRaw__default.default;
|
|
3742
|
-
}
|
|
3743
|
-
const addSchema = (db, tableName) => {
|
|
3744
|
-
const schemaName = db.getSchemaName();
|
|
3745
|
-
return schemaName ? `${schemaName}.${tableName}` : tableName;
|
|
3746
|
-
};
|
|
3747
3899
|
const isRecord$1 = (value) => _.isPlainObject(value);
|
|
3748
3900
|
const castValue = (value, attribute) => {
|
|
3749
3901
|
if (!attribute) {
|
|
@@ -3785,8 +3937,8 @@ const processNested = (where, ctx) => {
|
|
|
3785
3937
|
return processWhere(where, ctx);
|
|
3786
3938
|
};
|
|
3787
3939
|
const processRelationWhere = (where, ctx) => {
|
|
3788
|
-
const { qb, alias } = ctx;
|
|
3789
|
-
const idAlias = qb.aliasColumn("id",
|
|
3940
|
+
const { qb, alias: alias2 } = ctx;
|
|
3941
|
+
const idAlias = qb.aliasColumn("id", alias2);
|
|
3790
3942
|
if (!isRecord$1(where)) {
|
|
3791
3943
|
return { [idAlias]: where };
|
|
3792
3944
|
}
|
|
@@ -3816,7 +3968,7 @@ function processWhere(where, ctx) {
|
|
|
3816
3968
|
if (_.isArray(where)) {
|
|
3817
3969
|
return where.map((sub) => processWhere(sub, ctx));
|
|
3818
3970
|
}
|
|
3819
|
-
const { db, uid, qb, alias } = ctx;
|
|
3971
|
+
const { db, uid, qb, alias: alias2 } = ctx;
|
|
3820
3972
|
const meta = db.metadata.get(uid);
|
|
3821
3973
|
const filters = {};
|
|
3822
3974
|
for (const key of Object.keys(where)) {
|
|
@@ -3839,12 +3991,12 @@ function processWhere(where, ctx) {
|
|
|
3839
3991
|
}
|
|
3840
3992
|
const attribute = meta.attributes[key];
|
|
3841
3993
|
if (!attribute) {
|
|
3842
|
-
filters[qb.aliasColumn(key,
|
|
3994
|
+
filters[qb.aliasColumn(key, alias2)] = processAttributeWhere(null, value);
|
|
3843
3995
|
continue;
|
|
3844
3996
|
}
|
|
3845
3997
|
if (isRelation(attribute.type) && "target" in attribute) {
|
|
3846
3998
|
const subAlias = createJoin(ctx, {
|
|
3847
|
-
alias:
|
|
3999
|
+
alias: alias2 || qb.alias,
|
|
3848
4000
|
attributeName: key,
|
|
3849
4001
|
attribute
|
|
3850
4002
|
});
|
|
@@ -3859,7 +4011,7 @@ function processWhere(where, ctx) {
|
|
|
3859
4011
|
}
|
|
3860
4012
|
if (isScalar(attribute.type)) {
|
|
3861
4013
|
const columnName = toColumnName(meta, key);
|
|
3862
|
-
const aliasedColumnName = qb.aliasColumn(columnName,
|
|
4014
|
+
const aliasedColumnName = qb.aliasColumn(columnName, alias2);
|
|
3863
4015
|
filters[aliasedColumnName] = processAttributeWhere(attribute, value);
|
|
3864
4016
|
continue;
|
|
3865
4017
|
}
|
|
@@ -4087,7 +4239,7 @@ class ReadableStrapiQuery extends stream.Readable {
|
|
|
4087
4239
|
* Custom ._read() implementation
|
|
4088
4240
|
*
|
|
4089
4241
|
* NOTE: Here "size" means the number of entities to be read from the database.
|
|
4090
|
-
* Not the actual byte size, as it would
|
|
4242
|
+
* Not the actual byte size, as it would mean that we need to return partial entities.
|
|
4091
4243
|
*
|
|
4092
4244
|
*/
|
|
4093
4245
|
async _read(size) {
|
|
@@ -4150,61 +4302,6 @@ class ReadableStrapiQuery extends stream.Readable {
|
|
|
4150
4302
|
}
|
|
4151
4303
|
}
|
|
4152
4304
|
}
|
|
4153
|
-
const storage = new node_async_hooks.AsyncLocalStorage();
|
|
4154
|
-
const transactionCtx = {
|
|
4155
|
-
async run(trx, cb) {
|
|
4156
|
-
const store = storage.getStore();
|
|
4157
|
-
return storage.run(
|
|
4158
|
-
{
|
|
4159
|
-
trx,
|
|
4160
|
-
// Fill with existing callbacks if nesting transactions
|
|
4161
|
-
commitCallbacks: store?.commitCallbacks || [],
|
|
4162
|
-
rollbackCallbacks: store?.rollbackCallbacks || []
|
|
4163
|
-
},
|
|
4164
|
-
cb
|
|
4165
|
-
);
|
|
4166
|
-
},
|
|
4167
|
-
get() {
|
|
4168
|
-
const store = storage.getStore();
|
|
4169
|
-
return store?.trx;
|
|
4170
|
-
},
|
|
4171
|
-
async commit(trx) {
|
|
4172
|
-
const store = storage.getStore();
|
|
4173
|
-
if (store?.trx) {
|
|
4174
|
-
store.trx = null;
|
|
4175
|
-
}
|
|
4176
|
-
await trx.commit();
|
|
4177
|
-
if (!store?.commitCallbacks.length) {
|
|
4178
|
-
return;
|
|
4179
|
-
}
|
|
4180
|
-
store.commitCallbacks.forEach((cb) => cb());
|
|
4181
|
-
store.commitCallbacks = [];
|
|
4182
|
-
},
|
|
4183
|
-
async rollback(trx) {
|
|
4184
|
-
const store = storage.getStore();
|
|
4185
|
-
if (store?.trx) {
|
|
4186
|
-
store.trx = null;
|
|
4187
|
-
}
|
|
4188
|
-
await trx.rollback();
|
|
4189
|
-
if (!store?.rollbackCallbacks.length) {
|
|
4190
|
-
return;
|
|
4191
|
-
}
|
|
4192
|
-
store.rollbackCallbacks.forEach((cb) => cb());
|
|
4193
|
-
store.rollbackCallbacks = [];
|
|
4194
|
-
},
|
|
4195
|
-
onCommit(cb) {
|
|
4196
|
-
const store = storage.getStore();
|
|
4197
|
-
if (store?.commitCallbacks) {
|
|
4198
|
-
store.commitCallbacks.push(cb);
|
|
4199
|
-
}
|
|
4200
|
-
},
|
|
4201
|
-
onRollback(cb) {
|
|
4202
|
-
const store = storage.getStore();
|
|
4203
|
-
if (store?.rollbackCallbacks) {
|
|
4204
|
-
store.rollbackCallbacks.push(cb);
|
|
4205
|
-
}
|
|
4206
|
-
}
|
|
4207
|
-
};
|
|
4208
4305
|
const createQueryBuilder = (uid, db, initialState = {}) => {
|
|
4209
4306
|
const meta = db.metadata.get(uid);
|
|
4210
4307
|
const { tableName } = meta;
|
|
@@ -4237,9 +4334,9 @@ const createQueryBuilder = (uid, db, initialState = {}) => {
|
|
|
4237
4334
|
initialState
|
|
4238
4335
|
);
|
|
4239
4336
|
const getAlias = () => {
|
|
4240
|
-
const
|
|
4337
|
+
const alias2 = `t${state.aliasCounter}`;
|
|
4241
4338
|
state.aliasCounter += 1;
|
|
4242
|
-
return
|
|
4339
|
+
return alias2;
|
|
4243
4340
|
};
|
|
4244
4341
|
return {
|
|
4245
4342
|
alias: getAlias(),
|
|
@@ -4406,15 +4503,15 @@ const createQueryBuilder = (uid, db, initialState = {}) => {
|
|
|
4406
4503
|
mustUseAlias() {
|
|
4407
4504
|
return ["select", "count"].includes(state.type);
|
|
4408
4505
|
},
|
|
4409
|
-
aliasColumn(key,
|
|
4506
|
+
aliasColumn(key, alias2) {
|
|
4410
4507
|
if (typeof key !== "string") {
|
|
4411
4508
|
return key;
|
|
4412
4509
|
}
|
|
4413
4510
|
if (key.indexOf(".") >= 0) {
|
|
4414
4511
|
return key;
|
|
4415
4512
|
}
|
|
4416
|
-
if (!___default.default.isNil(
|
|
4417
|
-
return `${
|
|
4513
|
+
if (!___default.default.isNil(alias2)) {
|
|
4514
|
+
return `${alias2}.${key}`;
|
|
4418
4515
|
}
|
|
4419
4516
|
return this.mustUseAlias() ? `${this.alias}.${key}` : key;
|
|
4420
4517
|
},
|
|
@@ -4449,6 +4546,20 @@ const createQueryBuilder = (uid, db, initialState = {}) => {
|
|
|
4449
4546
|
shouldUseDistinct() {
|
|
4450
4547
|
return state.joins.length > 0 && ___default.default.isEmpty(state.groupBy);
|
|
4451
4548
|
},
|
|
4549
|
+
shouldUseDeepSort() {
|
|
4550
|
+
return state.orderBy.filter(({ column }) => column.indexOf(".") >= 0).filter(({ column }) => {
|
|
4551
|
+
const col = column.split(".");
|
|
4552
|
+
for (let i = 0; i < col.length - 1; i += 1) {
|
|
4553
|
+
const el = col[i];
|
|
4554
|
+
const isRelationAttribute = meta.attributes[el]?.type === "relation";
|
|
4555
|
+
const isAliasedRelation = Object.values(state.joins).map((join) => join.alias).includes(el);
|
|
4556
|
+
if (isRelationAttribute || isAliasedRelation) {
|
|
4557
|
+
return true;
|
|
4558
|
+
}
|
|
4559
|
+
}
|
|
4560
|
+
return false;
|
|
4561
|
+
}).length > 0;
|
|
4562
|
+
},
|
|
4452
4563
|
processSelect() {
|
|
4453
4564
|
state.select = state.select.map((field) => {
|
|
4454
4565
|
if (isKnexQuery(field)) {
|
|
@@ -4566,6 +4677,9 @@ const createQueryBuilder = (uid, db, initialState = {}) => {
|
|
|
4566
4677
|
if (state.joins.length > 0) {
|
|
4567
4678
|
applyJoins(qb, state.joins);
|
|
4568
4679
|
}
|
|
4680
|
+
if (this.shouldUseDeepSort()) {
|
|
4681
|
+
return wrapWithDeepSort(qb, { qb: this, db, uid });
|
|
4682
|
+
}
|
|
4569
4683
|
return qb;
|
|
4570
4684
|
},
|
|
4571
4685
|
async execute({ mapResults = true } = {}) {
|
|
@@ -4767,7 +4881,7 @@ const deleteRelatedMorphOneRelationsAfterMorphToManyUpdate = async (rows, {
|
|
|
4767
4881
|
await createQueryBuilder(joinTable.name, db).delete().where({ $or: orWhere }).transacting(trx).execute();
|
|
4768
4882
|
}
|
|
4769
4883
|
};
|
|
4770
|
-
const getDocumentSiblingIdsQuery = (
|
|
4884
|
+
const getDocumentSiblingIdsQuery = (tableName, id) => {
|
|
4771
4885
|
const models = Array.from(strapi.db.metadata.values());
|
|
4772
4886
|
const isContentType = models.find((model) => {
|
|
4773
4887
|
return model.tableName === tableName && model.attributes.documentId;
|
|
@@ -4775,10 +4889,11 @@ const getDocumentSiblingIdsQuery = (con, tableName, id) => {
|
|
|
4775
4889
|
if (!isContentType) {
|
|
4776
4890
|
return [id];
|
|
4777
4891
|
}
|
|
4778
|
-
return
|
|
4779
|
-
"document_id",
|
|
4780
|
-
|
|
4781
|
-
|
|
4892
|
+
return function(query) {
|
|
4893
|
+
query.select("id").from(tableName).whereIn("document_id", (documentIDSubQuery) => {
|
|
4894
|
+
documentIDSubQuery.from(tableName).select("document_id").where("id", id);
|
|
4895
|
+
});
|
|
4896
|
+
};
|
|
4782
4897
|
};
|
|
4783
4898
|
const deletePreviousOneToAnyRelations = async ({
|
|
4784
4899
|
id,
|
|
@@ -4795,7 +4910,7 @@ const deletePreviousOneToAnyRelations = async ({
|
|
|
4795
4910
|
const { joinTable } = attribute;
|
|
4796
4911
|
const { joinColumn, inverseJoinColumn } = joinTable;
|
|
4797
4912
|
const con = db.getConnection();
|
|
4798
|
-
await con.delete().from(joinTable.name).whereNotIn(joinColumn.name, getDocumentSiblingIdsQuery(
|
|
4913
|
+
await con.delete().from(joinTable.name).whereNotIn(joinColumn.name, getDocumentSiblingIdsQuery(joinColumn.referencedTable, id)).whereIn(inverseJoinColumn.name, relIdsToadd).where(joinTable.on || {}).transacting(trx);
|
|
4799
4914
|
await cleanOrderColumns({ attribute, db, inverseRelIds: relIdsToadd, transaction: trx });
|
|
4800
4915
|
};
|
|
4801
4916
|
const deletePreviousAnyToOneRelations = async ({
|
|
@@ -4814,7 +4929,7 @@ const deletePreviousAnyToOneRelations = async ({
|
|
|
4814
4929
|
if (isManyToAny(attribute)) {
|
|
4815
4930
|
const relsToDelete = await con.select(inverseJoinColumn.name).from(joinTable.name).where(joinColumn.name, id).whereNotIn(
|
|
4816
4931
|
inverseJoinColumn.name,
|
|
4817
|
-
getDocumentSiblingIdsQuery(
|
|
4932
|
+
getDocumentSiblingIdsQuery(inverseJoinColumn.referencedTable, relIdToadd)
|
|
4818
4933
|
).where(joinTable.on || {}).transacting(trx);
|
|
4819
4934
|
const relIdsToDelete = _.map(inverseJoinColumn.name, relsToDelete);
|
|
4820
4935
|
await createQueryBuilder(joinTable.name, db).delete().where({
|
|
@@ -4825,7 +4940,7 @@ const deletePreviousAnyToOneRelations = async ({
|
|
|
4825
4940
|
} else {
|
|
4826
4941
|
await con.delete().from(joinTable.name).where(joinColumn.name, id).whereNotIn(
|
|
4827
4942
|
inverseJoinColumn.name,
|
|
4828
|
-
getDocumentSiblingIdsQuery(
|
|
4943
|
+
getDocumentSiblingIdsQuery(inverseJoinColumn.referencedTable, relIdToadd)
|
|
4829
4944
|
).where(joinTable.on || {}).transacting(trx);
|
|
4830
4945
|
}
|
|
4831
4946
|
};
|
|
@@ -5909,6 +6024,21 @@ const createStorage = (opts) => {
|
|
|
5909
6024
|
const wrapTransaction = (db) => (fn) => () => {
|
|
5910
6025
|
return db.transaction(({ trx }) => Promise.resolve(fn(trx, db)));
|
|
5911
6026
|
};
|
|
6027
|
+
const transformLogMessage = (level, message) => {
|
|
6028
|
+
if (typeof message === "string") {
|
|
6029
|
+
return { level, message };
|
|
6030
|
+
}
|
|
6031
|
+
if (typeof message === "object" && message !== null) {
|
|
6032
|
+
if ("event" in message && "name" in message) {
|
|
6033
|
+
return {
|
|
6034
|
+
level,
|
|
6035
|
+
message: `[internal migration]: ${message.event} ${message?.name}`,
|
|
6036
|
+
timestamp: Date.now()
|
|
6037
|
+
};
|
|
6038
|
+
}
|
|
6039
|
+
}
|
|
6040
|
+
return "";
|
|
6041
|
+
};
|
|
5912
6042
|
const migrationResolver = ({ name, path: path2, context }) => {
|
|
5913
6043
|
const { db } = context;
|
|
5914
6044
|
if (!path2) {
|
|
@@ -5937,7 +6067,20 @@ const createUserMigrationProvider = (db) => {
|
|
|
5937
6067
|
const context = { db };
|
|
5938
6068
|
const umzugProvider = new umzug.Umzug({
|
|
5939
6069
|
storage: createStorage({ db, tableName: "strapi_migrations" }),
|
|
5940
|
-
logger:
|
|
6070
|
+
logger: {
|
|
6071
|
+
info(message) {
|
|
6072
|
+
db.logger.info(transformLogMessage("info", message));
|
|
6073
|
+
},
|
|
6074
|
+
warn(message) {
|
|
6075
|
+
db.logger.warn(transformLogMessage("warn", message));
|
|
6076
|
+
},
|
|
6077
|
+
error(message) {
|
|
6078
|
+
db.logger.error(transformLogMessage("error", message));
|
|
6079
|
+
},
|
|
6080
|
+
debug(message) {
|
|
6081
|
+
db.logger.debug(transformLogMessage("debug", message));
|
|
6082
|
+
}
|
|
6083
|
+
},
|
|
5941
6084
|
context,
|
|
5942
6085
|
migrations: {
|
|
5943
6086
|
glob: ["*.{js,sql}", { cwd: dir }],
|
|
@@ -6243,7 +6386,8 @@ const createdLocale = {
|
|
|
6243
6386
|
if (!model) {
|
|
6244
6387
|
continue;
|
|
6245
6388
|
}
|
|
6246
|
-
|
|
6389
|
+
const hasLocaleColumn = await knex2.schema.hasColumn(meta.tableName, "locale");
|
|
6390
|
+
if (meta.attributes.locale && !hasLocaleColumn) {
|
|
6247
6391
|
await createLocaleColumn(knex2, meta.tableName);
|
|
6248
6392
|
}
|
|
6249
6393
|
}
|
|
@@ -6252,17 +6396,87 @@ const createdLocale = {
|
|
|
6252
6396
|
throw new Error("not implemented");
|
|
6253
6397
|
}
|
|
6254
6398
|
};
|
|
6399
|
+
const createPublishedAtColumn = async (db, tableName) => {
|
|
6400
|
+
await db.schema.alterTable(tableName, (table) => {
|
|
6401
|
+
table.string("published_at");
|
|
6402
|
+
});
|
|
6403
|
+
};
|
|
6404
|
+
const createdPublishedAt = {
|
|
6405
|
+
name: "5.0.0-04-created-published-at",
|
|
6406
|
+
async up(knex2, db) {
|
|
6407
|
+
for (const meta of db.metadata.values()) {
|
|
6408
|
+
const hasTable = await knex2.schema.hasTable(meta.tableName);
|
|
6409
|
+
if (!hasTable) {
|
|
6410
|
+
continue;
|
|
6411
|
+
}
|
|
6412
|
+
const uid = meta.uid;
|
|
6413
|
+
const model = strapi.getModel(uid);
|
|
6414
|
+
if (!model) {
|
|
6415
|
+
continue;
|
|
6416
|
+
}
|
|
6417
|
+
const hasPublishedAtColumn = await knex2.schema.hasColumn(meta.tableName, "published_at");
|
|
6418
|
+
if (meta.attributes.publishedAt && !hasPublishedAtColumn) {
|
|
6419
|
+
await createPublishedAtColumn(knex2, meta.tableName);
|
|
6420
|
+
}
|
|
6421
|
+
}
|
|
6422
|
+
},
|
|
6423
|
+
async down() {
|
|
6424
|
+
throw new Error("not implemented");
|
|
6425
|
+
}
|
|
6426
|
+
};
|
|
6427
|
+
const dropIndex = async (knex2, tableName, columnName) => {
|
|
6428
|
+
try {
|
|
6429
|
+
await knex2.schema.alterTable(tableName, (table) => {
|
|
6430
|
+
table.dropUnique([columnName], `${tableName}_${columnName}_unique`);
|
|
6431
|
+
});
|
|
6432
|
+
} catch (error) {
|
|
6433
|
+
}
|
|
6434
|
+
};
|
|
6435
|
+
const dropSlugFieldsIndex = {
|
|
6436
|
+
name: "5.0.0-05-drop-slug-fields-index",
|
|
6437
|
+
async up(knex2, db) {
|
|
6438
|
+
for (const meta of db.metadata.values()) {
|
|
6439
|
+
const hasTable = await knex2.schema.hasTable(meta.tableName);
|
|
6440
|
+
if (!hasTable) {
|
|
6441
|
+
continue;
|
|
6442
|
+
}
|
|
6443
|
+
for (const attribute of Object.values(meta.attributes)) {
|
|
6444
|
+
if (attribute.type === "uid" && attribute.columnName) {
|
|
6445
|
+
await dropIndex(knex2, meta.tableName, attribute.columnName);
|
|
6446
|
+
}
|
|
6447
|
+
}
|
|
6448
|
+
}
|
|
6449
|
+
},
|
|
6450
|
+
async down() {
|
|
6451
|
+
throw new Error("not implemented");
|
|
6452
|
+
}
|
|
6453
|
+
};
|
|
6255
6454
|
const internalMigrations = [
|
|
6256
6455
|
renameIdentifiersLongerThanMaxLength,
|
|
6257
6456
|
createdDocumentId,
|
|
6258
|
-
createdLocale
|
|
6457
|
+
createdLocale,
|
|
6458
|
+
createdPublishedAt,
|
|
6459
|
+
dropSlugFieldsIndex
|
|
6259
6460
|
];
|
|
6260
6461
|
const createInternalMigrationProvider = (db) => {
|
|
6261
6462
|
const context = { db };
|
|
6262
6463
|
const migrations = [...internalMigrations];
|
|
6263
6464
|
const umzugProvider = new umzug.Umzug({
|
|
6264
6465
|
storage: createStorage({ db, tableName: "strapi_migrations_internal" }),
|
|
6265
|
-
logger:
|
|
6466
|
+
logger: {
|
|
6467
|
+
info(message) {
|
|
6468
|
+
db.logger.debug(transformLogMessage("info", message));
|
|
6469
|
+
},
|
|
6470
|
+
warn(message) {
|
|
6471
|
+
db.logger.warn(transformLogMessage("warn", message));
|
|
6472
|
+
},
|
|
6473
|
+
error(message) {
|
|
6474
|
+
db.logger.error(transformLogMessage("error", message));
|
|
6475
|
+
},
|
|
6476
|
+
debug(message) {
|
|
6477
|
+
db.logger.debug(transformLogMessage("debug", message));
|
|
6478
|
+
}
|
|
6479
|
+
},
|
|
6266
6480
|
context,
|
|
6267
6481
|
migrations: () => migrations.map((migration) => {
|
|
6268
6482
|
return {
|
|
@@ -6533,6 +6747,7 @@ class Database {
|
|
|
6533
6747
|
migrations;
|
|
6534
6748
|
lifecycles;
|
|
6535
6749
|
entityManager;
|
|
6750
|
+
logger;
|
|
6536
6751
|
constructor(config) {
|
|
6537
6752
|
this.config = {
|
|
6538
6753
|
...config,
|
|
@@ -6552,6 +6767,7 @@ class Database {
|
|
|
6552
6767
|
this.migrations = createMigrationsProvider(this);
|
|
6553
6768
|
this.lifecycles = createLifecyclesProvider(this);
|
|
6554
6769
|
this.entityManager = createEntityManager(this);
|
|
6770
|
+
this.logger = config.logger ?? console;
|
|
6555
6771
|
}
|
|
6556
6772
|
async init({ models }) {
|
|
6557
6773
|
this.metadata.loadModels(models);
|