-
-
Notifications
You must be signed in to change notification settings - Fork 528
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PostgreSQL: Model file writing for tables with same names but different schemas #530
Comments
Should we prefix the filename with the schema name?
…On Thu, Jun 10, 2021, 8:50 AM Paul K. ***@***.***> wrote:
When programmatically writing your models to files using the option
directory, there is no distinction for tables with the same name but
different schemas.
Example:
Given the following 2 tables in a database schema1.users and schema2.users,
where schema1 and schema2 are different schemas, when creating the models
using the file writing option, the initial model file will get overridden
as the table names are the same, despite being different tables. So there
will be only 1 model file generated.
In the above example, the init-models.js file generated would look like
this:
var DataTypes = require("sequelize").DataTypes;var _users = require("./users");var _users = require("./users");
function initModels(sequelize) {
var users = _users(sequelize, DataTypes);
var users = _users(sequelize, DataTypes);
return {
users,
users,
};}module.exports = initModels;module.exports.initModels = initModels;module.exports.default = initModels;
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#530>, or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAMYFNWN7XPDJRQ2WUXB2BTTSDNNZANCNFSM46OZUC7A>
.
|
That would work! |
would be nice if the schema and the class prefix with "shema_" this will help a lot cause the foreign keys are also being affected in the init file import _sequelize from "sequelize";
const DataTypes = _sequelize.DataTypes;
import _public_users from "./public_users";
import _gpus_users from "./gpus_users";
import _gpus_userstatus from "./gpus_userstatus.js";
export default function initModels(sequelize) {
var public_users = _public_users.init(sequelize, DataTypes);
var gpus_users= _gpus_users.init(sequelize, DataTypes);
var gpus_userstatus = _gpus_userstatus.init(sequelize, DataTypes);
gpus_users.belongsTo(gpus_userstatus, { as: "status_gpus_userstatus", foreignKey: "status"});
gpus_userstatus.hasMany(gpus_users, { as: "gpus_users", foreignKey: "status"});
return {
public_users,
gpus_users,
gpus_userstatus,
};
} import _sequelize from 'sequelize';
const { Model, Sequelize } = _sequelize;
export default class public_users extends Model {
static init(sequelize, DataTypes) {
super.init({
iduser: {
autoIncrement: true,
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
name: {
type: DataTypes.TEXT,
allowNull: true
},
lastname: {
type: DataTypes.TEXT,
allowNull: true
}
}, {
sequelize,
tableName: 'users',
schema: 'public',
timestamps: true,
indexes: [
{
name: "users_pkey",
unique: true,
fields: [
{ name: "iduser" },
]
},
]
});
return public_users;
}
} |
Hey @paulkr here is a temp fix of this replace the auto-writer.js in your library with the code bellow "use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AutoWriter = void 0;
const fs_1 = __importDefault(require("fs"));
const lodash_1 = __importDefault(require("lodash"));
const path_1 = __importDefault(require("path"));
const util_1 = __importDefault(require("util"));
const sequelize_1 = require("sequelize");
const types_1 = require("./types");
const mkdirp = require('mkdirp');
/** Writes text into files from TableData.text, and writes init-models */
class AutoWriter {
constructor(tableData, options) {
this.tableText = tableData.text;
this.foreignKeys = tableData.foreignKeys;
this.relations = tableData.relations;
this.options = options;
}
write() {
if (this.options.noWrite) {
return Promise.resolve();
}
mkdirp.sync(path_1.default.resolve(this.options.directory || "./models"));
const tables = lodash_1.default.keys(this.tableText);
// write the individual model files
const promises = tables.map(t => {
return this.createFile(t);
});
const isTypeScript = this.options.lang === 'ts';
const assoc = this.createAssociations(isTypeScript);
// get table names without schema
// TODO: add schema to model and file names when schema is non-default for the dialect
const tableNames = tables.map(t => {
const [schemaName, tableName] = types_1.qNameSplit(t);
return schemaName+"_"+tableName;
}).sort();
// write the init-models file
if (!this.options.noInitModels) {
const initString = this.createInitString(tableNames, assoc, this.options.lang);
const initFilePath = path_1.default.join(this.options.directory, "init-models" + (isTypeScript ? '.ts' : '.js'));
const writeFile = util_1.default.promisify(fs_1.default.writeFile);
const initPromise = writeFile(path_1.default.resolve(initFilePath), initString);
promises.push(initPromise);
}
return Promise.all(promises);
}
createInitString(tableNames, assoc, lang) {
switch (lang) {
case 'ts':
return this.createTsInitString(tableNames, assoc);
case 'esm':
return this.createESMInitString(tableNames, assoc);
default:
return this.createES5InitString(tableNames, assoc);
}
}
createFile(table) {
// FIXME: schema is not used to write the file name and there could be collisions. For now it
// is up to the developer to pick the right schema, and potentially chose different output
// folders for each different schema.
const [schemaName, tableName] = types_1.qNameSplit(table);
const fileName = types_1.recase(this.options.caseFile, schemaName+"_"+tableName, this.options.singularize);
const filePath = path_1.default.join(this.options.directory, fileName + (this.options.lang === 'ts' ? '.ts' : '.js'));
const writeFile = util_1.default.promisify(fs_1.default.writeFile);
let replacer = new RegExp(" +" + tableName, "g");
let result = this.tableText[table].replace(replacer, " " + schemaName+"_"+tableName);
return writeFile(path_1.default.resolve(filePath),result);
}
/** Create the belongsToMany/belongsTo/hasMany/hasOne association strings */
createAssociations(typeScript) {
let strBelongs = "";
let strBelongsToMany = "";
const rels = this.relations;
rels.forEach(rel => {
if (rel.isM2M) {
const asprop = types_1.pluralize(rel.childProp);
strBelongsToMany += ` ${rel.parentTable.replace(".","_")}.belongsToMany(${rel.childTable.replace(".","_")}, { as: '${asprop}', through: ${rel.joinModel}, foreignKey: "${rel.parentId}", otherKey: "${rel.childId}" });\n`;
}
else {
const bAlias = (this.options.noAlias && rel.parentTable.replace(".","_").toLowerCase() === rel.parentProp.toLowerCase()) ? '' : `as: "${rel.parentProp}", `;
strBelongs += ` ${rel.childTable.replace(".","_")}.belongsTo(${rel.parentTable.replace(".","_")}, { ${bAlias}foreignKey: "${rel.parentId}"});\n`;
const hasRel = rel.isOne ? "hasOne" : "hasMany";
const hAlias = (this.options.noAlias && sequelize_1.Utils.pluralize(rel.childTable.replace(".","_").toLowerCase()) === rel.childProp.toLowerCase()) ? '' : `as: "${rel.childProp}", `;
strBelongs += ` ${rel.parentTable.replace(".","_")}.${hasRel}(${rel.childTable.replace(".","_")}, { ${hAlias}foreignKey: "${rel.parentId}"});\n`;
}
});
// belongsToMany must come first
return strBelongsToMany + strBelongs;
}
// create the TypeScript init-models file to load all the models into Sequelize
createTsInitString(tables, assoc) {
let str = 'import type { Sequelize, Model } from "sequelize";\n';
const modelNames = [];
// import statements
tables.forEach(t => {
const fileName = types_1.recase(this.options.caseFile, t, this.options.singularize);
const modelName = types_1.recase(this.options.caseModel, t, this.options.singularize);
modelNames.push(modelName);
str += `import { ${modelName} } from "./${fileName}";\n`;
str += `import type { ${modelName}Attributes, ${modelName}CreationAttributes } from "./${fileName}";\n`;
});
// re-export the model classes
str += '\nexport {\n';
modelNames.forEach(m => {
str += ` ${m},\n`;
});
str += '};\n';
// re-export the model attirbutes
str += '\nexport type {\n';
modelNames.forEach(m => {
str += ` ${m}Attributes,\n`;
str += ` ${m}CreationAttributes,\n`;
});
str += '};\n\n';
// create the initialization function
str += 'export function initModels(sequelize: Sequelize) {\n';
modelNames.forEach(m => {
str += ` ${m}.initModel(sequelize);\n`;
});
// add the asociations
str += "\n" + assoc;
// return the models
str += "\n return {\n";
modelNames.forEach(m => {
str += ` ${m}: ${m},\n`;
});
str += ' };\n';
str += '}\n';
return str;
}
// create the ES5 init-models file to load all the models into Sequelize
createES5InitString(tables, assoc) {
let str = 'var DataTypes = require("sequelize").DataTypes;\n';
const modelNames = [];
// import statements
tables.forEach(t => {
const fileName = types_1.recase(this.options.caseFile, t, this.options.singularize);
const modelName = types_1.recase(this.options.caseModel, t, this.options.singularize);
modelNames.push(modelName);
str += `var _${modelName} = require("./${fileName}");\n`;
});
// create the initialization function
str += '\nfunction initModels(sequelize) {\n';
modelNames.forEach(m => {
str += ` var ${m} = _${m}(sequelize, DataTypes);\n`;
});
// add the asociations
str += "\n" + assoc;
// return the models
str += "\n return {\n";
modelNames.forEach(m => {
str += ` ${m},\n`;
});
str += ' };\n';
str += '}\n';
str += 'module.exports = initModels;\n';
str += 'module.exports.initModels = initModels;\n';
str += 'module.exports.default = initModels;\n';
return str;
}
// create the ESM init-models file to load all the models into Sequelize
createESMInitString(tables, assoc) {
let str = 'import _sequelize from "sequelize";\n';
str += 'const DataTypes = _sequelize.DataTypes;\n';
const modelNames = [];
// import statements
tables.forEach(t => {
const fileName = types_1.recase(this.options.caseFile, t, this.options.singularize);
const modelName = types_1.recase(this.options.caseModel, t, this.options.singularize);
modelNames.push(modelName);
str += `import _${modelName} from "./${fileName}.js";\n`;
});
// create the initialization function
str += '\nexport default function initModels(sequelize) {\n';
modelNames.forEach(m => {
str += ` var ${m} = _${m}.init(sequelize, DataTypes);\n`;
});
// add the asociations
str += "\n" + assoc;
// return the models
str += "\n return {\n";
modelNames.forEach(m => {
str += ` ${m},\n`;
});
str += ' };\n';
str += '}\n';
return str;
}
}
exports.AutoWriter = AutoWriter;
//# sourceMappingURL=auto-writer.js.map |
Ah, I was about to open an issue with a similar request, I am writing a large app with many schemas, and I also have tables with the same name in different schemas. I am trying to merge the auto-writer in the last comment with the current one. |
When writing your models to files using the option
directory
, there is no distinction for tables with the same name but different schemas.Example:
Given the following 2 tables in a database
schema1.users
andschema2.users
, whereschema1
andschema2
are different schemas, when creating the models using the file writing option, the initial model file will get overridden as the table names are the same, despite being different tables. So there will be only 1 model file generated.In the above example, the
init-models.js
file generated would look like this:The text was updated successfully, but these errors were encountered: