#8 schemas support for postgres and mssql

This commit is contained in:
Kononnable 2017-10-15 18:11:08 +02:00
parent 54fc6317d5
commit 9205cee926
9 changed files with 62 additions and 43 deletions

View File

@ -11,7 +11,7 @@ export class Engine {
}
public async createModelFromDatabase(): Promise<boolean> {
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<DatabaseModel> {
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<DatabaseModel> {
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
}

View File

@ -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<DatabaseModel> {
async GetDataFromServer(database: string, server: string, port: number, user: string, password: string, schema:string): Promise<DatabaseModel> {
let dbModel = <DatabaseModel>{};
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<EntityInfo[]>
abstract async GetCoulmnsFromEntity(entities: EntityInfo[]): Promise<EntityInfo[]>;
abstract async GetIndexesFromEntity(entities: EntityInfo[]): Promise<EntityInfo[]>;
abstract async GetRelations(entities: EntityInfo[]): Promise<EntityInfo[]>;
abstract async GetAllTables(schema:string): Promise<EntityInfo[]>
abstract async GetCoulmnsFromEntity(entities: EntityInfo[],schema:string): Promise<EntityInfo[]>;
abstract async GetIndexesFromEntity(entities: EntityInfo[],schema:string): Promise<EntityInfo[]>;
abstract async GetRelations(entities: EntityInfo[],schema:string): Promise<EntityInfo[]>;
abstract async FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel);
abstract async DisconnectFromServer();

View File

@ -21,7 +21,7 @@ export class MariaDbDriver extends AbstractDriver {
});
}
async GetAllTables(): Promise<EntityInfo[]> {
async GetAllTables(schema:string): Promise<EntityInfo[]> {
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<EntityInfo[]> {
async GetCoulmnsFromEntity(entities: EntityInfo[],schema:string): Promise<EntityInfo[]> {
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<EntityInfo[]> {
async GetIndexesFromEntity(entities: EntityInfo[],schema:string): Promise<EntityInfo[]> {
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<EntityInfo[]> {
async GetRelations(entities: EntityInfo[],schema:string): Promise<EntityInfo[]> {
let response = await this.ExecQuery<{
TableWithForeignKey: string, FK_PartNo: number, ForeignKeyColumn: string,
TableReferenced: string, ForeignKeyColumnReferenced: string,

View File

@ -21,10 +21,10 @@ export class MssqlDriver extends AbstractDriver {
});
}
async GetAllTables(): Promise<EntityInfo[]> {
async GetAllTables(schema:string): Promise<EntityInfo[]> {
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[] = <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<EntityInfo[]> {
async GetCoulmnsFromEntity(entities: EntityInfo[],schema:string): Promise<EntityInfo[]> {
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<EntityInfo[]> {
async GetIndexesFromEntity(entities: EntityInfo[],schema:string): Promise<EntityInfo[]> {
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<EntityInfo[]> {
async GetRelations(entities: EntityInfo[],schema:string): Promise<EntityInfo[]> {
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[] = <RelationTempInfo[]>[];

View File

@ -21,7 +21,7 @@ export class MysqlDriver extends AbstractDriver {
});
}
async GetAllTables(): Promise<EntityInfo[]> {
async GetAllTables(schema:string): Promise<EntityInfo[]> {
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<EntityInfo[]> {
async GetCoulmnsFromEntity(entities: EntityInfo[],schema:string): Promise<EntityInfo[]> {
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<EntityInfo[]> {
async GetIndexesFromEntity(entities: EntityInfo[],schema:string): Promise<EntityInfo[]> {
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<EntityInfo[]> {
async GetRelations(entities: EntityInfo[],schema:string): Promise<EntityInfo[]> {
let response = await this.ExecQuery<{
TableWithForeignKey: string, FK_PartNo: number, ForeignKeyColumn: string,
TableReferenced: string, ForeignKeyColumnReferenced: string,

View File

@ -23,10 +23,10 @@ export class PostgresDriver extends AbstractDriver {
});
}
async GetAllTables(): Promise<EntityInfo[]> {
async GetAllTables(schema:string): Promise<EntityInfo[]> {
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[] = <EntityInfo[]>[];
response.forEach((val) => {
@ -38,7 +38,7 @@ export class PostgresDriver extends AbstractDriver {
})
return ret;
}
async GetCoulmnsFromEntity(entities: EntityInfo[]): Promise<EntityInfo[]> {
async GetCoulmnsFromEntity(entities: EntityInfo[],schema:string): Promise<EntityInfo[]> {
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<EntityInfo[]> {
async GetIndexesFromEntity(entities: EntityInfo[],schema:string): Promise<EntityInfo[]> {
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<EntityInfo[]> {
async GetRelations(entities: EntityInfo[],schema:string): Promise<EntityInfo[]> {
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,

View File

@ -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.`);

View File

@ -57,7 +57,7 @@ describe('MssqlDriver', function () {
}
}
)
let result = await driver.GetAllTables()
let result = await driver.GetAllTables('schema')
let expectedResult = <EntityInfo[]>[];
let y = new EntityInfo();
y.EntityName = 'name'
@ -105,7 +105,7 @@ describe('MssqlDriver', function () {
ts_type: 'number',
relations: <RelationInfo[]>[]
})
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')

View File

@ -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'
});