diff --git a/src/Engine.ts b/src/Engine.ts index a613511..2e891ba 100644 --- a/src/Engine.ts +++ b/src/Engine.ts @@ -11,7 +11,7 @@ export class Engine { } public async createModelFromDatabase(): Promise { - let dbModel = await this.getEntitiesInfo(this.Options.databaseName, this.Options.host, this.Options.port, this.Options.user, this.Options.password); + let dbModel = await this.getEntitiesInfo(this.Options.databaseName, this.Options.host, this.Options.port, this.Options.user, this.Options.password, this.Options.schemaName); if (dbModel.entities.length > 0) { this.createModelFromMetadata(dbModel); } else { @@ -19,8 +19,8 @@ export class Engine { } return true; } - private async getEntitiesInfo(database: string, server: string, port: number, user: string, password: string): Promise { - return await this.driver.GetDataFromServer(database, server, port, user, password) + private async getEntitiesInfo(database: string, server: string, port: number, user: string, password: string, schemaName:string): Promise { + return await this.driver.GetDataFromServer(database, server, port, user, password,schemaName) } private createModelFromMetadata(databaseModel: DatabaseModel) { @@ -81,5 +81,6 @@ export interface EngineOptions { user: string, password: string, resultsPath: string, - databaseType: string + databaseType: string, + schemaName:string } \ No newline at end of file diff --git a/src/drivers/AbstractDriver.ts b/src/drivers/AbstractDriver.ts index 7f6f399..72329c5 100644 --- a/src/drivers/AbstractDriver.ts +++ b/src/drivers/AbstractDriver.ts @@ -4,22 +4,22 @@ import { DatabaseModel } from './../models/DatabaseModel' * AbstractDriver */ export abstract class AbstractDriver { - async GetDataFromServer(database: string, server: string, port: number, user: string, password: string): Promise { + async GetDataFromServer(database: string, server: string, port: number, user: string, password: string, schema:string): Promise { let dbModel = {}; await this.ConnectToServer(database, server, port, user, password); - dbModel.entities = await this.GetAllTables(); - await this.GetCoulmnsFromEntity(dbModel.entities); - await this.GetIndexesFromEntity(dbModel.entities); - dbModel.entities = await this.GetRelations(dbModel.entities); + dbModel.entities = await this.GetAllTables(schema); + await this.GetCoulmnsFromEntity(dbModel.entities,schema); + await this.GetIndexesFromEntity(dbModel.entities,schema); + dbModel.entities = await this.GetRelations(dbModel.entities,schema); await this.DisconnectFromServer(); this.FindPrimaryColumnsFromIndexes(dbModel) return dbModel; } abstract async ConnectToServer(database: string, server: string, port: number, user: string, password: string); - abstract async GetAllTables(): Promise - abstract async GetCoulmnsFromEntity(entities: EntityInfo[]): Promise; - abstract async GetIndexesFromEntity(entities: EntityInfo[]): Promise; - abstract async GetRelations(entities: EntityInfo[]): Promise; + abstract async GetAllTables(schema:string): Promise + abstract async GetCoulmnsFromEntity(entities: EntityInfo[],schema:string): Promise; + abstract async GetIndexesFromEntity(entities: EntityInfo[],schema:string): Promise; + abstract async GetRelations(entities: EntityInfo[],schema:string): Promise; abstract async FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel); abstract async DisconnectFromServer(); diff --git a/src/drivers/MariaDbDriver.ts b/src/drivers/MariaDbDriver.ts index 75ddcfa..77b9a4d 100644 --- a/src/drivers/MariaDbDriver.ts +++ b/src/drivers/MariaDbDriver.ts @@ -21,7 +21,7 @@ export class MariaDbDriver extends AbstractDriver { }); } - async GetAllTables(): Promise { + async GetAllTables(schema:string): Promise { let response = await this.ExecQuery<{ TABLE_SCHEMA: string, TABLE_NAME: string }>(`SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.tables @@ -37,7 +37,7 @@ export class MariaDbDriver extends AbstractDriver { }) return ret; } - async GetCoulmnsFromEntity(entities: EntityInfo[]): Promise { + async GetCoulmnsFromEntity(entities: EntityInfo[],schema:string): Promise { let response = await this.ExecQuery<{ TABLE_NAME: string, COLUMN_NAME: string, COLUMN_DEFAULT: string, IS_NULLABLE: string, DATA_TYPE: string, CHARACTER_MAXIMUM_LENGTH: number, @@ -162,7 +162,7 @@ export class MariaDbDriver extends AbstractDriver { }) return entities; } - async GetIndexesFromEntity(entities: EntityInfo[]): Promise { + async GetIndexesFromEntity(entities: EntityInfo[],schema:string): Promise { let response = await this.ExecQuery<{ TableName: string, IndexName: string, ColumnName: string, is_unique: number, is_primary_key: number//, is_descending_key: number//, is_included_column: number @@ -200,7 +200,7 @@ export class MariaDbDriver extends AbstractDriver { return entities; } - async GetRelations(entities: EntityInfo[]): Promise { + async GetRelations(entities: EntityInfo[],schema:string): Promise { let response = await this.ExecQuery<{ TableWithForeignKey: string, FK_PartNo: number, ForeignKeyColumn: string, TableReferenced: string, ForeignKeyColumnReferenced: string, diff --git a/src/drivers/MssqlDriver.ts b/src/drivers/MssqlDriver.ts index 030dee6..c804111 100644 --- a/src/drivers/MssqlDriver.ts +++ b/src/drivers/MssqlDriver.ts @@ -21,10 +21,10 @@ export class MssqlDriver extends AbstractDriver { }); } - async GetAllTables(): Promise { + async GetAllTables(schema:string): Promise { let request = new MSSQL.Request(this.Connection) let response: { TABLE_SCHEMA: string, TABLE_NAME: string }[] - = (await request.query("SELECT TABLE_SCHEMA,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'")).recordset; + = (await request.query(`SELECT TABLE_SCHEMA,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA='${schema}'`)).recordset; let ret: EntityInfo[] = []; response.forEach((val) => { let ent: EntityInfo = new EntityInfo(); @@ -35,7 +35,7 @@ export class MssqlDriver extends AbstractDriver { }) return ret; } - async GetCoulmnsFromEntity(entities: EntityInfo[]): Promise { + async GetCoulmnsFromEntity(entities: EntityInfo[],schema:string): Promise { let request = new MSSQL.Request(this.Connection) let response: { TABLE_NAME: string, COLUMN_NAME: string, COLUMN_DEFAULT: string, @@ -44,7 +44,7 @@ export class MssqlDriver extends AbstractDriver { }[] = (await request.query(`SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE, DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE, - COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') IsIdentity FROM INFORMATION_SCHEMA.COLUMNS`)).recordset; + COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') IsIdentity FROM INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA='${schema}'`)).recordset; entities.forEach((ent) => { response.filter((filterVal) => { return filterVal.TABLE_NAME == ent.EntityName; @@ -154,7 +154,7 @@ export class MssqlDriver extends AbstractDriver { }) return entities; } - async GetIndexesFromEntity(entities: EntityInfo[]): Promise { + async GetIndexesFromEntity(entities: EntityInfo[],schema:string): Promise { let request = new MSSQL.Request(this.Connection) let response: { TableName: string, IndexName: string, ColumnName: string, is_unique: number, @@ -176,8 +176,10 @@ INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id INNER JOIN sys.tables t ON ind.object_id = t.object_id +INNER JOIN + sys.schemas s on s.schema_id=t.schema_id WHERE - t.is_ms_shipped = 0 + t.is_ms_shipped = 0 and s.name='${schema}' ORDER BY t.name, ind.name, ind.index_id, ic.key_ordinal;`)).recordset; entities.forEach((ent) => { @@ -209,7 +211,7 @@ ORDER BY return entities; } - async GetRelations(entities: EntityInfo[]): Promise { + async GetRelations(entities: EntityInfo[],schema:string): Promise { let request = new MSSQL.Request(this.Connection) let response: { TableWithForeignKey: string, FK_PartNo: number, ForeignKeyColumn: string, @@ -238,8 +240,10 @@ inner join sys.tables as referencedTable on fkc.referenced_object_id = referencedTable.object_id inner join sys.columns as referencedColumn on fkc.referenced_object_id = referencedColumn.object_id and fkc.referenced_column_id = referencedColumn.column_id +inner join + sys.schemas as parentSchema on parentSchema.schema_id=parentTable.schema_id where - fk.is_disabled=0 and fk.is_ms_shipped=0 + fk.is_disabled=0 and fk.is_ms_shipped=0 and parentSchema.name='${schema}' order by TableWithForeignKey, FK_PartNo`)).recordset; let relationsTemp: RelationTempInfo[] = []; diff --git a/src/drivers/MysqlDriver.ts b/src/drivers/MysqlDriver.ts index 0b823c0..637bf85 100644 --- a/src/drivers/MysqlDriver.ts +++ b/src/drivers/MysqlDriver.ts @@ -21,7 +21,7 @@ export class MysqlDriver extends AbstractDriver { }); } - async GetAllTables(): Promise { + async GetAllTables(schema:string): Promise { let response = await this.ExecQuery<{ TABLE_SCHEMA: string, TABLE_NAME: string }>(`SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.tables @@ -37,7 +37,7 @@ export class MysqlDriver extends AbstractDriver { }) return ret; } - async GetCoulmnsFromEntity(entities: EntityInfo[]): Promise { + async GetCoulmnsFromEntity(entities: EntityInfo[],schema:string): Promise { let response = await this.ExecQuery<{ TABLE_NAME: string, COLUMN_NAME: string, COLUMN_DEFAULT: string, IS_NULLABLE: string, DATA_TYPE: string, CHARACTER_MAXIMUM_LENGTH: number, @@ -162,7 +162,7 @@ export class MysqlDriver extends AbstractDriver { }) return entities; } - async GetIndexesFromEntity(entities: EntityInfo[]): Promise { + async GetIndexesFromEntity(entities: EntityInfo[],schema:string): Promise { let response = await this.ExecQuery<{ TableName: string, IndexName: string, ColumnName: string, is_unique: number, is_primary_key: number//, is_descending_key: number//, is_included_column: number @@ -200,7 +200,7 @@ export class MysqlDriver extends AbstractDriver { return entities; } - async GetRelations(entities: EntityInfo[]): Promise { + async GetRelations(entities: EntityInfo[],schema:string): Promise { let response = await this.ExecQuery<{ TableWithForeignKey: string, FK_PartNo: number, ForeignKeyColumn: string, TableReferenced: string, ForeignKeyColumnReferenced: string, diff --git a/src/drivers/PostgresDriver.ts b/src/drivers/PostgresDriver.ts index 6108cb4..4895f74 100644 --- a/src/drivers/PostgresDriver.ts +++ b/src/drivers/PostgresDriver.ts @@ -23,10 +23,10 @@ export class PostgresDriver extends AbstractDriver { }); } - async GetAllTables(): Promise { + async GetAllTables(schema:string): Promise { let response: { table_schema: string, table_name: string }[] - = (await this.Connection.query("SELECT table_schema,table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND table_schema = 'public' ")).rows; + = (await this.Connection.query(`SELECT table_schema,table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND table_schema = '${schema}' `)).rows; let ret: EntityInfo[] = []; response.forEach((val) => { @@ -38,7 +38,7 @@ export class PostgresDriver extends AbstractDriver { }) return ret; } - async GetCoulmnsFromEntity(entities: EntityInfo[]): Promise { + async GetCoulmnsFromEntity(entities: EntityInfo[],schema:string): Promise { let response: { table_name: string, column_name: string, column_default: string, is_nullable: string, data_type: string, character_maximum_length: number, @@ -48,7 +48,7 @@ export class PostgresDriver extends AbstractDriver { data_type,character_maximum_length,numeric_precision,numeric_scale --,COLUMNPROPERTY(object_id(table_name), column_name, 'isidentity') isidentity , case when column_default LIKE 'nextval%' then 'YES' else 'NO' end isidentity - FROM INFORMATION_SCHEMA.COLUMNS where table_schema ='public'`)).rows; + FROM INFORMATION_SCHEMA.COLUMNS where table_schema ='${schema}'`)).rows; entities.forEach((ent) => { response.filter((filterVal) => { return filterVal.table_name == ent.EntityName; @@ -134,7 +134,7 @@ export class PostgresDriver extends AbstractDriver { }) return entities; } - async GetIndexesFromEntity(entities: EntityInfo[]): Promise { + async GetIndexesFromEntity(entities: EntityInfo[],schema:string): Promise { let response: { tablename: string, indexname: string, columnname: string, is_unique: number, is_primary_key: number//, is_descending_key: number//, is_included_column: number @@ -162,7 +162,7 @@ export class PostgresDriver extends AbstractDriver { LEFT JOIN pg_class AS i ON ix.indexrelid = i.oid WHERE c.relkind = 'r'::char - AND n.nspname = 'public' -- Replace with Schema name + AND n.nspname = '${schema}' --AND c.relname = 'nodes' -- Replace with table name, or Comment this for get all tables AND f.attnum > 0 AND i.oid<>0 @@ -199,7 +199,7 @@ export class PostgresDriver extends AbstractDriver { return entities; } - async GetRelations(entities: EntityInfo[]): Promise { + async GetRelations(entities: EntityInfo[],schema:string): Promise { let response: { tablewithforeignkey: string, fk_partno: number, foreignkeycolumn: string, tablereferenced: string, foreignkeycolumnreferenced: string, @@ -231,6 +231,7 @@ export class PostgresDriver extends AbstractDriver { con1.contype = 'f'::"char" AND cl_1.relnamespace = ns.oid AND con1.conrelid = cl_1.oid + and nspname='${schema}' ) con, pg_attribute att, pg_class cl, diff --git a/src/index.ts b/src/index.ts index 1e18b40..43810df 100644 --- a/src/index.ts +++ b/src/index.ts @@ -46,19 +46,26 @@ var argv = Yargs describe: 'Where to place generated models.', default: path.resolve(process.cwd(), 'output') }) + .option('s', { + alias: 'schema', + describe: 'Schema name to create model from. Only for mssql and postgres.' + }) .argv; var driver: AbstractDriver; var standardPort: number; +var standardSchema: string = ''; switch (argv.e) { case 'mssql': driver = new MssqlDriver(); standardPort = 1433; + standardSchema = 'dbo'; break; case 'postgres': driver = new PostgresDriver(); standardPort = 5432; + standardSchema = 'public'; break; case 'mysql': driver = new MysqlDriver(); @@ -74,6 +81,7 @@ switch (argv.e) { throw new Error('Database engine not recognized.'); } + let engine = new Engine( driver, { host: argv.h, @@ -82,7 +90,8 @@ let engine = new Engine( user: argv.u, password: argv.x, databaseType: argv.e, - resultsPath: argv.o + resultsPath: argv.o, + schemaName: argv.s || standardSchema }); console.log(`[${new Date().toLocaleTimeString()}] Starting creation of model classes.`); diff --git a/test/drivers/MssqlDriver.test.ts b/test/drivers/MssqlDriver.test.ts index 52771eb..bbcb22a 100644 --- a/test/drivers/MssqlDriver.test.ts +++ b/test/drivers/MssqlDriver.test.ts @@ -57,7 +57,7 @@ describe('MssqlDriver', function () { } } ) - let result = await driver.GetAllTables() + let result = await driver.GetAllTables('schema') let expectedResult = []; let y = new EntityInfo(); y.EntityName = 'name' @@ -105,7 +105,7 @@ describe('MssqlDriver', function () { ts_type: 'number', relations: [] }) - let result = await driver.GetCoulmnsFromEntity(entities); + let result = await driver.GetCoulmnsFromEntity(entities,'schema'); expect(result).to.be.deep.equal(expected) }) it('should find primary indexes') diff --git a/test/integration/integration.test.ts b/test/integration/integration.test.ts index 0e1d859..d30cea9 100644 --- a/test/integration/integration.test.ts +++ b/test/integration/integration.test.ts @@ -139,7 +139,8 @@ async function createMSSQLModels(filesOrgPath: string, resultsPath: string): Pro user: String(process.env.MSSQL_Username), password: String(process.env.MSSQL_Password), databaseType: 'mssql', - resultsPath: resultsPath + resultsPath: resultsPath, + schemaName:'dbo' }); @@ -180,7 +181,8 @@ async function createPostgresModels(filesOrgPath: string, resultsPath: string): user: String(process.env.POSTGRES_Username), password: String(process.env.POSTGRES_Password), databaseType: 'postgres', - resultsPath: resultsPath + resultsPath: resultsPath, + schemaName:'public' }); @@ -222,7 +224,8 @@ async function createMysqlModels(filesOrgPath: string, resultsPath: string): Pro user: String(process.env.MYSQL_Username), password: String(process.env.MYSQL_Password), databaseType: 'mysql', - resultsPath: resultsPath + resultsPath: resultsPath, + schemaName:'ignored' }); @@ -264,7 +267,8 @@ async function createMariaDBModels(filesOrgPath: string, resultsPath: string): P user: String(process.env.MARIADB_Username), password: String(process.env.MARIADB_Password), databaseType: 'mariadb', - resultsPath: resultsPath + resultsPath: resultsPath, + schemaName:'ignored' });