fix(cm): update to bigint
This commit is contained in:
		
							parent
							
								
									c52f451840
								
							
						
					
					
						commit
						c888d793ee
					
				@ -0,0 +1,145 @@
 | 
				
			|||||||
 | 
					import { DataTypes } from '@nocobase/database';
 | 
				
			||||||
 | 
					import { Migration } from '@nocobase/server';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class UpdateIdToBigIntMigrator extends Migration {
 | 
				
			||||||
 | 
					  async up() {
 | 
				
			||||||
 | 
					    const db = this.app.db;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await db.getCollection('fields').repository.update({
 | 
				
			||||||
 | 
					      filter: {
 | 
				
			||||||
 | 
					        name: 'id',
 | 
				
			||||||
 | 
					        type: 'integer',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      values: {
 | 
				
			||||||
 | 
					        type: 'bigInt',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!db.inDialect('mysql', 'postgres')) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const models = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const queryInterface = db.sequelize.getQueryInterface() as any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const queryGenerator = queryInterface.queryGenerator as any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const updateToBigInt = async (model, fieldName) => {
 | 
				
			||||||
 | 
					      let sql;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const tableName = model.tableName;
 | 
				
			||||||
 | 
					      if (model.rawAttributes[fieldName].type instanceof DataTypes.INTEGER) {
 | 
				
			||||||
 | 
					        if (db.inDialect('postgres')) {
 | 
				
			||||||
 | 
					          sql = `ALTER TABLE "${tableName}" ALTER COLUMN "${fieldName}" SET DATA TYPE BIGINT;`;
 | 
				
			||||||
 | 
					        } else if (db.inDialect('mysql')) {
 | 
				
			||||||
 | 
					          const dataTypeOrOptions = model.rawAttributes[fieldName];
 | 
				
			||||||
 | 
					          const attributeName = fieldName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          const query = queryGenerator.attributesToSQL(
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              [attributeName]: queryInterface.normalizeAttribute({
 | 
				
			||||||
 | 
					                ...dataTypeOrOptions,
 | 
				
			||||||
 | 
					                type: DataTypes.BIGINT,
 | 
				
			||||||
 | 
					              }),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              context: 'changeColumn',
 | 
				
			||||||
 | 
					              table: tableName,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					          sql = queryGenerator.changeColumnQuery(tableName, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          sql = sql.replace(' PRIMARY KEY;', ' ;');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					          await this.sequelize.query(sql, {});
 | 
				
			||||||
 | 
					        } catch (err) {
 | 
				
			||||||
 | 
					          if (err.message.includes('does not exist')) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          throw err;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.app.log.info(`updated ${tableName}.${fieldName} to BIGINT`, tableName, fieldName);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //@ts-ignore
 | 
				
			||||||
 | 
					    this.app.db.sequelize.modelManager.forEachModel((model) => {
 | 
				
			||||||
 | 
					      models.push(model);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const model of models) {
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        const primaryKeyField = model.tableAttributes[model.primaryKeyField];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const collection = db.modelCollection.get(model);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!collection) {
 | 
				
			||||||
 | 
					          continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (primaryKeyField && primaryKeyField.primaryKey) {
 | 
				
			||||||
 | 
					          await updateToBigInt(model, model.primaryKeyField);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (model.tableAttributes['sort'] && model.tableAttributes['sort'].type instanceof DataTypes.INTEGER) {
 | 
				
			||||||
 | 
					          await updateToBigInt(model, 'sort');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const associations = model.associations;
 | 
				
			||||||
 | 
					        for (const associationName of Object.keys(associations)) {
 | 
				
			||||||
 | 
					          const association = associations[associationName];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          const type = association.associationType;
 | 
				
			||||||
 | 
					          let foreignModel;
 | 
				
			||||||
 | 
					          let fieldName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (type === 'BelongsTo') {
 | 
				
			||||||
 | 
					            foreignModel = association.source;
 | 
				
			||||||
 | 
					            fieldName = association.foreignKey;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (type === 'HasMany') {
 | 
				
			||||||
 | 
					            foreignModel = association.target;
 | 
				
			||||||
 | 
					            fieldName = association.foreignKey;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (type === 'HasOne') {
 | 
				
			||||||
 | 
					            foreignModel = association.target;
 | 
				
			||||||
 | 
					            fieldName = association.foreignKey;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (foreignModel && fieldName) {
 | 
				
			||||||
 | 
					            const cf = await db.getRepository<any>('collections.fields', foreignModel.name).findOne({
 | 
				
			||||||
 | 
					              filterByTk: fieldName,
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            if (cf) {
 | 
				
			||||||
 | 
					              cf.interface = 'integer';
 | 
				
			||||||
 | 
					              cf.type = 'bigInt';
 | 
				
			||||||
 | 
					              await cf.save();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            await updateToBigInt(foreignModel, fieldName);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (type === 'BelongsToMany') {
 | 
				
			||||||
 | 
					            const throughModel = association.through.model;
 | 
				
			||||||
 | 
					            const otherKey = association.otherKey;
 | 
				
			||||||
 | 
					            const foreignKey = association.foreignKey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            await updateToBigInt(throughModel, otherKey);
 | 
				
			||||||
 | 
					            await updateToBigInt(throughModel, foreignKey);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } catch (error) {
 | 
				
			||||||
 | 
					        if (error.message.includes('cannot alter inherited column')) {
 | 
				
			||||||
 | 
					          continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        throw error;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user