mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-08 06:59:26 +08:00
Merge branch 'main' into next
This commit is contained in:
commit
c79018774a
@ -447,4 +447,23 @@ describe('collection sync', () => {
|
|||||||
|
|
||||||
expect(error).toBeInstanceOf(IdentifierError);
|
expect(error).toBeInstanceOf(IdentifierError);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('paranoid', async () => {
|
||||||
|
const postCollection = db.collection({
|
||||||
|
name: 'posts',
|
||||||
|
fields: [{ type: 'string', name: 'title' }],
|
||||||
|
paranoid: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.sync();
|
||||||
|
|
||||||
|
const p1 = await postCollection.repository.create({ values: { title: 't1' } });
|
||||||
|
await p1.destroy();
|
||||||
|
|
||||||
|
const p2 = await postCollection.repository.findOne({ filterByTk: p1.id });
|
||||||
|
expect(p2).toBeNull();
|
||||||
|
|
||||||
|
const p3 = await postCollection.repository.findOne({ filterByTk: p1.id, paranoid: false });
|
||||||
|
expect(p3).not.toBeNull();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -12,6 +12,8 @@ import { describe, test } from 'vitest';
|
|||||||
import workflowManualTasks from '../../collections/workflowManualTasks';
|
import workflowManualTasks from '../../collections/workflowManualTasks';
|
||||||
import Migration from '../../migrations/20250312100512-change-table-name';
|
import Migration from '../../migrations/20250312100512-change-table-name';
|
||||||
|
|
||||||
|
const skipSqlite = process.env.DB_DIALECT === 'sqlite' ? test.skip : test;
|
||||||
|
|
||||||
const matrix: [string, string][] = [
|
const matrix: [string, string][] = [
|
||||||
// schema, tablePrefix
|
// schema, tablePrefix
|
||||||
[undefined, undefined],
|
[undefined, undefined],
|
||||||
@ -80,4 +82,50 @@ describe('20250225175712-change-table-name.test', () => {
|
|||||||
|
|
||||||
await app.destroy();
|
await app.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
skipSqlite(`multiple primary keys`, async () => {
|
||||||
|
const app = await createMockServer();
|
||||||
|
await app.version.update('1.5.0');
|
||||||
|
// mock m2m collections
|
||||||
|
app.db.collection({
|
||||||
|
...workflowManualTasks,
|
||||||
|
name: 'users_jobs',
|
||||||
|
});
|
||||||
|
app.db.collection({
|
||||||
|
name: 'users',
|
||||||
|
fields: [{ name: 'id', type: 'bigInt', primaryKey: true }],
|
||||||
|
});
|
||||||
|
app.db.collection({
|
||||||
|
name: 'jobs',
|
||||||
|
fields: [
|
||||||
|
{ name: 'id', type: 'bigInt', primaryKey: true },
|
||||||
|
{
|
||||||
|
type: 'belongsToMany',
|
||||||
|
name: 'users',
|
||||||
|
through: 'users_jobs',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
await app.db.sync();
|
||||||
|
|
||||||
|
const migration = new Migration({ db: app.db, app } as any);
|
||||||
|
await migration.up();
|
||||||
|
|
||||||
|
app.db.collection({
|
||||||
|
...workflowManualTasks,
|
||||||
|
});
|
||||||
|
app.db.removeCollection('jobs');
|
||||||
|
app.db.collection({
|
||||||
|
name: 'jobs',
|
||||||
|
fields: [{ name: 'id', type: 'bigInt', primaryKey: true }],
|
||||||
|
});
|
||||||
|
await app.db.sync();
|
||||||
|
const columns = await app.db.sequelize
|
||||||
|
.getQueryInterface()
|
||||||
|
.describeTable(app.db.getCollection(workflowManualTasks.name).getTableNameWithSchema());
|
||||||
|
const primaryKeys = Object.values(columns).filter((c) => c.primaryKey);
|
||||||
|
expect(primaryKeys.length).toBe(1);
|
||||||
|
|
||||||
|
await app.destroy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -7,7 +7,9 @@
|
|||||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Transaction } from 'sequelize';
|
||||||
import { Migration } from '@nocobase/server';
|
import { Migration } from '@nocobase/server';
|
||||||
|
import workflowManualTasks from '../collections/workflowManualTasks';
|
||||||
|
|
||||||
export default class extends Migration {
|
export default class extends Migration {
|
||||||
appVersion = '<1.7.0';
|
appVersion = '<1.7.0';
|
||||||
@ -16,24 +18,55 @@ export default class extends Migration {
|
|||||||
const { db } = this.context;
|
const { db } = this.context;
|
||||||
const queryInterface = db.sequelize.getQueryInterface();
|
const queryInterface = db.sequelize.getQueryInterface();
|
||||||
const usersJobsCollection = db.collection({
|
const usersJobsCollection = db.collection({
|
||||||
|
...workflowManualTasks,
|
||||||
name: 'users_jobs',
|
name: 'users_jobs',
|
||||||
fields: [{ name: 'id', type: 'bigInt' }],
|
|
||||||
});
|
});
|
||||||
const workflowManualTasksCollection = db.collection({
|
const workflowManualTasksCollection = db.collection({
|
||||||
name: 'workflowManualTasks',
|
...workflowManualTasks,
|
||||||
fields: [{ name: 'id', type: 'bigInt' }],
|
|
||||||
});
|
});
|
||||||
const oldTableName = usersJobsCollection.getTableNameWithSchema();
|
const oldTableName = usersJobsCollection.getTableNameWithSchema();
|
||||||
const oldTableNameWithQuotes = usersJobsCollection.getRealTableName(true);
|
const oldTableNameWithQuotes = usersJobsCollection.getRealTableName(true);
|
||||||
const newTableName = workflowManualTasksCollection.getTableNameWithSchema();
|
const newTableName = workflowManualTasksCollection.getTableNameWithSchema();
|
||||||
const newTableNameWithQuotes = workflowManualTasksCollection.getRealTableName(true);
|
const newTableNameWithQuotes = workflowManualTasksCollection.getRealTableName(true);
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
const exists = await queryInterface.tableExists(oldTableName, { transaction });
|
const exists = await queryInterface.tableExists(oldTableName);
|
||||||
if (exists) {
|
if (!exists) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
const constraints: any = await queryInterface.showConstraint(oldTableName);
|
||||||
|
// PG:
|
||||||
|
// {
|
||||||
|
// constraintCatalog: 'nocobase_test',
|
||||||
|
// constraintSchema: 'public',
|
||||||
|
// constraintName: 'posts_tags_pkey',
|
||||||
|
// tableCatalog: 'nocobase_test',
|
||||||
|
// tableSchema: 'public',
|
||||||
|
// tableName: 'posts_tags',
|
||||||
|
// constraintType: 'PRIMARY KEY', // use this to determine
|
||||||
|
// isDeferrable: 'NO',
|
||||||
|
// initiallyDeferred: 'NO'
|
||||||
|
// }
|
||||||
|
// MYSQL:
|
||||||
|
// {
|
||||||
|
// constraintCatalog: 'def',
|
||||||
|
// constraintName: 'PRIMARY',
|
||||||
|
// constraintSchema: 'nocobase_test',
|
||||||
|
// constraintType: 'PRIMARY KEY', // use this to determine
|
||||||
|
// tableName: 'posts_tags',
|
||||||
|
// tableSchema: 'nocobase_test'
|
||||||
|
// }
|
||||||
|
|
||||||
|
await db.sequelize.transaction(
|
||||||
|
{
|
||||||
|
isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE,
|
||||||
|
},
|
||||||
|
async (transaction) => {
|
||||||
const newExists = await queryInterface.tableExists(newTableName, { transaction });
|
const newExists = await queryInterface.tableExists(newTableName, { transaction });
|
||||||
if (newExists) {
|
if (newExists) {
|
||||||
await queryInterface.dropTable(newTableName, { transaction });
|
await queryInterface.dropTable(newTableName, { transaction });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.db.isPostgresCompatibleDialect()) {
|
if (this.db.isPostgresCompatibleDialect()) {
|
||||||
await db.sequelize.query(
|
await db.sequelize.query(
|
||||||
`ALTER TABLE ${oldTableNameWithQuotes} RENAME TO "${db.options.tablePrefix || ''}${
|
`ALTER TABLE ${oldTableNameWithQuotes} RENAME TO "${db.options.tablePrefix || ''}${
|
||||||
@ -47,6 +80,19 @@ export default class extends Migration {
|
|||||||
await queryInterface.renameTable(oldTableName, newTableName, { transaction });
|
await queryInterface.renameTable(oldTableName, newTableName, { transaction });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.db.isPostgresCompatibleDialect()) {
|
||||||
|
const primaryKeys = constraints.filter((item) => item.constraintType === 'PRIMARY KEY');
|
||||||
|
if (primaryKeys.length) {
|
||||||
|
for (const primaryKey of primaryKeys) {
|
||||||
|
await queryInterface.removeConstraint(newTableName, primaryKey.constraintName, { transaction });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (this.db.isMySQLCompatibleDialect()) {
|
||||||
|
await db.sequelize.query(`ALTER TABLE ${newTableNameWithQuotes} DROP PRIMARY KEY, ADD PRIMARY KEY (id)`, {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const indexes: any = await queryInterface.showIndex(newTableName, { transaction });
|
const indexes: any = await queryInterface.showIndex(newTableName, { transaction });
|
||||||
|
|
||||||
const oldIndexPrefix = `${db.options.tablePrefix || ''}users_jobs`;
|
const oldIndexPrefix = `${db.options.tablePrefix || ''}users_jobs`;
|
||||||
@ -71,8 +117,8 @@ export default class extends Migration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
});
|
);
|
||||||
db.removeCollection('users_jobs');
|
db.removeCollection('users_jobs');
|
||||||
db.removeCollection('workflowManualTasks');
|
db.removeCollection('workflowManualTasks');
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the NocoBase (R) project.
|
||||||
|
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||||
|
* Authors: NocoBase Team.
|
||||||
|
*
|
||||||
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||||
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Migration } from '@nocobase/server';
|
||||||
|
|
||||||
|
export default class extends Migration {
|
||||||
|
appVersion = '<1.7.0';
|
||||||
|
on = 'afterLoad';
|
||||||
|
async up() {
|
||||||
|
const { db } = this.context;
|
||||||
|
await db.sequelize.transaction(async (transaction) => {
|
||||||
|
const FieldRepo = db.getCollection('fields').repository;
|
||||||
|
await FieldRepo.destroy({
|
||||||
|
filter: {
|
||||||
|
collectionName: 'users',
|
||||||
|
name: 'jobs',
|
||||||
|
},
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await FieldRepo.destroy({
|
||||||
|
filter: {
|
||||||
|
collectionName: 'jobs',
|
||||||
|
name: 'users',
|
||||||
|
},
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
db.removeCollection('fields');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user