Issue #35: Add possibility to configParser parse clauses/filters

Signed-off-by: Lucas Fernandes de Oliveira's avatarLucas Fernandes de Oliveira <lfo14@inf.ufpr.br>
parent e019f6c1
Pipeline #11376 passed with stage
in 42 seconds
......@@ -103,6 +103,8 @@ schema:
- "met:5"
- "met:6"
- "met:7"
clauses:
- "dim:2!=1"
metrics:
-
name: "met:0"
......
......@@ -304,7 +304,7 @@ describe("postgres adapter", () => {
adapter.getDataFromView(view, (err, result) => {
expect(err).to.be.a("null");
expect(result).to.be.an("array");
expect(result).to.have.length(5);
expect(result).to.have.length(4);
expect(result[0]).to.be.an("object");
let keys: string[] = [];
keys = keys.concat(view.metrics.map((item) => item.name));
......
......@@ -138,6 +138,10 @@ export class Filter {
}
private static isTypeValid(op: FilterOptions): boolean {
if (op.operator === FilterOperator.NONE) {
return false;
}
if (op.operator === FilterOperator.GREATER ||
op.operator === FilterOperator.LOWER ||
op.operator === FilterOperator.GREATEREQ ||
......
......@@ -40,8 +40,6 @@ function strToRelationType (str: string): RelationType {
}
describe("configParser utility library", () => {
let metMap = new Map();
let dimMap = new Map();
it("should throw expection for inexistent metric", () => {
let opts: ViewParsingOptions = {
alias: "Test",
......@@ -52,7 +50,7 @@ describe("configParser utility library", () => {
let error: boolean = false;
try {
ConfigParser.parseViewOpt(opts, metMap, dimMap);
ConfigParser.parseViewOpt(opts, {}, {});
}
catch (e) {
error = true;
......@@ -73,7 +71,7 @@ describe("configParser utility library", () => {
let error: boolean = false;
try {
ConfigParser.parseViewOpt(opts, metMap, dimMap);
ConfigParser.parseViewOpt(opts, {}, {});
}
catch (e) {
error = true;
......@@ -107,6 +105,62 @@ describe("configParser utility library", () => {
expect(error).to.be.true;
});
it("should throw expection for bad formed clause, invalid operator", () => {
let opts: ViewParsingOptions = {
alias: "thisMUSTgoesWrong",
data: "someRandomPath",
origin: true,
dimensions: ["dim:0"],
metrics: [],
clauses: ["dim:0?=1"]
};
let dimMap: {[key: string]: Dimension} = {
"dim:0" : new Dimension({name: "dim:0", dataType: "integer"})
};
let error: boolean = false;
try {
ConfigParser.parseViewOpt(opts, {}, dimMap);
}
catch (e) {
error = true;
expect(e.message).to.be
.equal("[Parsing error] Bad formed clause: on view \"" + opts.alias +
"\" the clause \"dim:0?=1\" could not be created");
}
expect(error).to.be.true;
});
it("should throw expection for bad formed clause, invalid target", () => {
let opts: ViewParsingOptions = {
alias: "thisMUSTgoesWrong",
data: "someRandomPath",
origin: true,
dimensions: ["dim:0"],
metrics: [],
clauses: ["dim:1==1"]
};
let dimMap: {[key: string]: Dimension} = {
"dim:0" : new Dimension({name: "dim:0", dataType: "integer"})
};
let error: boolean = false;
try {
ConfigParser.parseViewOpt(opts, {}, dimMap);
}
catch (e) {
error = true;
expect(e.message).to.be
.equal("[Parsing error] Bad formed clause: on view \"" + opts.alias +
"\" the clause \"dim:1==1\" could not be created");
}
expect(error).to.be.true;
});
it("should parse subdimentions relations correctly", () => {
let opts: DimensionStrOptions[] = [
{
......
......@@ -22,6 +22,8 @@ import { Metric, MetricOptions } from "../core/metric";
import { Dimension, DimensionOptions } from "../core/dimension";
import { View, ViewOptions, LoadView } from "../core/view";
import { AggregationType, RelationType } from "../common/types";
import { Filter } from "../core/filter";
import { Clause } from "../core/clause";
import { PoolConfig } from "pg";
import * as fs from "fs";
import * as yaml from "js-yaml";
......@@ -32,6 +34,7 @@ export interface ViewParsingOptions {
origin?: boolean;
dimensions: string[];
metrics: string[];
clauses?: string[];
}
interface MetricStrOptions {
......@@ -73,6 +76,14 @@ export interface ParsedConfig {
loadViews: LoadView[];
}
interface DimensionMap {
[key: string]: Dimension;
}
interface MetricMap {
[key: string]: Metric;
}
export class ConfigParser {
public static parse(configPath: string): ParsedConfig {
let config: ConfigFile = yaml.safeLoad(fs.readFileSync(configPath, {
......@@ -91,19 +102,19 @@ export class ConfigParser {
loadViews: []
};
let metMap: Map<string, Metric> = new Map();
let dimMap: Map<string, Dimension> = new Map();
let metMap: MetricMap = {};
let dimMap: DimensionMap = {};
for (let i = 0; i < metricsOpts.length; ++i) {
let met = new Metric(this.parseMetOpts(metricsOpts[i]));
parsed.metrics.push(met);
metMap.set(met.name, met);
metMap[met.name] = met;
}
for (let i = 0; i < dimensionsOpts.length; ++i) {
let dim = new Dimension(this.parseDimOpts(dimensionsOpts[i], parsed.dimensions));
parsed.dimensions.push(dim);
dimMap.set(dim.name, dim);
dimMap[dim.name] = dim;
}
for (let i = 0; i < viewsOpts.length; ++i) {
......@@ -121,8 +132,8 @@ export class ConfigParser {
}
public static parseViewOpt(opts: ViewParsingOptions,
metMap: Map<string, Metric>,
dimMap: Map<string, Dimension>): ViewOptions {
metMap: MetricMap,
dimMap: DimensionMap): ViewOptions {
let viewOpt: ViewOptions = {
metrics: [],
......@@ -130,11 +141,12 @@ export class ConfigParser {
materialized: true,
origin: opts.origin,
childViews: [],
clauses: []
};
for (let i = 0; i < opts.metrics.length; ++i) {
if (metMap.has(opts.metrics[i])) {
viewOpt.metrics.push(metMap.get(opts.metrics[i]));
if (metMap[opts.metrics[i]]) {
viewOpt.metrics.push(metMap[opts.metrics[i]]);
}
else {
......@@ -143,14 +155,28 @@ export class ConfigParser {
}
for (let i = 0; i < opts.dimensions.length; ++i) {
if (dimMap.has(opts.dimensions[i])) {
viewOpt.dimensions.push(dimMap.get(opts.dimensions[i]));
if (dimMap[opts.dimensions[i]]) {
viewOpt.dimensions.push(dimMap[opts.dimensions[i]]);
}
else {
throw new Error("[Parsing error] Non exist dimension set to view " + opts.alias);
}
}
if (opts.clauses) {
for (let i = 0; i < opts.clauses.length; ++i) {
const clause = this.parseClause(opts.clauses[i], metMap, dimMap);
if (clause) {
viewOpt.clauses.push(clause);
}
else {
throw new Error("[Parsing error] Bad formed clause: on view \"" +
opts.alias + "\" the clause \"" + opts.clauses[i] +
"\" could not be created");
}
}
}
return viewOpt;
}
......@@ -185,6 +211,43 @@ export class ConfigParser {
};
}
private static parseClause (opts: string, metMap: MetricMap, dimMap: DimensionMap): Clause {
const strFilters = opts.split(",");
const filters: Filter[] = strFilters.map((item) => {
return this.parseFilter(item, metMap, dimMap);
});
for (let i = 0; i < filters.length; ++i) {
if (!filters[i] || !filters[i].isValid) {
return null;
}
}
return new Clause ({filters: filters});
}
private static parseFilter (opts: string, metMap: MetricMap, dimMap: DimensionMap): Filter {
const strFilter = Filter.segment(opts);
if (!strFilter) {
return null;
}
let target: Metric|Dimension = dimMap[strFilter.target];
if (!target) {
target = metMap[strFilter.target];
if (!target) {
return null;
}
}
const operator = Filter.parseOperator(strFilter.operator);
return new Filter({
target: target,
operator: operator,
value: strFilter.value
});
}
private static strToAggregationType (str: string): AggregationType {
switch (str) {
case "sum":
......
[
{"dim:2":"1","met:5":"1","met:6":"1","met:7":"1"},
{"dim:2":"2","met:5":"2","met:6":"1","met:7":"1"},
{"dim:2":"3","met:5":"3","met:6":"1","met:7":"1"},
{"dim:2":"4","met:5":"4","met:6":"1","met:7":"1"},
......
......@@ -98,6 +98,11 @@ const filters: { [key: string]: Filter } = {
operator: FilterOperator.LOWEREQ,
value: "2017-01-04"
}),
"dim:2" : new Filter({
target: dims[2],
operator: FilterOperator.NOTEQUAL,
value: "1"
}),
"dim:5" : new Filter({
target: dims[5],
operator: FilterOperator.NOTEQUAL,
......@@ -117,6 +122,7 @@ const clauses: { [key: string]: Clause } = {
"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"]]}),
"view7dim5": new Clause({filters: [filters["dim:5"]]})
};
......@@ -304,7 +310,8 @@ const notOriginCount = new View({
metrics: [mets[5], mets[6], mets[7]],
dimensions: [dims[2]],
materialized: true,
origin: false
origin: false,
clauses: [clauses.view9dim2]
});
export const engineScenario: EngineScenario = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment