parent
03fed9361b
commit
5591a7bc77
@ -11,9 +11,9 @@ env:
|
||||
matrix:
|
||||
- POSTGRES_Skip=0 POSTGRES_Host=localhost POSTGRES_Port=5432 POSTGRES_Username=test
|
||||
POSTGRES_Password=test POSTGRES_Database=test POSTGRES_SSL=0 MYSQL_Skip=0
|
||||
MYSQL_Host=localhost MYSQL_Port=3306 MYSQL_Username=test MYSQL_Password=test
|
||||
MYSQL_Host=localhost MYSQL_Port=3306 MYSQL_Username=root MYSQL_Password=admin
|
||||
MYSQL_Database=test MYSQL_SSL=0 MARIADB_Skip=0 MARIADB_Host=localhost MARIADB_Port=3307
|
||||
MARIADB_Username=test MARIADB_Password=test MARIADB_Database=test MARIADB_SSL=0
|
||||
MARIADB_Username=root MARIADB_Password=admin MARIADB_Database=test MARIADB_SSL=0
|
||||
MSSQL_Skip=0 MSSQL_Host=localhost MSSQL_Port=1433 MSSQL_Username=sa MSSQL_Password=Admin12345
|
||||
MSSQL_Database=typeorm_mg MSSQL_SSL=0
|
||||
ORACLE_Skip=0
|
||||
|
@ -1,5 +1,6 @@
|
||||
# Changelog
|
||||
|
||||
* added option to generate models based on multiple databases(#144)
|
||||
* fixed generation of ManyToMany relations on junction tables with custom names(#151)
|
||||
|
||||
## 0.3.1
|
||||
|
@ -60,11 +60,13 @@ export abstract class AbstractDriver {
|
||||
];
|
||||
|
||||
public abstract GetAllTablesQuery: (
|
||||
schema: string
|
||||
schema: string,
|
||||
dbNames: string
|
||||
) => Promise<
|
||||
Array<{
|
||||
TABLE_SCHEMA: string;
|
||||
TABLE_NAME: string;
|
||||
DB_NAME: string;
|
||||
}>
|
||||
>;
|
||||
|
||||
@ -146,12 +148,28 @@ export abstract class AbstractDriver {
|
||||
): Promise<EntityInfo[]> {
|
||||
let dbModel = [] as EntityInfo[];
|
||||
await this.ConnectToServer(connectionOptons);
|
||||
const sqlEscapedSchema =
|
||||
"'" + connectionOptons.schemaName.split(",").join("','") + "'";
|
||||
dbModel = await this.GetAllTables(sqlEscapedSchema);
|
||||
await this.GetCoulmnsFromEntity(dbModel, sqlEscapedSchema);
|
||||
await this.GetIndexesFromEntity(dbModel, sqlEscapedSchema);
|
||||
dbModel = await this.GetRelations(dbModel, sqlEscapedSchema);
|
||||
const sqlEscapedSchema = this.escapeCommaSeparatedList(
|
||||
connectionOptons.schemaName
|
||||
);
|
||||
dbModel = await this.GetAllTables(
|
||||
sqlEscapedSchema,
|
||||
connectionOptons.databaseName
|
||||
);
|
||||
await this.GetCoulmnsFromEntity(
|
||||
dbModel,
|
||||
sqlEscapedSchema,
|
||||
connectionOptons.databaseName
|
||||
);
|
||||
await this.GetIndexesFromEntity(
|
||||
dbModel,
|
||||
sqlEscapedSchema,
|
||||
connectionOptons.databaseName
|
||||
);
|
||||
dbModel = await this.GetRelations(
|
||||
dbModel,
|
||||
sqlEscapedSchema,
|
||||
connectionOptons.databaseName
|
||||
);
|
||||
await this.DisconnectFromServer();
|
||||
dbModel = this.FindManyToManyRelations(dbModel);
|
||||
this.FindPrimaryColumnsFromIndexes(dbModel);
|
||||
@ -160,8 +178,11 @@ export abstract class AbstractDriver {
|
||||
|
||||
public abstract async ConnectToServer(connectionOptons: IConnectionOptions);
|
||||
|
||||
public async GetAllTables(schema: string): Promise<EntityInfo[]> {
|
||||
const response = await this.GetAllTablesQuery(schema);
|
||||
public async GetAllTables(
|
||||
schema: string,
|
||||
dbNames: string
|
||||
): Promise<EntityInfo[]> {
|
||||
const response = await this.GetAllTablesQuery(schema, dbNames);
|
||||
const ret: EntityInfo[] = [] as EntityInfo[];
|
||||
response.forEach(val => {
|
||||
const ent: EntityInfo = new EntityInfo();
|
||||
@ -170,6 +191,7 @@ export abstract class AbstractDriver {
|
||||
ent.Schema = val.TABLE_SCHEMA;
|
||||
ent.Columns = [] as ColumnInfo[];
|
||||
ent.Indexes = [] as IndexInfo[];
|
||||
ent.Database = dbNames.includes(",") ? val.DB_NAME : "";
|
||||
ret.push(ent);
|
||||
});
|
||||
return ret;
|
||||
@ -325,15 +347,18 @@ export abstract class AbstractDriver {
|
||||
}
|
||||
public abstract async GetCoulmnsFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
schema: string,
|
||||
dbNames: string
|
||||
): Promise<EntityInfo[]>;
|
||||
public abstract async GetIndexesFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
schema: string,
|
||||
dbNames: string
|
||||
): Promise<EntityInfo[]>;
|
||||
public abstract async GetRelations(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
schema: string,
|
||||
dbNames: string
|
||||
): Promise<EntityInfo[]>;
|
||||
|
||||
public FindPrimaryColumnsFromIndexes(dbModel: EntityInfo[]) {
|
||||
@ -364,4 +389,9 @@ export abstract class AbstractDriver {
|
||||
public abstract async DropDB(dbName: string);
|
||||
public abstract async UseDB(dbName: string);
|
||||
public abstract async CheckIfDBExists(dbName: string): Promise<boolean>;
|
||||
|
||||
// TODO: change name
|
||||
protected escapeCommaSeparatedList(commaSeparatedList: string) {
|
||||
return "'" + commaSeparatedList.split(",").join("','") + "'";
|
||||
}
|
||||
}
|
||||
|
@ -17,20 +17,25 @@ export class MssqlDriver extends AbstractDriver {
|
||||
public readonly standardUser = "sa";
|
||||
|
||||
private Connection: MSSQL.ConnectionPool;
|
||||
public GetAllTablesQuery = async (schema: string) => {
|
||||
public GetAllTablesQuery = async (schema: string, dbNames: string) => {
|
||||
const request = new MSSQL.Request(this.Connection);
|
||||
const response: Array<{
|
||||
TABLE_SCHEMA: string;
|
||||
TABLE_NAME: string;
|
||||
DB_NAME: string;
|
||||
}> = (await request.query(
|
||||
`SELECT TABLE_SCHEMA,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema})`
|
||||
`SELECT TABLE_SCHEMA,TABLE_NAME, table_catalog as "DB_NAME" FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG in (${this.escapeCommaSeparatedList(
|
||||
dbNames
|
||||
)})`
|
||||
)).recordset;
|
||||
return response;
|
||||
};
|
||||
|
||||
public async GetCoulmnsFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
schema: string,
|
||||
dbNames: string
|
||||
): Promise<EntityInfo[]> {
|
||||
const request = new MSSQL.Request(this.Connection);
|
||||
const response: Array<{
|
||||
@ -56,8 +61,9 @@ export class MssqlDriver extends AbstractDriver {
|
||||
and tc.TABLE_NAME = c.TABLE_NAME
|
||||
and cu.COLUMN_NAME = c.COLUMN_NAME
|
||||
and tc.TABLE_SCHEMA=c.TABLE_SCHEMA) IsUnique
|
||||
FROM INFORMATION_SCHEMA.COLUMNS c where TABLE_SCHEMA in (${schema})`))
|
||||
.recordset;
|
||||
FROM INFORMATION_SCHEMA.COLUMNS c where TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG in (${this.escapeCommaSeparatedList(
|
||||
dbNames
|
||||
)})`)).recordset;
|
||||
entities.forEach(ent => {
|
||||
response
|
||||
.filter(filterVal => {
|
||||
@ -213,7 +219,8 @@ export class MssqlDriver extends AbstractDriver {
|
||||
}
|
||||
public async GetIndexesFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
schema: string,
|
||||
dbNames: string
|
||||
): Promise<EntityInfo[]> {
|
||||
const request = new MSSQL.Request(this.Connection);
|
||||
const response: Array<{
|
||||
@ -222,26 +229,37 @@ export class MssqlDriver extends AbstractDriver {
|
||||
ColumnName: string;
|
||||
is_unique: boolean;
|
||||
is_primary_key: boolean;
|
||||
}> = (await request.query(`SELECT
|
||||
TableName = t.name,
|
||||
IndexName = ind.name,
|
||||
ColumnName = col.name,
|
||||
ind.is_unique,
|
||||
ind.is_primary_key
|
||||
FROM
|
||||
sys.indexes ind
|
||||
INNER JOIN
|
||||
sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id
|
||||
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 and s.name in (${schema})
|
||||
ORDER BY
|
||||
t.name, ind.name, ind.index_id, ic.key_ordinal;`)).recordset;
|
||||
}> = [];
|
||||
for (const dbName of dbNames.split(",")) {
|
||||
await this.UseDB(dbName);
|
||||
const resp: Array<{
|
||||
TableName: string;
|
||||
IndexName: string;
|
||||
ColumnName: string;
|
||||
is_unique: boolean;
|
||||
is_primary_key: boolean;
|
||||
}> = (await request.query(`SELECT
|
||||
TableName = t.name,
|
||||
IndexName = ind.name,
|
||||
ColumnName = col.name,
|
||||
ind.is_unique,
|
||||
ind.is_primary_key
|
||||
FROM
|
||||
sys.indexes ind
|
||||
INNER JOIN
|
||||
sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id
|
||||
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 and s.name in (${schema})
|
||||
ORDER BY
|
||||
t.name, ind.name, ind.index_id, ic.key_ordinal;`)).recordset;
|
||||
response.push(...resp);
|
||||
}
|
||||
entities.forEach(ent => {
|
||||
response
|
||||
.filter(filterVal => filterVal.TableName === ent.tsEntityName)
|
||||
@ -272,7 +290,8 @@ ORDER BY
|
||||
}
|
||||
public async GetRelations(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
schema: string,
|
||||
dbNames: string
|
||||
): Promise<EntityInfo[]> {
|
||||
const request = new MSSQL.Request(this.Connection);
|
||||
const response: Array<{
|
||||
@ -284,7 +303,19 @@ ORDER BY
|
||||
onDelete: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION";
|
||||
onUpdate: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION";
|
||||
object_id: number;
|
||||
}> = (await request.query(`select
|
||||
}> = [];
|
||||
for (const dbName of dbNames.split(",")) {
|
||||
await this.UseDB(dbName);
|
||||
const resp: Array<{
|
||||
TableWithForeignKey: string;
|
||||
FK_PartNo: number;
|
||||
ForeignKeyColumn: string;
|
||||
TableReferenced: string;
|
||||
ForeignKeyColumnReferenced: string;
|
||||
onDelete: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION";
|
||||
onUpdate: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION";
|
||||
object_id: number;
|
||||
}> = (await request.query(`select
|
||||
parentTable.name as TableWithForeignKey,
|
||||
fkc.constraint_column_id as FK_PartNo,
|
||||
parentColumn.name as ForeignKeyColumn,
|
||||
@ -311,6 +342,8 @@ where
|
||||
fk.is_disabled=0 and fk.is_ms_shipped=0 and parentSchema.name in (${schema})
|
||||
order by
|
||||
TableWithForeignKey, FK_PartNo`)).recordset;
|
||||
response.push(...resp);
|
||||
}
|
||||
const relationsTemp: IRelationTempInfo[] = [] as IRelationTempInfo[];
|
||||
response.forEach(resp => {
|
||||
let rels = relationsTemp.find(
|
||||
@ -362,8 +395,9 @@ order by
|
||||
}
|
||||
}
|
||||
public async ConnectToServer(connectionOptons: IConnectionOptions) {
|
||||
const databaseName = connectionOptons.databaseName.split(",")[0];
|
||||
const config: MSSQL.config = {
|
||||
database: connectionOptons.databaseName,
|
||||
database: databaseName,
|
||||
options: {
|
||||
appName: "typeorm-model-generator",
|
||||
encrypt: connectionOptons.ssl
|
||||
|
@ -19,20 +19,22 @@ export class MysqlDriver extends AbstractDriver {
|
||||
|
||||
private Connection: MYSQL.Connection;
|
||||
|
||||
public GetAllTablesQuery = async (schema: string) => {
|
||||
public GetAllTablesQuery = async (schema: string, dbNames: string) => {
|
||||
const response = this.ExecQuery<{
|
||||
TABLE_SCHEMA: string;
|
||||
TABLE_NAME: string;
|
||||
}>(`SELECT TABLE_SCHEMA, TABLE_NAME
|
||||
DB_NAME: string;
|
||||
}>(`SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_SCHEMA as DB_NAME
|
||||
FROM information_schema.tables
|
||||
WHERE table_type='BASE TABLE'
|
||||
AND table_schema like DATABASE()`);
|
||||
AND table_schema IN (${this.escapeCommaSeparatedList(dbNames)})`);
|
||||
return response;
|
||||
};
|
||||
|
||||
public async GetCoulmnsFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
schema: string,
|
||||
dbNames: string
|
||||
): Promise<EntityInfo[]> {
|
||||
const response = await this.ExecQuery<{
|
||||
TABLE_NAME: string;
|
||||
@ -49,7 +51,9 @@ export class MysqlDriver extends AbstractDriver {
|
||||
}>(`SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,
|
||||
DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE,
|
||||
CASE WHEN EXTRA like '%auto_increment%' THEN 1 ELSE 0 END IsIdentity, column_type, column_key
|
||||
FROM INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA like DATABASE()`);
|
||||
FROM INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA IN (${this.escapeCommaSeparatedList(
|
||||
dbNames
|
||||
)})`);
|
||||
entities.forEach(ent => {
|
||||
response
|
||||
.filter(filterVal => filterVal.TABLE_NAME === ent.tsEntityName)
|
||||
@ -228,7 +232,8 @@ export class MysqlDriver extends AbstractDriver {
|
||||
}
|
||||
public async GetIndexesFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
schema: string,
|
||||
dbNames: string
|
||||
): Promise<EntityInfo[]> {
|
||||
const response = await this.ExecQuery<{
|
||||
TableName: string;
|
||||
@ -239,8 +244,7 @@ export class MysqlDriver extends AbstractDriver {
|
||||
}>(`SELECT TABLE_NAME TableName,INDEX_NAME IndexName,COLUMN_NAME ColumnName,CASE WHEN NON_UNIQUE=0 THEN 1 ELSE 0 END is_unique,
|
||||
CASE WHEN INDEX_NAME='PRIMARY' THEN 1 ELSE 0 END is_primary_key
|
||||
FROM information_schema.statistics sta
|
||||
WHERE table_schema like DATABASE();
|
||||
`);
|
||||
WHERE table_schema IN (${this.escapeCommaSeparatedList(dbNames)})`);
|
||||
entities.forEach(ent => {
|
||||
response
|
||||
.filter(filterVal => filterVal.TableName === ent.tsEntityName)
|
||||
@ -271,7 +275,8 @@ export class MysqlDriver extends AbstractDriver {
|
||||
}
|
||||
public async GetRelations(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
schema: string,
|
||||
dbNames: string
|
||||
): Promise<EntityInfo[]> {
|
||||
const response = await this.ExecQuery<{
|
||||
TableWithForeignKey: string;
|
||||
@ -297,7 +302,7 @@ export class MysqlDriver extends AbstractDriver {
|
||||
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC
|
||||
ON CU.CONSTRAINT_NAME=RC.CONSTRAINT_NAME AND CU.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA
|
||||
WHERE
|
||||
TABLE_SCHEMA = SCHEMA()
|
||||
TABLE_SCHEMA IN (${this.escapeCommaSeparatedList(dbNames)})
|
||||
AND CU.REFERENCED_TABLE_NAME IS NOT NULL;
|
||||
`);
|
||||
const relationsTemp: IRelationTempInfo[] = [] as IRelationTempInfo[];
|
||||
@ -347,10 +352,11 @@ export class MysqlDriver extends AbstractDriver {
|
||||
}
|
||||
}
|
||||
public async ConnectToServer(connectionOptons: IConnectionOptions) {
|
||||
const databaseName = connectionOptons.databaseName.split(",")[0];
|
||||
let config: MYSQL.ConnectionConfig;
|
||||
if (connectionOptons.ssl) {
|
||||
config = {
|
||||
database: connectionOptons.databaseName,
|
||||
database: databaseName,
|
||||
host: connectionOptons.host,
|
||||
password: connectionOptons.password,
|
||||
port: connectionOptons.port,
|
||||
@ -361,7 +367,7 @@ export class MysqlDriver extends AbstractDriver {
|
||||
};
|
||||
} else {
|
||||
config = {
|
||||
database: connectionOptons.databaseName,
|
||||
database: databaseName,
|
||||
host: connectionOptons.host,
|
||||
password: connectionOptons.password,
|
||||
port: connectionOptons.port,
|
||||
|
@ -32,8 +32,9 @@ export class OracleDriver extends AbstractDriver {
|
||||
const response: Array<{
|
||||
TABLE_SCHEMA: string;
|
||||
TABLE_NAME: string;
|
||||
DB_NAME: string;
|
||||
}> = (await this.Connection.execute(
|
||||
` SELECT NULL AS TABLE_SCHEMA, TABLE_NAME FROM all_tables WHERE owner = (select user from dual)`
|
||||
` SELECT NULL AS TABLE_SCHEMA, TABLE_NAME, NULL AS DB_NAME FROM all_tables WHERE owner = (select user from dual)`
|
||||
)).rows!;
|
||||
return response;
|
||||
};
|
||||
|
@ -22,8 +22,9 @@ export class PostgresDriver extends AbstractDriver {
|
||||
const response: Array<{
|
||||
TABLE_SCHEMA: string;
|
||||
TABLE_NAME: string;
|
||||
DB_NAME: string;
|
||||
}> = (await this.Connection.query(
|
||||
`SELECT table_schema as "TABLE_SCHEMA",table_name as "TABLE_NAME" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND table_schema in (${schema}) `
|
||||
`SELECT table_schema as "TABLE_SCHEMA",table_name as "TABLE_NAME", table_catalog as "DB_NAME" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND table_schema in (${schema}) `
|
||||
)).rows;
|
||||
return response;
|
||||
};
|
||||
|
@ -3,7 +3,7 @@ import {BaseEntity,Column,Entity,Index,JoinColumn,JoinTable,ManyToMany,ManyToOne
|
||||
{{/each}}
|
||||
|
||||
|
||||
@Entity("{{sqlEntityName}}"{{#Schema}},{schema:"{{.}}"}{{/Schema}})
|
||||
@Entity("{{sqlEntityName}}"{{#Schema}},{schema:"{{.}}"{{#if ../Database}}, database:"{{../Database}}"{{/if}} } {{/Schema}})
|
||||
{{#Indexes}}{{^isPrimaryKey}}@Index("{{name}}",[{{#columns}}"{{toPropertyName name}}",{{/columns}}]{{#isUnique}},{unique:true}{{/isUnique}})
|
||||
{{/isPrimaryKey}}{{/Indexes}}export class {{toEntityName tsEntityName}}{{#IsActiveRecord}} extends BaseEntity{{/IsActiveRecord}} {
|
||||
{{#Columns}}
|
||||
|
16
src/index.ts
16
src/index.ts
@ -23,7 +23,10 @@ async function CliLogic() {
|
||||
} else {
|
||||
if (fs.existsSync(path.resolve(process.cwd(), ".tomg-config"))) {
|
||||
console.log(
|
||||
`[${new Date().toLocaleTimeString()}] Using configuration file.`
|
||||
`[${new Date().toLocaleTimeString()}] Using configuration file. [${path.resolve(
|
||||
process.cwd(),
|
||||
".tomg-config"
|
||||
)}]`
|
||||
);
|
||||
const retVal = await fs.readJson(
|
||||
path.resolve(process.cwd(), ".tomg-config")
|
||||
@ -62,7 +65,8 @@ function GetUtilParametersByArgs() {
|
||||
.option("d", {
|
||||
alias: "database",
|
||||
demand: true,
|
||||
describe: "Database name(or path for sqlite)"
|
||||
describe:
|
||||
"Database name(or path for sqlite). You can pass multiple values separted by comma."
|
||||
})
|
||||
.option("u", {
|
||||
alias: "user",
|
||||
@ -98,7 +102,7 @@ function GetUtilParametersByArgs() {
|
||||
.option("s", {
|
||||
alias: "schema",
|
||||
describe:
|
||||
"Schema name to create model from. Only for mssql and postgres"
|
||||
"Schema name to create model from. Only for mssql and postgres. You can pass multiple values separted by comma."
|
||||
})
|
||||
.option("ssl", {
|
||||
boolean: true,
|
||||
@ -258,7 +262,8 @@ async function GetUtilParametersByInquirer() {
|
||||
},
|
||||
{
|
||||
default: "",
|
||||
message: "Database name:",
|
||||
message:
|
||||
"Database name: (You can pass multiple values separted by comma)",
|
||||
name: "dbName",
|
||||
type: "input"
|
||||
}
|
||||
@ -270,7 +275,8 @@ async function GetUtilParametersByInquirer() {
|
||||
connectionOptions.schemaName = ((await inquirer.prompt([
|
||||
{
|
||||
default: driver.standardSchema,
|
||||
message: "Database schema:",
|
||||
message:
|
||||
"Database schema: (You can pass multiple values separted by comma)",
|
||||
name: "schema",
|
||||
type: "input"
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ export class EntityInfo {
|
||||
public Schema: string;
|
||||
public GenerateConstructor: boolean;
|
||||
public IsActiveRecord: boolean;
|
||||
public Database: string;
|
||||
|
||||
public relationImports() {
|
||||
const imports: string[] = [];
|
||||
|
@ -45,7 +45,7 @@ describe('MssqlDriver', function () {
|
||||
return response;
|
||||
}
|
||||
})
|
||||
const result = await driver.GetAllTables('schema')
|
||||
const result = await driver.GetAllTables('schema', 'db')
|
||||
const expectedResult = [] as EntityInfo[];
|
||||
const y = new EntityInfo();
|
||||
y.tsEntityName = 'name'
|
||||
@ -53,6 +53,7 @@ describe('MssqlDriver', function () {
|
||||
y.Schema='schema'
|
||||
y.Columns = [] as ColumnInfo[];
|
||||
y.Indexes = [] as IndexInfo[];
|
||||
y.Database = "";
|
||||
expectedResult.push(y)
|
||||
expect(result).to.be.deep.equal(expectedResult)
|
||||
})
|
||||
@ -78,6 +79,7 @@ describe('MssqlDriver', function () {
|
||||
y.tsEntityName = 'name'
|
||||
y.Columns = [] as ColumnInfo[];
|
||||
y.Indexes = [] as IndexInfo[];
|
||||
y.Database = "";
|
||||
entities.push(y)
|
||||
const expected: EntityInfo[] = JSON.parse(JSON.stringify(entities));
|
||||
expected[0].Columns.push({
|
||||
@ -93,7 +95,7 @@ describe('MssqlDriver', function () {
|
||||
tsType: 'number',
|
||||
relations: [] as RelationInfo[],
|
||||
})
|
||||
const result = await driver.GetCoulmnsFromEntity(entities, 'schema');
|
||||
const result = await driver.GetCoulmnsFromEntity(entities, 'schema','db');
|
||||
expect(result).to.be.deep.equal(expected)
|
||||
})
|
||||
it('should find primary indexes')
|
||||
|
22
test/integration/github-issues/144/entity/Post.ts
Normal file
22
test/integration/github-issues/144/entity/Post.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, JoinColumn, Index } from "typeorm";
|
||||
import { PostAuthor } from "./PostAuthor";
|
||||
|
||||
@Entity("Post", {database: "db1"})
|
||||
export class Post {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@Column()
|
||||
text: string;
|
||||
|
||||
// post has relation with details. not cascades here. means cannot be persisted, updated or removed
|
||||
@OneToOne(type => PostAuthor, author => author.post)
|
||||
@JoinColumn()
|
||||
// @Index({ unique: true })
|
||||
author: PostAuthor;
|
||||
|
||||
}
|
16
test/integration/github-issues/144/entity/PostAuthor.ts
Normal file
16
test/integration/github-issues/144/entity/PostAuthor.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, JoinColumn } from "typeorm";
|
||||
import { Post } from "./Post";
|
||||
|
||||
@Entity("PostAuthor", {database: "db2"})
|
||||
export class PostAuthor {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@OneToOne(type => Post, post => post.author)
|
||||
post: Post;
|
||||
|
||||
}
|
@ -9,6 +9,9 @@ import * as ts from "typescript";
|
||||
import * as GTU from "../utils/GeneralTestUtils"
|
||||
import chaiSubset = require('chai-subset');
|
||||
import chai = require('chai');
|
||||
import { IConnectionOptions } from "../../src/IConnectionOptions";
|
||||
import yn = require("yn");
|
||||
import { EntityInfo } from "../../src/models/EntityInfo";
|
||||
|
||||
chai.use(chaiSubset);
|
||||
|
||||
@ -63,7 +66,17 @@ function runTestForMultipleDrivers(testName: string, dbDrivers: string[], testPa
|
||||
const driversToRun = selectDriversForSpecyficTest();
|
||||
const modelGenerationPromises = driversToRun.map(async (dbDriver) => {
|
||||
const { generationOptions, driver, connectionOptions, resultsPath, filesOrgPathTS } = await prepareTestRuns(testPartialPath, testName, dbDriver);
|
||||
let dbModel = await dataCollectionPhase(driver, connectionOptions);
|
||||
let dbModel: EntityInfo[] = [];
|
||||
switch (testName) {
|
||||
case '144':
|
||||
dbModel = await dataCollectionPhase(driver, Object.assign(connectionOptions, { databaseName: 'db1,db2' }));
|
||||
break;
|
||||
|
||||
default:
|
||||
dbModel = await dataCollectionPhase(driver, connectionOptions);
|
||||
break;
|
||||
}
|
||||
|
||||
dbModel = modelCustomizationPhase(dbModel, generationOptions, driver.defaultValues);
|
||||
modelGenerationPhase(connectionOptions, generationOptions, dbModel);
|
||||
const filesGenPath = path.resolve(resultsPath, 'entities');
|
||||
@ -78,6 +91,8 @@ function runTestForMultipleDrivers(testName: string, dbDrivers: string[], testPa
|
||||
switch (testName) {
|
||||
case '39':
|
||||
return dbDrivers.filter(dbDriver => !['mysql', 'mariadb', 'oracle', 'sqlite'].includes(dbDriver))
|
||||
case '144':
|
||||
return dbDrivers.filter(dbDriver => ['mysql', 'mariadb'].includes(dbDriver))
|
||||
default:
|
||||
return dbDrivers;
|
||||
}
|
||||
@ -115,8 +130,11 @@ function compareGeneratedFiles(filesOrgPathTS: string, filesGenPath: string) {
|
||||
function compileGeneratedModel(filesGenPath: string, drivers: string[]) {
|
||||
let currentDirectoryFiles: string[] = [];
|
||||
drivers.forEach(driver => {
|
||||
currentDirectoryFiles.push(...fs.readdirSync(path.resolve(filesGenPath, driver, "entities")).
|
||||
const entitiesPath = path.resolve(filesGenPath, driver, "entities");
|
||||
if (fs.existsSync(entitiesPath)){
|
||||
currentDirectoryFiles.push(...fs.readdirSync(entitiesPath).
|
||||
filter(fileName => fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts").map(v => path.resolve(filesGenPath, driver, "entities", v)));
|
||||
}
|
||||
});
|
||||
const compileErrors = GTU.compileTsFiles(currentDirectoryFiles, {
|
||||
experimentalDecorators: true,
|
||||
@ -135,7 +153,6 @@ async function prepareTestRuns(testPartialPath: string, testName: string, dbDriv
|
||||
const resultsPath = path.resolve(process.cwd(), `output`, dbDriver);
|
||||
fs.removeSync(resultsPath);
|
||||
const driver = createDriver(dbDriver);
|
||||
const connectionOptions = await GTU.createModelsInDb(dbDriver, filesOrgPathJS);
|
||||
const generationOptions = GTU.getGenerationOptions(resultsPath);
|
||||
switch (testName) {
|
||||
case '65':
|
||||
@ -144,9 +161,52 @@ async function prepareTestRuns(testPartialPath: string, testName: string, dbDriv
|
||||
case 'sample18-lazy-relations':
|
||||
generationOptions.lazy = true;
|
||||
break;
|
||||
case '144':
|
||||
|
||||
let connectionOptions: IConnectionOptions;
|
||||
switch (dbDriver) {
|
||||
case 'mysql':
|
||||
connectionOptions = {
|
||||
host: String(process.env.MYSQL_Host),
|
||||
port: Number(process.env.MYSQL_Port),
|
||||
databaseName: String(process.env.MYSQL_Database),
|
||||
user: String(process.env.MYSQL_Username),
|
||||
password: String(process.env.MYSQL_Password),
|
||||
databaseType: 'mysql',
|
||||
schemaName: 'ignored',
|
||||
ssl: yn(process.env.MYSQL_SSL),
|
||||
}
|
||||
break;
|
||||
case 'mariadb':
|
||||
connectionOptions = {
|
||||
host: String(process.env.MARIADB_Host),
|
||||
port: Number(process.env.MARIADB_Port),
|
||||
databaseName: String(process.env.MARIADB_Database),
|
||||
user: String(process.env.MARIADB_Username),
|
||||
password: String(process.env.MARIADB_Password),
|
||||
databaseType: 'mariadb',
|
||||
schemaName: 'ignored',
|
||||
ssl: yn(process.env.MARIADB_SSL),
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
await driver.ConnectToServer(connectionOptions!);
|
||||
if (! await driver.CheckIfDBExists('db1')) {
|
||||
var x = await driver.CreateDB('db1')
|
||||
}
|
||||
if (! await driver.CheckIfDBExists('db2')) {
|
||||
var t = await driver.CreateDB('db2')
|
||||
}
|
||||
await driver.DisconnectFromServer();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const connectionOptions = await GTU.createModelsInDb(dbDriver, filesOrgPathJS);
|
||||
return { generationOptions, driver, connectionOptions, resultsPath, filesOrgPathTS };
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user