Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • develop
  • drill-experiment
  • feature/diagrams
  • icde-2019-experiments
  • issue/20
  • issue/6
  • issue/63
  • issue/85
  • issue/97
  • master
  • refactor/engine
  • simmc-based
  • tg-felipe
  • wip-transformers
14 results

Target

Select target project
  • c3sl/blendb
  • pdts20/blendb
2 results
Select Git revision
  • develop
  • feature/diagrams
  • icde-2019-experiments
  • issue/20
  • issue/6
  • issue/63
  • issue/85
  • issue/97
  • master
  • refactor/engine
  • tg-felipe
  • wip-transformers
12 results
Show changes
Showing
with 6022 additions and 369 deletions
dim:seller:sex,dim:seller:cpf,met:seller:avg:age
male,604.424.718-07,27
female,575.657.111-60,26
nonbinary,977.221.375-39,24
undecided,344.805.128-45,23
female,885.517.020-17,25
\ No newline at end of file
dim:seller:sex;dim:seller:cpf;met:seller:avg:age
male;604.424.718-07;27
female;575.657.111-60;26
nonbinary;977.221.375-39;24
undecided;344.805.128-45;23
female;885.517.020-17;25
\ No newline at end of file
dim:seller:sex dim:seller:cpf met:seller:avg:age
male 604.424.718-07 27
female 575.657.111-60 26
nonbinary 977.221.375-39 24
undecided 344.805.128-45 23
female 885.517.020-17 25
\ No newline at end of file
name;aggregation;dataType;description;tags
met:seller:avg:age;avg;float;The seller average age;"[""seller"",""age""]"
met:seller:max:age;max;integer;The seller highest age;"[""seller"",""age"",""max""]"
met:seller:min:age;min;integer;The seller lowest age;"[""seller"",""age""]"
met:seller:count:age;count;integer;The number of seller's;"[""seller"",""age""]"
met:product:avg:pricein;avg;float;The average product pricein;"[""product""]"
met:product:max:pricein;max;float;The highest product pricein;"[""product"",""max""]"
met:product:min:pricein;min;float;The lowest product pricein;"[""product""]"
met:product:avg:priceout;avg;float;The average product priceout;"[""product""]"
met:product:max:priceout;max;float;The highest product priceout;"[""product"",""max""]"
met:product:min:priceout;min;float;The lowest product priceout;"[""product""]"
met:sell:sum:quantity;sum;integer;The sum of sales quantity;[]
met:sell:avg:quantity;avg;float;The average of sales quantity;[]
met:sell:count:quantity;count;integer;The total number of sales;[]
met:buyout:avg:quantity;avg;float;The average of quantity bought;"[""buyout""]"
met:buyout:max:quantity;max;integer;The highest quantity bought;"[""buyout"",""max""]"
met:buyout:min:quantity;min;integer;The lowest quantity bought;"[""buyout""]"
\ No newline at end of file
......@@ -8,3 +8,4 @@
--check-leaks
--globals expect
./src/**/*.spec.ts
--exit
\ No newline at end of file
/*
* Copyright (C) 2017 Centro de Computacao Cientifica e Software Livre
* Departamento de Informatica - Universidade Federal do Parana
*
* This file is part of blend.
*
* blend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* blend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with blend. If not, see <http://www.gnu.org/licenses/>.
*/
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";
export interface Schema {
alias?: string;
query?: string;
data?: string;
fields: any[];
}
export class Fixture {
private database: string;
private config: Connection;
constructor(config: Connection) {
this.config = config;
this.database = config.database;
}
public load(schemas: LoadView[], 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,
});
/*
Loading data has 2 steps:
1 - Create a table or truncate a existing one.
2 - Insert data.
*/
let data: string[] = [];
for (let i = 0; i < schemas.length; ++i) {
data = data.concat(this.extractDataView(schemas[i].view, schemas[i].data));
}
client.connect();
/*
Tables must be creates before data could be inserted, so the
queries that create and insert are splited in 2 arrays.
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(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((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())
.fail((err: Error) => (cback(err)));
}, (errQuery: Error) => callback(errQuery));
}], (errQuery: Error) => {
client.close();
cb(errQuery);
});
}
private typeConvertion(t: DataType): string {
switch (t) {
case DataType.INTEGER:
return "INTEGER";
case DataType.DATE:
return "TIMESTAMP";
case DataType.STRING:
return "TEXT";
case DataType.BOOLEAN:
return "BOOLEAN";
case DataType.FLOAT:
return "DOUBLE PRECISION";
default:
return "TEXT";
}
}
private extractDataView(view: View, filePath: string): string[]{
let name = view.name;
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.name;
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));
}
if (create) {
init = "CREATE TABLE " + name + "(" + props.join(", ") + ")";
}
else {
init = "DELETE FROM " + name;
}
return init;
}
private boolCast(text: string): string {
if (text === "t") {
return "true";
}
else if (text === "f") {
return "false";
}
else {
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;
}
}
../postgres/fixtures/
\ No newline at end of file
......@@ -20,14 +20,22 @@
import { Client, PoolConfig } from "pg";
import { View, LoadView } from "../../src/core/view";
import { Source } from "../../src/core/source";
import { each, series } from "async";
import * as fs from "fs";
import { DataType } from "../../src/common/types";
interface TransSet {
init: string;
data: string[];
}
interface SoucerParse{
name: string;
type: string[];
fields: string[];
}
export interface Schema {
alias?: string;
query?: string;
......@@ -44,31 +52,23 @@ export class Fixture {
this.database = config.database;
}
public load(schemas: LoadView[], create: boolean, cb: (err: Error) => void) {
public load(schemas: LoadView[], cb: (err: Error) => void): void {
let client = new Client(this.config);
/*
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((error) => {
if (error) {
cb(error);
return;
}
/*
Tables must be creates before data could be inserted, so the
queries that create and insert are splited in 2 arrays.
......@@ -76,8 +76,16 @@ export class Fixture {
is used. Inside series each query is executed, using each;
*/
series([(callback: (err: Error) => void) => {
each(init, (query, cback) => {
return client.query(query, [], (err: Error) => cback(err));
each(schemas, (query, cback) => {
client.query(this.createTransSet(query.view, query.data, true), [], (errCreate: Error) => {
if (errCreate) {
let regex = new RegExp(/relation \".*\" already exists/);
if (regex.test(errCreate.message.toLowerCase())){
return client.query(this.createTransSet(query.view, query.data, false), [], (errTrunc: Error) => cback(errTrunc));
}
}
return cback(errCreate);
});
}, (errQuery: Error) => callback(errQuery));
}, (callback: (err: Error) => void) => {
each(data, (query, cback) => {
......@@ -96,56 +104,119 @@ export class Fixture {
});
}
private typeConvertion(t: string) {
private typeConvertion(t: DataType): string {
switch (t) {
case "integer":
case DataType.INTEGER:
return "INTEGER";
case "date":
case DataType.DATE:
return "DATE";
case "string":
case DataType.STRING:
return "TEXT";
case "boolean":
case DataType.BOOLEAN:
return "BOOLEAN";
case DataType.FLOAT:
return "DOUBLE PRECISION";
default:
return "";
return "TEXT";
}
}
private createTransSet(view: View, filePath: string, create: boolean) {
let props = [];
private extractDataView(view: View, filePath: string): string[]{
let name = view.name;
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("'" + 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.name;
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 = "TRUNCATE TABLE " + name;
init = "TRUNCATE TABLE " + name;
}
return init;
}
public loadSource(source: Source[] , cb: (err: Error) => void): void {
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 in rows[i]) {
keys.push("\"" + key + "\"");
values.push("'" + rows[i][key] + "'");
let client = new Client(this.config);
client.connect((error) => {
if (error) {
cb(error);
return;
}
transaction.data.push("INSERT INTO " + name +
"(" + keys.join(", ") + ") " +
"VALUES (" + values.join(", ") + ")");
series([(callback: (err: Error) => void) => {
each(source, (insere, cback) => {
client.query ( this.extractData(insere, true), [], (errCreate: Error) => {
if (errCreate) {
let regex = new RegExp(/relation \".*\" already exists/);
if (regex.test(errCreate.message.toLowerCase())){
return client.query ( this.extractData(insere, false), [], (errTrunc: Error) => cback(errTrunc));
}
}
return cback(errCreate);
});
}, (errQuery: Error) => callback(errQuery));
}], (errQuery: Error) => {
if (errQuery) {
client.end();
cb(errQuery);
}
return transaction;
client.end((err) => {
cb(err);
});
});
});
}
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 = "TRUNCATE TABLE " + name + ";";
}
return consult;
}
}
[
{"met:seller:max:age": 23, "dim:seller:name": "Ade", "dim:seller:status": "active"}
,{"met:seller:max:age": 24, "dim:seller:name": "Luanne", "dim:seller:status": "active"}
,{"met:seller:max:age": 25, "dim:seller:name": "Florinda", "dim:seller:status": "active"}
,{"met:seller:max:age": 26, "dim:seller:name": "Bryanna", "dim:seller:status": "active"}
,{"met:seller:max:age": 27, "dim:seller:name": "Salvatore", "dim:seller:status": "sick leave"}
]
[
{ "dim:buyout:datein": "2018-01-01", "dim:provider:id": 20, "dim:product:id": 53
, "met:buyout:avg:quantity": 100,"met:buyout:max:quantity": 100,"met:buyout:min:quantity": 100},
{ "dim:buyout:datein": "2018-01-01", "dim:provider:id": 21, "dim:product:id": 54
, "met:buyout:avg:quantity": 120,"met:buyout:max:quantity": 120,"met:buyout:min:quantity": 120},
{ "dim:buyout:datein": "2018-01-01", "dim:provider:id": 22, "dim:product:id": 55
, "met:buyout:avg:quantity": 130,"met:buyout:max:quantity": 130,"met:buyout:min:quantity": 130},
{ "dim:buyout:datein": "2018-01-01", "dim:provider:id": 23, "dim:product:id": 56
, "met:buyout:avg:quantity": 140,"met:buyout:max:quantity": 140,"met:buyout:min:quantity": 140},
{ "dim:buyout:datein": "2018-01-01", "dim:provider:id": 24, "dim:product:id": 57
, "met:buyout:avg:quantity": 200,"met:buyout:max:quantity": 200,"met:buyout:min:quantity": 200}
]
[
{"dim:client:name": "Somboom", "dim:client:cpf": "500.345.583-65","dim:client:id": "7"},
{"dim:client:name": "Laci", "dim:client:cpf": "787.785.521-41","dim:client:id": "8"},
{"dim:client:name": "Rosalin", "dim:client:cpf": "463.478.120-45","dim:client:id": "9"},
{"dim:client:name": "Firoz", "dim:client:cpf": "352.324.206-15","dim:client:id": "10"},
{"dim:client:name": "Ravindra", "dim:client:cpf": "944.189.449-40","dim:client:id": "11"}
]
[
{"dim:provider:id": 1,"dim:product:id": 53},
{"dim:provider:id": 2,"dim:product:id": 54},
{"dim:provider:id": 3,"dim:product:id": 55},
{"dim:provider:id": 4,"dim:product:id": 56},
{"dim:provider:id": 5,"dim:product:id": 57}
]
\ No newline at end of file
[
{"dim:product:name": "Bacon", "dim:product:validity": "2018-03-01", "dim:product:id":53,
"met:product:avg:pricein": 10.20, "met:product:max:pricein": 10.20, "met:product:min:pricein":10.20,
"met:product:avg:priceout": 10.20, "met:product:max:priceout": 10.20, "met:product:min:priceout":10.20},
{"dim:product:name": "Coal", "dim:product:validity": "2018-05-10", "dim:product:id": 54,
"met:product:avg:pricein": 8.20, "met:product:max:pricein": 8.20, "met:product:min:pricein":8.20,
"met:product:avg:priceout": 8.20, "met:product:max:priceout": 8.20, "met:product:min:priceout": 8.20},
{"dim:product:name": "Meat", "dim:product:validity": "2018-02-17", "dim:product:id": 55 ,
"met:product:avg:pricein": 17.50, "met:product:max:pricein": 17.50, "met:product:min:pricein":17.50,
"met:product:avg:priceout": 17.50, "met:product:max:priceout": 17.50, "met:product:min:priceout": 17.50},
{"dim:product:name": "Beer", "dim:product:validity": "2018-06-10", "dim:product:id": 56 ,
"met:product:avg:pricein": 6.50 , "met:product:max:pricein": 6.50, "met:product:min:pricein":6.50,
"met:product:avg:priceout": 6.50, "met:product:max:priceout": 6.50, "met:product:min:priceout":6.50},
{"dim:product:name": "Trento", "dim:product:validity": "2018-08-23" , "dim:product:id": 57 ,
"met:product:avg:pricein": 2.50, "met:product:max:pricein": 2.50, "met:product:min:pricein": 2.50,
"met:product:avg:priceout": 2.50, "met:product:max:priceout": 2.50, "met:product:min:priceout": 2.50}
]
[
{"dim:provider:name": "ProviderA","dim:provider:id": 1 },
{"dim:provider:name": "ProviderB","dim:provider:id": 2 },
{"dim:provider:name": "ProviderC","dim:provider:id": 3 },
{"dim:provider:name": "ProviderD","dim:provider:id": 4 },
{"dim:provider:name": "ProviderE","dim:provider:id": 5 }
]
[
{ "dim:sell:registered": true, "dim:product:id": 53, "dim:seller:id": 1
, "dim:client:id": 7, "dim:sell:datein": "2018-02-17", "met:sell:sum:quantity": 10
, "met:sell:avg:quantity": 10 , "met:sell:count:quantity": 1},
{ "dim:sell:registered": true, "dim:product:id": 54, "dim:seller:id": 2
, "dim:client:id": 8, "dim:sell:datein": "2018-01-23", "met:sell:sum:quantity": 12
, "met:sell:avg:quantity": 12, "met:sell:count:quantity": 1},
{ "dim:sell:registered": false, "dim:product:id": 55, "dim:seller:id": 3
, "dim:client:id": 0, "dim:sell:datein": "2018-01-25", "met:sell:sum:quantity": 5
, "met:sell:avg:quantity": 5, "met:sell:count:quantity": 1},
{ "dim:sell:registered": true, "dim:product:id": 56, "dim:seller:id": 4
, "dim:client:id": 9, "dim:sell:datein": "2018-03-22", "met:sell:sum:quantity": 2
, "met:sell:avg:quantity": 2, "met:sell:count:quantity": 1},
{ "dim:sell:registered": true, "dim:product:id": 57, "dim:seller:id": 5
, "dim:client:id": 10, "dim:sell:datein": "2018-02-21", "met:sell:sum:quantity": 10
, "met:sell:avg:quantity": 10, "met:sell:count:quantity": 1}
]
[
{"dim:seller:name": "Ade", "dim:seller:sex": "undecided", "dim:seller:cpf":"344.805.128-45"
, "dim:seller:id": 1 , "dim:seller:status": "active", "met:seller:avg:age": 23
, "met:seller:max:age": 23, "met:seller:min:age":23, "met:seller:count:age": 1},
{"dim:seller:name": "Luanne", "dim:seller:sex": "nonbinary", "dim:seller:cpf":"977.221.375-39"
, "dim:seller:id": 2 , "dim:seller:status": "active", "met:seller:avg:age": 24
, "met:seller:max:age": 24, "met:seller:min:age":24, "met:seller:count:age": 1},
{"dim:seller:name": "Florinda", "dim:seller:sex": "female", "dim:seller:cpf":"885.517.020-17"
, "dim:seller:id": 3 , "dim:seller:status": "active", "met:seller:avg:age": 25
, "met:seller:max:age": 25, "met:seller:min:age":25, "met:seller:count:age": 1},
{"dim:seller:name": "Bryanna", "dim:seller:sex": "female", "dim:seller:cpf":"575.657.111-60"
, "dim:seller:id": 4 , "dim:seller:status": "active", "met:seller:avg:age": 26
, "met:seller:max:age": 26, "met:seller:min:age":26, "met:seller:count:age": 1},
{"dim:seller:name": "Salvatore", "dim:seller:sex": "male", "dim:seller:cpf":"604.424.718-07"
, "dim:seller:id": 5 , "dim:seller:status": "sick leave", "met:seller:avg:age": 27
, "met:seller:max:age": 27, "met:seller:min:age":27, "met:seller:count:age": 1}
]
[
{"met:seller:count:age" : 4, "dim:seller:status" : "active"},
{"met:seller:count:age" : 1, "dim:seller:status" : "sick leave"}
]
......@@ -24,390 +24,422 @@ import { Dimension } from "../src/core/dimension";
import { View } from "../src/core/view";
import { Filter, FilterOperator } from "../src/core/filter";
import { Clause } from "../src/core/clause";
import { AggregationType, RelationType } from "../src/common/types";
import { Query} from "../src/common/query";
interface EngineScenario {
metrics: Metric[];
dimensions: Dimension[];
subDimensions: Dimension[];
wrongMet: Metric;
wrongDim: Dimension;
views: View[];
import { AggregationType, RelationType , DataType} from "../src/common/types";
import { ViewHandler } from "../src/util/viewHandler";
import { EngineScenario, AdapterScenario, DataCtrlScenario } from "../src/util/scenarioHandler";
import { Query, QueryOpts } from "../src/common/query";
let configPath;
if(process.env.BLENDB_SCHEMA_FILE){
configPath = process.env.BLENDB_SCHEMA_FILE;
}
else{
throw new Error("BLENDB_SCHEMA_FILE wasn't informed");
}
interface AdapterScenario {
materializedView: View;
noSelectionView: View;
withSelectionView: View;
subDimensionView: View;
join4View: View;
dateView: View;
aggrView: View;
clauseView: View;
multiFilterView: View;
multiClauseView: View;
notEqualView: View;
gtltView: View;
geleView: View;
notMatchFilterView: View;
notOriginCount: View;
unMaterializebleView: View;
partialJoinView: View;
propagatedClauseView: View;
propagatedClauseAggrView: View;
const config = ConfigParser.parse(configPath);
const mets : {[key: string]: Metric} = {};
for (let i in config.metrics) {
let met = config.metrics[i];
mets[met.name] = met;
}
interface DataCtrlScenario {
wrongMet: Query;
wrongDim: Query;
correct: Query;
clausal: Query;
const dims : {[key:string]: Dimension} = {};
for (let i in config.dimensions) {
let dim = config.dimensions[i];
dims[dim.name] = dim;
}
const config = ConfigParser.parse("config/test.yaml");
const views : {[key:string]: View} = {};
for (let i in config.buildViews){
let view = config.buildViews[i];
views[view.alias] = view.view;
}
const mets = config.metrics.sort((a, b) => {
const aValue = parseInt(a.name.split(":")[1], 10);
const bValue = parseInt(b.name.split(":")[1], 10);
return aValue - bValue;
});
const dims = config.dimensions.sort((a, b) => {
const aValue = parseInt(a.name.split(":")[1], 10);
const bValue = parseInt(b.name.split(":")[1], 10);
return aValue - bValue;
const wrongMet = new Metric({
name: "met:this:is:just:a:test",
aggregation: AggregationType.COUNT,
dataType: DataType.INTEGER
});
const views = config.buildViews.sort((a, b) => {
const aValue = parseInt(a.alias.split(" ")[1], 10);
const bValue = parseInt(b.alias.split(" ")[1], 10);
return aValue - bValue;
}).map((item) => item.view);
const wrongDim = new Dimension({ name: "dim:this:is:just:a:test", dataType: DataType.INTEGER });
/**
* Create new filters to use in clause and test
* the clauses
*/
const filters: { [key: string]: Filter } = {
"dim:0:0" : new Filter({
target: dims[0],
"equal" : new Filter({
target : dims["dim:product:validity"],
operator : FilterOperator.EQUAL,
value: "2017-01-02"
value: "2018-05-10"
}),
"dim:0:1" : new Filter({
target: dims[0],
operator: FilterOperator.EQUAL,
value: "2017-01-03"
"lower" : new Filter({
target : dims["dim:product:validity"],
operator : FilterOperator.LOWER,
value: "2018-05-10"
}),
"dim:0:gt" : new Filter({
target: dims[0],
"greater" : new Filter({
target : dims["dim:product:validity"],
operator : FilterOperator.GREATER,
value: "2017-01-02"
}),
"dim:0:lt" : new Filter({
target: dims[0],
operator: FilterOperator.LOWER,
value: "2017-01-04"
value: "2018-05-10"
}),
"dim:0:ge" : new Filter({
target: dims[0],
"greaterq" : new Filter({
target : dims["dim:product:validity"],
operator : FilterOperator.GREATEREQ,
value: "2017-01-02"
value: "2018-06-10"
}),
"dim:0:le" : new Filter({
target: dims[0],
"lowerq" : new Filter({
target : dims["dim:product:validity"],
operator : FilterOperator.LOWEREQ,
value: "2017-01-04"
value: "2018-06-10"
}),
"dim:2" : new Filter({
target: dims[2],
"noteq" : new Filter({
target: dims["dim:product:validity"],
operator: FilterOperator.NOTEQUAL,
value: "1"
value: "2018-08-23"
}),
"dim:4" : new Filter({
target: dims[4],
operator: FilterOperator.NOTEQUAL,
value: "dim:4:1"
"clientRegistered" : new Filter({
target: dims["dim:sell:registered"],
operator: FilterOperator.EQUAL,
value: "false"
}),
"dim:5" : new Filter({
target: dims[5],
operator: FilterOperator.NOTEQUAL,
value: "true"
"averageBought": new Filter({
target: mets["met:sell:avg:quantity"],
operator: FilterOperator.GREATEREQ,
value: "10"
}),
"dim:7" : new Filter({
target: dims[7],
"equalFilterView": new Filter({
target: dims["dim:seller:status"],
operator: FilterOperator.EQUAL,
value: "1"
value: "active"
}),
"noneFilter": new Filter({
target: dims["dim:seller:status"],
operator: FilterOperator.NONE,
value: "active"
})
};
const clauses: { [key: string]: Clause } = {
"view0dim7": new Clause({filters: [filters["dim:7"]]}),
"view0gt": new Clause({filters: [filters["dim:0:gt"]]}),
"view0lt": new Clause({filters: [filters["dim:0:lt"]]}),
"view0ge": new Clause({filters: [filters["dim:0:ge"]]}),
"view0le": new Clause({filters: [filters["dim:0:le"]]}),
"view0dim0": new Clause({filters: [filters["dim:0:0"], filters["dim:0:1"]]}),
"view9dim2": new Clause({filters: [filters["dim:2"]]}),
"view6dim4": new Clause({filters: [filters["dim:4"]]}),
"view7dim5": new Clause({filters: [filters["dim:5"]]})
};
const wrongMet = new Metric({
name: "met:-1",
aggregation: AggregationType.COUNT,
dataType: "integer"
});
const wrongDim = new Dimension({ name: "dim:11", dataType: "integer" });
const subdimAux = new Dimension({
name: "sub:0",
dataType: "integer",
parent: dims[0],
relation: RelationType.DAY
});
}
const subdims = [
subdimAux,
new Dimension({
name: "sub:1",
dataType: "integer",
parent: dims[1],
const subdims : {[key:string]: Dimension} = {
"subdims_day" : new Dimension({
name: "subdims_day",
dataType: DataType.INTEGER,
parent: dims["dim:sell:datein"],
relation: RelationType.DAY
}),
new Dimension({
name: "sub:2",
dataType: "integer",
parent: subdimAux,
relation: RelationType.DAY
}),
new Dimension({
name: "sub:3",
dataType: "integer",
parent: null,
relation: RelationType.DAY
}),
new Dimension({
name: "sub:4",
dataType: "integer",
parent: dims[1],
relation: RelationType.DAY
})
].sort((a, b) => {
const aValue = parseInt(a.name.split(":")[1], 10);
const bValue = parseInt(b.name.split(":")[1], 10);
return aValue - bValue;
});
const dateSubDim = [
new Dimension ({
name: "dim:0:month",
dataType: "integer",
parent: dims[0],
"subdims_month" : new Dimension({
name: "subdims_month",
dataType: DataType.INTEGER,
parent: dims["dim:sell:datein"],
relation: RelationType.MONTH
}),
new Dimension ({
name: "dim:0:day",
dataType: "integer",
parent: dims[0],
relation: RelationType.DAY
}),
new Dimension ({
name: "dim:0:year",
dataType: "integer",
parent: dims[0],
"subdims_year" : new Dimension({
name: "subdims_year",
dataType: DataType.INTEGER,
parent: dims["dim:sell:datein"],
relation: RelationType.YEAR
}),
new Dimension ({
name: "dim:0:dow",
dataType: "integer",
parent: dims[0],
relation: RelationType.DAYOFWEEK
}),
];
"subdims_none" : new Dimension({
name: "subdims_none",
dataType: DataType.INTEGER,
parent: null,
relation: RelationType.NONE
})
}
const clauses: { [key: string]: Clause } = {
"lastDay":
new Clause({filters: [filters["equal"]]}),
"undefined":
new Clause({filters: [filters["noteq"]]}),
"unexpired":
new Clause({filters: [filters["greater"]]}),
"expired":
new Clause({filters: [filters["lower"]]}),
"unexpiredLastDay":
new Clause({filters: [filters["greaterq"]]}),
"expiredlastDay":
new Clause({filters: [filters["lowerq"]]}),
"clientRegistered":
new Clause({filters: [filters["clientRegistered"]]}),
"averageBought":
new Clause({filters: [filters["averageBought"]]}),
"expiredAndAverage":
// or between filteres => (A) || (B)
new Clause ({filters: [filters["lower"],filters["averageBought"]]}),
"equalClauseView":
new Clause ({filters: [filters["equalFilterView"]]}),
"emptyClause":
new Clause ({filters: []})
}
const dateView = new View({
metrics: [],
dimensions: dateSubDim,
materialized: false,
origin: false,
childViews: [views[0]]
});
const aggrView = new View({
metrics: [mets[0], mets[1], mets[6], mets[10], mets[11]],
let qOpts : {[key: string]: QueryOpts} = {
"JoinWithAncestors":
{
metrics: [mets["met:sell:count:quantity"]],
dimensions: [dims["dim:seller:id"],dims["dim:provider:id"]]
},
"joinWithNoMetrics":
{
metrics: [],
dimensions: [dims["dim:product:name"],dims["dim:seller:name"]]
},
"growOneView":
{
metrics: [mets["met:seller:min:age"]],
dimensions: [dims["dim:seller:name"],dims["dim:seller:sex"]]
},
"multipleClause":
{
metrics: [mets["met:sell:avg:quantity"]],
dimensions: [dims["dim:sell:datein"],dims["dim:seller:name"],
dims["dim:client:name"]],
// and between filters => (A) and (B)
clauses: [clauses["expired"],clauses["averageBought"]],
},
"singleClause":
{
metrics: [mets["met:sell:avg:quantity"]],
dimensions: [dims["dim:sell:datein"],dims["dim:seller:name"],
dims["dim:client:name"]],
clauses: [clauses["expiredAndAverage"]],
},
"equalfilter":
{
metrics: [],
dimensions: [dims["dim:client:name"],dims["dim:product:validity"]],
clauses: [clauses["lastDay"]],
},
"withSortView:0":
{
metrics: [mets["met:sell:sum:quantity"]],
dimensions: [dims["dim:client:name"]],
sort: [mets["met:sell:sum:quantity"]]
},
"withSortView:1":
{
metrics: [mets["met:sell:sum:quantity"]],
dimensions: [dims["dim:client:id"]]
},
"subDimView:0":
{
metrics: [],
dimensions : [dims["dim:sell:datein"],subdims["subdims_day"],
subdims["subdims_month"],subdims["subdims_year"]]
},
"subDimView:1":
{
metrics: [],
dimensions: [dims["dim:sell:datein"]]
},
"joinOneView":
{
metrics: [mets["met:product:avg:pricein"]],
dimensions: [],
materialized: false,
origin: false,
childViews: [views[0], views[2], views[3]]
});
},
"reduceAsView":
{
metrics: [mets["met:sell:sum:quantity"],mets["met:sell:avg:quantity"],
mets["met:sell:count:quantity"]],
dimensions: [dims["dim:sell:registered"], dims["dim:product:id"],
dims["dim:seller:id"], dims["dim:client:id"],dims["dim:sell:datein"]],
sort: [mets["met:sell:sum:quantity"]]
},
"clientAverageBought:0":
{
metrics: [mets["met:sell:avg:quantity"]],
dimensions: [dims["dim:client:name"]],
clauses: [clauses["averageBought"]]
},
"clientAverageBought:1":
{
metrics: [mets["met:sell:avg:quantity"]],
dimensions: [dims["dim:client:name"], dims["dim:seller:id"]]
},
"queryNoParent":
{
metrics: [mets["met:sell:count:quantity"]],
dimensions: [subdims["subdims_none"]]
},
"queryMetsDims":
{
metrics : Object.keys(mets).map((key) => mets[key]),
dimensions : Object.keys(dims).map((key) => dims[key])
},
"queryNoMets":
{
metrics: [wrongMet],
dimensions: [dims["dim:product:name"]]
},
"queryNoDims":
{
metrics: [mets["met:buyout:min:quantity"]],
dimensions: [wrongDim]
},
"queryProduct":
{
metrics: [mets["met:product:avg:pricein"], mets["met:product:max:pricein"], mets["met:product:min:pricein"],
mets["met:product:avg:priceout"],mets["met:product:max:priceout"],mets["met:product:min:priceout"]],
dimensions: [dims["dim:product:name"], dims["dim:product:validity"],dims["dim:product:id"]]
},
"queryActive":
{
metrics: [mets["met:seller:max:age"]],
dimensions: [dims["dim:seller:name"],dims["dim:seller:status"]],
clauses: [clauses["equalClauseView"]]
},
"querySubDim":
{
metrics : [],
dimensions : [subdims["subdims_day"],subdims["subdims_month"]]
},
"wrongMet":
{
metrics: [wrongMet],
dimensions: [dims["dim:product:id"]]
},
"seller":
{
metrics:[mets["met:sell:sum:quantity"]],
dimensions:[dims["dim:sell:registered"],dims["dim:product:id"]]
},
"wrongDim":
{
metrics: [mets["met:sell:avg:quantity"]],
dimensions: [wrongDim]
},
"correct":
{
metrics: [mets["met:buyout:avg:quantity"]],
dimensions: [dims["dim:provider:id"]]
},
"clausal":
{
metrics: [mets["met:product:avg:pricein"]],
dimensions: [dims["dim:product:name"],
dims["dim:product:id"]]
},
"expensive":
{
metrics: [mets["met:product:max:pricein"]],
dimensions: [dims["dim:product:name"],
dims["dim:product:id"]]
},
"originfalse":
{
metrics: [mets["met:seller:count:age"]],
dimensions: []
},
"csv": {
metrics: [mets["met:seller:avg:age"]],
dimensions: [dims["dim:seller:cpf"], dims["dim:seller:sex"]]
}
}
const clauseView = new View({
metrics: [mets[0], mets[1], mets[2]],
dimensions: [dims[0]],
materialized: false,
origin: false,
childViews: [views[0]],
clauses: [clauses.view0dim7]
});
const queries : {[key: string]: Query} = {};
for(let i in qOpts){
queries[i] = new Query(qOpts[i]);
}
const multiFilterView = new View({
metrics: [mets[0], mets[1]],
dimensions: [dims[0]],
materialized: false,
origin: false,
childViews: [views[0]],
clauses: [clauses.view0dim0]
});
const JoinWithAncestors = ViewHandler.growView(queries["JoinWithAncestors"],
[views["view:Sell"]]);
const multiClauseView = new View({
metrics: [mets[0], mets[1]],
dimensions: [dims[0]],
materialized: false,
origin: false,
childViews: [views[0]],
clauses: [clauses.view0dim0, clauses.view0dim7]
});
const joinWithNoMetrics = ViewHandler.growView(queries["joinWithNoMetrics"],
[views["view:Product"],
views["view:Sell"],
views["view:Seller"]]);
const notEqualView = new View({
metrics: [],
dimensions: [dims[4], dims[5]],
materialized: false,
origin: false,
childViews: [views[7]],
clauses: [clauses.view7dim5]
});
const growOneView = ViewHandler.growView(queries["growOneView"],
[views["view:Seller"]]);
const gtltView = new View({
metrics: [],
dimensions: [dims[0]],
materialized: false,
origin: false,
childViews: [views[0]],
clauses: [clauses.view0gt, clauses.view0lt]
});
const multipleClause = ViewHandler.growView(queries["multipleClause"],
[views["view:Sell"],
views["view:Seller"],
views["view:Client"],
views["view:Product"]]);
const geleView = new View({
metrics: [],
dimensions: [dims[0]],
materialized: false,
origin: false,
childViews: [views[0]],
clauses: [clauses.view0ge, clauses.view0le]
});
const singleClause = ViewHandler.growView(queries["singleClause"],
[views["view:Sell"],
views["view:Seller"],
views["view:Client"],
views["view:Product"]]);
const notMatchFilterView = new View({
metrics: [mets[0]],
dimensions: [dims[0]],
materialized: false,
origin: false,
childViews: [views[0]],
clauses: [clauses.view7dim5]
});
const equalfilter = ViewHandler.queryJoin(queries["equalfilter"],
[views["view:Sell"],
views["view:Client"],
views["view:Product"]]);
const subDimView = new View({
metrics: [mets[0]],
dimensions: [subdims[0], subdims[1], dims[7], dims[8]],
materialized: false,
origin: false,
childViews: [views[0], views[1], views[4]]
});
const withSortView = ViewHandler.queryJoin(queries["withSortView:0"],
[ViewHandler.queryReduce(queries["withSortView:1"],
views["view:Sell"]),
views["view:Client"]]);
const join4View = new View({
metrics: [mets[0], mets[1], mets[2], mets[3], mets[4], mets[5]],
dimensions: [dims[2], dims[7], dims[8]],
materialized: false,
origin: false,
childViews: [views[0], views[1], views[2], views[4]]
});
const subDimView = ViewHandler.queryJoin(queries["subDimView:0"],
[ViewHandler.queryReduce(queries["subDimView:1"],
views["view:Sell"]),
views["view:Sell"]]);
const noSelView = new View({
metrics: [mets[0], mets[3]],
dimensions: [],
materialized: false,
origin: false,
childViews: [views[0], views[1]]
});
const joinOneView = ViewHandler.queryJoin(queries["joinOneView"],
[views["view:Product"]]);
const withSelView = new View({
metrics: [mets[0], mets[1]],
dimensions: [dims[7], dims[8]],
materialized: false,
origin: false,
childViews: [views[0], views[4]]
});
const reduceAsView = ViewHandler.queryReduce(queries["reduceAsView"],
views["view:Sell"]);
const notOriginCount = new View({
metrics: [mets[5], mets[6], mets[7]],
dimensions: [dims[2]],
materialized: true,
origin: false,
clauses: [clauses.view9dim2]
});
const clientAverageBought = ViewHandler.queryReduce(queries["clientAverageBought:0"],
ViewHandler.queryJoin(queries["clientAverageBought:1"],
[views["view:Sell"],views["view:Client"]]));
const unMaterializebleView = new View({
metrics: [mets[7], mets[9]],
dimensions: [dims[5]],
materialized: false,
origin: false,
childViews: [views[3], views[5], views[7], views[8]]
});
const viewProduct = views["view:Product"];
const partialJoinView = new View({
metrics: [mets[7], mets[8]],
dimensions: [],
materialized: false,
origin: false,
childViews: [views[3], views[5], views[6]]
});
const viewActiveSeller = views["view:ActiveSeller"];
const propagatedClauseView = new View({
metrics: [mets[8]],
dimensions: [dims[4]],
materialized: false,
origin: false,
childViews: [views[6], views[7]],
clauses: [clauses.view7dim5, clauses.view6dim4]
});
const viewSumCount = ViewHandler.queryReduce(queries["originfalse"],views["view:SellerStatus"]);
const propagatedClauseAggrView = new View({
metrics: [mets[8], mets[5]],
dimensions: [dims[2]],
materialized: false,
origin: false,
childViews: [views[9], views[6], views[7]],
clauses: [clauses.view7dim5, clauses.view6dim4, clauses.view9dim2]
});
// Exports
export const engineScenario: EngineScenario = {
metrics: mets,
dimensions: dims,
wrongMet: wrongMet,
wrongDim: wrongDim,
subDimensions: subdims,
views: views
queryMetsDims: queries["queryMetsDims"],
queryNoMets: queries["queryNoMets"],
queryNoDims: queries["queryNoDims"],
queryProduct: queries["queryProduct"],
viewProduct: viewProduct,
queryActive: queries["queryActive"],
viewActiveSeller: viewActiveSeller,
querySubDim: queries["querySubDim"],
queryNoParent: queries["queryNoParent"],
config: config
};
export const adapterScenario: AdapterScenario = {
materializedView: views[0],
noSelectionView: noSelView,
withSelectionView: withSelView,
materializedView: views["view:Product"],
sortView: withSortView,
joinWithOneView: joinOneView,
singleClause: singleClause,
multipleClause: multipleClause,
filterAverageBought: clientAverageBought,
reduceAsView: reduceAsView,
filterWithEqual: equalfilter,
subDimensionView: subDimView,
join4View: join4View,
dateView: dateView,
aggrView: aggrView,
clauseView: clauseView,
multiFilterView: multiFilterView,
multiClauseView: multiClauseView,
notEqualView: notEqualView,
gtltView: gtltView,
geleView: geleView,
notMatchFilterView: notMatchFilterView,
notOriginCount: notOriginCount,
unMaterializebleView: unMaterializebleView,
partialJoinView: partialJoinView,
propagatedClauseView: propagatedClauseView,
propagatedClauseAggrView: propagatedClauseAggrView
joinWithNoMetrics: joinWithNoMetrics,
growOneView: growOneView,
JoinWithAncestors:JoinWithAncestors,
viewSumCount: viewSumCount,
config: config
};
export const dataCtrlScenario: DataCtrlScenario = {
wrongMet: { metrics: [wrongMet], dimensions: [dims[0]] },
wrongDim: { metrics: [mets[0]], dimensions: [wrongDim] },
correct: { metrics: [mets[0]], dimensions: [dims[0]] },
clausal: { metrics: [mets[0]], dimensions: [dims[7]] }
seller: queries["seller"],
wrongMet: queries["wrongMet"],
wrongDim: queries["wrongDim"],
correct: queries["correct"],
clausal: queries["clausal"],
expensive: queries["expensive"],
csv: queries["csv"],
};
{
"extends": "tslint:recommended",
"rules": {
"no-string-literal" : false,
"no-var-requires": false,
"object-literal-sort-keys": false,
"one-line": false,
"trailing-comma": false,
"interface-name": false
"interface-name": false,
"max-line-length": false,
"member-ordering": false,
"ordered-imports": false,
"prefer-const": false,
"prefer-for-of": false,
"only-arrow-functions": false,
"no-unused-expression": false,
"space-before-function-paren": false,
"object-literal-shorthand":false,
"array-type": false,
"arrow-parens": false,
"callable-types": false,
"no-shadowed-variable": false
}
}
Source diff could not be displayed: it is too large. Options to address this: view the blob.