addedsupport for multiple schemas on postgres,mssql

closes #39
This commit is contained in:
Kononnable 2018-03-04 23:39:15 +01:00
parent 3eeb7be881
commit a19d82609c
11 changed files with 124 additions and 25 deletions

View File

@ -15,10 +15,11 @@ export abstract class AbstractDriver {
): Promise<DatabaseModel> {
let dbModel = <DatabaseModel>{};
await this.ConnectToServer(database, server, port, user, password, ssl);
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);
let sqlEscapedSchema='\''+ schema.split(',').join('\',\'')+'\''
dbModel.entities = await this.GetAllTables(sqlEscapedSchema);
await this.GetCoulmnsFromEntity(dbModel.entities, sqlEscapedSchema);
await this.GetIndexesFromEntity(dbModel.entities, sqlEscapedSchema);
dbModel.entities = await this.GetRelations(dbModel.entities, sqlEscapedSchema);
await this.DisconnectFromServer();
this.FindPrimaryColumnsFromIndexes(dbModel);
return dbModel;

View File

@ -37,12 +37,13 @@ export class MssqlDriver extends AbstractDriver {
TABLE_SCHEMA: string;
TABLE_NAME: string;
}[] = (await request.query(
`SELECT TABLE_SCHEMA,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA='${schema}'`
`SELECT TABLE_SCHEMA,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema})`
)).recordset;
let ret: EntityInfo[] = <EntityInfo[]>[];
response.forEach(val => {
let ent: EntityInfo = new EntityInfo();
ent.EntityName = val.TABLE_NAME;
ent.Schema=val.TABLE_SCHEMA;
ent.Columns = <ColumnInfo[]>[];
ent.Indexes = <IndexInfo[]>[];
ret.push(ent);
@ -66,7 +67,7 @@ export class MssqlDriver extends AbstractDriver {
IsIdentity: number;
}[] = (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 where TABLE_SCHEMA='${schema}'`))
COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') IsIdentity FROM INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA in (${schema})`))
.recordset;
entities.forEach(ent => {
response
@ -278,7 +279,7 @@ INNER JOIN
INNER JOIN
sys.schemas s on s.schema_id=t.schema_id
WHERE
t.is_ms_shipped = 0 and s.name='${schema}'
t.is_ms_shipped = 0 and s.name in (${schema})
ORDER BY
t.name, ind.name, ind.index_id, ic.key_ordinal;`)).recordset;
entities.forEach(ent => {
@ -352,7 +353,7 @@ inner join
inner join
sys.schemas as parentSchema on parentSchema.schema_id=parentTable.schema_id
where
fk.is_disabled=0 and fk.is_ms_shipped=0 and parentSchema.name='${schema}'
fk.is_disabled=0 and fk.is_ms_shipped=0 and parentSchema.name in (${schema})
order by
TableWithForeignKey, FK_PartNo`)).recordset;
let relationsTemp: RelationTempInfo[] = <RelationTempInfo[]>[];

View File

@ -37,13 +37,14 @@ export class PostgresDriver extends AbstractDriver {
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 = '${schema}' `
`SELECT table_schema,table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND table_schema in (${schema}) `
)).rows;
let ret: EntityInfo[] = <EntityInfo[]>[];
response.forEach(val => {
let ent: EntityInfo = new EntityInfo();
ent.EntityName = val.table_name;
ent.Schema=val.table_schema;
ent.Columns = <ColumnInfo[]>[];
ent.Indexes = <IndexInfo[]>[];
ret.push(ent);
@ -69,7 +70,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 ='${schema}'`))
FROM INFORMATION_SCHEMA.COLUMNS where table_schema in (${schema})`))
.rows;
entities.forEach(ent => {
response
@ -84,7 +85,7 @@ export class PostgresDriver extends AbstractDriver {
colInfo.is_generated =
resp.isidentity == "YES" ? true : false;
colInfo.default = colInfo.is_generated
? ""
? null
: resp.column_default;
colInfo.sql_type = resp.data_type;
switch (resp.data_type) {
@ -252,7 +253,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 = '${schema}'
AND n.nspname in (${schema})
--AND c.relname = 'nodes' -- Replace with table name, or Comment this for get all tables
AND f.attnum > 0
AND i.oid<>0
@ -331,7 +332,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}'
and nspname in (${schema})
) con,
pg_attribute att,
pg_class cl,

View File

@ -3,7 +3,7 @@ import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, Joi
{{/each}}
@Entity("{{EntityName}}")
@Entity("{{EntityName}}"{{#Schema}},{schema:"{{.}}"}{{/Schema}})
{{#Indexes}}{{^isPrimaryKey}}@Index("{{name}}",[{{#columns}}"{{name}}",{{/columns}}]{{#isUnique}},{unique:true}{{/isUnique}})
{{/isPrimaryKey}}{{/Indexes}}export class {{toEntityName EntityName}} {
{{#Columns}}

View File

@ -10,6 +10,7 @@ export class EntityInfo {
Imports: string[];
UniqueImports: string[];
Indexes: IndexInfo[];
Schema:string;
relationImports(): any {
var returnString = "";

View File

@ -61,6 +61,7 @@ describe('MssqlDriver', function () {
let expectedResult = <EntityInfo[]>[];
let y = new EntityInfo();
y.EntityName = 'name'
y.Schema='schema'
y.Columns = <ColumnInfo[]>[];
y.Indexes = <IndexInfo[]>[];
expectedResult.push(y)

View File

@ -0,0 +1,28 @@
import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, JoinColumn} from "typeorm";
import {User} from "./User";
@Entity("Post",{schema:"sch1"})
export class Post {
@Column("integer",{
nullable:false,
primary:true,
name:"id"
})
id:number;
@ManyToOne(type=>User, userId=>userId.posts)
@JoinColumn({ name:"userId"})
userId:User;
@Column("text",{
nullable:true,
name:"body"
})
body:string;
}

View File

@ -0,0 +1,27 @@
import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, JoinColumn} from "typeorm";
import {Post} from "./Post";
@Entity("User",{schema:"sch2"})
export class User {
@Column("integer",{
nullable:false,
primary:true,
name:"id"
})
id:number;
@Column("text",{
nullable:true,
name:"name"
})
name:string;
@OneToMany(type=>Post, posts=>posts.userId)
posts:Post[];
}

View File

@ -34,6 +34,16 @@ describe("GitHub issues", async function () {
describe(`#${folder}`, async function () {
for (let dbDriver of dbDrivers) {
switch (folder) {
case '39':
if (dbDriver =='mysql' || dbDriver=='mariadb')
continue;
break;
default:
break;
}
it(dbDriver, async function () {
let filesOrgPathJS = path.resolve(examplesPathJS, folder, 'entity')

View File

@ -1,4 +1,21 @@
import { debug } from "util";
export class EntityFileToJson {
getEntityOptions(trimmedLine: string, ent: EntityJson) {
let decoratorParameters = trimmedLine.slice(trimmedLine.indexOf('(') + 1, trimmedLine.lastIndexOf(')'))
if (decoratorParameters.length > 0) {
if (decoratorParameters[0] == '"' && decoratorParameters.endsWith('"')) {
} else {
let badJSON = decoratorParameters.substring(decoratorParameters.indexOf(',') + 1).trim()
if (badJSON.lastIndexOf(',') == badJSON.length - 3) {
badJSON = badJSON.slice(0, badJSON.length - 3) + badJSON[badJSON.length - 2] + badJSON[badJSON.length - 1]
}
ent.entityOptions = JSON.parse(badJSON.replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, '"$2": '))
}
}
}
getColumnOptionsAndType(trimmedLine: string, col: EntityColumn) {
let decoratorParameters = trimmedLine.slice(trimmedLine.indexOf('(') + 1, trimmedLine.lastIndexOf(')'))
@ -104,7 +121,15 @@ export class EntityFileToJson {
if (trimmedLine.startsWith('import')) {
continue; //import statement is not part of entity definition
} else if (trimmedLine.startsWith('@Entity')) {
continue; //TODO:entity options
if (this.isPartOfMultilineStatement(trimmedLine)) {
isMultilineStatement = true;
priorPartOfMultilineStatement = trimmedLine;
continue;
} else {
let options = trimmedLine.substring(trimmedLine.lastIndexOf('{'), trimmedLine.lastIndexOf('}')+1).trim().toLowerCase()
this.getEntityOptions(trimmedLine,retVal);
continue;
}
} else if (trimmedLine.startsWith('export class')) {
retVal.entityName = trimmedLine.substring(trimmedLine.indexOf('class') + 5, trimmedLine.lastIndexOf('{')).trim().toLowerCase()
isInClassBody = true;

View File

@ -17,8 +17,9 @@ export async function createMSSQLModels(filesOrgPath: string, resultsPath: strin
driver = new MssqlDriver();
await driver.ConnectToServer(`master`, String(process.env.MSSQL_Host), Number(process.env.MSSQL_Port), String(process.env.MSSQL_Username), String(process.env.MSSQL_Password), yn(process.env.MSSQL_SSL));
if (! await driver.CheckIfDBExists(String(process.env.MSSQL_Database)))
await driver.CreateDB(String(process.env.MSSQL_Database));
if (await driver.CheckIfDBExists(String(process.env.MSSQL_Database)))
await driver.DropDB(String(process.env.MSSQL_Database));
await driver.CreateDB(String(process.env.MSSQL_Database));
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
@ -49,7 +50,7 @@ export async function createMSSQLModels(filesOrgPath: string, resultsPath: strin
password: String(process.env.MSSQL_Password),
databaseType: 'mssql',
resultsPath: resultsPath,
schemaName: 'dbo',
schemaName: 'dbo,sch1,sch2',
ssl: yn(process.env.MSSQL_SSL),
noConfigs: false,
convertCaseEntity: 'none',
@ -66,8 +67,9 @@ export async function createPostgresModels(filesOrgPath: string, resultsPath: st
driver = new PostgresDriver();
await driver.ConnectToServer(`postgres`, String(process.env.POSTGRES_Host), Number(process.env.POSTGRES_Port), String(process.env.POSTGRES_Username), String(process.env.POSTGRES_Password), yn(process.env.POSTGRES_SSL));
if (! await driver.CheckIfDBExists(String(process.env.POSTGRES_Database)))
await driver.CreateDB(String(process.env.POSTGRES_Database));
if (await driver.CheckIfDBExists(String(process.env.POSTGRES_Database)))
await driver.DropDB(String(process.env.POSTGRES_Database));
await driver.CreateDB(String(process.env.POSTGRES_Database));
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
@ -96,7 +98,7 @@ export async function createPostgresModels(filesOrgPath: string, resultsPath: st
password: String(process.env.POSTGRES_Password),
databaseType: 'postgres',
resultsPath: resultsPath,
schemaName: 'public',
schemaName: 'public,sch1,sch2',
ssl: yn(process.env.POSTGRES_SSL),
noConfigs: false,
convertCaseEntity: 'none',
@ -114,8 +116,9 @@ export async function createMysqlModels(filesOrgPath: string, resultsPath: strin
driver = new MysqlDriver();
await driver.ConnectToServer(`mysql`, String(process.env.MYSQL_Host), Number(process.env.MYSQL_Port), String(process.env.MYSQL_Username), String(process.env.MYSQL_Password), yn(process.env.MYSQL_SSL));
if (! await driver.CheckIfDBExists(String(process.env.MYSQL_Database)))
await driver.CreateDB(String(process.env.MYSQL_Database));
if (await driver.CheckIfDBExists(String(process.env.MYSQL_Database)))
await driver.DropDB(String(process.env.MYSQL_Database));
await driver.CreateDB(String(process.env.MYSQL_Database));
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
@ -161,8 +164,9 @@ export async function createMariaDBModels(filesOrgPath: string, resultsPath: str
driver = new MariaDbDriver();
await driver.ConnectToServer(`mysql`, String(process.env.MARIADB_Host), Number(process.env.MARIADB_Port), String(process.env.MARIADB_Username), String(process.env.MARIADB_Password), yn(process.env.MARIADB_SSL));
if (! await driver.CheckIfDBExists(String(process.env.MARIADB_Database)))
await driver.CreateDB(String(process.env.MARIADB_Database));
if (await driver.CheckIfDBExists(String(process.env.MARIADB_Database)))
await driver.DropDB(String(process.env.MARIADB_Database));
await driver.CreateDB(String(process.env.MARIADB_Database));
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {