From f26a44196bf51e10445e9bc5a2eca1395b1185cb Mon Sep 17 00:00:00 2001 From: Lucas Fernandes de Oliveira <lfo14@inf.ufpr.br> Date: Thu, 3 Aug 2017 11:55:16 -0300 Subject: [PATCH] Issue #27: Fix count aggregation Signed-off-by: Lucas Fernandes de Oliveira <lfo14@inf.ufpr.br> --- config/ci_test.yaml.example | 9 +++++++++ src/adapter/postgres.spec.ts | 21 +++++++++++++++++++++ src/adapter/postgres.ts | 9 +++++---- src/core/engine.ts | 1 + src/core/view.ts | 3 +++ src/util/configParser.ts | 2 ++ src/util/graph.spec.ts | 15 +++++++++++++++ test/scenario.ts | 28 +++++++++++++++++++++++++++- 8 files changed, 83 insertions(+), 5 deletions(-) diff --git a/config/ci_test.yaml.example b/config/ci_test.yaml.example index 4ec663f5..4a6d5858 100644 --- a/config/ci_test.yaml.example +++ b/config/ci_test.yaml.example @@ -17,6 +17,7 @@ schema: - alias: "View 0" data: "test/postgres/fixtures/view0.json" + origin: true dimensions: - "dim:0" - "dim:7" @@ -27,6 +28,7 @@ schema: - alias: "View 1" data: "test/postgres/fixtures/view1.json" + origin: true dimensions: - "dim:1" - "dim:8" @@ -36,6 +38,7 @@ schema: - alias: "View 2" data: "test/postgres/fixtures/view2.json" + origin: true dimensions: - "dim:2" metrics: @@ -44,6 +47,7 @@ schema: - alias: "View 3" data: "test/postgres/fixtures/view3.json" + origin: true dimensions: - "dim:2" - "dim:3" @@ -51,6 +55,7 @@ schema: - alias: "View 4" data: "test/postgres/fixtures/view4.json" + origin: true dimensions: - "dim:2" - "dim:7" @@ -58,6 +63,7 @@ schema: - alias: "View 5" data: "test/postgres/fixtures/view5.json" + origin: true dimensions: - "dim:3" metrics: @@ -65,6 +71,7 @@ schema: - alias: "View 6" data: "test/postgres/fixtures/view6.json" + origin: true dimensions: - "dim:4" metrics: @@ -72,6 +79,7 @@ schema: - alias: "View 7" data: "test/postgres/fixtures/view7.json" + origin: true dimensions: - "dim:4" - "dim:5" @@ -79,6 +87,7 @@ schema: - alias: "View 8" data: "test/postgres/fixtures/view8.json" + origin: true dimensions: - "dim:5" - "dim:6" diff --git a/src/adapter/postgres.spec.ts b/src/adapter/postgres.spec.ts index 370c7bdf..cae97a84 100644 --- a/src/adapter/postgres.spec.ts +++ b/src/adapter/postgres.spec.ts @@ -148,4 +148,25 @@ describe("postgres adapter", () => { done(); }); }); + it("should get data from view with all types of agreggation", (done) => { + let view = adapterScenario.aggrView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(1); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); + }); + + expect(parseInt(result[0]["met:0"], 10)).to.be.equal(15); + expect(parseInt(result[0]["met:1"], 10)).to.be.equal(3); + expect(parseInt(result[0]["met:6"], 10)).to.be.equal(5); + done(); + }); + }); }); diff --git a/src/adapter/postgres.ts b/src/adapter/postgres.ts index c7353aa2..685963c4 100644 --- a/src/adapter/postgres.ts +++ b/src/adapter/postgres.ts @@ -66,7 +66,7 @@ export class PostgresAdapter extends Adapter { view. So is possible only get useful data in the sub-querys. */ let strMetrics = metrics.map((metric) => { - let func = this.getAggregateFunction(metric.aggregation); + let func = this.getAggregateFunction(metric.aggregation, view.origin); let quotedName = "\"" + metric.name + "\""; let extMetric = func + "(" + quotedName + ") AS " + quotedName; return extMetric; @@ -167,7 +167,8 @@ export class PostgresAdapter extends Adapter { }); child.metrics.forEach((metric: Metric) => { - let func = this.getAggregateFunction(metric.aggregation); + // Only materialized views can have origin as true + let func = this.getAggregateFunction(metric.aggregation, false); let quotedName = "\"" + metric.name + "\""; let extMetric = func + "(" + child.alias + "." + quotedName + ") AS " + quotedName; elements.push(extMetric); @@ -189,14 +190,14 @@ export class PostgresAdapter extends Adapter { } } - private getAggregateFunction(aggrType: AggregationType): string { + private getAggregateFunction(aggrType: AggregationType, origin: boolean): string { switch (aggrType) { case AggregationType.SUM: return "SUM"; case AggregationType.AVG: return "AVG"; case AggregationType.COUNT: - return "COUNT"; + return (origin) ? "COUNT" : "SUM"; default: return ""; } diff --git a/src/core/engine.ts b/src/core/engine.ts index 39fbfbb5..f96a5b78 100644 --- a/src/core/engine.ts +++ b/src/core/engine.ts @@ -112,6 +112,7 @@ export class Engine { metrics: q.metrics, dimensions: q.dimensions, materialized: false, + origin: false, // Never a dynamic generated view will be origin childViews: optimalViews }; diff --git a/src/core/view.ts b/src/core/view.ts index 6de687e4..dba8c040 100644 --- a/src/core/view.ts +++ b/src/core/view.ts @@ -36,6 +36,7 @@ export interface ChildView { export interface ViewOptions { metrics: Metric[]; dimensions: Dimension[]; + origin: boolean; materialized?: boolean; childViews?: ChildView[]; } @@ -45,12 +46,14 @@ export class View { public readonly metrics: Metric[]; public readonly dimensions: Dimension[]; public readonly materialized: boolean; + public readonly origin: boolean; public childViews: ChildView[]; constructor (options: ViewOptions) { this.metrics = options.metrics.sort(); this.dimensions = options.dimensions.sort(); this.materialized = options.materialized || false; + this.origin = options.origin || false; this.childViews = (options.childViews) ? options.childViews : []; // calculate the id of the view based on it's metrics and dimensions diff --git a/src/util/configParser.ts b/src/util/configParser.ts index 1aaf8c66..3064e7b1 100644 --- a/src/util/configParser.ts +++ b/src/util/configParser.ts @@ -29,6 +29,7 @@ import * as yaml from "js-yaml"; export interface ViewParsingOptions { alias: string; data: string; + origin?: boolean; dimensions: string[]; metrics: string[]; } @@ -127,6 +128,7 @@ export class ConfigParser { metrics: [], dimensions: [], materialized: true, + origin: opts.origin, childViews: [], }; diff --git a/src/util/graph.spec.ts b/src/util/graph.spec.ts index 17de06d0..6b0cc095 100644 --- a/src/util/graph.spec.ts +++ b/src/util/graph.spec.ts @@ -93,16 +93,19 @@ describe("graph class", () => { new View({ metrics: [], dimensions: [dims[0], dims[1]], + origin: true, materialized: true }), new View({ metrics: [], dimensions: [dims[2], dims[3]], + origin: true, materialized: true }), new View({ metrics: [], dimensions: dims, + origin: true, materialized: true }) ]; @@ -127,6 +130,7 @@ describe("graph class", () => { let view = new View({ metrics: [], dimensions: [dims[0], dims[1]], + origin: true, materialized: true }); @@ -148,6 +152,7 @@ describe("graph class", () => { let view = new View({ metrics: [], dimensions: dims, + origin: true, materialized: true }); @@ -169,6 +174,7 @@ describe("graph class", () => { let view = new View({ metrics: [], dimensions: [dim], + origin: true, materialized: true }); @@ -186,6 +192,7 @@ describe("graph class", () => { let view = new View({ metrics: [], dimensions: [dim], + origin: true, materialized: true }); @@ -220,31 +227,37 @@ describe("graph class", () => { new View({ metrics: [mets[0]], dimensions: [dims[0]], + origin: true, materialized: true }), new View({ metrics: [mets[1]], dimensions: [dims[1]], + origin: true, materialized: true }), new View({ metrics: [mets[2]], dimensions: [dims[2]], + origin: true, materialized: true }), new View({ metrics: [], dimensions: dims, + origin: true, materialized: true }), new View({ metrics: mets, dimensions: dims, + origin: true, materialized: true }), new View({ metrics: [mets[0], mets[1]], dimensions: [dims[0], dims[1]], + origin: true, materialized: true }), ]; @@ -286,6 +299,7 @@ describe("graph class", () => { let view = new View({ metrics: [], dimensions: [dims[0]], + origin: true, materialized: true }); @@ -324,6 +338,7 @@ describe("graph class", () => { let view = new View({ metrics: [], dimensions: [dims[0]], + origin: true, materialized: true }); diff --git a/test/scenario.ts b/test/scenario.ts index f5d778d8..45a428c1 100644 --- a/test/scenario.ts +++ b/test/scenario.ts @@ -41,6 +41,7 @@ interface AdapterScenario { subDimensionView: View; join4View: View; dateView: View; + aggrView: View; } interface DataCtrlScenario { @@ -128,6 +129,7 @@ const dateView = new View({ metrics: [], dimensions: dateSubDim, materialized: false, + origin: false, childViews: [{ view: views[0], metrics: [], @@ -135,10 +137,30 @@ const dateView = new View({ }] }); +const aggrView = new View({ + metrics: [mets[0], mets[1], mets[6]], + dimensions: [], + materialized: false, + origin: false, + childViews: [ + { + view: views[0], + metrics: [mets[0], mets[1]], + dimensions: [] + }, + { + view: views[2], + metrics: [mets[6]], + dimensions: [] + } + ] +}); + const subDimView = new View({ metrics: [mets[0]], dimensions: [subdims[0], subdims[1], dims[7], dims[8]], materialized: false, + origin: false, childViews: [ { view: views[0], @@ -162,6 +184,7 @@ 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: [ { view: views[0], @@ -190,6 +213,7 @@ const noSelView = new View({ metrics: [mets[0], mets[3]], dimensions: [], materialized: false, + origin: false, childViews: [ { view: views[0], @@ -208,6 +232,7 @@ const withSelView = new View({ metrics: [mets[0], mets[1]], dimensions: [dims[7], dims[8]], materialized: false, + origin: false, childViews: [ { view: views[0], @@ -237,7 +262,8 @@ export const adapterScenario: AdapterScenario = { withSelectionView: withSelView, subDimensionView: subDimView, join4View: join4View, - dateView: dateView + dateView: dateView, + aggrView: aggrView }; export const dataCtrlScenario: DataCtrlScenario = { -- GitLab