integration tests column options comparision, added generated column option to creating model from db
This commit is contained in:
parent
5e307aca65
commit
126d9ce185
@ -32,6 +32,7 @@
|
||||
"devDependencies": {
|
||||
"@types/chai": "^3.5.2",
|
||||
"@types/chai-as-promised": "0.0.30",
|
||||
"@types/chai-subset": "^1.3.0",
|
||||
"@types/fs-extra": "^3.0.0",
|
||||
"@types/mocha": "^2.2.41",
|
||||
"@types/mssql": "^3.3.0",
|
||||
@ -39,6 +40,7 @@
|
||||
"@types/sinon": "^2.1.3",
|
||||
"chai": "^3.5.0",
|
||||
"chai-as-promised": "^6.0.0",
|
||||
"chai-subset": "^1.5.0",
|
||||
"codecov": "^2.1.0",
|
||||
"dotenv": "^4.0.0",
|
||||
"fs-extra": "^3.0.1",
|
||||
|
@ -39,9 +39,10 @@ export class MssqlDriver extends AbstractDriver {
|
||||
let request = new MSSQL.Request(this.Connection)
|
||||
let response: { TABLE_NAME: string, COLUMN_NAME: string, COLUMN_DEFAULT: string,
|
||||
IS_NULLABLE: string, DATA_TYPE: string, CHARACTER_MAXIMUM_LENGTH: number,
|
||||
NUMERIC_PRECISION:number,NUMERIC_SCALE:number }[]
|
||||
NUMERIC_PRECISION:number,NUMERIC_SCALE:number,IsIdentity:number }[]
|
||||
= await request.query(`SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,
|
||||
DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE FROM INFORMATION_SCHEMA.COLUMNS`);
|
||||
DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE,
|
||||
COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') IsIdentity FROM INFORMATION_SCHEMA.COLUMNS`);
|
||||
entities.forEach((ent) => {
|
||||
response.filter((filterVal) => {
|
||||
return filterVal.TABLE_NAME == ent.EntityName;
|
||||
@ -49,6 +50,7 @@ export class MssqlDriver extends AbstractDriver {
|
||||
let colInfo: ColumnInfo = new ColumnInfo();
|
||||
colInfo.name = resp.COLUMN_NAME;
|
||||
colInfo.is_nullable = resp.IS_NULLABLE == 'YES' ? true : false;
|
||||
colInfo.is_generated = resp.IsIdentity == 1 ? true : false;
|
||||
colInfo.default = resp.COLUMN_DEFAULT;
|
||||
switch (resp.DATA_TYPE) {
|
||||
case "int":
|
||||
|
@ -7,7 +7,7 @@ import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, Joi
|
||||
|
||||
{{#Columns}}
|
||||
|
||||
@Column("{{sql_type}}",{ {{#is_nullable}}nullable:true,{{/is_nullable}}{{#char_max_lenght}}length:{{char_max_lenght}},{{/char_max_lenght}}{{#default}}default:"{{default}}",{{/default}}{{#numericPrecision}}precision:{{numericPrecision}},{{/numericPrecision}}{{#numericScale}}scale:{{numericScale}},{{/numericScale}}{{#isPrimary}}primary:{{isPrimary}},{{/isPrimary}}}){{#relations}}
|
||||
@Column("{{sql_type}}",{ {{#is_generated}}generated:true,{{/is_generated}}{{#is_nullable}}nullable:true,{{/is_nullable}}{{^is_nullable}}nullable:false,{{/is_nullable}}{{#char_max_lenght}}length:{{char_max_lenght}},{{/char_max_lenght}}{{#default}}default:"{{default}}",{{/default}}{{#numericPrecision}}precision:{{numericPrecision}},{{/numericPrecision}}{{#numericScale}}scale:{{numericScale}},{{/numericScale}}{{#isPrimary}}primary:{{isPrimary}},{{/isPrimary}}}){{#relations}}
|
||||
@{{relationType}}(type=>{{relatedTable}},x=>x.{{relatedColumn}}){{#isOwner}}
|
||||
@JoinTable(){{/isOwner}}{{/relations}}
|
||||
{{name}}:{{ts_type}};
|
||||
|
@ -10,10 +10,12 @@ export class ColumnInfo {
|
||||
"float" | "double" | "decimal" | "date" | "time" | "datetime" | "boolean" | "json";
|
||||
char_max_lenght: number|null=null;
|
||||
isPrimary:boolean=false;
|
||||
is_generated:boolean=false;
|
||||
numericPrecision:number|null=null;
|
||||
numericScale:number|null=null;
|
||||
relations:RelationInfo[];
|
||||
|
||||
|
||||
constructor() {
|
||||
this.relations=[];
|
||||
}
|
||||
|
@ -56,12 +56,13 @@ describe('MssqlDriver', function () {
|
||||
let response = <{
|
||||
TABLE_NAME: string, COLUMN_NAME: string, COLUMN_DEFAULT: string,
|
||||
IS_NULLABLE: string, DATA_TYPE: string, CHARACTER_MAXIMUM_LENGTH: number,
|
||||
NUMERIC_PRECISION: number, NUMERIC_SCALE: number
|
||||
NUMERIC_PRECISION: number, NUMERIC_SCALE: number, IsIdentity:number
|
||||
}[]>[]
|
||||
response.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
|
||||
IS_NULLABLE: 'YES', NUMERIC_PRECISION: 0, NUMERIC_SCALE: 0,
|
||||
IsIdentity:1
|
||||
})
|
||||
return response;
|
||||
}
|
||||
@ -81,6 +82,7 @@ describe('MssqlDriver', function () {
|
||||
default: 'a',
|
||||
is_nullable: true,
|
||||
isPrimary: false,
|
||||
is_generated:true,
|
||||
name: 'name',
|
||||
numericPrecision: null,
|
||||
numericScale: null,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import {Column, Entity,PrimaryColumn,Index} from "typeorm";
|
||||
|
||||
@Entity()
|
||||
@Entity("Post")
|
||||
export class Post {
|
||||
|
||||
@PrimaryColumn("int", { generated: true })
|
||||
|
@ -3,7 +3,6 @@ import "reflect-metadata";
|
||||
import { createConnection, ConnectionOptions, Connection } from "typeorm";
|
||||
import fs = require('fs-extra');
|
||||
import path = require('path')
|
||||
import { Post } from "./examples/sample1-simple-entity/entity/Post";
|
||||
import { Engine } from "./../../src/Engine";
|
||||
import { AbstractDriver } from "./../../src/drivers/AbstractDriver";
|
||||
import { MssqlDriver } from "./../../src/drivers/MssqlDriver";
|
||||
@ -11,7 +10,10 @@ import { DriverType } from "typeorm/driver/DriverOptions";
|
||||
import { expect } from "chai";
|
||||
import * as Sinon from 'sinon'
|
||||
import { EntityFileToJson } from "../utils/EntityFileToJson";
|
||||
var chai = require('chai');
|
||||
var chaiSubset = require('chai-subset');
|
||||
|
||||
chai.use(chaiSubset);
|
||||
|
||||
describe("integration tests", async function () {
|
||||
let examplesPath = path.resolve(process.cwd(), 'test/integration/examples')
|
||||
@ -54,7 +56,6 @@ describe("integration tests", async function () {
|
||||
let resultsPath = path.resolve(process.cwd(), `output`)
|
||||
let engine = new Engine(
|
||||
driver, {
|
||||
//TODO:get data from env
|
||||
host: process.env.MSSQL_Host,
|
||||
port: process.env.MSSQL_Port,
|
||||
databaseName: process.env.MSSQL_Database,
|
||||
@ -70,8 +71,8 @@ describe("integration tests", async function () {
|
||||
|
||||
let filesGenPath = path.resolve(resultsPath, 'entities')
|
||||
|
||||
let filesOrg = fs.readdirSync(filesOrgPath).map(function (this, val) { return val.toString().toLowerCase(); }).filter(function (this, val, ind, arr) { return val.toString().endsWith('.ts') })
|
||||
let filesGen = fs.readdirSync(filesGenPath).map(function (this, val) { return val.toString().toLowerCase(); }).filter(function (this, val, ind, arr) { return val.toString().endsWith('.ts') })
|
||||
let filesOrg = fs.readdirSync(filesOrgPath).filter(function (this, val, ind, arr) { return val.toString().endsWith('.ts') })
|
||||
let filesGen = fs.readdirSync(filesGenPath).filter(function (this, val, ind, arr) { return val.toString().endsWith('.ts') })
|
||||
|
||||
expect(filesOrg).to.be.deep.equal(filesGen)
|
||||
|
||||
@ -79,7 +80,7 @@ describe("integration tests", async function () {
|
||||
let entftj = new EntityFileToJson();
|
||||
let jsonEntityOrg= entftj.convert(fs.readFileSync(path.resolve(filesOrgPath, file)))
|
||||
let jsonEntityGen= entftj.convert(fs.readFileSync(path.resolve(filesGenPath, file)))
|
||||
expect(jsonEntityGen).to.be.deep.eq(jsonEntityOrg)
|
||||
expect(jsonEntityGen).to.containSubset(jsonEntityOrg)
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,4 +1,28 @@
|
||||
export class EntityFileToJson {
|
||||
getColumnOptionsAndType(trimmedLine: string, col: EntityColumn) {
|
||||
let decoratorParameters = trimmedLine.slice(trimmedLine.indexOf('(') + 1, trimmedLine.lastIndexOf(')'))
|
||||
|
||||
if (decoratorParameters.length > 0) {
|
||||
if (decoratorParameters.search(',') > 0) {
|
||||
col.columnType = decoratorParameters.substring(0, decoratorParameters.indexOf(',')).trim()
|
||||
let badJSON = decoratorParameters.substring(decoratorParameters.indexOf(',') + 1).trim()
|
||||
if (badJSON.lastIndexOf(',') == badJSON.length - 2) {
|
||||
badJSON = badJSON.slice(0, badJSON.length - 2) + badJSON[badJSON.length - 1]
|
||||
}
|
||||
col.columnOptions = JSON.parse(badJSON.replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, '"$2": '))
|
||||
} else {
|
||||
if (decoratorParameters[0] == '"' && decoratorParameters.endsWith('"')) {
|
||||
col.columnType = decoratorParameters
|
||||
} else {
|
||||
let badJSON = decoratorParameters.substring(decoratorParameters.indexOf(',') + 1).trim()
|
||||
if (badJSON.lastIndexOf(',') == badJSON.length - 2) {
|
||||
badJSON = badJSON.slice(0, badJSON.length - 2) + badJSON[badJSON.length - 1]
|
||||
}
|
||||
col.columnOptions = JSON.parse(badJSON.replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, '"$2": '))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
convert(entityFile: Buffer): EntityJson {
|
||||
let retVal = new EntityJson();
|
||||
@ -7,7 +31,7 @@ export class EntityFileToJson {
|
||||
let isMultilineStatement = false;
|
||||
let priorPartOfMultilineStatement = '';
|
||||
|
||||
let lines = entityFile.toString().replace('\r','').split('\n');
|
||||
let lines = entityFile.toString().replace('\r', '').split('\n');
|
||||
for (let line of lines) {
|
||||
let trimmedLine = line.trim();
|
||||
if (isMultilineStatement)
|
||||
@ -33,8 +57,9 @@ export class EntityFileToJson {
|
||||
continue;
|
||||
} else {
|
||||
isMultilineStatement = false;
|
||||
retVal.columns.push(new EntityColumn())
|
||||
//TODO:Options, column type if declared
|
||||
let col = new EntityColumn()
|
||||
this.getColumnOptionsAndType(trimmedLine, col)
|
||||
retVal.columns.push(col);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -45,8 +70,10 @@ export class EntityFileToJson {
|
||||
continue;
|
||||
} else {
|
||||
isMultilineStatement = false;
|
||||
retVal.columns.push(new EntityColumn())
|
||||
//TODO:Options, column type if declared
|
||||
let col = new EntityColumn()
|
||||
this.getColumnOptionsAndType(trimmedLine, col)
|
||||
col.columnOptions['primary'] = true
|
||||
retVal.columns.push(col);
|
||||
continue;
|
||||
}
|
||||
} else if (trimmedLine.startsWith('@PrimaryGeneratedColumn')) {
|
||||
@ -56,8 +83,11 @@ export class EntityFileToJson {
|
||||
continue;
|
||||
} else {
|
||||
isMultilineStatement = false;
|
||||
retVal.columns.push(new EntityColumn())
|
||||
//TODO:Options, column type if declared
|
||||
let col = new EntityColumn()
|
||||
this.getColumnOptionsAndType(trimmedLine, col)
|
||||
col.columnOptions['primary'] = true
|
||||
col.columnOptions['generated'] = true
|
||||
retVal.columns.push(col);
|
||||
continue;
|
||||
}
|
||||
} else if (trimmedLine.startsWith('@ManyToOne')) {
|
||||
@ -83,11 +113,11 @@ export class EntityFileToJson {
|
||||
continue;
|
||||
}
|
||||
} else if (trimmedLine.split(':').length - 1 > 0) {
|
||||
retVal.columns[retVal.columns.length-1].columnName=trimmedLine.split(':')[0].trim();
|
||||
retVal.columns[retVal.columns.length-1].columnType=trimmedLine.split(':')[1].split(';')[0].trim();
|
||||
retVal.columns[retVal.columns.length - 1].columnName = trimmedLine.split(':')[0].trim();
|
||||
retVal.columns[retVal.columns.length - 1].columnType = trimmedLine.split(':')[1].split(';')[0].trim();
|
||||
continue
|
||||
}else if(trimmedLine='}'){
|
||||
isInClassBody=false;
|
||||
} else if (trimmedLine = '}') {
|
||||
isInClassBody = false;
|
||||
continue; //class declaration end
|
||||
}
|
||||
}
|
||||
@ -112,4 +142,5 @@ class EntityJson {
|
||||
class EntityColumn {
|
||||
columnName: string
|
||||
columnType: string
|
||||
columnOptions: any = {}
|
||||
}
|
Loading…
Reference in New Issue
Block a user