allow database names with special characters(#273)
This commit is contained in:
parent
c011ed3957
commit
cfa6799226
17
.eslintrc.js
17
.eslintrc.js
@ -32,7 +32,22 @@ module.exports = {
|
||||
"no-param-reassign": ["off"],
|
||||
"@typescript-eslint/no-explicit-any": ["off"],
|
||||
"no-loop-func": ["off"],
|
||||
"@typescript-eslint/explicit-module-boundary-types": ["off"]
|
||||
"@typescript-eslint/explicit-module-boundary-types": ["off"],
|
||||
'no-restricted-syntax': [
|
||||
'error',
|
||||
{
|
||||
selector: 'ForInStatement',
|
||||
message: 'for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.',
|
||||
},
|
||||
{
|
||||
selector: 'LabeledStatement',
|
||||
message: 'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.',
|
||||
},
|
||||
{
|
||||
selector: 'WithStatement',
|
||||
message: '`with` is disallowed in strict mode because it makes code impossible to predict and optimize.',
|
||||
},
|
||||
],
|
||||
},
|
||||
settings: {
|
||||
"import/resolver": {
|
||||
|
@ -4,7 +4,7 @@
|
||||
export default interface IConnectionOptions {
|
||||
host: string;
|
||||
port: number;
|
||||
databaseName: string;
|
||||
databaseNames: string[];
|
||||
user: string;
|
||||
password: string;
|
||||
databaseType:
|
||||
@ -14,7 +14,7 @@ export default interface IConnectionOptions {
|
||||
| "mariadb"
|
||||
| "oracle"
|
||||
| "sqlite";
|
||||
schemaName: string;
|
||||
schemaNames: string[];
|
||||
instanceName?: string;
|
||||
ssl: boolean;
|
||||
skipTables: string[];
|
||||
@ -25,11 +25,11 @@ export function getDefaultConnectionOptions(): IConnectionOptions {
|
||||
const connectionOptions: IConnectionOptions = {
|
||||
host: "127.0.0.1",
|
||||
port: 0,
|
||||
databaseName: "",
|
||||
databaseNames: [""],
|
||||
user: "",
|
||||
password: "",
|
||||
databaseType: undefined as any,
|
||||
schemaName: "",
|
||||
schemaNames: [""],
|
||||
instanceName: undefined,
|
||||
ssl: false,
|
||||
skipTables: [],
|
||||
|
@ -80,3 +80,6 @@ export function requireLocalFile(fileName: string): any {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
export function assertUnreachable(x: never): never {
|
||||
throw new Error("Didn't expect to get here");
|
||||
}
|
||||
|
@ -67,17 +67,6 @@ export default abstract class AbstractDriver {
|
||||
"varbinary",
|
||||
];
|
||||
|
||||
public abstract GetAllTablesQuery: (
|
||||
schema: string,
|
||||
dbNames: string
|
||||
) => Promise<
|
||||
{
|
||||
TABLE_SCHEMA: string;
|
||||
TABLE_NAME: string;
|
||||
DB_NAME: string;
|
||||
}[]
|
||||
>;
|
||||
|
||||
public static FindManyToManyRelations(dbModel: Entity[]) {
|
||||
let retVal = dbModel;
|
||||
const manyToManyEntities = retVal.filter(
|
||||
@ -182,28 +171,25 @@ export default abstract class AbstractDriver {
|
||||
): Promise<Entity[]> {
|
||||
let dbModel = [] as Entity[];
|
||||
await this.ConnectToServer(connectionOptions);
|
||||
const sqlEscapedSchema = AbstractDriver.escapeCommaSeparatedList(
|
||||
connectionOptions.schemaName
|
||||
);
|
||||
dbModel = await this.GetAllTables(
|
||||
sqlEscapedSchema,
|
||||
connectionOptions.databaseName
|
||||
connectionOptions.schemaNames,
|
||||
connectionOptions.databaseNames
|
||||
);
|
||||
await this.GetCoulmnsFromEntity(
|
||||
dbModel,
|
||||
sqlEscapedSchema,
|
||||
connectionOptions.databaseName
|
||||
connectionOptions.schemaNames,
|
||||
connectionOptions.databaseNames
|
||||
);
|
||||
await this.GetIndexesFromEntity(
|
||||
dbModel,
|
||||
sqlEscapedSchema,
|
||||
connectionOptions.databaseName
|
||||
connectionOptions.schemaNames,
|
||||
connectionOptions.databaseNames
|
||||
);
|
||||
AbstractDriver.FindPrimaryColumnsFromIndexes(dbModel);
|
||||
dbModel = await this.GetRelations(
|
||||
dbModel,
|
||||
sqlEscapedSchema,
|
||||
connectionOptions.databaseName,
|
||||
connectionOptions.schemaNames,
|
||||
connectionOptions.databaseNames,
|
||||
generationOptions
|
||||
);
|
||||
await this.DisconnectFromServer();
|
||||
@ -230,30 +216,14 @@ export default abstract class AbstractDriver {
|
||||
);
|
||||
}
|
||||
|
||||
public abstract async ConnectToServer(connectionOptons: IConnectionOptions);
|
||||
public abstract ConnectToServer(
|
||||
connectionOptons: IConnectionOptions
|
||||
): Promise<void>;
|
||||
|
||||
public async GetAllTables(
|
||||
schema: string,
|
||||
dbNames: string
|
||||
): Promise<Entity[]> {
|
||||
const response = await this.GetAllTablesQuery(schema, dbNames);
|
||||
const ret: Entity[] = [] as Entity[];
|
||||
response.forEach((val) => {
|
||||
ret.push({
|
||||
columns: [],
|
||||
indices: [],
|
||||
relations: [],
|
||||
relationIds: [],
|
||||
sqlName: val.TABLE_NAME,
|
||||
tscName: val.TABLE_NAME,
|
||||
fileName: val.TABLE_NAME,
|
||||
database: dbNames.includes(",") ? val.DB_NAME : "",
|
||||
schema: val.TABLE_SCHEMA,
|
||||
fileImports: [],
|
||||
});
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
public abstract GetAllTables(
|
||||
schemas: string[],
|
||||
dbNames: string[]
|
||||
): Promise<Entity[]>;
|
||||
|
||||
public static GetRelationsFromRelationTempInfo(
|
||||
relationsTemp: RelationInternal[],
|
||||
@ -405,22 +375,22 @@ export default abstract class AbstractDriver {
|
||||
return entities;
|
||||
}
|
||||
|
||||
public abstract async GetCoulmnsFromEntity(
|
||||
public abstract GetCoulmnsFromEntity(
|
||||
entities: Entity[],
|
||||
schema: string,
|
||||
dbNames: string
|
||||
schemas: string[],
|
||||
dbNames: string[]
|
||||
): Promise<Entity[]>;
|
||||
|
||||
public abstract async GetIndexesFromEntity(
|
||||
public abstract GetIndexesFromEntity(
|
||||
entities: Entity[],
|
||||
schema: string,
|
||||
dbNames: string
|
||||
schemas: string[],
|
||||
dbNames: string[]
|
||||
): Promise<Entity[]>;
|
||||
|
||||
public abstract async GetRelations(
|
||||
public abstract GetRelations(
|
||||
entities: Entity[],
|
||||
schema: string,
|
||||
dbNames: string,
|
||||
schemas: string[],
|
||||
dbNames: string[],
|
||||
generationOptions: IGenerationOptions
|
||||
): Promise<Entity[]>;
|
||||
|
||||
@ -455,18 +425,15 @@ export default abstract class AbstractDriver {
|
||||
});
|
||||
}
|
||||
|
||||
public abstract async DisconnectFromServer();
|
||||
public abstract DisconnectFromServer(): Promise<void>;
|
||||
|
||||
public abstract async CreateDB(dbName: string);
|
||||
public abstract CreateDB(dbName: string): Promise<void>;
|
||||
|
||||
public abstract async DropDB(dbName: string);
|
||||
public abstract DropDB(dbName: string): Promise<void>;
|
||||
|
||||
public abstract async UseDB(dbName: string);
|
||||
public abstract CheckIfDBExists(dbName: string): Promise<boolean>;
|
||||
|
||||
public abstract async CheckIfDBExists(dbName: string): Promise<boolean>;
|
||||
|
||||
// TODO: change name
|
||||
protected static escapeCommaSeparatedList(commaSeparatedList: string) {
|
||||
return `'${commaSeparatedList.split(",").join("','")}'`;
|
||||
protected static buildEscapedObjectList(dbNames: string[]) {
|
||||
return `'${dbNames.join("','")}'`;
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,10 @@ export default class MssqlDriver extends AbstractDriver {
|
||||
}
|
||||
}
|
||||
|
||||
public GetAllTablesQuery = async (schema: string, dbNames: string) => {
|
||||
public async GetAllTables(
|
||||
schemas: string[],
|
||||
dbNames: string[]
|
||||
): Promise<Entity[]> {
|
||||
const request = new this.MSSQL.Request(this.Connection);
|
||||
const response: {
|
||||
TABLE_SCHEMA: string;
|
||||
@ -46,18 +49,36 @@ export default class MssqlDriver extends AbstractDriver {
|
||||
}[] = (
|
||||
await request.query(
|
||||
`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 (${MssqlDriver.escapeCommaSeparatedList(
|
||||
WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${MssqlDriver.buildEscapedObjectList(
|
||||
schemas
|
||||
)}) AND TABLE_CATALOG in (${MssqlDriver.buildEscapedObjectList(
|
||||
dbNames
|
||||
)})`
|
||||
)
|
||||
).recordset;
|
||||
return response;
|
||||
};
|
||||
// const response = await this.GetAllTablesQuery(schemas, dbNames);
|
||||
const ret: Entity[] = [] as Entity[];
|
||||
response.forEach((val) => {
|
||||
ret.push({
|
||||
columns: [],
|
||||
indices: [],
|
||||
relations: [],
|
||||
relationIds: [],
|
||||
sqlName: val.TABLE_NAME,
|
||||
tscName: val.TABLE_NAME,
|
||||
fileName: val.TABLE_NAME,
|
||||
database: dbNames.length > 1 ? val.DB_NAME : "",
|
||||
schema: val.TABLE_SCHEMA,
|
||||
fileImports: [],
|
||||
});
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
public async GetCoulmnsFromEntity(
|
||||
entities: Entity[],
|
||||
schema: string,
|
||||
dbNames: string
|
||||
schemas: string[],
|
||||
dbNames: string[]
|
||||
): Promise<Entity[]> {
|
||||
const request = new this.MSSQL.Request(this.Connection);
|
||||
const response: {
|
||||
@ -86,7 +107,9 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG
|
||||
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}) AND TABLE_CATALOG in (${MssqlDriver.escapeCommaSeparatedList(
|
||||
where TABLE_SCHEMA in (${MssqlDriver.buildEscapedObjectList(
|
||||
schemas
|
||||
)}) AND TABLE_CATALOG in (${MssqlDriver.buildEscapedObjectList(
|
||||
dbNames
|
||||
)})
|
||||
order by ordinal_position`)
|
||||
@ -255,8 +278,8 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG
|
||||
|
||||
public async GetIndexesFromEntity(
|
||||
entities: Entity[],
|
||||
schema: string,
|
||||
dbNames: string
|
||||
schemas: string[],
|
||||
dbNames: string[]
|
||||
): Promise<Entity[]> {
|
||||
const request = new this.MSSQL.Request(this.Connection);
|
||||
/* eslint-disable camelcase */
|
||||
@ -269,38 +292,40 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG
|
||||
is_primary_key: boolean;
|
||||
}[] = [];
|
||||
/* eslint-enable camelcase */
|
||||
await Promise.all(
|
||||
dbNames.split(",").map(async (dbName) => {
|
||||
if (dbNames.length > 1) {
|
||||
await this.UseDB(dbName);
|
||||
}
|
||||
const resp = (
|
||||
await request.query(`SELECT
|
||||
TableName = t.name,
|
||||
TableSchema = s.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);
|
||||
})
|
||||
);
|
||||
/* eslint-disable no-await-in-loop */
|
||||
for (const dbName of dbNames) {
|
||||
if (dbNames.length > 1) {
|
||||
await this.UseDB(dbName);
|
||||
}
|
||||
const resp = (
|
||||
await request.query(`SELECT
|
||||
TableName = t.name,
|
||||
TableSchema = s.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 (${MssqlDriver.buildEscapedObjectList(
|
||||
schemas
|
||||
)})
|
||||
ORDER BY
|
||||
t.name, ind.name, ind.index_id, ic.key_ordinal;`)
|
||||
).recordset;
|
||||
response.push(...resp);
|
||||
}
|
||||
|
||||
/* eslint-enable no-await-in-loop */
|
||||
entities.forEach((ent) => {
|
||||
const entityIndices = response.filter(
|
||||
(filterVal) =>
|
||||
@ -331,8 +356,8 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG
|
||||
|
||||
public async GetRelations(
|
||||
entities: Entity[],
|
||||
schema: string,
|
||||
dbNames: string,
|
||||
schemas: string[],
|
||||
dbNames: string[],
|
||||
generationOptions: IGenerationOptions
|
||||
): Promise<Entity[]> {
|
||||
const request = new this.MSSQL.Request(this.Connection);
|
||||
@ -347,53 +372,56 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG
|
||||
onUpdate: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION";
|
||||
objectId: number;
|
||||
}[] = [];
|
||||
await Promise.all(
|
||||
dbNames.split(",").map(async (dbName) => {
|
||||
if (dbNames.length > 1) {
|
||||
await this.UseDB(dbName);
|
||||
}
|
||||
const resp: {
|
||||
TableWithForeignKey: string;
|
||||
// eslint-disable-next-line camelcase
|
||||
FK_PartNo: number;
|
||||
ForeignKeyColumn: string;
|
||||
TableReferenced: string;
|
||||
ForeignKeyColumnReferenced: string;
|
||||
onDelete: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION";
|
||||
onUpdate: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION";
|
||||
objectId: number;
|
||||
}[] = (
|
||||
await request.query(`select
|
||||
parentTable.name as TableWithForeignKey,
|
||||
fkc.constraint_column_id as FK_PartNo,
|
||||
parentColumn.name as ForeignKeyColumn,
|
||||
referencedTable.name as TableReferenced,
|
||||
referencedColumn.name as ForeignKeyColumnReferenced,
|
||||
fk.delete_referential_action_desc as onDelete,
|
||||
fk.update_referential_action_desc as onUpdate,
|
||||
fk.object_id as objectId
|
||||
from
|
||||
sys.foreign_keys fk
|
||||
inner join
|
||||
sys.foreign_key_columns as fkc on fkc.constraint_object_id=fk.object_id
|
||||
inner join
|
||||
sys.tables as parentTable on fkc.parent_object_id = parentTable.object_id
|
||||
inner join
|
||||
sys.columns as parentColumn on fkc.parent_object_id = parentColumn.object_id and fkc.parent_column_id = parentColumn.column_id
|
||||
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 and parentSchema.name in (${schema})
|
||||
order by
|
||||
TableWithForeignKey, FK_PartNo`)
|
||||
).recordset;
|
||||
response.push(...resp);
|
||||
})
|
||||
);
|
||||
/* eslint-disable no-await-in-loop */
|
||||
for (const dbName of dbNames) {
|
||||
if (dbNames.length > 1) {
|
||||
await this.UseDB(dbName);
|
||||
}
|
||||
const resp: {
|
||||
TableWithForeignKey: string;
|
||||
// eslint-disable-next-line camelcase
|
||||
FK_PartNo: number;
|
||||
ForeignKeyColumn: string;
|
||||
TableReferenced: string;
|
||||
ForeignKeyColumnReferenced: string;
|
||||
onDelete: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION";
|
||||
onUpdate: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION";
|
||||
objectId: number;
|
||||
}[] = (
|
||||
await request.query(`select
|
||||
parentTable.name as TableWithForeignKey,
|
||||
fkc.constraint_column_id as FK_PartNo,
|
||||
parentColumn.name as ForeignKeyColumn,
|
||||
referencedTable.name as TableReferenced,
|
||||
referencedColumn.name as ForeignKeyColumnReferenced,
|
||||
fk.delete_referential_action_desc as onDelete,
|
||||
fk.update_referential_action_desc as onUpdate,
|
||||
fk.object_id as objectId
|
||||
from
|
||||
sys.foreign_keys fk
|
||||
inner join
|
||||
sys.foreign_key_columns as fkc on fkc.constraint_object_id=fk.object_id
|
||||
inner join
|
||||
sys.tables as parentTable on fkc.parent_object_id = parentTable.object_id
|
||||
inner join
|
||||
sys.columns as parentColumn on fkc.parent_object_id = parentColumn.object_id and fkc.parent_column_id = parentColumn.column_id
|
||||
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 and parentSchema.name in (${MssqlDriver.buildEscapedObjectList(
|
||||
schemas
|
||||
)})
|
||||
order by
|
||||
TableWithForeignKey, FK_PartNo`)
|
||||
).recordset;
|
||||
response.push(...resp);
|
||||
}
|
||||
/* eslint-enable no-await-in-loop */
|
||||
|
||||
const relationsTemp: RelationInternal[] = [] as RelationInternal[];
|
||||
const relationKeys = new Set(response.map((v) => v.objectId));
|
||||
|
||||
@ -460,7 +488,7 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG
|
||||
}
|
||||
|
||||
public async ConnectToServer(connectionOptons: IConnectionOptions) {
|
||||
const databaseName = connectionOptons.databaseName.split(",")[0];
|
||||
const databaseName = connectionOptons.databaseNames[0];
|
||||
const config: MSSQL.config = {
|
||||
database: databaseName,
|
||||
options: {
|
||||
@ -495,17 +523,17 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG
|
||||
|
||||
public async CreateDB(dbName: string) {
|
||||
const request = new this.MSSQL.Request(this.Connection);
|
||||
await request.query(`CREATE DATABASE ${dbName}; `);
|
||||
await request.query(`CREATE DATABASE "${dbName}"; `);
|
||||
}
|
||||
|
||||
public async UseDB(dbName: string) {
|
||||
const request = new this.MSSQL.Request(this.Connection);
|
||||
await request.query(`USE ${dbName}; `);
|
||||
await request.query(`USE "${dbName}"; `);
|
||||
}
|
||||
|
||||
public async DropDB(dbName: string) {
|
||||
const request = new this.MSSQL.Request(this.Connection);
|
||||
await request.query(`DROP DATABASE ${dbName}; `);
|
||||
await request.query(`DROP DATABASE "${dbName}"; `);
|
||||
}
|
||||
|
||||
public async CheckIfDBExists(dbName: string): Promise<boolean> {
|
||||
|
@ -39,24 +39,45 @@ export default class MysqlDriver extends AbstractDriver {
|
||||
}
|
||||
}
|
||||
|
||||
public GetAllTablesQuery = async (schema: string, dbNames: string) => {
|
||||
const response = this.ExecQuery<{
|
||||
public async GetAllTables(
|
||||
schemas: string[],
|
||||
dbNames: string[]
|
||||
): Promise<Entity[]> {
|
||||
const response: {
|
||||
TABLE_SCHEMA: string;
|
||||
TABLE_NAME: string;
|
||||
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 IN (${MysqlDriver.escapeCommaSeparatedList(
|
||||
dbNames
|
||||
)})`);
|
||||
return response;
|
||||
};
|
||||
}[] = await this.ExecQuery(
|
||||
`SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_SCHEMA as DB_NAME
|
||||
FROM information_schema.tables
|
||||
WHERE table_type='BASE TABLE'
|
||||
AND table_schema IN (${MysqlDriver.buildEscapedObjectList(
|
||||
dbNames
|
||||
)})`
|
||||
);
|
||||
// const response = await this.GetAllTablesQuery(schemas, dbNames);
|
||||
const ret: Entity[] = [] as Entity[];
|
||||
response.forEach((val) => {
|
||||
ret.push({
|
||||
columns: [],
|
||||
indices: [],
|
||||
relations: [],
|
||||
relationIds: [],
|
||||
sqlName: val.TABLE_NAME,
|
||||
tscName: val.TABLE_NAME,
|
||||
fileName: val.TABLE_NAME,
|
||||
database: dbNames.length > 1 ? val.DB_NAME : "",
|
||||
schema: val.TABLE_SCHEMA,
|
||||
fileImports: [],
|
||||
});
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
public async GetCoulmnsFromEntity(
|
||||
entities: Entity[],
|
||||
schema: string,
|
||||
dbNames: string
|
||||
schemas: string[],
|
||||
dbNames: string[]
|
||||
): Promise<Entity[]> {
|
||||
const response = await this.ExecQuery<{
|
||||
TABLE_NAME: string;
|
||||
@ -74,7 +95,7 @@ export default 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, COLUMN_COMMENT
|
||||
FROM INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA IN (${MysqlDriver.escapeCommaSeparatedList(
|
||||
FROM INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA IN (${MysqlDriver.buildEscapedObjectList(
|
||||
dbNames
|
||||
)})
|
||||
order by ordinal_position`);
|
||||
@ -297,8 +318,8 @@ export default class MysqlDriver extends AbstractDriver {
|
||||
|
||||
public async GetIndexesFromEntity(
|
||||
entities: Entity[],
|
||||
schema: string,
|
||||
dbNames: string
|
||||
schemas: string[],
|
||||
dbNames: string[]
|
||||
): Promise<Entity[]> {
|
||||
/* eslint-disable camelcase */
|
||||
const response = await this.ExecQuery<{
|
||||
@ -310,7 +331,7 @@ export default 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 IN (${MysqlDriver.escapeCommaSeparatedList(
|
||||
WHERE table_schema IN (${MysqlDriver.buildEscapedObjectList(
|
||||
dbNames
|
||||
)})`);
|
||||
/* eslint-enable camelcase */
|
||||
@ -344,8 +365,8 @@ export default class MysqlDriver extends AbstractDriver {
|
||||
|
||||
public async GetRelations(
|
||||
entities: Entity[],
|
||||
schema: string,
|
||||
dbNames: string,
|
||||
schemas: string[],
|
||||
dbNames: string[],
|
||||
generationOptions: IGenerationOptions
|
||||
): Promise<Entity[]> {
|
||||
const response = await this.ExecQuery<{
|
||||
@ -374,7 +395,7 @@ export default 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 IN (${MysqlDriver.escapeCommaSeparatedList(dbNames)})
|
||||
TABLE_SCHEMA IN (${MysqlDriver.buildEscapedObjectList(dbNames)})
|
||||
AND CU.REFERENCED_TABLE_NAME IS NOT NULL;
|
||||
`);
|
||||
const relationsTemp: RelationInternal[] = [] as RelationInternal[];
|
||||
@ -444,7 +465,7 @@ export default class MysqlDriver extends AbstractDriver {
|
||||
}
|
||||
|
||||
public async ConnectToServer(connectionOptons: IConnectionOptions) {
|
||||
const databaseName = connectionOptons.databaseName.split(",")[0];
|
||||
const databaseName = connectionOptons.databaseNames[0];
|
||||
let config: MYSQL.ConnectionConfig;
|
||||
if (connectionOptons.ssl) {
|
||||
config = {
|
||||
@ -490,19 +511,19 @@ export default class MysqlDriver extends AbstractDriver {
|
||||
}
|
||||
|
||||
public async CreateDB(dbName: string) {
|
||||
await this.ExecQuery(`CREATE DATABASE ${dbName}; `);
|
||||
await this.ExecQuery(`CREATE DATABASE \`${dbName}\`; `);
|
||||
}
|
||||
|
||||
public async UseDB(dbName: string) {
|
||||
await this.ExecQuery(`USE ${dbName}; `);
|
||||
await this.ExecQuery(`USE \`${dbName}\`; `);
|
||||
}
|
||||
|
||||
public async DropDB(dbName: string) {
|
||||
await this.ExecQuery(`DROP DATABASE ${dbName}; `);
|
||||
await this.ExecQuery(`DROP DATABASE \`${dbName}\`; `);
|
||||
}
|
||||
|
||||
public async CheckIfDBExists(dbName: string): Promise<boolean> {
|
||||
const resp = await this.ExecQuery(`SHOW DATABASES LIKE '${dbName}' `);
|
||||
const resp = await this.ExecQuery(`SHOW DATABASES LIKE "${dbName}" `);
|
||||
return resp.length > 0;
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,10 @@ export default class OracleDriver extends AbstractDriver {
|
||||
}
|
||||
}
|
||||
|
||||
public GetAllTablesQuery = async (schema: string, dbNames: string) => {
|
||||
public async GetAllTables(
|
||||
schemas: string[],
|
||||
dbNames: string[]
|
||||
): Promise<Entity[]> {
|
||||
const response = (
|
||||
await this.Connection.execute<{
|
||||
TABLE_SCHEMA: string;
|
||||
@ -48,8 +51,23 @@ export default class OracleDriver extends AbstractDriver {
|
||||
`SELECT NULL AS TABLE_SCHEMA, TABLE_NAME, NULL AS DB_NAME FROM all_tables WHERE owner = (select user from dual)`
|
||||
)
|
||||
).rows!;
|
||||
return response;
|
||||
};
|
||||
const ret: Entity[] = [];
|
||||
response.forEach((val) => {
|
||||
ret.push({
|
||||
columns: [],
|
||||
indices: [],
|
||||
relations: [],
|
||||
relationIds: [],
|
||||
sqlName: val.TABLE_NAME,
|
||||
tscName: val.TABLE_NAME,
|
||||
fileName: val.TABLE_NAME,
|
||||
database: dbNames.length > 1 ? val.DB_NAME : "",
|
||||
schema: val.TABLE_SCHEMA,
|
||||
fileImports: [],
|
||||
});
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
public async GetCoulmnsFromEntity(entities: Entity[]): Promise<Entity[]> {
|
||||
const response = (
|
||||
@ -262,8 +280,8 @@ export default class OracleDriver extends AbstractDriver {
|
||||
|
||||
public async GetRelations(
|
||||
entities: Entity[],
|
||||
schema: string,
|
||||
dbNames: string,
|
||||
schemas: string[],
|
||||
dbNames: string[],
|
||||
generationOptions: IGenerationOptions
|
||||
): Promise<Entity[]> {
|
||||
const response = (
|
||||
@ -341,7 +359,7 @@ export default class OracleDriver extends AbstractDriver {
|
||||
let config: Oracle.ConnectionAttributes;
|
||||
if (connectionOptions.user === String(process.env.ORACLE_UsernameSys)) {
|
||||
config = {
|
||||
connectString: `${connectionOptions.host}:${connectionOptions.port}/${connectionOptions.databaseName}`,
|
||||
connectString: `${connectionOptions.host}:${connectionOptions.port}/${connectionOptions.databaseNames[0]}`,
|
||||
externalAuth: connectionOptions.ssl,
|
||||
password: connectionOptions.password,
|
||||
privilege: this.Oracle.SYSDBA,
|
||||
@ -349,7 +367,7 @@ export default class OracleDriver extends AbstractDriver {
|
||||
};
|
||||
} else {
|
||||
config = {
|
||||
connectString: `${connectionOptions.host}:${connectionOptions.port}/${connectionOptions.databaseName}`,
|
||||
connectString: `${connectionOptions.host}:${connectionOptions.port}/${connectionOptions.databaseNames[0]}`,
|
||||
externalAuth: connectionOptions.ssl,
|
||||
password: connectionOptions.password,
|
||||
user: connectionOptions.user,
|
||||
|
@ -37,22 +37,42 @@ export default class PostgresDriver extends AbstractDriver {
|
||||
}
|
||||
}
|
||||
|
||||
public GetAllTablesQuery = async (schema: string, dbNames: string) => {
|
||||
public async GetAllTables(
|
||||
schemas: string[],
|
||||
dbNames: string[]
|
||||
): Promise<Entity[]> {
|
||||
const response: {
|
||||
TABLE_SCHEMA: string;
|
||||
TABLE_NAME: string;
|
||||
DB_NAME: string;
|
||||
}[] = (
|
||||
await this.Connection.query(
|
||||
`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})`
|
||||
`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 (${PostgresDriver.buildEscapedObjectList(
|
||||
schemas
|
||||
)})`
|
||||
)
|
||||
).rows;
|
||||
return response;
|
||||
};
|
||||
const ret: Entity[] = [];
|
||||
response.forEach((val) => {
|
||||
ret.push({
|
||||
columns: [],
|
||||
indices: [],
|
||||
relations: [],
|
||||
relationIds: [],
|
||||
sqlName: val.TABLE_NAME,
|
||||
tscName: val.TABLE_NAME,
|
||||
fileName: val.TABLE_NAME,
|
||||
database: dbNames.length > 1 ? val.DB_NAME : "",
|
||||
schema: val.TABLE_SCHEMA,
|
||||
fileImports: [],
|
||||
});
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
public async GetCoulmnsFromEntity(
|
||||
entities: Entity[],
|
||||
schema: string
|
||||
schemas: string[]
|
||||
): Promise<Entity[]> {
|
||||
const response: {
|
||||
/* eslint-disable camelcase */
|
||||
@ -93,7 +113,9 @@ export default class PostgresDriver extends AbstractDriver {
|
||||
WHERE "n"."nspname" = table_schema AND "t"."typname"=udt_name
|
||||
) enumValues
|
||||
FROM INFORMATION_SCHEMA.COLUMNS c
|
||||
where table_schema in (${schema})
|
||||
where table_schema in (${PostgresDriver.buildEscapedObjectList(
|
||||
schemas
|
||||
)})
|
||||
order by ordinal_position`)
|
||||
).rows;
|
||||
entities.forEach((ent) => {
|
||||
@ -428,7 +450,7 @@ export default class PostgresDriver extends AbstractDriver {
|
||||
|
||||
public async GetIndexesFromEntity(
|
||||
entities: Entity[],
|
||||
schema: string
|
||||
schemas: string[]
|
||||
): Promise<Entity[]> {
|
||||
const response: {
|
||||
tablename: string;
|
||||
@ -459,7 +481,7 @@ export default class PostgresDriver extends AbstractDriver {
|
||||
LEFT JOIN pg_index AS ix ON f.attnum = ANY(ix.indkey) and c.oid = f.attrelid and c.oid = ix.indrelid
|
||||
LEFT JOIN pg_class AS i ON ix.indexrelid = i.oid
|
||||
WHERE c.relkind = 'r'::char
|
||||
AND n.nspname in (${schema})
|
||||
AND n.nspname in (${PostgresDriver.buildEscapedObjectList(schemas)})
|
||||
AND f.attnum > 0
|
||||
AND i.oid<>0
|
||||
ORDER BY c.relname,f.attname;`)
|
||||
@ -492,8 +514,8 @@ export default class PostgresDriver extends AbstractDriver {
|
||||
|
||||
public async GetRelations(
|
||||
entities: Entity[],
|
||||
schema: string,
|
||||
dbNames: string,
|
||||
schemas: string[],
|
||||
dbNames: string[],
|
||||
generationOptions: IGenerationOptions
|
||||
): Promise<Entity[]> {
|
||||
const response: {
|
||||
@ -535,7 +557,9 @@ export default class PostgresDriver extends AbstractDriver {
|
||||
con1.contype = 'f'::"char"
|
||||
AND cl_1.relnamespace = ns.oid
|
||||
AND con1.conrelid = cl_1.oid
|
||||
and nspname in (${schema})
|
||||
and nspname in (${PostgresDriver.buildEscapedObjectList(
|
||||
schemas
|
||||
)})
|
||||
) con,
|
||||
pg_attribute att,
|
||||
pg_class cl,
|
||||
@ -618,7 +642,7 @@ export default class PostgresDriver extends AbstractDriver {
|
||||
|
||||
public async ConnectToServer(connectionOptons: IConnectionOptions) {
|
||||
this.Connection = new this.PG.Client({
|
||||
database: connectionOptons.databaseName,
|
||||
database: connectionOptons.databaseNames[0],
|
||||
host: connectionOptons.host,
|
||||
password: connectionOptons.password,
|
||||
port: connectionOptons.port,
|
||||
@ -649,10 +673,6 @@ export default class PostgresDriver extends AbstractDriver {
|
||||
await this.Connection.query(`CREATE DATABASE ${dbName}; `);
|
||||
}
|
||||
|
||||
public async UseDB(dbName: string) {
|
||||
await this.Connection.query(`USE ${dbName}; `);
|
||||
}
|
||||
|
||||
public async DropDB(dbName: string) {
|
||||
await this.Connection.query(`DROP DATABASE ${dbName}; `);
|
||||
}
|
||||
|
@ -45,8 +45,10 @@ export default class SqliteDriver extends AbstractDriver {
|
||||
}
|
||||
|
||||
public async GetAllTables(
|
||||
schema: string,
|
||||
dbNames: string
|
||||
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
|
||||
schemas: string[],
|
||||
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
|
||||
dbNames: string[]
|
||||
): Promise<Entity[]> {
|
||||
const ret: Entity[] = [] as Entity[];
|
||||
// eslint-disable-next-line camelcase
|
||||
@ -307,8 +309,8 @@ export default class SqliteDriver extends AbstractDriver {
|
||||
|
||||
public async GetRelations(
|
||||
entities: Entity[],
|
||||
schema: string,
|
||||
dbNames: string,
|
||||
schemas: string[],
|
||||
dbNames: string[],
|
||||
generationOptions: IGenerationOptions
|
||||
): Promise<Entity[]> {
|
||||
let retVal = entities;
|
||||
@ -387,7 +389,24 @@ export default class SqliteDriver extends AbstractDriver {
|
||||
}
|
||||
|
||||
public async ConnectToServer(connectionOptons: IConnectionOptions) {
|
||||
await this.UseDB(connectionOptons.databaseName);
|
||||
const promise = new Promise<void>((resolve, reject) => {
|
||||
this.db = new this.sqlite.Database(
|
||||
connectionOptons.databaseNames[0],
|
||||
(err) => {
|
||||
if (err) {
|
||||
TomgUtils.LogError(
|
||||
"Error connecting to SQLite database.",
|
||||
false,
|
||||
err.message
|
||||
);
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
}
|
||||
);
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
@ -395,24 +414,6 @@ export default class SqliteDriver extends AbstractDriver {
|
||||
// not supported
|
||||
}
|
||||
|
||||
public async UseDB(dbName: string) {
|
||||
const promise = new Promise<boolean>((resolve, reject) => {
|
||||
this.db = new this.sqlite.Database(dbName, (err) => {
|
||||
if (err) {
|
||||
TomgUtils.LogError(
|
||||
"Error connecting to SQLite database.",
|
||||
false,
|
||||
err.message
|
||||
);
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
public async DropDB() {
|
||||
// not supported
|
||||
|
30
src/index.ts
30
src/index.ts
@ -140,7 +140,7 @@ function checkYargsParameters(options: options): options {
|
||||
alias: "database",
|
||||
string: true,
|
||||
demand: true,
|
||||
default: options.connectionOptions.databaseName,
|
||||
default: options.connectionOptions.databaseNames.join(","),
|
||||
describe:
|
||||
"Database name(or path for sqlite). You can pass multiple values separated by comma.",
|
||||
},
|
||||
@ -184,7 +184,7 @@ function checkYargsParameters(options: options): options {
|
||||
s: {
|
||||
alias: "schema",
|
||||
string: true,
|
||||
default: options.connectionOptions.schemaName,
|
||||
default: options.connectionOptions.schemaNames.join(","),
|
||||
describe:
|
||||
"Schema name to create model from. Only for mssql and postgres. You can pass multiple values separated by comma eg. -s scheme1,scheme2,scheme3",
|
||||
},
|
||||
@ -299,7 +299,7 @@ function checkYargsParameters(options: options): options {
|
||||
},
|
||||
});
|
||||
|
||||
options.connectionOptions.databaseName = argv.d;
|
||||
options.connectionOptions.databaseNames = argv.d.split(",");
|
||||
options.connectionOptions.databaseType = argv.e;
|
||||
|
||||
const driver = createDriver(options.connectionOptions.databaseType);
|
||||
@ -308,9 +308,9 @@ function checkYargsParameters(options: options): options {
|
||||
options.connectionOptions.host = argv.h;
|
||||
options.connectionOptions.password = argv.x;
|
||||
options.connectionOptions.port = argv.p || standardPort;
|
||||
options.connectionOptions.schemaName = argv.s
|
||||
? argv.s.toString()
|
||||
: standardSchema;
|
||||
options.connectionOptions.schemaNames = argv.s
|
||||
? argv.s.split(",")
|
||||
: [standardSchema];
|
||||
options.connectionOptions.instanceName = argv.i || undefined;
|
||||
options.connectionOptions.ssl = argv.ssl;
|
||||
options.connectionOptions.user = argv.u || standardUser;
|
||||
@ -371,7 +371,7 @@ async function useInquirer(options: options): Promise<options> {
|
||||
if (options.connectionOptions.databaseType !== oldDatabaseType) {
|
||||
options.connectionOptions.port = driver.standardPort;
|
||||
options.connectionOptions.user = driver.standardUser;
|
||||
options.connectionOptions.schemaName = driver.standardSchema;
|
||||
options.connectionOptions.schemaNames = [driver.standardSchema];
|
||||
}
|
||||
if (options.connectionOptions.databaseType !== "sqlite") {
|
||||
if (options.connectionOptions.databaseType === "mssql") {
|
||||
@ -423,7 +423,7 @@ async function useInquirer(options: options): Promise<options> {
|
||||
type: "password",
|
||||
},
|
||||
{
|
||||
default: options.connectionOptions.databaseName,
|
||||
default: options.connectionOptions.databaseNames.join(","),
|
||||
message:
|
||||
"Database name: (You can pass multiple values separated by comma)",
|
||||
name: "dbName",
|
||||
@ -434,29 +434,31 @@ async function useInquirer(options: options): Promise<options> {
|
||||
options.connectionOptions.databaseType === "mssql" ||
|
||||
options.connectionOptions.databaseType === "postgres"
|
||||
) {
|
||||
options.connectionOptions.schemaName = (
|
||||
options.connectionOptions.schemaNames = (
|
||||
await inquirer.prompt([
|
||||
{
|
||||
default: options.connectionOptions.schemaName,
|
||||
default: options.connectionOptions.schemaNames.join(
|
||||
","
|
||||
),
|
||||
message:
|
||||
"Database schema: (You can pass multiple values separated by comma)",
|
||||
name: "schema",
|
||||
type: "input",
|
||||
},
|
||||
])
|
||||
).schema;
|
||||
).schema.split(",");
|
||||
}
|
||||
options.connectionOptions.port = parseInt(answ.port, 10);
|
||||
options.connectionOptions.host = answ.host;
|
||||
options.connectionOptions.user = answ.login;
|
||||
options.connectionOptions.password = answ.password;
|
||||
options.connectionOptions.databaseName = answ.dbName;
|
||||
options.connectionOptions.databaseNames = answ.dbName.split(",");
|
||||
options.connectionOptions.ssl = answ.ssl;
|
||||
} else {
|
||||
options.connectionOptions.databaseName = (
|
||||
options.connectionOptions.databaseNames = (
|
||||
await inquirer.prompt([
|
||||
{
|
||||
default: options.connectionOptions.databaseName,
|
||||
default: options.connectionOptions.databaseNames,
|
||||
message: "Path to database file:",
|
||||
name: "dbName",
|
||||
type: "input",
|
||||
|
20
test/integration/github-issues/273/entity/Post.ts
Normal file
20
test/integration/github-issues/273/entity/Post.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, JoinColumn, Index } from "typeorm";
|
||||
import { PostAuthor } from "./PostAuthor";
|
||||
|
||||
@Entity("Post", {database: "db-1"})
|
||||
export class Post {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@Column()
|
||||
text: string;
|
||||
|
||||
@OneToOne(type => PostAuthor, author => author.post)
|
||||
@JoinColumn()
|
||||
author: PostAuthor;
|
||||
|
||||
}
|
16
test/integration/github-issues/273/entity/PostAuthor.ts
Normal file
16
test/integration/github-issues/273/entity/PostAuthor.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, JoinColumn } from "typeorm";
|
||||
import { Post } from "./Post";
|
||||
|
||||
@Entity("PostAuthor", {database: "db-1"})
|
||||
export class PostAuthor {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@OneToOne(type => Post, post => post.author)
|
||||
post: Post;
|
||||
|
||||
}
|
@ -5,7 +5,6 @@ import * as fs from "fs-extra";
|
||||
import * as path from "path";
|
||||
import * as chaiSubset from "chai-subset";
|
||||
import * as flatMap from "array.prototype.flatmap";
|
||||
import * as yn from "yn";
|
||||
import { CLIEngine } from "eslint";
|
||||
import * as dotEnv from "dotenv"
|
||||
import EntityFileToJson from "../utils/EntityFileToJson";
|
||||
@ -15,6 +14,7 @@ import { Entity } from "../../src/models/Entity";
|
||||
import IConnectionOptions from "../../src/IConnectionOptions";
|
||||
import modelCustomizationPhase from "../../src/ModelCustomization";
|
||||
import modelGenerationPhase from "../../src/ModelGeneration";
|
||||
import AbstractDriver from "../../src/drivers/AbstractDriver";
|
||||
|
||||
dotEnv.config();
|
||||
|
||||
@ -41,7 +41,7 @@ describe("TypeOrm examples", async () => {
|
||||
describe("Filtering tables", async () => {
|
||||
const testPartialPath = "test/integration/examples";
|
||||
it("skipTables",async ()=>{
|
||||
const dbDrivers: string[] = GTU.getEnabledDbDrivers();
|
||||
const dbDrivers = GTU.getEnabledDbDrivers();
|
||||
const modelGenerationPromises = dbDrivers.map(async dbDriver => {
|
||||
const {
|
||||
generationOptions,
|
||||
@ -61,7 +61,7 @@ describe("Filtering tables", async () => {
|
||||
await Promise.all(modelGenerationPromises);
|
||||
});
|
||||
it("onlyTables",async ()=>{
|
||||
const dbDrivers: string[] = GTU.getEnabledDbDrivers();
|
||||
const dbDrivers = GTU.getEnabledDbDrivers();
|
||||
const modelGenerationPromises = dbDrivers.map(async dbDriver => {
|
||||
const {
|
||||
generationOptions,
|
||||
@ -87,7 +87,7 @@ async function runTestsFromPath(
|
||||
testPartialPath: string,
|
||||
isDbSpecific: boolean
|
||||
) {
|
||||
const dbDrivers: string[] = GTU.getEnabledDbDrivers();
|
||||
const dbDrivers: IConnectionOptions["databaseType"][] = GTU.getEnabledDbDrivers();
|
||||
createOutputDirs(dbDrivers);
|
||||
const files = fs.readdirSync(path.resolve(process.cwd(), testPartialPath));
|
||||
if (isDbSpecific) {
|
||||
@ -114,7 +114,7 @@ function createOutputDirs(dbDrivers: string[]) {
|
||||
|
||||
function runTestForMultipleDrivers(
|
||||
testName: string,
|
||||
dbDrivers: string[],
|
||||
dbDrivers: IConnectionOptions["databaseType"][],
|
||||
testPartialPath: string
|
||||
) {
|
||||
it(testName, async () => {
|
||||
@ -127,13 +127,23 @@ function runTestForMultipleDrivers(
|
||||
resultsPath,
|
||||
filesOrgPathTS
|
||||
} = await prepareTestRuns(testPartialPath, testName, dbDriver);
|
||||
let dbModel: Entity[] = [];
|
||||
let dbModel: Entity[] = [];
|
||||
switch (testName) {
|
||||
case "144":
|
||||
dbModel = await dataCollectionPhase(
|
||||
driver,
|
||||
Object.assign(connectionOptions, {
|
||||
databaseName: "db1,db2"
|
||||
databaseNames: ["db1","db2"]
|
||||
}),
|
||||
generationOptions
|
||||
);
|
||||
break;
|
||||
|
||||
case "273":
|
||||
dbModel = await dataCollectionPhase(
|
||||
driver,
|
||||
Object.assign(connectionOptions, {
|
||||
databaseNames: ["db-1","db-2"]
|
||||
}),
|
||||
generationOptions
|
||||
);
|
||||
@ -147,13 +157,13 @@ function runTestForMultipleDrivers(
|
||||
);
|
||||
break;
|
||||
}
|
||||
dbModel = modelCustomizationPhase(
|
||||
dbModel = modelCustomizationPhase(
|
||||
dbModel,
|
||||
generationOptions,
|
||||
driver.defaultValues
|
||||
);
|
||||
modelGenerationPhase(connectionOptions, generationOptions, dbModel);
|
||||
const filesGenPath = path.resolve(resultsPath, "entities");
|
||||
const filesGenPath = path.resolve(resultsPath, "entities");
|
||||
compareGeneratedFiles(filesOrgPathTS, filesGenPath);
|
||||
return {
|
||||
dbModel,
|
||||
@ -189,6 +199,9 @@ function runTestForMultipleDrivers(
|
||||
case "248":
|
||||
return dbDrivers.filter(dbDriver =>
|
||||
dbDriver === "postgres"
|
||||
);case "273":
|
||||
return dbDrivers.filter(dbDriver =>
|
||||
["mysql", "mariadb","mssql"].includes(dbDriver)
|
||||
);
|
||||
default:
|
||||
return dbDrivers;
|
||||
@ -197,7 +210,7 @@ function runTestForMultipleDrivers(
|
||||
}
|
||||
|
||||
async function runTest(
|
||||
dbDrivers: string[],
|
||||
dbDrivers: IConnectionOptions["databaseType"][],
|
||||
testPartialPath: string,
|
||||
files: string[]
|
||||
) {
|
||||
@ -359,7 +372,7 @@ export function compileGeneratedModel(
|
||||
async function prepareTestRuns(
|
||||
testPartialPath: string,
|
||||
testName: string,
|
||||
dbDriver: string
|
||||
dbDriver: IConnectionOptions["databaseType"]
|
||||
) {
|
||||
const filesOrgPathJS = path.resolve(
|
||||
process.cwd(),
|
||||
@ -373,6 +386,7 @@ async function prepareTestRuns(
|
||||
testName,
|
||||
"entity"
|
||||
);
|
||||
|
||||
const resultsPath = path.resolve(process.cwd(), `output`, dbDriver);
|
||||
fs.removeSync(resultsPath);
|
||||
const driver = createDriver(dbDriver);
|
||||
@ -385,51 +399,28 @@ async function prepareTestRuns(
|
||||
generationOptions.lazy = true;
|
||||
break;
|
||||
case "144":
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
{
|
||||
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, { default: false }),
|
||||
skipTables: [],
|
||||
onlyTables: [],
|
||||
};
|
||||
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, { default: false }),
|
||||
skipTables: [],
|
||||
onlyTables: []
|
||||
};
|
||||
case "mysql":
|
||||
connectionOptions = GTU.getTomgConnectionOptions(dbDriver);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
await driver.ConnectToServer(connectionOptions!);
|
||||
if (!(await driver.CheckIfDBExists("db1"))) {
|
||||
await driver.CreateDB("db1");
|
||||
}
|
||||
if (!(await driver.CheckIfDBExists("db2"))) {
|
||||
await driver.CreateDB("db2");
|
||||
}
|
||||
await createDatabases(["db1","db2"], driver);
|
||||
await driver.DisconnectFromServer();
|
||||
break;
|
||||
}
|
||||
case "273":{
|
||||
const connectionOptions= GTU.getTomgConnectionOptions(dbDriver);
|
||||
await driver.ConnectToServer(connectionOptions!);
|
||||
await createDatabases(["db-1","db-2"], driver);
|
||||
await driver.DisconnectFromServer();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -445,3 +436,11 @@ async function prepareTestRuns(
|
||||
filesOrgPathTS
|
||||
};
|
||||
}
|
||||
async function createDatabases(databases: string[], driver: AbstractDriver) {
|
||||
for await (const db of databases) {
|
||||
if (!(await driver.CheckIfDBExists(db))) {
|
||||
await driver.CreateDB(db);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ import MariaDbDriver from "../../src/drivers/MariaDbDriver";
|
||||
import PostgresDriver from "../../src/drivers/PostgresDriver";
|
||||
import OracleDriver from "../../src/drivers/OracleDriver";
|
||||
import MysqlDriver from "../../src/drivers/MysqlDriver";
|
||||
import { assertUnreachable } from "../../src/Utils";
|
||||
|
||||
export function getGenerationOptions(resultsPath: string): IGenerationOptions {
|
||||
const retVal = getDefaultGenerationOptions();
|
||||
@ -22,20 +23,9 @@ export async function createMSSQLModels(
|
||||
filesOrgPath: string
|
||||
): Promise<IConnectionOptions> {
|
||||
const driver = new MssqlDriver();
|
||||
const connectionOptions: IConnectionOptions = {
|
||||
host: String(process.env.MSSQL_Host),
|
||||
port: Number(process.env.MSSQL_Port),
|
||||
databaseName: `master`,
|
||||
user: String(process.env.MSSQL_Username),
|
||||
password: String(process.env.MSSQL_Password),
|
||||
databaseType: "mssql",
|
||||
schemaName: "dbo,sch1,sch2",
|
||||
ssl: yn(process.env.MSSQL_SSL, { default: false }),
|
||||
skipTables: [],
|
||||
onlyTables: []
|
||||
};
|
||||
const connectionOptions = getTomgConnectionOptions("mssql");
|
||||
await driver.ConnectToServer(connectionOptions);
|
||||
connectionOptions.databaseName = String(process.env.MSSQL_Database);
|
||||
connectionOptions.databaseNames = [String(process.env.MSSQL_Database)];
|
||||
|
||||
if (await driver.CheckIfDBExists(String(process.env.MSSQL_Database))) {
|
||||
await driver.DropDB(String(process.env.MSSQL_Database));
|
||||
@ -75,20 +65,9 @@ export async function createPostgresModels(
|
||||
filesOrgPath: string
|
||||
): Promise<IConnectionOptions> {
|
||||
const driver = new PostgresDriver();
|
||||
const connectionOptions: IConnectionOptions = {
|
||||
host: String(process.env.POSTGRES_Host),
|
||||
port: Number(process.env.POSTGRES_Port),
|
||||
databaseName: `postgres`,
|
||||
user: String(process.env.POSTGRES_Username),
|
||||
password: String(process.env.POSTGRES_Password),
|
||||
databaseType: "postgres",
|
||||
schemaName: "public,sch1,sch2",
|
||||
ssl: yn(process.env.POSTGRES_SSL, { default: false }),
|
||||
skipTables: ["spatial_ref_sys"],
|
||||
onlyTables: []
|
||||
};
|
||||
const connectionOptions = getTomgConnectionOptions("postgres");
|
||||
await driver.ConnectToServer(connectionOptions);
|
||||
connectionOptions.databaseName = String(process.env.POSTGRES_Database);
|
||||
connectionOptions.databaseNames = [String(process.env.POSTGRES_Database)];
|
||||
|
||||
if (await driver.CheckIfDBExists(String(process.env.POSTGRES_Database))) {
|
||||
await driver.DropDB(String(process.env.POSTGRES_Database));
|
||||
@ -127,18 +106,7 @@ export async function createPostgresModels(
|
||||
export async function createSQLiteModels(
|
||||
filesOrgPath: string
|
||||
): Promise<IConnectionOptions> {
|
||||
const connectionOptions: IConnectionOptions = {
|
||||
host: "",
|
||||
port: 0,
|
||||
databaseName: String(process.env.SQLITE_Database),
|
||||
user: "",
|
||||
password: "",
|
||||
databaseType: "sqlite",
|
||||
schemaName: "",
|
||||
ssl: false,
|
||||
skipTables: [],
|
||||
onlyTables: []
|
||||
};
|
||||
const connectionOptions = getTomgConnectionOptions("sqlite");
|
||||
|
||||
const connOpt: ConnectionOptions = {
|
||||
database: String(process.env.SQLITE_Database),
|
||||
@ -163,18 +131,7 @@ export async function createMysqlModels(
|
||||
filesOrgPath: string
|
||||
): Promise<IConnectionOptions> {
|
||||
const driver = new MysqlDriver();
|
||||
const connectionOptions: IConnectionOptions = {
|
||||
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, { default: false }),
|
||||
skipTables: [],
|
||||
onlyTables: []
|
||||
};
|
||||
const connectionOptions = getTomgConnectionOptions("mysql");
|
||||
await driver.ConnectToServer(connectionOptions);
|
||||
|
||||
if (await driver.CheckIfDBExists(String(process.env.MYSQL_Database))) {
|
||||
@ -207,18 +164,7 @@ export async function createMariaDBModels(
|
||||
filesOrgPath: string
|
||||
): Promise<IConnectionOptions> {
|
||||
const driver = new MariaDbDriver();
|
||||
const connectionOptions: IConnectionOptions = {
|
||||
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, { default: false }),
|
||||
skipTables: [],
|
||||
onlyTables: []
|
||||
};
|
||||
const connectionOptions = getTomgConnectionOptions("mariadb");
|
||||
await driver.ConnectToServer(connectionOptions);
|
||||
|
||||
if (await driver.CheckIfDBExists(String(process.env.MARIADB_Database))) {
|
||||
@ -253,18 +199,8 @@ export async function createOracleDBModels(
|
||||
): Promise<IConnectionOptions> {
|
||||
const driver = new OracleDriver();
|
||||
|
||||
const connectionOptions: IConnectionOptions = {
|
||||
host: String(process.env.ORACLE_Host),
|
||||
port: Number(process.env.ORACLE_Port),
|
||||
databaseName: String(process.env.ORACLE_Database),
|
||||
user: String(process.env.ORACLE_UsernameSys),
|
||||
password: String(process.env.ORACLE_PasswordSys),
|
||||
databaseType: "oracle",
|
||||
schemaName: String(process.env.ORACLE_Username),
|
||||
ssl: yn(process.env.ORACLE_SSL, { default: false }),
|
||||
skipTables: [],
|
||||
onlyTables: []
|
||||
};
|
||||
const connectionOptions = getTomgConnectionOptions("oracle");
|
||||
|
||||
await driver.ConnectToServer(connectionOptions);
|
||||
connectionOptions.user = String(process.env.ORACLE_Username);
|
||||
connectionOptions.password = String(process.env.ORACLE_Password);
|
||||
@ -317,7 +253,7 @@ export function compileTsFiles(
|
||||
);
|
||||
console.log(
|
||||
`${diagnostic.file!.fileName} (${lineAndCharacter.line +
|
||||
1},${lineAndCharacter.character + 1}): ${message}`
|
||||
1},${lineAndCharacter.character + 1}): ${message}`
|
||||
);
|
||||
compiledWithoutErrors = false;
|
||||
});
|
||||
@ -325,8 +261,8 @@ export function compileTsFiles(
|
||||
return compiledWithoutErrors;
|
||||
}
|
||||
|
||||
export function getEnabledDbDrivers(): string[] {
|
||||
const dbDrivers: string[] = [];
|
||||
export function getEnabledDbDrivers(): IConnectionOptions["databaseType"][] {
|
||||
const dbDrivers: IConnectionOptions["databaseType"][] = [];
|
||||
if (process.env.SQLITE_Skip === "0") {
|
||||
dbDrivers.push("sqlite");
|
||||
}
|
||||
@ -370,3 +306,89 @@ export function createModelsInDb(
|
||||
throw new Error("Unknown engine type");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function getTomgConnectionOptions(dbType: IConnectionOptions["databaseType"]): IConnectionOptions {
|
||||
switch (dbType) {
|
||||
case "mssql":
|
||||
return {
|
||||
host: String(process.env.MSSQL_Host),
|
||||
port: Number(process.env.MSSQL_Port),
|
||||
databaseNames: ["master"],
|
||||
user: String(process.env.MSSQL_Username),
|
||||
password: String(process.env.MSSQL_Password),
|
||||
databaseType: "mssql",
|
||||
schemaNames: ["dbo","sch1","sch2"],
|
||||
ssl: yn(process.env.MSSQL_SSL, { default: false }),
|
||||
skipTables: [],
|
||||
onlyTables: []
|
||||
};
|
||||
case "mariadb":
|
||||
return {
|
||||
host: String(process.env.MARIADB_Host),
|
||||
port: Number(process.env.MARIADB_Port),
|
||||
databaseNames: [String(process.env.MARIADB_Database)],
|
||||
user: String(process.env.MARIADB_Username),
|
||||
password: String(process.env.MARIADB_Password),
|
||||
databaseType: "mariadb",
|
||||
schemaNames: ["ignored"],
|
||||
ssl: yn(process.env.MARIADB_SSL, { default: false }),
|
||||
skipTables: [],
|
||||
onlyTables: []
|
||||
};
|
||||
case "mysql":
|
||||
return {
|
||||
host: String(process.env.MYSQL_Host),
|
||||
port: Number(process.env.MYSQL_Port),
|
||||
databaseNames: [String(process.env.MYSQL_Database)],
|
||||
user: String(process.env.MYSQL_Username),
|
||||
password: String(process.env.MYSQL_Password),
|
||||
databaseType: "mysql",
|
||||
schemaNames: ["ignored"],
|
||||
ssl: yn(process.env.MYSQL_SSL, { default: false }),
|
||||
skipTables: [],
|
||||
onlyTables: []
|
||||
};
|
||||
case "oracle":
|
||||
return {
|
||||
host: String(process.env.ORACLE_Host),
|
||||
port: Number(process.env.ORACLE_Port),
|
||||
databaseNames: [String(process.env.ORACLE_Database)],
|
||||
user: String(process.env.ORACLE_UsernameSys),
|
||||
password: String(process.env.ORACLE_PasswordSys),
|
||||
databaseType: "oracle",
|
||||
schemaNames: [String(process.env.ORACLE_Username)],
|
||||
ssl: yn(process.env.ORACLE_SSL, { default: false }),
|
||||
skipTables: [],
|
||||
onlyTables: []
|
||||
};
|
||||
case "postgres":
|
||||
return {
|
||||
host: String(process.env.POSTGRES_Host),
|
||||
port: Number(process.env.POSTGRES_Port),
|
||||
databaseNames: ["postgres"],
|
||||
user: String(process.env.POSTGRES_Username),
|
||||
password: String(process.env.POSTGRES_Password),
|
||||
databaseType: "postgres",
|
||||
schemaNames: ["public","sch1","sch2"],
|
||||
ssl: yn(process.env.POSTGRES_SSL, { default: false }),
|
||||
skipTables: ["spatial_ref_sys"],
|
||||
onlyTables: []
|
||||
};
|
||||
case "sqlite": return {
|
||||
host: "",
|
||||
port: 0,
|
||||
databaseNames: [String(process.env.SQLITE_Database)],
|
||||
user: "",
|
||||
password: "",
|
||||
databaseType: "sqlite",
|
||||
schemaNames: [""],
|
||||
ssl: false,
|
||||
skipTables: [],
|
||||
onlyTables: []
|
||||
};
|
||||
default:
|
||||
return assertUnreachable(dbType);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user