diff --git a/src/adapter/postgres.ts b/src/adapter/postgres.ts index fc5af7bbd14e467357ac171fcb0147c73dc3ff36..d12c6894a930d0408e98892d09c93a43ce7080fd 100644 --- a/src/adapter/postgres.ts +++ b/src/adapter/postgres.ts @@ -125,7 +125,7 @@ export class PostgresAdapter extends Adapter { } else { - let children = view.childViews.map((item) => item.view); + let children = view.childViews; for (let i = 0; i < children.length; ++i) { r = r.concat(this.searchMaterializedViews(children[i])); } diff --git a/src/core/engine.spec.ts b/src/core/engine.spec.ts index 2bdbb74939686f442f35c24e8e476b3bf46dcaa8..cefbf13d104a7db4be78c4939300fefb146fb26f 100644 --- a/src/core/engine.spec.ts +++ b/src/core/engine.spec.ts @@ -137,10 +137,10 @@ describe("engine class", () => { expect(optimalView.childViews).to.have.length(1); expect(optimalView).satisfy((optView: View) => { - return optView.childViews[0].dimensions.some((item) => item.name === subdim[0].name); + return optView.dimensions.some((item) => item.name === subdim[0].name); }); expect(optimalView).satisfy((optView: View) => { - return optView.childViews[0].dimensions.some((item) => item.name === subdim[1].name); + return optView.dimensions.some((item) => item.name === subdim[1].name); }); }); @@ -163,10 +163,10 @@ describe("engine class", () => { expect(optimalView.childViews).to.have.length(1); expect(optimalView).satisfy((optView: View) => { - return optView.childViews[0].dimensions.some((item) => item.name === subdim[2].name); + return optView.dimensions.some((item) => item.name === subdim[2].name); }); expect(optimalView).satisfy((optView: View) => { - return optView.childViews[0].dimensions.some((item) => item.name === subdim[4].name); + return optView.dimensions.some((item) => item.name === subdim[4].name); }); }); diff --git a/src/core/engine.ts b/src/core/engine.ts index f96a5b782c2341a72351c4d60b6760f91c76086b..b4684354dcee877d9908c7ececda68db423b599e 100644 --- a/src/core/engine.ts +++ b/src/core/engine.ts @@ -101,11 +101,11 @@ export class Engine { // If all the metrics and dimensions are the same and only exist one child view // return this single child view if (optimalViews.length === 1 && - optimalViews[0].view.metrics.length === q.metrics.length && - optimalViews[0].view.dimensions.length === q.dimensions.length && - optimalViews[0].view.metrics.every((item) => q.metrics.indexOf(item) !== -1) && - optimalViews[0].view.dimensions.every((item) => q.dimensions.indexOf(item) !== -1)) { - return optimalViews[0].view; + optimalViews[0].metrics.length === q.metrics.length && + optimalViews[0].dimensions.length === q.dimensions.length && + optimalViews[0].metrics.every((item) => q.metrics.indexOf(item) !== -1) && + optimalViews[0].dimensions.every((item) => q.dimensions.indexOf(item) !== -1)) { + return optimalViews[0]; } else { let options = { diff --git a/src/core/view.ts b/src/core/view.ts index dba8c040398b31fe0ed4ee061863beccdd2f8b3a..8d1f9545cf566a958c8e7c7c3dc47dba13718126 100644 --- a/src/core/view.ts +++ b/src/core/view.ts @@ -27,18 +27,12 @@ export interface LoadView { data: string; } -export interface ChildView { - metrics: Metric[]; - dimensions: Dimension[]; - view: View; -} - export interface ViewOptions { metrics: Metric[]; dimensions: Dimension[]; origin: boolean; materialized?: boolean; - childViews?: ChildView[]; + childViews?: View[]; } export class View { @@ -47,7 +41,7 @@ export class View { public readonly dimensions: Dimension[]; public readonly materialized: boolean; public readonly origin: boolean; - public childViews: ChildView[]; + public childViews: View[]; constructor (options: ViewOptions) { this.metrics = options.metrics.sort(); diff --git a/src/util/graph.spec.ts b/src/util/graph.spec.ts index 6b0cc095ba6838d50b5f40ee3bc1efc304afcd54..268011f60260d7e769d0a189f41966d0ce513dca 100644 --- a/src/util/graph.spec.ts +++ b/src/util/graph.spec.ts @@ -200,7 +200,7 @@ describe("graph class", () => { let children = g.cover([], [dim]); expect(children).to.be.an("array"); expect(children).to.have.length(1); - expect(children[0].view.id).to.be.equal(view.id); + expect(children[0].id).to.be.equal(view.id); }); it("should create a cover for several vertices", () => { @@ -269,7 +269,7 @@ describe("graph class", () => { let children = g.cover([mets[0], mets[1]], [dims[0], dims[1]]); expect(children).to.be.an("array"); expect(children).to.have.length(1); - expect(children[0].view.id).to.be.equal(views[views.length - 1].id); + expect(children[0].id).to.be.equal(views[views.length - 1].id); }); it("should create a cover with sub dimensions", () => { @@ -308,7 +308,7 @@ describe("graph class", () => { let children = g.cover([], [dims[1], dims[2]]); expect(children).to.be.an("array"); expect(children).to.have.length(1); - expect(children[0].view.id).to.be.equal(view.id); + expect(children[0].id).to.be.equal(view.id); }); it("should return empty when try to cover a empty list", () => { diff --git a/src/util/graph.ts b/src/util/graph.ts index 7ee9c094033266eb6d80c7e1059a505f7b9d9316..da49807dc1ed500c6722306e359e81f528b9280c 100644 --- a/src/util/graph.ts +++ b/src/util/graph.ts @@ -18,7 +18,7 @@ * along with blendb. If not, see <http://www.gnu.org/licenses/>. */ -import { View, ChildView } from "../core/view"; +import { View } from "../core/view"; import { Metric } from "../core/metric"; import { Dimension } from "../core/dimension"; @@ -300,13 +300,13 @@ export class Graph { /* Given a list of metrics and dimensions returns a set - of ChildViews that can be used to create a query that + of Views (children) that can be used to create a query that returns the data asked. If this set cannot be created, throws a error */ - public cover(metrics: Metric[], dimensions: Dimension[]): ChildView[] { - let output: ChildView[] = []; + public cover(metrics: Metric[], dimensions: Dimension[]): View[] { + let output: View[] = []; let verticesIds = metrics.map((met) => met.name); verticesIds = verticesIds.concat(dimensions.map((dim) => dim.name)); for (let i = 0; i < this.vertices.length; ++i) { @@ -374,7 +374,7 @@ export class Graph { return edge.isView; }).map((edge) => edge.view); // Check if there is a intersection between output and options - if (output.some((child) => options.some((view) => child.view === view))) { + if (output.some((child) => options.some((view) => child === view))) { // If there is a intersection, does not pick any new view v = v.parent; continue; @@ -414,7 +414,7 @@ export class Graph { } // Check if some of its views were picked - if (output.some((child) => views.some((view) => child.view === view))) { + if (output.some((child) => views.some((view) => child === view))) { // If yes, do nothing and return the actual set return output; } @@ -431,12 +431,12 @@ export class Graph { /* From a edge, coohse the best view, based on the metric and dimensions - that are not cover yet, return a childView. + that are not cover yet, return a View. The algorithm chooses the view that covers more metrics and dimensions that are not covered yet, if there is a tie chooses the one with less dimensions, if tie again, the earliest in the list. */ - private pickEdge (views: View[], metToCover: Metric[], dimToCover: Dimension[]): ChildView { + private pickEdge (views: View[], metToCover: Metric[], dimToCover: Dimension[]): View { // Picks the first option as the best one until now let bestView = views[0]; let bestCoverMet = metToCover.filter((met) => { @@ -483,12 +483,7 @@ export class Graph { } } - return { - view: bestView, - metrics: bestCoverMet, - dimensions: bestCoverDim - }; - + return bestView; } } diff --git a/test/scenario.ts b/test/scenario.ts index 1e5e33e0ab67d96384ab6b2469f7e4bc9cd8f703..0a896280eccbcda089f14eb8a13e6e6ee6b39acf 100644 --- a/test/scenario.ts +++ b/test/scenario.ts @@ -130,11 +130,7 @@ const dateView = new View({ dimensions: dateSubDim, materialized: false, origin: false, - childViews: [{ - view: views[0], - metrics: [], - dimensions: [dims[0]] - }] + childViews: [views[0]] }); const aggrView = new View({ @@ -142,23 +138,7 @@ const aggrView = new View({ dimensions: [], materialized: false, origin: false, - childViews: [ - { - view: views[0], - metrics: [mets[0], mets[1]], - dimensions: [] - }, - { - view: views[2], - metrics: [mets[6]], - dimensions: [] - }, - { - view: views[4], - metrics: [], - dimensions: [] - } - ] + childViews: [views[0], views[2], views[4]] }); const subDimView = new View({ @@ -166,23 +146,7 @@ const subDimView = new View({ dimensions: [subdims[0], subdims[1], dims[7], dims[8]], materialized: false, origin: false, - childViews: [ - { - view: views[0], - metrics: [mets[0]], - dimensions: [dims[0], dims[7]] - }, - { - view: views[1], - metrics: [], - dimensions: [dims[1], dims[8]] - }, - { - view: views[4], - metrics: [], - dimensions: [] - } - ] + childViews: [views[0], views[1], views[4]] }); const join4View = new View({ @@ -190,28 +154,7 @@ const join4View = new View({ dimensions: [dims[2], dims[7], dims[8]], materialized: false, origin: false, - childViews: [ - { - view: views[0], - metrics: [mets[0], mets[1], mets[2]], - dimensions: [dims[7]] - }, - { - view: views[1], - metrics: [mets[3], mets[4]], - dimensions: [dims[8]] - }, - { - view: views[2], - metrics: [mets[5], mets[6]], - dimensions: [dims[2]] - }, - { - view: views[4], - metrics: [], - dimensions: [] - } - ] + childViews: [views[0], views[1], views[2], views[4]] }); const noSelView = new View({ @@ -219,18 +162,7 @@ const noSelView = new View({ dimensions: [], materialized: false, origin: false, - childViews: [ - { - view: views[0], - metrics: [mets[0]], - dimensions: [] - }, - { - view: views[1], - metrics: [mets[3]], - dimensions: [] - } - ] + childViews: [views[0], views[1]] }); const withSelView = new View({ @@ -238,18 +170,7 @@ const withSelView = new View({ dimensions: [dims[7], dims[8]], materialized: false, origin: false, - childViews: [ - { - view: views[0], - metrics: [mets[0], mets[1]], - dimensions: [dims[7]] - }, - { - view: views[4], - metrics: [], - dimensions: [dims[7], dims[8]] - } - ] + childViews: [views[0], views[4]] }); export const engineScenario: EngineScenario = {