diff --git a/.travis.yml b/.travis.yml index 56ecaf3..928ca73 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/CHANGELOG.md b/CHANGELOG.md index 07ef685..53181a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/drivers/AbstractDriver.ts b/src/drivers/AbstractDriver.ts index ec69693..b6db16f 100644 --- a/src/drivers/AbstractDriver.ts +++ b/src/drivers/AbstractDriver.ts @@ -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 { 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 { - const response = await this.GetAllTablesQuery(schema); + public async GetAllTables( + schema: string, + dbNames: string + ): Promise { + 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; public abstract async GetIndexesFromEntity( entities: EntityInfo[], - schema: string + schema: string, + dbNames: string ): Promise; public abstract async GetRelations( entities: EntityInfo[], - schema: string + schema: string, + dbNames: string ): Promise; 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; + + // TODO: change name + protected escapeCommaSeparatedList(commaSeparatedList: string) { + return "'" + commaSeparatedList.split(",").join("','") + "'"; + } } diff --git a/src/drivers/MssqlDriver.ts b/src/drivers/MssqlDriver.ts index 8925751..9de7ee4 100644 --- a/src/drivers/MssqlDriver.ts +++ b/src/drivers/MssqlDriver.ts @@ -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 { 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 { 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 { 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 diff --git a/src/drivers/MysqlDriver.ts b/src/drivers/MysqlDriver.ts index c95b29a..62c71ea 100644 --- a/src/drivers/MysqlDriver.ts +++ b/src/drivers/MysqlDriver.ts @@ -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 { 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) @@ -229,7 +233,8 @@ export class MysqlDriver extends AbstractDriver { } public async GetIndexesFromEntity( entities: EntityInfo[], - schema: string + schema: string, + dbNames: string ): Promise { const response = await this.ExecQuery<{ TableName: string; @@ -240,8 +245,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) @@ -272,7 +276,8 @@ export class MysqlDriver extends AbstractDriver { } public async GetRelations( entities: EntityInfo[], - schema: string + schema: string, + dbNames: string ): Promise { const response = await this.ExecQuery<{ TableWithForeignKey: string; @@ -298,7 +303,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[]; @@ -348,10 +353,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, @@ -362,7 +368,7 @@ export class MysqlDriver extends AbstractDriver { }; } else { config = { - database: connectionOptons.databaseName, + database: databaseName, host: connectionOptons.host, password: connectionOptons.password, port: connectionOptons.port, diff --git a/src/drivers/OracleDriver.ts b/src/drivers/OracleDriver.ts index b3500c2..3a1059c 100644 --- a/src/drivers/OracleDriver.ts +++ b/src/drivers/OracleDriver.ts @@ -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; }; diff --git a/src/drivers/PostgresDriver.ts b/src/drivers/PostgresDriver.ts index 03688e4..79b39a3 100644 --- a/src/drivers/PostgresDriver.ts +++ b/src/drivers/PostgresDriver.ts @@ -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; }; diff --git a/src/entity.mst b/src/entity.mst index 65675c2..3dc4226 100644 --- a/src/entity.mst +++ b/src/entity.mst @@ -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}} diff --git a/src/index.ts b/src/index.ts index 4b2b8dd..a87cb02 100644 --- a/src/index.ts +++ b/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" } diff --git a/src/models/EntityInfo.ts b/src/models/EntityInfo.ts index 1c51dba..4aad6c3 100644 --- a/src/models/EntityInfo.ts +++ b/src/models/EntityInfo.ts @@ -10,6 +10,7 @@ export class EntityInfo { public Schema: string; public GenerateConstructor: boolean; public IsActiveRecord: boolean; + public Database: string; public relationImports() { const imports: string[] = []; diff --git a/test/drivers/MssqlDriver.test.ts b/test/drivers/MssqlDriver.test.ts index c2cc4a2..3807ae3 100644 --- a/test/drivers/MssqlDriver.test.ts +++ b/test/drivers/MssqlDriver.test.ts @@ -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') diff --git a/test/integration/github-issues/144/entity/Post.ts b/test/integration/github-issues/144/entity/Post.ts new file mode 100644 index 0000000..9a5d1c7 --- /dev/null +++ b/test/integration/github-issues/144/entity/Post.ts @@ -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; + +} diff --git a/test/integration/github-issues/144/entity/PostAuthor.ts b/test/integration/github-issues/144/entity/PostAuthor.ts new file mode 100644 index 0000000..6acec97 --- /dev/null +++ b/test/integration/github-issues/144/entity/PostAuthor.ts @@ -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; + +} diff --git a/test/integration/runTestsFromPath.test.ts b/test/integration/runTestsFromPath.test.ts index c384725..14e36fa 100644 --- a/test/integration/runTestsFromPath.test.ts +++ b/test/integration/runTestsFromPath.test.ts @@ -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 }; }