Merge branch 'next'

This commit is contained in:
Kononnable 2018-01-16 23:16:32 +01:00
commit f1eb918526
57 changed files with 1502 additions and 1671 deletions

8
.editorconfig Normal file
View File

@ -0,0 +1,8 @@
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

View File

@ -1,30 +1,36 @@
language: node_js
node_js:
- stable
- 8
- 6
- stable
- 8
- 6
sudo: required
services:
- docker
- docker
env:
matrix:
- POSTGRES_Skip=0 POSTGRES_Host=localhost POSTGRES_Port=5432 POSTGRES_Username=postgres
POSTGRES_Password=!Passw0rd POSTGRES_Database=typeorm_mg POSTGRES_SSL=0 MYSQL_Skip=0
MYSQL_Host=localhost MYSQL_Port=3306 MYSQL_Username=root MYSQL_Password=!Passw0rd
MYSQL_Database=typeorm_mg MYSQL_SSL=1 MARIADB_Skip=0 MARIADB_Host=localhost MARIADB_Port=3307
MARIADB_Username=root MARIADB_Password=!Passw0rd MARIADB_Database=typeorm_mg MARIADB_SSL=0
global:
secure: Xj6wO8aghAhi6nvBI/HTtW9mIq9xfigIQfCC7ZkgAcqS4Oe3ba+7A5pCJq6Fxndadc6Bg1bZ3BGCH3Upf/Yv3zCFybsk43LwwXPJoG9gCrva/me7Sd+ws30EcD2dsKbvjZqNYai/XdrhzJY+KlxWvS/g3N/puBNffcU5hteo1zllxakQIAiavJ64D4g+Th8LSytmb2qDDToSsCxXkzNSutaKgZSf6T8QCWzcl0NCZkl69s9kX7L5335HVBD9lR/EKFC4wqHQjryCDRAyNRvItZRNlTPqgOI8lvcTsH9zKozDwEz7h/zcLebbY/+YTsLB5pb2sa62tkQE0x24TG7bLxujQShEQZU8itkRSV+w6+0JpBHQPlSUppkQJBNGKao7GaO/Eix4mSyvHkeECmTWDtEpBGWERYLqCKGe2Nj3BfcA2Ue6pjz9CX8wnrCbx53j6be3M/g/gcx7fbJbX3P95yc1CWAaR+tJKlP38rTcyo+o+Db1Ft0pzRJyZGmkGGPnCj6LxWYSmVqumLYDyqAMBDcQYuVwaKaTsJtU/2OBb3+zjKmWivV+19SXBqILvFbLv9IYLavpMr9OAwDGcJu0+mF+VCjGkZTlBxWJ53PmCoIJ6Qx/5o67LsCYL4L/hugNETlOEEKwe/k1mBraYWB0jI3mBUCV0d8J5P+ZQhwIZo4=
matrix:
- >-
POSTGRES_Skip=0 POSTGRES_Host=localhost POSTGRES_Port=5432
POSTGRES_Username=postgres POSTGRES_Password=!Passw0rd
POSTGRES_Database=typeorm_mg POSTGRES_SSL=0 MYSQL_Skip=0
MYSQL_Host=localhost MYSQL_Port=3306 MYSQL_Username=root
MYSQL_Password=!Passw0rd MYSQL_Database=typeorm_mg MYSQL_SSL=1
MARIADB_Skip=0 MARIADB_Host=localhost MARIADB_Port=3307
MARIADB_Username=root MARIADB_Password=!Passw0rd
MARIADB_Database=typeorm_mg MARIADB_SSL=0
global:
secure: >-
Xj6wO8aghAhi6nvBI/HTtW9mIq9xfigIQfCC7ZkgAcqS4Oe3ba+7A5pCJq6Fxndadc6Bg1bZ3BGCH3Upf/Yv3zCFybsk43LwwXPJoG9gCrva/me7Sd+ws30EcD2dsKbvjZqNYai/XdrhzJY+KlxWvS/g3N/puBNffcU5hteo1zllxakQIAiavJ64D4g+Th8LSytmb2qDDToSsCxXkzNSutaKgZSf6T8QCWzcl0NCZkl69s9kX7L5335HVBD9lR/EKFC4wqHQjryCDRAyNRvItZRNlTPqgOI8lvcTsH9zKozDwEz7h/zcLebbY/+YTsLB5pb2sa62tkQE0x24TG7bLxujQShEQZU8itkRSV+w6+0JpBHQPlSUppkQJBNGKao7GaO/Eix4mSyvHkeECmTWDtEpBGWERYLqCKGe2Nj3BfcA2Ue6pjz9CX8wnrCbx53j6be3M/g/gcx7fbJbX3P95yc1CWAaR+tJKlP38rTcyo+o+Db1Ft0pzRJyZGmkGGPnCj6LxWYSmVqumLYDyqAMBDcQYuVwaKaTsJtU/2OBb3+zjKmWivV+19SXBqILvFbLv9IYLavpMr9OAwDGcJu0+mF+VCjGkZTlBxWJ53PmCoIJ6Qx/5o67LsCYL4L/hugNETlOEEKwe/k1mBraYWB0jI3mBUCV0d8J5P+ZQhwIZo4=
before_install:
- sudo service mysql stop
- sudo service postgresql stop
- docker-compose up -d
- npm install -g npm@5
- npm install -g greenkeeper-lockfile@1
- sudo service mysql stop
- sudo service postgresql stop
- docker login -u "$DOCKER_USERNAME" -p "$DOCKER_PASSWORD"
- docker-compose up -d
- npm install -g npm@5
- npm install -g greenkeeper-lockfile@1
before_script:
- greenkeeper-lockfile-update
- npm run typings-install
- npm link typescript
- tsc
- greenkeeper-lockfile-update
- npm run typings-install
- npm link typescript
- tsc
after_script:
- greenkeeper-lockfile-upload
- greenkeeper-lockfile-upload

View File

@ -5,7 +5,7 @@
[![npm version](https://badge.fury.io/js/typeorm-model-generator.svg)](https://badge.fury.io/js/typeorm-model-generator)
[![codecov](https://codecov.io/gh/Kononnable/typeorm-model-generator/branch/master/graph/badge.svg)](https://codecov.io/gh/Kononnable/typeorm-model-generator)
Generates models for TypeORM from existing databases.
Generates models for TypeORM from existing databases.
Suported db engines:
* Microsoft SQL Server
* PostgreSQL
@ -19,7 +19,7 @@ Suported db engines:
To install module globally simply type `npm i -g typeorm-model-generator` in your console.
### Npx way
Thanks to npx you can use npm modules without polluting global installs. So nothing to do here :)
>To use `npx` you need to use npm at version at least 5.2.0. Try updating your npm by `npm i -g npm`
>To use `npx` you need to use npm at version at least 5.2.0. Try updating your npm by `npm i -g npm`
## Usage
```shell
@ -37,24 +37,26 @@ Options:
-o, --output Where to place generated models.
-s, --schema Schema name to create model from. Only for mssql and postgres.
--ssl [boolean] [default: false]
--noConfig Doesn't create tsconfig.json and ormconfig.json
[boolean] [default: false]
```
### Examples
* Creating model from local MSSQL database
* Global module
* Global module
```
typeorm-model-generator -h localhost -d tempdb -u sa -x !Passw0rd -e mssql -o .\
````
* Npx Way
* Npx Way
```
npx typeorm-model-generator -h localhost -d tempdb -u sa -x !Passw0rd -e mssql -o .\
````
* Creating model from local Postgres database, public schema with ssl connection
* Global module
* Global module
```
typeorm-model-generator -h localhost -d postgres -u postgres -x !Passw0rd -e postgres -o .\ -s public --ssl
````
* Npx Way
* Npx Way
```
npx typeorm-model-generator -h localhost -d postgres -u postgres -x !Passw0rd -e postgres -o .\ -s public --ssl
````
````

View File

@ -1,3 +1,14 @@
parsers:
javascript:
enable_partials: yes
javascript:
enable_partials: yes
comment:
layout: diff
behavior: default
codecov:
notify:
require_ci_to_pass: no
coverage:
status:
project:
default:
threshold: 5%

View File

@ -28,7 +28,7 @@ services:
environment:
POSTGRES_PASSWORD: "!Passw0rd"
# # mssql
# mssql
# mssql:
# image: "microsoft/mssql-server-linux:2017-GA"
# container_name: "typeorm-mg-mssql"
@ -37,4 +37,13 @@ services:
# environment:
# ACCEPT_EULA: "Y"
# SA_PASSWORD: "!Passw0rd"
# oracle
# oracle:
# image: "store/oracle/database-enterprise:12.2.0.1-slim"
# container_name: "typeorm-mg-oracle"
# ports:
# - "1521:1521"
# environment:
# DB_SID: "ORCLCDB"
# SYS_PASSWORD: "Oradoc_db1"

2049
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -27,9 +27,10 @@
"handlebars": "^4.0.11",
"mssql": "^4.0.4",
"mysql": "^2.15.0",
"oracledb": "^2.0.15",
"pg": "^7.4.0",
"reflect-metadata": "^0.1.10",
"typeorm": "^0.1.3",
"typeorm": "^0.2.0-alpha.13",
"typescript": "^2.6.1",
"yargs": "^10.0.3",
"yn": "^2.0.0"
@ -43,6 +44,7 @@
"@types/mocha": "^2.2.44",
"@types/mssql": "^4.0.4",
"@types/mysql": "2.15.2",
"@types/oracledb": "^1.11.34",
"@types/node": "^9.3.0",
"@types/pg": "^7.4.1",
"@types/sinon": "^4.1.2",
@ -54,7 +56,7 @@
"fs-extra": "^5.0.0",
"istanbul": "^0.4.5",
"mocha": "^4.0.1",
"remap-istanbul": "^0.9.5",
"remap-istanbul": "^0.10.0",
"sinon": "^4.1.2",
"sinon-chai": "^2.14.0",
"typings": "^2.1.1"

View File

@ -3,6 +3,7 @@ import { DatabaseModel } from './models/DatabaseModel'
import * as Handlebars from 'handlebars'
import fs = require('fs');
import path = require('path')
import * as TomgUtils from './Utils'
/**
* Engine
*/
@ -15,12 +16,12 @@ export class Engine {
if (dbModel.entities.length > 0) {
this.createModelFromMetadata(dbModel);
} else {
console.error('Tables not found in selected database. Skipping creation of typeorm model.');
TomgUtils.LogFatalError('Tables not found in selected database. Skipping creation of typeorm model.', false);
}
return true;
}
private async getEntitiesInfo(database: string, server: string, port: number, user: string, password: string, schemaName:string, ssl:boolean): Promise<DatabaseModel> {
return await this.driver.GetDataFromServer(database, server, port, user, password,schemaName,ssl)
private async getEntitiesInfo(database: string, server: string, port: number, user: string, password: string, schemaName: string, ssl: boolean): Promise<DatabaseModel> {
return await this.driver.GetDataFromServer(database, server, port, user, password, schemaName, ssl)
}
private createModelFromMetadata(databaseModel: DatabaseModel) {
@ -29,21 +30,25 @@ export class Engine {
let resultPath = this.Options.resultsPath
if (!fs.existsSync(resultPath))
fs.mkdirSync(resultPath);
this.createTsConfigFile(resultPath)
this.createTypeOrm(resultPath)
let entitesPath = path.resolve(resultPath, './entities')
let entitesPath = resultPath
if (!this.Options.noConfigs) {
this.createTsConfigFile(resultPath)
this.createTypeOrmConfig(resultPath)
entitesPath = path.resolve(resultPath, './entities')
if (!fs.existsSync(entitesPath))
fs.mkdirSync(entitesPath);
}
Handlebars.registerHelper('toLowerCase', function (str) {
return str.toLowerCase();
});
if (!fs.existsSync(entitesPath))
fs.mkdirSync(entitesPath);
let compliedTemplate = Handlebars.compile(template,{noEscape:true})
let compliedTemplate = Handlebars.compile(template, { noEscape: true })
databaseModel.entities.forEach(element => {
let resultFilePath = path.resolve(entitesPath, element.EntityName + '.ts');
let rendered =compliedTemplate(element)
let rendered = compliedTemplate(element)
fs.writeFileSync(resultFilePath, rendered, { encoding: 'UTF-8', flag: 'w' })
});
}
//TODO:Move to mustache template file
private createTsConfigFile(resultPath) {
fs.writeFileSync(path.resolve(resultPath, 'tsconfig.json'), `{"compilerOptions": {
"lib": ["es5", "es6"],
@ -55,8 +60,9 @@ export class Engine {
"sourceMap": true
}}`, { encoding: 'UTF-8', flag: 'w' });
}
private createTypeOrm(resultPath) {
fs.writeFileSync(path.resolve(resultPath, 'ormconfig.json'), `[
private createTypeOrmConfig(resultPath) {
if (this.Options.schemaName == '') {
fs.writeFileSync(path.resolve(resultPath, 'ormconfig.json'), `[
{
"name": "default",
"driver": {
@ -72,7 +78,28 @@ export class Engine {
]
}
]`, { encoding: 'UTF-8', flag: 'w' });
}
else {
fs.writeFileSync(path.resolve(resultPath, 'ormconfig.json'), `[
{
"name": "default",
"driver": {
"type": "${this.Options.databaseType}",
"host": "${this.Options.host}",
"port": ${this.Options.port},
"username": "${this.Options.user}",
"password": "${this.Options.password}",
"database": "${this.Options.databaseName}",
"schema": "${this.Options.schemaName}"
},
"entities": [
"entities/*.js"
]
}
]`, { encoding: 'UTF-8', flag: 'w' });
}
}
}
export interface EngineOptions {
host: string,
@ -82,6 +109,7 @@ export interface EngineOptions {
password: string,
resultsPath: string,
databaseType: string,
schemaName:string,
ssl:boolean
}
schemaName: string,
ssl: boolean,
noConfigs: boolean
}

12
src/Utils.ts Normal file
View File

@ -0,0 +1,12 @@
import * as data from './../../package.json'
export function LogFatalError(errText: string, isABug: boolean = true, errObject?: any) {
let x = <any>data;
console.error(`Fatal error occured.`)
console.error(`${x.name}@${x.version} node@${process.version}`)
console.error(`Fatal error occured in typeorm-model-generator.`)
console.error(`If this is a bug please open an issue including this log on ${x.bugs.url}`)
if (isABug && !errObject) errObject = new Error().stack
if (!!errObject) console.error(errObject)
process.abort()
}

View File

@ -4,22 +4,22 @@ import { DatabaseModel } from './../models/DatabaseModel'
* AbstractDriver
*/
export abstract class AbstractDriver {
async GetDataFromServer(database: string, server: string, port: number, user: string, password: string, schema:string, ssl:boolean): Promise<DatabaseModel> {
async GetDataFromServer(database: string, server: string, port: number, user: string, password: string, schema: string, ssl: boolean): Promise<DatabaseModel> {
let dbModel = <DatabaseModel>{};
await this.ConnectToServer(database, server, port, user, password,ssl);
await this.ConnectToServer(database, server, port, user, password, ssl);
dbModel.entities = await this.GetAllTables(schema);
await this.GetCoulmnsFromEntity(dbModel.entities,schema);
await this.GetIndexesFromEntity(dbModel.entities,schema);
dbModel.entities = await this.GetRelations(dbModel.entities,schema);
await this.GetCoulmnsFromEntity(dbModel.entities, schema);
await this.GetIndexesFromEntity(dbModel.entities, schema);
dbModel.entities = await this.GetRelations(dbModel.entities, schema);
await this.DisconnectFromServer();
this.FindPrimaryColumnsFromIndexes(dbModel)
return dbModel;
}
abstract async ConnectToServer(database: string, server: string, port: number, user: string, password: string,ssl:boolean);
abstract async GetAllTables(schema:string): Promise<EntityInfo[]>
abstract async GetCoulmnsFromEntity(entities: EntityInfo[],schema:string): Promise<EntityInfo[]>;
abstract async GetIndexesFromEntity(entities: EntityInfo[],schema:string): Promise<EntityInfo[]>;
abstract async GetRelations(entities: EntityInfo[],schema:string): Promise<EntityInfo[]>;
abstract async ConnectToServer(database: string, server: string, port: number, user: string, password: string, ssl: boolean);
abstract async GetAllTables(schema: string): Promise<EntityInfo[]>
abstract async GetCoulmnsFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]>;
abstract async GetIndexesFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]>;
abstract async GetRelations(entities: EntityInfo[], schema: string): Promise<EntityInfo[]>;
abstract async FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel);
abstract async DisconnectFromServer();
@ -27,4 +27,4 @@ export abstract class AbstractDriver {
abstract async DropDB(dbName: string);
abstract async UseDB(dbName: string);
abstract async CheckIfDBExists(dbName: string): Promise<boolean>;
}
}

View File

@ -9,6 +9,6 @@ import { MysqlDriver } from './MysqlDriver';
* MariaDb
*/
export class MariaDbDriver extends MysqlDriver {
readonly EngineName:string = 'MariaDb'
}
readonly EngineName: string = 'MariaDb'
}

View File

@ -4,6 +4,8 @@ import { ColumnInfo } from './../models/ColumnInfo'
import { EntityInfo } from './../models/EntityInfo'
import { RelationInfo } from './../models/RelationInfo'
import { DatabaseModel } from './../models/DatabaseModel'
import * as TomgUtils from './../Utils'
/**
* MssqlDriver
*/
@ -12,7 +14,7 @@ export class MssqlDriver extends AbstractDriver {
dbModel.entities.forEach(entity => {
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
if (!primaryIndex) {
console.error(`Table ${entity.EntityName} has no PK.`)
TomgUtils.LogFatalError(`Table ${entity.EntityName} has no PK.`, false)
return;
}
entity.Columns.forEach(col => {
@ -194,7 +196,7 @@ export class MssqlDriver extends AbstractDriver {
colInfo.sql_type = "text"
break;
default:
console.error("Unknown column type:" + resp.DATA_TYPE);
TomgUtils.LogFatalError("Unknown column type:" + resp.DATA_TYPE);
break;
}
@ -209,7 +211,7 @@ export class MssqlDriver extends AbstractDriver {
TableName: string, IndexName: string, ColumnName: string, is_unique: number,
is_primary_key: number//, is_descending_key: number//, is_included_column: number
}[]
= (await request.query(`SELECT
= (await request.query(`SELECT
TableName = t.name,
IndexName = ind.name,
ColumnName = col.name,
@ -217,19 +219,19 @@ export class MssqlDriver extends AbstractDriver {
ind.is_primary_key
-- ,ic.is_descending_key,
-- ic.is_included_column
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
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
WHERE
t.is_ms_shipped = 0 and s.name='${schema}'
ORDER BY
ORDER BY
t.name, ind.name, ind.index_id, ic.key_ordinal;`)).recordset;
entities.forEach((ent) => {
response.filter((filterVal) => {
@ -268,32 +270,32 @@ ORDER BY
onDelete: "RESTRICT" | "CASCADE" | "SET NULL",
onUpdate: "RESTRICT" | "CASCADE" | "SET NULL", object_id: number
}[]
= (await request.query(`select
parentTable.name as TableWithForeignKey,
= (await request.query(`select
parentTable.name as TableWithForeignKey,
fkc.constraint_column_id as FK_PartNo,
parentColumn.name as ForeignKeyColumn,
referencedTable.name as TableReferenced,
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
from
sys.foreign_keys fk
inner join
from
sys.foreign_keys fk
inner join
sys.foreign_key_columns as fkc on fkc.constraint_object_id=fk.object_id
inner join
inner join
sys.tables as parentTable on fkc.parent_object_id = parentTable.object_id
inner join
inner join
sys.columns as parentColumn on fkc.parent_object_id = parentColumn.object_id and fkc.parent_column_id = parentColumn.column_id
inner join
inner join
sys.tables as referencedTable on fkc.referenced_object_id = referencedTable.object_id
inner join
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
where
fk.is_disabled=0 and fk.is_ms_shipped=0 and parentSchema.name='${schema}'
order by
order by
TableWithForeignKey, FK_PartNo`)).recordset;
let relationsTemp: RelationTempInfo[] = <RelationTempInfo[]>[];
response.forEach((resp) => {
@ -319,28 +321,28 @@ order by
return entitity.EntityName == relationTmp.ownerTable;
})
if (!ownerEntity) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.ownerTable}.`)
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.ownerTable}.`)
return;
}
let referencedEntity = entities.find((entitity) => {
return entitity.EntityName == relationTmp.referencedTable;
})
if (!referencedEntity) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.referencedTable}.`)
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.referencedTable}.`)
return;
}
let ownerColumn = ownerEntity.Columns.find((column) => {
return column.name == relationTmp.ownerColumnsNames[0];
})
if (!ownerColumn) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.ownerTable}.${ownerColumn}.`)
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.ownerTable}.${ownerColumn}.`)
return;
}
let relatedColumn = referencedEntity.Columns.find((column) => {
return column.name == relationTmp.referencedColumnsNames[0];
})
if (!relatedColumn) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.referencedTable}.${relatedColumn}.`)
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.referencedTable}.${relatedColumn}.`)
return;
}
let ownColumn: ColumnInfo = ownerColumn;
@ -359,15 +361,15 @@ order by
isOneToMany = false;
}
let ownerRelation = new RelationInfo()
let columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
let columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
if (referencedEntity.Columns.filter((filterVal) => {
return filterVal.name == columnName;
}).length>0){
for (let i=2;i<=ownerEntity.Columns.length;i++){
columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')+i.toString();
}).length > 0) {
for (let i = 2; i <= ownerEntity.Columns.length; i++) {
columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '') + i.toString();
if (referencedEntity.Columns.filter((filterVal) => {
return filterVal.name == columnName;
}).length==0) break;
}).length == 0) break;
}
}
ownerRelation.actionOnDelete = relationTmp.actionOnDelete
@ -440,9 +442,7 @@ order by
resolve(true)
}
else {
console.error('Error connecting to MSSQL Server.')
console.error(err.message)
process.abort()
TomgUtils.LogFatalError('Error connecting to MSSQL Server.', false, err.message)
reject(err)
}
});
@ -468,4 +468,4 @@ order by
let resp = await request.query(`SELECT name FROM master.sys.databases WHERE name = N'${dbName}' `)
return resp.recordset.length > 0;
}
}
}

View File

@ -4,6 +4,7 @@ import { ColumnInfo } from './../models/ColumnInfo'
import { EntityInfo } from './../models/EntityInfo'
import { RelationInfo } from './../models/RelationInfo'
import { DatabaseModel } from './../models/DatabaseModel'
import * as TomgUtils from './../Utils'
/**
* MysqlDriver
*/
@ -14,7 +15,7 @@ export class MysqlDriver extends AbstractDriver {
dbModel.entities.forEach(entity => {
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
if (!primaryIndex) {
console.error(`Table ${entity.EntityName} has no PK.`)
TomgUtils.LogFatalError(`Table ${entity.EntityName} has no PK.`, false)
return;
}
entity.Columns.forEach(col => {
@ -196,7 +197,7 @@ export class MysqlDriver extends AbstractDriver {
colInfo.sql_type = "json"
break;
default:
console.error("Unknown column type:" + resp.DATA_TYPE);
TomgUtils.LogFatalError("Unknown column type:" + resp.DATA_TYPE);
break;
}
if (colInfo.sql_type) ent.Columns.push(colInfo);
@ -208,7 +209,7 @@ export class MysqlDriver extends AbstractDriver {
let response = await this.ExecQuery<{
TableName: string, IndexName: string, ColumnName: string, is_unique: number,
is_primary_key: number//, is_descending_key: number//, is_included_column: number
}>(`SELECT TABLE_NAME TableName,INDEX_NAME IndexName,COLUMN_NAME ColumnName,CASE WHEN NON_UNIQUE=0 THEN 1 ELSE 0 END is_unique,
}>(`SELECT TABLE_NAME TableName,INDEX_NAME IndexName,COLUMN_NAME ColumnName,CASE WHEN NON_UNIQUE=0 THEN 1 ELSE 0 END is_unique,
CASE WHEN INDEX_NAME='PRIMARY' THEN 1 ELSE 0 END is_primary_key
FROM information_schema.statistics sta
WHERE table_schema like DATABASE();
@ -248,22 +249,22 @@ export class MysqlDriver extends AbstractDriver {
TableReferenced: string, ForeignKeyColumnReferenced: string,
onDelete: "RESTRICT" | "CASCADE" | "SET NULL",
onUpdate: "RESTRICT" | "CASCADE" | "SET NULL", object_id: string
}>(`SELECT
CU.TABLE_NAME TableWithForeignKey,
}>(`SELECT
CU.TABLE_NAME TableWithForeignKey,
CU.ORDINAL_POSITION FK_PartNo,
CU.COLUMN_NAME ForeignKeyColumn,
CU.REFERENCED_TABLE_NAME TableReferenced,
CU.COLUMN_NAME ForeignKeyColumn,
CU.REFERENCED_TABLE_NAME TableReferenced,
CU.REFERENCED_COLUMN_NAME ForeignKeyColumnReferenced,
RC.DELETE_RULE onDelete,
RC.UPDATE_RULE onUpdate,
CU.CONSTRAINT_NAME object_id
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
JOIN
JOIN
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC ON CU.CONSTRAINT_NAME=RC.CONSTRAINT_NAME
WHERE
TABLE_SCHEMA = SCHEMA()
AND CU.REFERENCED_TABLE_NAME IS NOT NULL;
TABLE_SCHEMA = SCHEMA()
AND CU.REFERENCED_TABLE_NAME IS NOT NULL;
`);
let relationsTemp: RelationTempInfo[] = <RelationTempInfo[]>[];
response.forEach((resp) => {
@ -289,28 +290,28 @@ export class MysqlDriver extends AbstractDriver {
return entitity.EntityName == relationTmp.ownerTable;
})
if (!ownerEntity) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.ownerTable}.`)
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.ownerTable}.`)
return;
}
let referencedEntity = entities.find((entitity) => {
return entitity.EntityName == relationTmp.referencedTable;
})
if (!referencedEntity) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.referencedTable}.`)
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.referencedTable}.`)
return;
}
let ownerColumn = ownerEntity.Columns.find((column) => {
return column.name == relationTmp.ownerColumnsNames[0];
})
if (!ownerColumn) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.ownerTable}.${ownerColumn}.`)
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.ownerTable}.${ownerColumn}.`)
return;
}
let relatedColumn = referencedEntity.Columns.find((column) => {
return column.name == relationTmp.referencedColumnsNames[0];
})
if (!relatedColumn) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.referencedTable}.${relatedColumn}.`)
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.referencedTable}.${relatedColumn}.`)
return;
}
let ownColumn: ColumnInfo = ownerColumn;
@ -333,7 +334,7 @@ export class MysqlDriver extends AbstractDriver {
if (referencedEntity.Columns.filter((filterVal) => {
return filterVal.name == columnName;
}).length > 0) {
for (let i=2;i<=ownerEntity.Columns.length;i++){
for (let i = 2; i <= ownerEntity.Columns.length; i++) {
columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '') + i.toString();
if (referencedEntity.Columns.filter((filterVal) => {
return filterVal.name == columnName;
@ -391,9 +392,7 @@ export class MysqlDriver extends AbstractDriver {
resolve(true)
}
else {
console.error(`Error disconnecting to ${this.EngineName} Server.`)
console.error(err.message)
process.abort()
TomgUtils.LogFatalError(`Error disconnecting to ${this.EngineName} Server.`, false, err.message)
reject(err)
}
});
@ -440,9 +439,7 @@ export class MysqlDriver extends AbstractDriver {
resolve(true)
}
else {
console.error(`Error connecting to ${this.EngineName} Server.`)
console.error(err.message)
process.abort()
TomgUtils.LogFatalError(`Error connecting to ${this.EngineName} Server.`, false, err.message)
reject(err)
}
});
@ -480,4 +477,4 @@ export class MysqlDriver extends AbstractDriver {
await promise;
return ret;
}
}
}

306
src/drivers/OracleDriver.ts Normal file
View File

@ -0,0 +1,306 @@
import { AbstractDriver } from './AbstractDriver'
import { ColumnInfo } from './../models/ColumnInfo'
import { EntityInfo } from './../models/EntityInfo'
import { RelationInfo } from './../models/RelationInfo'
import { DatabaseModel } from './../models/DatabaseModel'
import { promisify } from 'util'
import { request } from 'https';
import * as TomgUtils from './../Utils'
/**
* OracleDriver
*/
export class OracleDriver extends AbstractDriver {
Oracle: any;
constructor() {
super();
try {
this.Oracle = require('oracledb')
} catch (error) {
TomgUtils.LogFatalError('', false, error);
throw error;
}
}
FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel) {
dbModel.entities.forEach(entity => {
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
if (!primaryIndex) {
TomgUtils.LogFatalError(`Table ${entity.EntityName} has no PK.`, false)
return;
}
entity.Columns.forEach(col => {
if (primaryIndex!.columns.some(cIndex => cIndex.name == col.name)) col.isPrimary = true
})
});
}
async GetAllTables(schema: string): Promise<EntityInfo[]> {
let response: any[][] = (await this.Connection.execute(` SELECT TABLE_NAME FROM all_tables WHERE owner = (select user from dual)`)).rows!;
let ret: EntityInfo[] = <EntityInfo[]>[];
response.forEach((val) => {
let ent: EntityInfo = new EntityInfo();
ent.EntityName = val[0];
ent.Columns = <ColumnInfo[]>[];
ent.Indexes = <IndexInfo[]>[];
ret.push(ent);
})
return ret;
}
async GetCoulmnsFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
let response: any[][] = (await this.Connection.execute(`SELECT TABLE_NAME, COLUMN_NAME, DATA_DEFAULT, NULLABLE, DATA_TYPE, DATA_LENGTH,
DATA_PRECISION, DATA_SCALE, IDENTITY_COLUMN
FROM USER_TAB_COLUMNS`)).rows!;
entities.forEach((ent) => {
response.filter((filterVal) => {
return filterVal[0] == ent.EntityName;
}).forEach((resp) => {
let colInfo: ColumnInfo = new ColumnInfo();
colInfo.name = resp[1];
colInfo.is_nullable = resp[3] == 'Y' ? true : false;
colInfo.is_generated = resp[8] == 'YES' ? true : false;
colInfo.default = resp[2];
switch (resp[4].toLowerCase()) {
case "number":
colInfo.ts_type = "number"
colInfo.sql_type = "int"
colInfo.char_max_lenght = resp[5] > 0 ? resp[5] : null;
break;
case "varchar2":
colInfo.ts_type = "number"
colInfo.sql_type = "smallint"
colInfo.char_max_lenght = resp[5] > 0 ? resp[5] : null;
break;
default:
TomgUtils.LogFatalError("Unknown column type:" + resp[4]);
break;
}
if (colInfo.sql_type) ent.Columns.push(colInfo);
})
})
return entities;
}
async GetIndexesFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
let response: any[][] = (await this.Connection.execute(`SELECT ind.TABLE_NAME, ind.INDEX_NAME, col.COLUMN_NAME,ind.UNIQUENESS, CASE WHEN uc.CONSTRAINT_NAME IS NULL THEN 0 ELSE 1 END
FROM USER_INDEXES ind
JOIN USER_IND_COLUMNS col ON ind.INDEX_NAME=col.INDEX_NAME
LEFT JOIN USER_CONSTRAINTS uc ON uc.INDEX_NAME = ind.INDEX_NAME
ORDER BY col.INDEX_NAME ASC ,col.COLUMN_POSITION ASC`)).rows!;
entities.forEach((ent) => {
response.filter((filterVal) => {
return filterVal[0] == ent.EntityName;
}).forEach((resp) => {
let indexInfo: IndexInfo = <IndexInfo>{};
let indexColumnInfo: IndexColumnInfo = <IndexColumnInfo>{};
if (ent.Indexes.filter((filterVal) => {
return filterVal.name == resp[1]
}).length > 0) {
indexInfo = ent.Indexes.filter((filterVal) => {
return filterVal.name == resp[1]
})[0];
} else {
indexInfo.columns = <IndexColumnInfo[]>[];
indexInfo.name = resp[1];
indexInfo.isUnique = resp[3] == 'UNIQUE' ? true : false;
indexInfo.isPrimaryKey = resp[4] == 1 ? true : false;
ent.Indexes.push(indexInfo);
}
indexColumnInfo.name = resp[2];
// indexColumnInfo.isIncludedColumn = resp.is_included_column == 1 ? true : false;
// indexColumnInfo.isDescending = resp.is_descending_key == 1 ? true : false;
indexInfo.columns.push(indexColumnInfo);
})
})
return entities;
}
async GetRelations(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
let response: any[][] = (await this.Connection.execute(`select owner.TABLE_NAME ownTbl,ownCol.POSITION,ownCol.COLUMN_NAME,
child.TABLE_NAME,childCol.COLUMN_NAME,
owner.DELETE_RULE,
4,owner.CONSTRAINT_NAME
from user_constraints owner
join user_constraints child on owner.r_constraint_name=child.CONSTRAINT_NAME and child.constraint_type in ('P','U')
JOIN USER_CONS_COLUMNS ownCol ON owner.CONSTRAINT_NAME = ownCol.CONSTRAINT_NAME
JOIN USER_CONS_COLUMNS childCol ON child.CONSTRAINT_NAME = childCol.CONSTRAINT_NAME AND ownCol.POSITION=childCol.POSITION
ORDER BY ownTbl ASC, owner.CONSTRAINT_NAME ASC, ownCol.POSITION ASC`)).rows!;
let relationsTemp: RelationTempInfo[] = <RelationTempInfo[]>[];
response.forEach((resp) => {
let rels = relationsTemp.find((val) => {
return val.object_id == resp[6];
})
if (rels == undefined) {
rels = <RelationTempInfo>{};
rels.ownerColumnsNames = [];
rels.referencedColumnsNames = [];
rels.actionOnDelete = resp[5];
rels.actionOnUpdate = "NO ACTION";
rels.object_id = resp[6];
rels.ownerTable = resp[0];
rels.referencedTable = resp[3];
relationsTemp.push(rels);
}
rels.ownerColumnsNames.push(resp[2]);
rels.referencedColumnsNames.push(resp[4]);
})
relationsTemp.forEach((relationTmp) => {
let ownerEntity = entities.find((entitity) => {
return entitity.EntityName == relationTmp.ownerTable;
})
if (!ownerEntity) {
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.ownerTable}.`)
return;
}
let referencedEntity = entities.find((entitity) => {
return entitity.EntityName == relationTmp.referencedTable;
})
if (!referencedEntity) {
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.referencedTable}.`)
return;
}
let ownerColumn = ownerEntity.Columns.find((column) => {
return column.name == relationTmp.ownerColumnsNames[0];
})
if (!ownerColumn) {
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.ownerTable}.${ownerColumn}.`)
return;
}
let relatedColumn = referencedEntity.Columns.find((column) => {
return column.name == relationTmp.referencedColumnsNames[0];
})
if (!relatedColumn) {
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.referencedTable}.${relatedColumn}.`)
return;
}
let ownColumn: ColumnInfo = ownerColumn;
let isOneToMany: boolean;
isOneToMany = false;
let index = ownerEntity.Indexes.find(
(index) => {
return index.isUnique && index.columns.some(col => {
return col.name == ownerColumn!.name
})
}
)
if (!index) {
isOneToMany = true;
} else {
isOneToMany = false;
}
let ownerRelation = new RelationInfo()
let columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
if (referencedEntity.Columns.filter((filterVal) => {
return filterVal.name == columnName;
}).length > 0) {
for (let i = 2; i <= ownerEntity.Columns.length; i++) {
columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '') + i.toString();
if (referencedEntity.Columns.filter((filterVal) => {
return filterVal.name == columnName;
}).length == 0) break;
}
}
ownerRelation.actionOnDelete = relationTmp.actionOnDelete
ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate
ownerRelation.isOwner = true
ownerRelation.relatedColumn = relatedColumn.name.toLowerCase()
ownerRelation.relatedTable = relationTmp.referencedTable
ownerRelation.ownerTable = relationTmp.ownerTable
ownerRelation.ownerColumn = columnName
ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne"
ownerColumn.relations.push(ownerRelation)
if (isOneToMany) {
let col = new ColumnInfo()
col.name = columnName
let referencedRelation = new RelationInfo();
col.relations.push(referencedRelation)
referencedRelation.actionOnDelete = relationTmp.actionOnDelete
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate
referencedRelation.isOwner = false
referencedRelation.relatedColumn = ownerColumn.name
referencedRelation.relatedTable = relationTmp.ownerTable
referencedRelation.ownerTable = relationTmp.referencedTable
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase()
referencedRelation.relationType = "OneToMany"
referencedEntity.Columns.push(col)
} else {
let col = new ColumnInfo()
col.name = columnName
let referencedRelation = new RelationInfo();
col.relations.push(referencedRelation)
referencedRelation.actionOnDelete = relationTmp.actionOnDelete
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate
referencedRelation.isOwner = false
referencedRelation.relatedColumn = ownerColumn.name
referencedRelation.relatedTable = relationTmp.ownerTable
referencedRelation.ownerTable = relationTmp.referencedTable
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase()
referencedRelation.relationType = "OneToOne"
referencedEntity.Columns.push(col)
}
})
return entities;
}
async DisconnectFromServer() {
if (this.Connection)
await this.Connection.close();
}
private Connection: any/*Oracle.IConnection*/;
async ConnectToServer(database: string, server: string, port: number, user: string, password: string, ssl: boolean) {
let config: any/*Oracle.IConnectionAttributes*/ = {
user: user,
password: password,
// connectString: `${server}:${port}/ORCLCDB.localdomain/${database}`,
connectString: `${server}:${port}/${database}`,
externalAuth: ssl
}
let that = this;
let promise = new Promise<boolean>(
(resolve, reject) => {
this.Oracle.getConnection(
config,
function (err, connection) {
if (!err) {
//Connection successfull
that.Connection = connection
resolve(true)
}
else {
TomgUtils.LogFatalError('Error connecting to Oracle Server.', false, err.message)
reject(err)
}
});
}
)
await promise;
}
async CreateDB(dbName: string) {
}
async UseDB(dbName: string) {
}
async DropDB(dbName: string) {
}
async CheckIfDBExists(dbName: string): Promise<boolean> {
return true;
}
}

View File

@ -4,6 +4,7 @@ import { ColumnInfo } from './../models/ColumnInfo'
import { EntityInfo } from './../models/EntityInfo'
import { RelationInfo } from './../models/RelationInfo'
import { DatabaseModel } from './../models/DatabaseModel'
import * as TomgUtils from './../Utils'
/**
* PostgresDriver
*/
@ -14,7 +15,7 @@ export class PostgresDriver extends AbstractDriver {
dbModel.entities.forEach(entity => {
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
if (!primaryIndex) {
console.error(`Table ${entity.EntityName} has no PK.`)
TomgUtils.LogFatalError(`Table ${entity.EntityName} has no PK.`, false)
return;
}
entity.Columns.forEach(col => {
@ -116,7 +117,7 @@ export class PostgresDriver extends AbstractDriver {
break;
case "timestamp without time zone":
colInfo.ts_type = "Date"
colInfo.sql_type = "datetime"
colInfo.sql_type = "timestamp"
break;
case "timestamp with time zone":
colInfo.ts_type = "Date"
@ -205,7 +206,7 @@ export class PostgresDriver extends AbstractDriver {
break;
default:
console.error("Unknown column type:" + resp.data_type);
TomgUtils.LogFatalError("Unknown column type:" + resp.data_type);
break;
}
@ -348,28 +349,28 @@ export class PostgresDriver extends AbstractDriver {
return entitity.EntityName == relationTmp.ownerTable;
})
if (!ownerEntity) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.ownerTable}.`)
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.ownerTable}.`)
return;
}
let referencedEntity = entities.find((entitity) => {
return entitity.EntityName == relationTmp.referencedTable;
})
if (!referencedEntity) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.referencedTable}.`)
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.referencedTable}.`)
return;
}
let ownerColumn = ownerEntity.Columns.find((column) => {
return column.name == relationTmp.ownerColumnsNames[0];
})
if (!ownerColumn) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.ownerTable}.${ownerColumn}.`)
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.ownerTable}.${ownerColumn}.`)
return;
}
let relatedColumn = referencedEntity.Columns.find((column) => {
return column.name == relationTmp.referencedColumnsNames[0];
})
if (!relatedColumn) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.referencedTable}.${relatedColumn}.`)
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.referencedTable}.${relatedColumn}.`)
return;
}
let ownColumn: ColumnInfo = ownerColumn;
@ -388,15 +389,15 @@ export class PostgresDriver extends AbstractDriver {
isOneToMany = false;
}
let ownerRelation = new RelationInfo()
let columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
let columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
if (referencedEntity.Columns.filter((filterVal) => {
return filterVal.name == columnName;
}).length>0){
for (let i=2;i<=ownerEntity.Columns.length;i++){
columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')+i.toString();
}).length > 0) {
for (let i = 2; i <= ownerEntity.Columns.length; i++) {
columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '') + i.toString();
if (referencedEntity.Columns.filter((filterVal) => {
return filterVal.name == columnName;
}).length==0) break;
}).length == 0) break;
}
}
ownerRelation.actionOnDelete = relationTmp.actionOnDelete
@ -451,9 +452,7 @@ export class PostgresDriver extends AbstractDriver {
resolve(true)
}
else {
console.error('Error connecting to Postgres Server.')
console.error(err.message)
process.abort()
TomgUtils.LogFatalError('Error connecting to Postgres Server.', false, err.message)
reject(err)
}
});
@ -481,9 +480,7 @@ export class PostgresDriver extends AbstractDriver {
resolve(true)
}
else {
console.error('Error connecting to Postgres Server.')
console.error(err.message)
process.abort()
TomgUtils.LogFatalError('Error connecting to Postgres Server.', false, err.message)
reject(err)
}
});
@ -507,4 +504,4 @@ export class PostgresDriver extends AbstractDriver {
let resp = await this.Connection.query(`SELECT datname FROM pg_database WHERE datname ='${dbName}' `)
return resp.rowCount > 0;
}
}
}

View File

@ -15,14 +15,14 @@ import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, Joi
default:"{{.}}",{{/default}}{{#numericPrecision}}
precision:{{.}},{{/numericPrecision}}{{#numericScale}}
scale:{{.}},{{/numericScale}}{{#isPrimary}}
primary:{{isPrimary}},{{/isPrimary}}
primary:{{isPrimary}},{{/isPrimary}}
})
{{name}}:{{ts_type}};
{{/relations}}{{#relations}}
@{{relationType}}(type=>{{relatedTable}}, {{../name}}=>{{../name}}.{{#if isOwner}}{{ownerColumn}}{{else}}{{relatedColumn}}{{/if}}){{#isOwner}}
@JoinColumn(){{/isOwner}}
@JoinColumn({name:'{{../name}}'}){{/isOwner}}
{{#if isOneToMany}}{{../name}}:{{relatedTable}}[];
{{else}}{{../name}}:{{relatedTable}};
{{/if}}{{/relations}}
{{/Columns}}
}
}

View File

@ -3,8 +3,10 @@ import { MssqlDriver } from './drivers/MssqlDriver';
import { PostgresDriver } from "./drivers/PostgresDriver";
import { MysqlDriver } from "./drivers/MysqlDriver";
import { MariaDbDriver } from "./drivers/MariaDbDriver";
import { OracleDriver } from "./drivers/OracleDriver";
import { Engine } from './Engine'
import * as Yargs from 'yargs'
import * as TomgUtils from './Utils'
import path = require('path')
@ -50,9 +52,14 @@ var argv = Yargs
alias: 'schema',
describe: 'Schema name to create model from. Only for mssql and postgres.'
})
.option('ssl',{
boolean:true,
default:false
.option('ssl', {
boolean: true,
default: false
})
.option('noConfig', {
boolean: true,
describe: `Doesn't create tsconfig.json and ormconfig.json`,
default: false
})
.argv;
@ -79,9 +86,12 @@ switch (argv.e) {
driver = new MysqlDriver();
standardPort = 3306;
break;
case 'oracle':
driver = new OracleDriver();
standardPort = 1521;
break;
default:
console.error('Database engine not recognized.')
process.abort();
TomgUtils.LogFatalError('Database engine not recognized.', false)
throw new Error('Database engine not recognized.');
}
@ -95,11 +105,11 @@ let engine = new Engine(
databaseType: argv.e,
resultsPath: argv.o,
schemaName: argv.s || standardSchema,
ssl:argv.ssl
ssl: argv.ssl,
noConfigs: argv.noConfig
});
console.log(`[${new Date().toLocaleTimeString()}] Starting creation of model classes.`);
engine.createModelFromDatabase().then(() => {
console.info(`[${new Date().toLocaleTimeString()}] Typeorm model classes created.`)
})

View File

@ -22,5 +22,3 @@ export class ColumnInfo {
}
}

View File

@ -1,4 +1,4 @@
import {EntityInfo} from './EntityInfo'
import { EntityInfo } from './EntityInfo'
export class DatabaseModel {
entities: EntityInfo[];
config: {
@ -6,11 +6,11 @@ export class DatabaseModel {
cascadeUpdate: boolean,
cascadeRemove: boolean,
}
relationImports():any{
let that=this;
return function(text, render) {
if ('l'!=render(text)) return `import {${render(text)}} from "./${render(text)}"`
else return '';
relationImports(): any {
let that = this;
return function (text, render) {
if ('l' != render(text)) return `import {${render(text)}} from "./${render(text)}"`
else return '';
}
}
}
}
}

View File

@ -8,23 +8,23 @@ export class EntityInfo {
Indexes: IndexInfo[];
relationImports(): any {
var returnString = "";
var imports: string[] = [];
this.Columns.forEach((column) => {
column.relations.forEach(
(relation) => {
if (this.EntityName!=relation.relatedTable)
var returnString = "";
var imports: string[] = [];
this.Columns.forEach((column) => {
column.relations.forEach(
(relation) => {
if (this.EntityName != relation.relatedTable)
imports.push(relation.relatedTable);
}
)
});
imports.filter(function (elem, index, self) {
return index == self.indexOf(elem);
}).forEach((imp)=>{
returnString+=`import {${imp}} from './${imp}'\n`
})
}
)
});
imports.filter(function (elem, index, self) {
return index == self.indexOf(elem);
}).forEach((imp) => {
returnString += `import {${imp}} from './${imp}'\n`
})
return returnString;
return returnString;
}
}
}

View File

@ -1,5 +1,5 @@
interface IndexColumnInfo{
name:string,
interface IndexColumnInfo {
name: string,
//isDescending:boolean,
// isIncludedColumn:boolean
}
}

View File

@ -2,8 +2,8 @@
* IndexInfo
*/
interface IndexInfo {
name:string,
columns:IndexColumnInfo[],
isUnique:boolean,
isPrimaryKey:boolean,
name: string,
columns: IndexColumnInfo[],
isUnique: boolean,
isPrimaryKey: boolean,
}

View File

@ -1,4 +1,5 @@
export class RelationInfo { [x: string]: any;
export class RelationInfo {
[x: string]: any;
isOwner: boolean
relationType: "OneToOne" | "OneToMany" | "ManyToOne"
@ -13,4 +14,4 @@ export class RelationInfo { [x: string]: any;
return this.relationType == "OneToMany"
}
}
}

View File

@ -1,9 +1,9 @@
interface RelationTempInfo{
ownerTable:string,
ownerColumnsNames:string[],
referencedTable:string,
referencedColumnsNames:string[],
actionOnDelete:"RESTRICT"|"CASCADE"|"SET NULL"|"NO ACTION",
actionOnUpdate:"RESTRICT"|"CASCADE"|"SET NULL"|"NO ACTION",
object_id:number|string
}
interface RelationTempInfo {
ownerTable: string,
ownerColumnsNames: string[],
referencedTable: string,
referencedColumnsNames: string[],
actionOnDelete: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION",
actionOnUpdate: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION",
object_id: number | string
}

4
src/typings.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
declare module "*.json" {
const value: any;
export default value;
}

View File

@ -7,19 +7,19 @@ import { ColumnInfo } from './../../src/models/ColumnInfo'
import { RelationInfo } from './../../src/models/RelationInfo'
import { Table, IColumnMetadata } from "mssql";
class fakeResponse implements MSSQL.IResult<any> {
recordsets: MSSQL.IRecordSet<any>[];
recordset: MSSQL.IRecordSet<any>;
rowsAffected: number[];
output: { [key: string]: any; };
}
class fakeRecordset extends Array<any> implements MSSQL.IRecordSet<any>{
class fakeResponse implements MSSQL.IResult<any> {
recordsets: MSSQL.IRecordSet<any>[];
recordset: MSSQL.IRecordSet<any>;
rowsAffected: number[];
output: { [key: string]: any; };
}
class fakeRecordset extends Array<any> implements MSSQL.IRecordSet<any>{
columns: IColumnMetadata;
toTable(): Table{
toTable(): Table {
return new Table();
}
}
}
describe('MssqlDriver', function () {
let driver: MssqlDriver
@ -48,10 +48,10 @@ describe('MssqlDriver', function () {
.returns(
{
query: (q) => {
let response=new fakeResponse();
response.recordset=new fakeRecordset();
let response = new fakeResponse();
response.recordset = new fakeRecordset();
response.recordset.push({ TABLE_SCHEMA: 'schema', TABLE_NAME: 'name' })
return response;
}
@ -71,13 +71,13 @@ describe('MssqlDriver', function () {
.returns(
{
query: (q) => {
let response=new fakeResponse();
response.recordset=new fakeRecordset();
let response = new fakeResponse();
response.recordset = new fakeRecordset();
response.recordset.push({
TABLE_NAME: 'name', CHARACTER_MAXIMUM_LENGTH: 0,
COLUMN_DEFAULT: 'a', COLUMN_NAME: 'name', DATA_TYPE: 'int',
IS_NULLABLE: 'YES', NUMERIC_PRECISION: 0, NUMERIC_SCALE: 0,
IsIdentity:1
IsIdentity: 1
})
return response;
}
@ -97,7 +97,7 @@ describe('MssqlDriver', function () {
default: 'a',
is_nullable: true,
isPrimary: false,
is_generated:true,
is_generated: true,
name: 'name',
numericPrecision: null,
numericScale: null,
@ -105,10 +105,10 @@ describe('MssqlDriver', function () {
ts_type: 'number',
relations: <RelationInfo[]>[]
})
let result = await driver.GetCoulmnsFromEntity(entities,'schema');
let result = await driver.GetCoulmnsFromEntity(entities, 'schema');
expect(result).to.be.deep.equal(expected)
})
it('should find primary indexes')
it('should get indexes info')
it('should get relations info')
})
})

View File

@ -30,9 +30,9 @@ describe("Platform specyfic types", async function () {
let examplesPathTS = path.resolve(process.cwd(), 'test/integration/entityTypes')
let files = fs.readdirSync(examplesPathTS)
for (let folder of files) {
for (let dbDriver of dbDrivers) {
for (let dbDriver of dbDrivers) {
for (let folder of files) {
if (dbDriver == folder) {
it(dbDriver, async function () {

View File

@ -91,4 +91,4 @@ export class Post {
// @Column("simple-array")
// simpleArray: string[];
}
}

View File

@ -118,4 +118,4 @@ export class Post {
// @Column("simple-array")
// simpleArray: string[];
}
}

View File

@ -90,4 +90,4 @@ export class Post {
// @Column("simple-array")
// simpleArray: string[];
}
}

View File

@ -237,4 +237,4 @@ export class Post {
// @Column("simple-array")
// simpleArray: string[];
}
}

View File

@ -1,4 +1,4 @@
import {Column, Entity,PrimaryGeneratedColumn,Index,Generated} from "typeorm";
import { Column, Entity, PrimaryGeneratedColumn, Index, Generated } from "typeorm";
@Entity("Post")
export class Post {
@ -17,4 +17,4 @@ export class Post {
})
likesCount: number;
}
}

View File

@ -2,7 +2,7 @@ import { PrimaryGeneratedColumn, Column, Entity, OneToOne, JoinColumn, Index } f
@Entity("EverythingEntity")
export class EverythingEntity {
//TODO: change to check column types per database engine
//TODO: change to check column types per database engine
@PrimaryGeneratedColumn()
id: number;
@ -69,4 +69,4 @@ export class EverythingEntity {
// @UpdateDateColumn()
// updatedDate: Date;
}
}

View File

@ -1,8 +1,8 @@
import { Column, Entity, Index, PrimaryGeneratedColumn } from "typeorm"
import { Column, Entity, Index, PrimaryGeneratedColumn } from "typeorm"
@Entity("Post")
@Index("my_index_with_id_and_text", ["id", "text"], {unique:true})
@Index("my_index_with_id_and_title", (post: Post) => [post.id, post.title], {unique:true})
@Index("my_index_with_id_and_text", ["id", "text"], { unique: true })
@Index("my_index_with_id_and_title", (post: Post) => [post.id, post.title], { unique: true })
export class Post {
@PrimaryGeneratedColumn()
@ -23,4 +23,4 @@ export class Post {
@Index()
likesCount: number;
}
}

View File

@ -1,4 +1,4 @@
import { Column, Entity, Index, PrimaryGeneratedColumn, VersionColumn } from "typeorm"
import { Column, Entity, Index, PrimaryGeneratedColumn, VersionColumn } from "typeorm"
@Entity("Post")
export class Post {
@ -14,5 +14,5 @@ export class Post {
@VersionColumn()
version: number;
}
}

View File

@ -1,10 +1,10 @@
import {PrimaryGeneratedColumn, Column, Entity, OneToOne,JoinColumn,Index} from "typeorm";
import {PostDetails} from "./PostDetails";
import {PostCategory} from "./PostCategory";
import {PostAuthor} from "./PostAuthor";
import {PostInformation} from "./PostInformation";
import {PostImage} from "./PostImage";
import {PostMetadata} from "./PostMetadata";
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, JoinColumn, Index } from "typeorm";
import { PostDetails } from "./PostDetails";
import { PostCategory } from "./PostCategory";
import { PostAuthor } from "./PostAuthor";
import { PostInformation } from "./PostInformation";
import { PostImage } from "./PostImage";
import { PostMetadata } from "./PostMetadata";
@Entity("Post")
export class Post {
@ -20,18 +20,17 @@ export class Post {
// post has relation with category, however inverse relation is not set (category does not have relation with post set)
@OneToOne(type => PostCategory, {
cascadeInsert: true,
cascadeUpdate: true,
cascadeRemove: true
cascade: true,
onDelete: 'CASCADE'
})
@JoinColumn()
@Index({ unique: true })
category: PostCategory;
// post has relation with details. cascade inserts here means if new PostDetails instance will be set to this
// post has relation with details. cascade inserts here means if new PostDetails instance will be set to this
// relation it will be inserted automatically to the db when you save this Post entity
@OneToOne(type => PostDetails, details => details.post, {
cascadeInsert: true
cascade: true
})
@JoinColumn()
@Index({ unique: true })
@ -40,7 +39,7 @@ export class Post {
// post has relation with details. cascade update here means if new PostDetail instance will be set to this relation
// it will be inserted automatically to the db when you save this Post entity
@OneToOne(type => PostImage, image => image.post, {
cascadeUpdate: true
cascade: true,
})
@JoinColumn()
@Index({ unique: true })
@ -49,17 +48,16 @@ export class Post {
// post has relation with details. cascade update here means if new PostDetail instance will be set to this relation
// it will be inserted automatically to the db when you save this Post entity
@OneToOne(type => PostMetadata, metadata => metadata.post, {
cascadeRemove: true
onDelete: 'CASCADE'
})
@JoinColumn()
@Index({ unique: true })
metadata: PostMetadata|null;
metadata: PostMetadata | null;
// post has relation with details. full cascades here
@OneToOne(type => PostInformation, information => information.post, {
cascadeInsert: true,
cascadeUpdate: true,
cascadeRemove: true
cascade: true,
onDelete: 'CASCADE'
})
@JoinColumn()
@Index({ unique: true })
@ -71,4 +69,4 @@ export class Post {
@Index({ unique: true })
author: PostAuthor;
}
}

View File

@ -1,5 +1,5 @@
import {PrimaryGeneratedColumn, Column, Entity, OneToOne,JoinColumn} from "typeorm";
import {Post} from "./Post";
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, JoinColumn } from "typeorm";
import { Post } from "./Post";
@Entity("PostAuthor")
export class PostAuthor {
@ -13,4 +13,4 @@ export class PostAuthor {
@OneToOne(type => Post, post => post.author)
post: Post;
}
}

View File

@ -1,4 +1,4 @@
import {PrimaryGeneratedColumn, Column, Entity, OneToOne,JoinColumn} from "typeorm";
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, JoinColumn } from "typeorm";
@Entity("PostCategory")
export class PostCategory {
@ -9,4 +9,4 @@ export class PostCategory {
@Column()
name: string;
}
}

View File

@ -1,5 +1,5 @@
import {PrimaryGeneratedColumn, Column, Entity, OneToOne,JoinColumn} from "typeorm";
import {Post} from "./Post";
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, JoinColumn } from "typeorm";
import { Post } from "./Post";
@Entity("PostDetails")
export class PostDetails {
@ -15,12 +15,11 @@ export class PostDetails {
@Column()
metadata: string;
@OneToOne(type => Post, post => post.details, {
cascadeInsert: true,
cascadeUpdate: true,
cascadeRemove: true
// cascade: true,
onDelete: 'CASCADE'
})
post: Post;
}
}

View File

@ -1,5 +1,5 @@
import {PrimaryGeneratedColumn, Column, Entity, OneToOne,JoinColumn} from "typeorm";
import {Post} from "./Post";
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, JoinColumn } from "typeorm";
import { Post } from "./Post";
@Entity("PostImage")
export class PostImage {
@ -13,4 +13,4 @@ export class PostImage {
@OneToOne(type => Post, post => post.image)
post: Post;
}
}

View File

@ -1,5 +1,5 @@
import {PrimaryGeneratedColumn, Column, Entity, OneToOne,JoinColumn} from "typeorm";
import {Post} from "./Post";
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, JoinColumn } from "typeorm";
import { Post } from "./Post";
@Entity("PostInformation")
export class PostInformation {
@ -9,10 +9,8 @@ export class PostInformation {
@Column()
text: string;
@OneToOne(type => Post, post => post.information, {
cascadeUpdate: true,
})
@OneToOne(type => Post, post => post.information)
post: Post;
}
}

View File

@ -1,5 +1,5 @@
import {PrimaryGeneratedColumn, Column, Entity, OneToOne,JoinColumn} from "typeorm";
import {Post} from "./Post";
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, JoinColumn } from "typeorm";
import { Post } from "./Post";
@Entity("PostMetadata")
export class PostMetadata {
@ -13,4 +13,4 @@ export class PostMetadata {
@OneToOne(type => Post, post => post.metadata)
post: Post;
}
}

View File

@ -1,4 +1,4 @@
import {Column, Entity, PrimaryColumn} from "typeorm";
import { Column, Entity, PrimaryColumn } from "typeorm";
@Entity("Post")
export class Post {
@ -12,4 +12,4 @@ export class Post {
@Column()
text: string;
}
}

View File

@ -1,10 +1,10 @@
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, JoinColumn } from "typeorm";
import {PostDetails} from "./PostDetails";
import {PostCategory} from "./PostCategory";
import {PostAuthor} from "./PostAuthor";
import {PostInformation} from "./PostInformation";
import {PostImage} from "./PostImage";
import {PostMetadata} from "./PostMetadata";
import { PostDetails } from "./PostDetails";
import { PostCategory } from "./PostCategory";
import { PostAuthor } from "./PostAuthor";
import { PostInformation } from "./PostInformation";
import { PostImage } from "./PostImage";
import { PostMetadata } from "./PostMetadata";
@Entity("Post")
export class Post {
@ -20,38 +20,36 @@ export class Post {
// post has relation with category, however inverse relation is not set (category does not have relation with post set)
@ManyToOne(type => PostCategory, {
cascadeInsert: true,
cascadeUpdate: true,
cascadeRemove: true
cascade: true,
onDelete: 'CASCADE'
})
category: PostCategory;
// post has relation with details. cascade inserts here means if new PostDetails instance will be set to this
// post has relation with details. cascade inserts here means if new PostDetails instance will be set to this
// relation it will be inserted automatically to the db when you save this Post entity
@ManyToOne(type => PostDetails, details => details.posts, {
cascadeInsert: true
cascade: true,
})
details: PostDetails;
// post has relation with details. cascade update here means if new PostDetail instance will be set to this relation
// it will be inserted automatically to the db when you save this Post entity
@ManyToOne(type => PostImage, image => image.posts, {
cascadeUpdate: true
cascade: true,
})
image: PostImage;
// post has relation with details. cascade update here means if new PostDetail instance will be set to this relation
// it will be inserted automatically to the db when you save this Post entity
@ManyToOne(type => PostMetadata, metadata => metadata.posts, {
cascadeRemove: true
cascade: true,
})
metadata: PostMetadata|null;
metadata: PostMetadata | null;
// post has relation with details. full cascades here
@ManyToOne(type => PostInformation, information => information.posts, {
cascadeInsert: true,
cascadeUpdate: true,
cascadeRemove: true
cascade: true,
onDelete: 'CASCADE'
})
information: PostInformation;
@ -59,4 +57,4 @@ export class Post {
@ManyToOne(type => PostAuthor, author => author.posts)
author: PostAuthor;
}
}

View File

@ -1,5 +1,5 @@
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, JoinColumn } from "typeorm";
import {Post} from "./Post";
import { Post } from "./Post";
@Entity("PostAuthor")
export class PostAuthor {
@ -13,4 +13,4 @@ export class PostAuthor {
@OneToMany(type => Post, post => post.author)
posts: Post[];
}
}

View File

@ -9,4 +9,4 @@ export class PostCategory {
@Column()
name: string;
}
}

View File

@ -1,5 +1,5 @@
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, JoinColumn } from "typeorm";
import {Post} from "./Post";
import { Post } from "./Post";
@Entity("PostDetails")
export class PostDetails {
@ -21,11 +21,8 @@ export class PostDetails {
nullable: true
})
metadata: string;
@OneToMany(type => Post, post => post.details, {
cascadeInsert: true,
cascadeUpdate: true
})
@OneToMany(type => Post, post => post.details)
posts: Post[];
}
}

View File

@ -13,4 +13,4 @@ export class PostImage {
@OneToMany(type => Post, post => post.image)
posts: Post[];
}
}

View File

@ -1,5 +1,5 @@
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, JoinColumn } from "typeorm";
import {Post} from "./Post";
import { Post } from "./Post";
@Entity("PostInformation")
export class PostInformation {
@ -9,10 +9,8 @@ export class PostInformation {
@Column()
text: string;
@OneToMany(type => Post, post => post.information, {
cascadeUpdate: true,
})
@OneToMany(type => Post, post => post.information)
posts: Post[];
}
}

View File

@ -1,5 +1,5 @@
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, JoinColumn } from "typeorm";
import {Post} from "./Post";
import { Post } from "./Post";
@Entity("PostMetadata")
export class PostMetadata {
@ -13,4 +13,4 @@ export class PostMetadata {
@OneToMany(type => Post, post => post.metadata)
posts: Post[];
}
}

View File

@ -13,4 +13,4 @@ export class Post {
@ManyToOne(type => PostAuthor, author => author.posts2)
author2: PostAuthor;
}
}

View File

@ -13,4 +13,4 @@ export class PostAuthor {
@OneToMany(type => Post, post => post.author2)
posts2: Post[];
}
}

View File

@ -25,6 +25,7 @@ describe("TypeOrm examples", async function () {
if (process.env.MYSQL_Skip == '0') dbDrivers.push('mysql')
if (process.env.MARIADB_Skip == '0') dbDrivers.push('mariadb')
if (process.env.MSSQL_Skip == '0') dbDrivers.push('mssql')
if (process.env.Oracle_Skip == '0') dbDrivers.push('oracle')
let examplesPathJS = path.resolve(process.cwd(), 'dist/test/integration/examples')
let examplesPathTS = path.resolve(process.cwd(), 'test/integration/examples')
@ -55,6 +56,9 @@ describe("TypeOrm examples", async function () {
case 'mariadb':
engine = await GTU.createMariaDBModels(filesOrgPathJS, resultsPath)
break;
case 'oracle':
engine = await GTU.createOracleDBModels(filesOrgPathJS, resultsPath)
break;
default:
console.log(`Unknown engine type`);

View File

@ -21,6 +21,7 @@ export class EntityFileToJson {
// if (!x.endsWith('[]')) {
// x = x + '[]'// can't distinguish OneTwoMany from OneToOne without indexes
// }
x = x.trim();
return x;
});
} else {
@ -92,7 +93,7 @@ export class EntityFileToJson {
for (let line of lines) {
let trimmedLine = line.trim();
if (trimmedLine.startsWith('//')) {
continue; //commented line
continue; //commented line
}
if (isMultilineStatement)
trimmedLine = priorPartOfMultilineStatement + ' ' + trimmedLine
@ -101,7 +102,7 @@ export class EntityFileToJson {
else if (!isInClassBody) {
if (trimmedLine.startsWith('import')) {
continue; //import statement is not part of entity definition
continue; //import statement is not part of entity definition
} else if (trimmedLine.startsWith('@Entity')) {
continue; //TODO:entity options
} else if (trimmedLine.startsWith('export class')) {
@ -243,6 +244,7 @@ export class EntityFileToJson {
// if (!x.endsWith('[]')) {
// x = x + '[]'// can't distinguish OneTwoMany from OneToOne without indexes
// }
x = x.trim();
return x;
});
@ -272,15 +274,15 @@ export class EntityFileToJson {
console.log(`${trimmedLine}`)
}
retVal.columns=retVal.columns.map(col=>{
retVal.columns = retVal.columns.map(col => {
if (col.columnName.endsWith('Id'))
col.columnName=col.columnName.substr(0,col.columnName.length-2)
col.columnName = col.columnName.substr(0, col.columnName.length - 2)
return col;
})
retVal.indicies=retVal.indicies.map(ind=>{
ind.columnNames=ind.columnNames.map(colName=>{
retVal.indicies = retVal.indicies.map(ind => {
ind.columnNames = ind.columnNames.map(colName => {
if (colName.endsWith('Id'))
colName=colName.substr(0,colName.length-2)
colName = colName.substr(0, colName.length - 2)
return colName;
})
return ind;
@ -312,4 +314,4 @@ class EntityIndex {
indexName: string
columnNames: string[] = []
isUnique: boolean = false
}
}

View File

@ -4,6 +4,7 @@ import { MssqlDriver } from "../../src/drivers/MssqlDriver";
import { PostgresDriver } from "./../../src/drivers/PostgresDriver";
import { MysqlDriver } from "../../src/drivers/MysqlDriver";
import { MariaDbDriver } from "../../src/drivers/MariaDbDriver";
import { OracleDriver } from "../../src/drivers/OracleDriver";
import { Engine } from "../../src/Engine";
import { createConnection, ConnectionOptions, Connection } from "typeorm";
import * as yn from "yn"
@ -48,7 +49,8 @@ export async function createMSSQLModels(filesOrgPath: string, resultsPath: strin
databaseType: 'mssql',
resultsPath: resultsPath,
schemaName: 'dbo',
ssl: yn(process.env.MSSQL_SSL)
ssl: yn(process.env.MSSQL_SSL),
noConfigs: false
});
@ -91,7 +93,8 @@ export async function createPostgresModels(filesOrgPath: string, resultsPath: st
databaseType: 'postgres',
resultsPath: resultsPath,
schemaName: 'public',
ssl: yn(process.env.POSTGRES_SSL)
ssl: yn(process.env.POSTGRES_SSL),
noConfigs: false
});
@ -135,7 +138,8 @@ export async function createMysqlModels(filesOrgPath: string, resultsPath: strin
databaseType: 'mysql',
resultsPath: resultsPath,
schemaName: 'ignored',
ssl: yn(process.env.MYSQL_SSL)
ssl: yn(process.env.MYSQL_SSL),
noConfigs: false
});
@ -179,7 +183,55 @@ export async function createMariaDBModels(filesOrgPath: string, resultsPath: str
databaseType: 'mariadb',
resultsPath: resultsPath,
schemaName: 'ignored',
ssl: yn(process.env.MARIADB_SSL)
ssl: yn(process.env.MARIADB_SSL),
noConfigs: false
});
return engine;
}
export async function createOracleDBModels(filesOrgPath: string, resultsPath: string): Promise<Engine> {
let driver: AbstractDriver;
driver = new OracleDriver();
await driver.ConnectToServer(String(process.env.ORACLE_Database), String(process.env.ORACLE_Host), Number(process.env.ORACLE_Port), String(process.env.ORACLE_Username), String(process.env.ORACLE_Password), yn(process.env.ORACLE_SSL));
if (! await driver.CheckIfDBExists(String(process.env.ORACLE_Database)))
await driver.CreateDB(String(process.env.ORACLE_Database));
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
database: String(process.env.ORACLE_Database),
sid: String(process.env.ORACLE_Database),
host: String(process.env.ORACLE_Host),
password: String(process.env.ORACLE_Password),
type: 'oracle',
username: String(process.env.ORACLE_Username),
port: Number(process.env.ORACLE_Port),
// dropSchema: true,
synchronize: true,
entities: [path.resolve(filesOrgPath, '*.js')],
}
let conn = await createConnection(connOpt)
if (conn.isConnected)
await conn.close()
driver = new OracleDriver();
let engine = new Engine(
driver, {
host: String(process.env.ORACLE_Host),
port: Number(process.env.ORACLE_Port),
databaseName: String(process.env.ORACLE_Database),
user: String(process.env.ORACLE_Username),
password: String(process.env.ORACLE_Password),
databaseType: 'oracle',
resultsPath: resultsPath,
schemaName: String(process.env.ORACLE_Username),
ssl: yn(process.env.ORACLE_SSL),
noConfigs: false
});
@ -203,4 +255,4 @@ export function compileTsFiles(fileNames: string[], options: ts.CompilerOptions)
});
return compileErrors;
}
}

View File

@ -14,8 +14,9 @@
"moduleResolution": "node",
"outDir": "dist",
"newLine": "LF"
}, "include": [
},
"include": [
"src",
"test"
]
}
}

View File

@ -1,10 +1,10 @@
{
"globalDevDependencies": {
"mustache": "registry:dt/mustache#0.8.2+20160510002910"
},
"dependencies": {
"mssql": "registry:dt/mssql#3.3.0+20170311011547",
"yargs": "registry:npm/yargs#5.0.0+20160907000723",
"yn": "registry:npm/yn#1.3.0+20170508185912"
}
"globalDevDependencies": {
"mustache": "registry:dt/mustache#0.8.2+20160510002910"
},
"dependencies": {
"mssql": "registry:dt/mssql#3.3.0+20170311011547",
"yargs": "registry:npm/yargs#5.0.0+20160907000723",
"yn": "registry:npm/yn#1.3.0+20170508185912"
}
}