allow database names with special characters(#273)

This commit is contained in:
kononnable 2020-12-27 00:31:27 +01:00
parent c011ed3957
commit cfa6799226
14 changed files with 500 additions and 368 deletions

View File

@ -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": {

View File

@ -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: [],

View File

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

View File

@ -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("','")}'`;
}
}

View File

@ -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> {

View File

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

View File

@ -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,

View File

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

View File

@ -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

View File

@ -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",

View 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;
}

View 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;
}

View File

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

View File

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