chore: remove field from db (#3233)
* chore: remove field from db * fix: test * chore: test
This commit is contained in:
parent
a8ae078baa
commit
2289bb7418
@ -97,7 +97,7 @@ describe('collection', () => {
|
|||||||
const field = collection.getField('name');
|
const field = collection.getField('name');
|
||||||
const r1 = await field.existsInDb();
|
const r1 = await field.existsInDb();
|
||||||
expect(r1).toBe(true);
|
expect(r1).toBe(true);
|
||||||
await field.removeFromDb();
|
await collection.removeFieldFromDb('name');
|
||||||
const r2 = await field.existsInDb();
|
const r2 = await field.existsInDb();
|
||||||
expect(r2).toBe(false);
|
expect(r2).toBe(false);
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import {
|
|||||||
ModelOptions,
|
ModelOptions,
|
||||||
ModelStatic,
|
ModelStatic,
|
||||||
QueryInterfaceDropTableOptions,
|
QueryInterfaceDropTableOptions,
|
||||||
|
QueryInterfaceOptions,
|
||||||
SyncOptions,
|
SyncOptions,
|
||||||
Transactionable,
|
Transactionable,
|
||||||
Utils,
|
Utils,
|
||||||
@ -382,6 +383,84 @@ export class Collection<
|
|||||||
return this.context.database.removeCollection(this.name);
|
return this.context.database.removeCollection(this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async removeFieldFromDb(name: string, options?: QueryInterfaceOptions) {
|
||||||
|
const field = this.getField(name);
|
||||||
|
if (!field) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const attribute = this.model.rawAttributes[name];
|
||||||
|
|
||||||
|
if (!attribute) {
|
||||||
|
field.remove();
|
||||||
|
// console.log('field is not attribute');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
if (this.isInherited() && this.parentFields().has(name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((this.model as any)._virtualAttributes.has(this.name)) {
|
||||||
|
field.remove();
|
||||||
|
// console.log('field is virtual attribute');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.model.primaryKeyAttributes.includes(this.name)) {
|
||||||
|
// 主键不能删除
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.model.options.timestamps !== false) {
|
||||||
|
// timestamps 相关字段不删除
|
||||||
|
let timestampsFields = ['createdAt', 'updatedAt', 'deletedAt'];
|
||||||
|
if (this.db.options.underscored) {
|
||||||
|
timestampsFields = timestampsFields.map((fieldName) => snakeCase(fieldName));
|
||||||
|
}
|
||||||
|
if (timestampsFields.includes(field.columnName())) {
|
||||||
|
this.fields.delete(name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 排序字段通过 sortable 控制
|
||||||
|
const sortable = this.options.sortable;
|
||||||
|
if (sortable) {
|
||||||
|
let sortField: any;
|
||||||
|
if (sortable === true) {
|
||||||
|
sortField = 'sort';
|
||||||
|
} else if (typeof sortable === 'string') {
|
||||||
|
sortField = sortable;
|
||||||
|
} else if (sortable.name) {
|
||||||
|
sortField = sortable.name || 'sort';
|
||||||
|
}
|
||||||
|
if (field.name === sortField) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isView()) {
|
||||||
|
field.remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const columnReferencesCount = _.filter(this.model.rawAttributes, (attr) => attr.field == field.columnName()).length;
|
||||||
|
|
||||||
|
if (
|
||||||
|
(await field.existsInDb({
|
||||||
|
transaction: options?.transaction,
|
||||||
|
})) &&
|
||||||
|
columnReferencesCount == 1
|
||||||
|
) {
|
||||||
|
const queryInterface = this.db.sequelize.getQueryInterface();
|
||||||
|
await queryInterface.removeColumn(this.getTableNameWithSchema(), field.columnName(), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
field.remove();
|
||||||
|
}
|
||||||
|
|
||||||
async removeFromDb(options?: QueryInterfaceDropTableOptions) {
|
async removeFromDb(options?: QueryInterfaceDropTableOptions) {
|
||||||
if (
|
if (
|
||||||
!this.isView() &&
|
!this.isView() &&
|
||||||
|
@ -1,15 +1,7 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import {
|
import { DataType, ModelAttributeColumnOptions, ModelIndexesOptions, SyncOptions, Transactionable } from 'sequelize';
|
||||||
DataType,
|
|
||||||
ModelAttributeColumnOptions,
|
|
||||||
ModelIndexesOptions,
|
|
||||||
QueryInterfaceOptions,
|
|
||||||
SyncOptions,
|
|
||||||
Transactionable,
|
|
||||||
} from 'sequelize';
|
|
||||||
import { Collection } from '../collection';
|
import { Collection } from '../collection';
|
||||||
import { Database } from '../database';
|
import { Database } from '../database';
|
||||||
import { InheritedCollection } from '../inherited-collection';
|
|
||||||
import { ModelEventTypes } from '../types';
|
import { ModelEventTypes } from '../types';
|
||||||
import { snakeCase } from '../utils';
|
import { snakeCase } from '../utils';
|
||||||
|
|
||||||
@ -102,84 +94,6 @@ export abstract class Field {
|
|||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeFromDb(options?: QueryInterfaceOptions) {
|
|
||||||
const attribute = this.collection.model.rawAttributes[this.name];
|
|
||||||
|
|
||||||
if (!attribute) {
|
|
||||||
this.remove();
|
|
||||||
// console.log('field is not attribute');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.collection.isInherited() && (<InheritedCollection>this.collection).parentFields().has(this.name)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((this.collection.model as any)._virtualAttributes.has(this.name)) {
|
|
||||||
this.remove();
|
|
||||||
// console.log('field is virtual attribute');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.collection.model.primaryKeyAttributes.includes(this.name)) {
|
|
||||||
// 主键不能删除
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.collection.model.options.timestamps !== false) {
|
|
||||||
// timestamps 相关字段不删除
|
|
||||||
let timestampsFields = ['createdAt', 'updatedAt', 'deletedAt'];
|
|
||||||
if (this.database.options.underscored) {
|
|
||||||
timestampsFields = timestampsFields.map((field) => snakeCase(field));
|
|
||||||
}
|
|
||||||
if (timestampsFields.includes(this.columnName())) {
|
|
||||||
this.collection.fields.delete(this.name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 排序字段通过 sortable 控制
|
|
||||||
const sortable = this.collection.options.sortable;
|
|
||||||
if (sortable) {
|
|
||||||
let sortField: any;
|
|
||||||
if (sortable === true) {
|
|
||||||
sortField = 'sort';
|
|
||||||
} else if (typeof sortable === 'string') {
|
|
||||||
sortField = sortable;
|
|
||||||
} else if (sortable.name) {
|
|
||||||
sortField = sortable.name || 'sort';
|
|
||||||
}
|
|
||||||
if (this.name === sortField) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (this.options.field && this.name !== this.options.field) {
|
|
||||||
// // field 指向的是真实的字段名,如果与 name 不一样,说明字段只是引用
|
|
||||||
// this.remove();
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (this.collection.isView()) {
|
|
||||||
this.remove();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const columnReferencesCount = _.filter(
|
|
||||||
this.collection.model.rawAttributes,
|
|
||||||
(attr) => attr.field == this.columnName(),
|
|
||||||
).length;
|
|
||||||
|
|
||||||
if (
|
|
||||||
(await this.existsInDb({
|
|
||||||
transaction: options?.transaction,
|
|
||||||
})) &&
|
|
||||||
columnReferencesCount == 1
|
|
||||||
) {
|
|
||||||
const queryInterface = this.database.sequelize.getQueryInterface();
|
|
||||||
await queryInterface.removeColumn(this.collection.getTableNameWithSchema(), this.columnName(), options);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
async existsInDb(options?: Transactionable) {
|
async existsInDb(options?: Transactionable) {
|
||||||
const opts = {
|
const opts = {
|
||||||
transaction: options?.transaction,
|
transaction: options?.transaction,
|
||||||
|
@ -98,16 +98,12 @@ export class FieldModel extends MagicAttributeModel {
|
|||||||
|
|
||||||
async remove(options?: any) {
|
async remove(options?: any) {
|
||||||
const collection = this.getFieldCollection();
|
const collection = this.getFieldCollection();
|
||||||
|
|
||||||
if (!collection) {
|
if (!collection) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const field = collection.getField(this.get('name'));
|
return collection.removeFieldFromDb(this.get('name'), {
|
||||||
if (!field) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return field.removeFromDb({
|
|
||||||
transaction: options.transaction,
|
transaction: options.transaction,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const collection = db.getCollection(filterByTk);
|
const collection = db.getCollection(filterByTk);
|
||||||
|
|
||||||
await collection.sync({
|
await collection.sync({
|
||||||
force: false,
|
force: false,
|
||||||
alter: {
|
alter: {
|
||||||
|
Loading…
Reference in New Issue
Block a user