From 15bd4c9e50943f810a219057d2c00fb12018b37d Mon Sep 17 00:00:00 2001 From: Rafael <rpd17@inf.ufpr.br> Date: Wed, 23 May 2018 09:52:32 -0300 Subject: [PATCH] Issue #83:Fix test Monet and Postgres Signed-off-by: Rafael <rpd17@inf.ufpr.br> --- src/adapter/monet.ts | 21 +++- src/adapter/postgres.spec.ts | 7 +- src/adapter/sql.ts | 2 +- src/api/controllers/collect.spec.ts | 2 +- test/monet/fixture.ts | 145 ++++++++++++++++++++-------- 5 files changed, 129 insertions(+), 48 deletions(-) diff --git a/src/adapter/monet.ts b/src/adapter/monet.ts index 5675b014..d96c9080 100644 --- a/src/adapter/monet.ts +++ b/src/adapter/monet.ts @@ -118,6 +118,25 @@ export class MonetAdapter extends SQLAdapter { }); pool.close(); } + /** + * Asynchronously executes a query from Source and get its resut + */ + + private executeQuerySource(query: string, cb: (error: Error, result?: any[]) => void): void { + let pool: any = new MDB(this.config); + pool.connect(); + pool.query(query).then((result: any) => { + if (result) { + cb(null, result); + } + else { + cb(null, null); + } + }).fail((err: Error) => { + cb(err, null); + }); + pool.close(); + } /** * Materialize a given view. @@ -136,7 +155,7 @@ export class MonetAdapter extends SQLAdapter { */ public insertIntoSource(source: Source, data: any[], cb: (err: Error, result: any[]) => void): void { const query = this.getQueryFromSource(source, data); - this.executeQuery(query, cb); + this.executeQuerySource(query, cb); } /** diff --git a/src/adapter/postgres.spec.ts b/src/adapter/postgres.spec.ts index ddbb00f6..3ec5c76c 100644 --- a/src/adapter/postgres.spec.ts +++ b/src/adapter/postgres.spec.ts @@ -25,11 +25,10 @@ import { MonetAdapter, MonetConfig } from "./monet"; import { Adapter } from "../core/adapter"; import { Fixture as FixPostgres } from "../../test/postgres/fixture"; import { Fixture as FixMonet } from "../../test/monet/fixture"; - import { ConfigParser } from "../util/configParser"; import { adapterScenario } from "../../test/scenario"; -describe("postgres adapter", () => { +describe("Sql adapter", () => { // Initializing let config: any; @@ -38,6 +37,7 @@ describe("postgres adapter", () => { before(function (done): void { // Arrow function not used to get acces to this and skip the test config = ConfigParser.parse("config/test.yaml"); + if (config.adapter === "postgres") { fixture = new FixPostgres(config.connection); fixture.load(config.loadViews, (err) => { @@ -50,7 +50,7 @@ describe("postgres adapter", () => { } else if (config.adapter === "monet") { fixture = new FixMonet(config.connection); - fixture.load(config.loadViews, config.struct.create, (err) => { + fixture.load(config.loadViews, (err) => { if (err) { throw err; } @@ -61,6 +61,7 @@ describe("postgres adapter", () => { host: config.connection.host, port: config.connection.port }; + adapter = new MonetAdapter(parsedConfig); done(); }); diff --git a/src/adapter/sql.ts b/src/adapter/sql.ts index b54fdab2..8958805c 100644 --- a/src/adapter/sql.ts +++ b/src/adapter/sql.ts @@ -468,7 +468,7 @@ export abstract class SQLAdapter extends Adapter { consult = consult.concat(colums.join("\",\"")); consult = consult.concat("\") VALUES ('"); consult = consult.concat(values.join("' , '")); - consult = consult.concat("');"); + consult = consult.concat("')"); return consult; } diff --git a/src/api/controllers/collect.spec.ts b/src/api/controllers/collect.spec.ts index d770c87d..dedb013a 100644 --- a/src/api/controllers/collect.spec.ts +++ b/src/api/controllers/collect.spec.ts @@ -49,7 +49,7 @@ describe("API collect controller", () => { } else if (config.adapter === "monet") { fixture = new FixMonet(config.connection); - fixture.load(config.sources, config.struct.create, (err) => { + fixture.loadSource(config.sources, (err) => { if (err) { throw err; } diff --git a/test/monet/fixture.ts b/test/monet/fixture.ts index c0cbee72..dffc845e 100644 --- a/test/monet/fixture.ts +++ b/test/monet/fixture.ts @@ -20,16 +20,12 @@ const MDB = require("monetdb")(); import { View, LoadView } from "../../src/core/view"; +import { Source } from "../../src/core/source"; import { each, series } from "async"; import { Connection } from "../../src/util/configParser"; import * as fs from "fs"; import { DataType } from "../../src/common/types"; -interface TransSet { - init: string; - data: string[]; -} - export interface Schema { alias?: string; query?: string; @@ -46,7 +42,7 @@ export class Fixture { this.database = config.database; } - public load(schemas: LoadView[], create: boolean, cb: (err: Error) => void): void { + public load(schemas: LoadView[], cb: (err: Error) => void): void { let client = new MDB({ user: this.config.user, dbname: this.config.database, @@ -58,19 +54,12 @@ export class Fixture { /* Loading data has 2 steps: 1 - Create a table or truncate a existing one. - Create or truncate dependes from a parameter in the configure - file, this parameter reaches this function as the create - parameter. 2 - Insert data. */ - let init: string[] = []; let data: string[] = []; for (let i = 0; i < schemas.length; ++i) { - let table: TransSet = this.createTransSet(schemas[i].view, schemas[i].data, create); - init.push(table.init); - data = data.concat(table.data); + data = data.concat(this.extractDataView(schemas[i].view, schemas[i].data)); } - client.connect(); /* Tables must be creates before data could be inserted, so the @@ -78,11 +67,21 @@ export class Fixture { To garantee that tables exists before start insert data, series is used. Inside series each query is executed, using each; */ + series([(callback: (err: Error) => void) => { - each(init, (query, cback) => { - return client.query(query).then((result: any) => cback()) - .fail((err: Error) => (cback(err))); - }, (errQuery: Error) => callback(errQuery)); + each(schemas, (query, cback) => { + client.query(this.createTransSet(query.view, query.data, true)).then((result: any) => cback()) + .fail((errCreate: Error) => { + if (errCreate){ + let regex = new RegExp(/42s01!create table: name \'.*\' already in use/); + if (regex.test(errCreate.message.toLocaleLowerCase())){ + return client.query(this.createTransSet(query.view, query.data, false)).then((result: any) => cback()) + .fail.fail((errTrunc: Error) => (cback(errTrunc))); + } + } + return cback(errCreate); + }); + }, (errQuery: Error) => callback(errQuery)); }, (callback: (err: Error) => void) => { each(data, (query, cback) => { return client.query(query).then((result: any) => cback()) @@ -92,6 +91,7 @@ export class Fixture { client.close(); cb(errQuery); }); + } private typeConvertion(t: DataType): string { @@ -105,46 +105,49 @@ export class Fixture { case DataType.BOOLEAN: return "BOOLEAN"; default: - return ""; + return "TEXT"; } } - private createTransSet(view: View, filePath: string, create: boolean): TransSet { - let props = []; + private extractDataView(view: View, filePath: string): string[]{ + let name = "view_" + view.id; + let data: string[] = []; + let rows = JSON.parse(fs.readFileSync(filePath, {encoding : "utf8"})); + for (let i = 0; i < rows.length; ++i) { + let values = []; + let keys = []; + for (let key of Object.keys(rows[i])) { + keys.push("\"" + key + "\""); + values.push("'" + this.boolCast(rows[i][key]) + "'"); + } + data.push("INSERT INTO " + name + + "(" + keys.join(", ") + ") " + + "VALUES (" + values.join(", ") + ")"); + } + return data; + + } + + private createTransSet(view: View, filePath: string, create: boolean): string { + let name = "view_" + view.id; + let init: string = ""; + let props = []; for (let i = 0; i < view.metrics.length; ++i) { let met = view.metrics[i]; props.push("\"" + met.name + "\" " + this.typeConvertion(met.dataType)); } - for (let i = 0; i < view.dimensions.length; ++i) { let dim = view.dimensions[i]; props.push("\"" + dim.name + "\" " + this.typeConvertion(dim.dataType)); } - - let name = "view_" + view.id; - let transaction: TransSet = {init: "", data: []}; if (create) { - transaction.init = "CREATE TABLE " + name + "(" + props.join(", ") + ")"; + init = "CREATE TABLE " + name + "(" + props.join(", ") + ")"; } else { - transaction.init = "DELETE FROM " + name; - } - - transaction.data = []; - let rows = JSON.parse(fs.readFileSync(filePath, {encoding : "utf8"})); - for (let i = 0; i < rows.length; ++i) { - let values = []; - let keys = []; - for (let key of Object.keys(rows[i])) { - keys.push("\"" + key + "\""); - values.push("'" + this.boolCast(rows[i][key]) + "'"); - } - transaction.data.push("INSERT INTO " + name + - "(" + keys.join(", ") + ") " + - "VALUES (" + values.join(", ") + ")"); + init = "DELETE FROM " + name; } - return transaction; + return init; } private boolCast(text: string): string { @@ -160,4 +163,62 @@ export class Fixture { return text; } } + + public loadSource(source: Source[] , cb: (err: Error) => void): void { + + let client = new MDB({ + user: this.config.user, + dbname: this.config.database, + password: this.config.password, + host: this.config.host, + port: this.config.port, + }); + + client.connect(); + + series([(callback: (err: Error) => void) => { + each(source, (insere, cback) => { + client.query(this.extractData(insere, true)).then((result: any) => cback()) + .fail((errCreate: Error) => { + if (errCreate) { + let regex = new RegExp(/42s01!create table: name \'.*\' already in use/); + if (regex.test(errCreate.message.toLocaleLowerCase())){ + return client.query(this.extractData(insere, false)).then((result: any) => cback()) + .fail((errTrunc: Error) => (cback(errTrunc))); + } + } + return cback(errCreate); + }); + }, (errQuery: Error) => callback(errQuery)); + }], (errQuery: Error) => { + client.close(); + cb(errQuery); + }); + } + + private extractData(data: Source, create: boolean): string{ + let name: string; + let type: DataType[]; + let fields: string[]; + let consult: string; + + name = data.name; + type = data.fields.map((item) => item.dataType); + fields = data.fields.map((item) => item.name); + + if (create){ + consult = "CREATE TABLE " + name + " (" + '"'; + for (let i = 0; i < fields.length; i++){ + fields[i] = fields[i].concat('"' + " " + this.typeConvertion(type[i])); + } + consult = consult.concat(fields.join(", " + '"')); + consult = consult.concat(");"); + } + else{ + consult = "DELETE FROM " + name + ";"; + } + + return consult; + + } } -- GitLab