Issue #100: Topological sort the query partial views in SQL adapter

Signed-off-by: Lucas Fernandes de Oliveira's avatarLucas Fernandes de Oliveira <lfoliveira@inf.ufpr.br>
parent 3b425558
Pipeline #18860 passed with stages
in 57 seconds
......@@ -27,6 +27,7 @@ import { Filter, FilterOperator } from "../core/filter";
import { AggregationType, RelationType, DataType } from "../common/types";
import { Operation, Opcode } from "../common/expression";
import { View } from "../core/view";
import { Tsort } from "../util/tsort";
/**
* Information required to make a join clause.
......@@ -62,6 +63,11 @@ interface QueryAndName {
name: string;
}
/** Dictonary indexed by view name, that returns the QueryAndName object. */
interface QNMap {
[key: string]: QueryAndName;
}
/**
* Two Dictionaries, both indexed with a dimension name.
* Used to get the views where a dimension is.
......@@ -90,7 +96,11 @@ export abstract class SQLAdapter extends Adapter {
* @param view - View to be translated.
*/
public getQueryFromView(view: View): string {
const partials = this.buildPartials(view).filter((i) => {
const map = this.buildPartials(view);
const topSort = Tsort.view(view);
const partials = topSort.map((i) => {
return (map[i]) ? map[i] : {query : "", name: i};
}).filter((i) => {
return i.query !== "";
}).map((i) => {
return i.name + " AS (" + i.query + ")";
......@@ -121,13 +131,14 @@ export abstract class SQLAdapter extends Adapter {
* partials can only have one metric.
* @param view - View which the partial will be built.
*/
private buildPartials(view: View): QueryAndName[] {
private buildPartials(view: View): QNMap {
let op = view.operation;
let queue: View[] = op.values.map((i) => i);
const output: QueryAndName[] = [{
const output: QNMap = {};
output[view.name] = {
query: this.operation(op, view),
name: view.name,
}];
name: view.name
};
const map: {[key: string]: boolean } = {};
......@@ -137,10 +148,12 @@ export abstract class SQLAdapter extends Adapter {
const query = this.operation(partial.operation, partial);
if (query !== "") {
map[partial.id] = true;
output.unshift({
if (!output[partial.name]) {
output[partial.name] = {
query: query,
name: partial.name
});
};
}
queue = queue.concat(partial.operation.values);
}
}
......
......@@ -22,6 +22,9 @@
* A representation of a dependency relation.
* Equivalent to a edge in a dependency graph.
*/
import { View } from "../core/view";
export interface TsortDep {
/** The value (vertex). */
value: string;
......@@ -60,6 +63,7 @@ export class Tsort {
* dependency graph).
*/
public static dependencies(deps: TsortDep[]): string[]{
// Graph Creation
let graph: Graph = {};
let mark: VertexMark = {};
for (let i = 0; i < deps.length; ++i) {
......@@ -82,6 +86,57 @@ export class Tsort {
}
// Topological Sort
let output: string[] = [];
for (let vertex of Object.keys(graph)) {
if (!mark[vertex]) {
Tsort.markVertex(vertex, graph, mark, output);
}
}
return output;
}
/**
* Topologicaly sort view descendents names.
* @param view - View to construct dependency tree(graph) and sort it
*/
public static view(view: View): string[] {
// Graph creation
const graph: Graph = {};
const mark: VertexMark = {};
let queue = [view];
while (queue.length > 0) {
const partial = queue.shift();
// If the dependent vertex does not exist, create it
// with a empty dependent list
if (!graph[partial.name]) {
graph[partial.name] = [];
mark[partial.name] = false;
}
for (let i = 0; i < partial.operation.values.length; ++i) {
const dep = partial.operation.values[i];
// If the required vertex does not exists create it
// and put the dependent vertex in the dependent list
if (!graph[dep.name]) {
graph[dep.name] = [partial.name];
mark[dep.name] = false;
}
// If the vertex already exists, add it in the dependent list
else {
graph[dep.name].push(partial.name);
}
// Add the other view. Could create replicated edges.
queue = queue.concat(partial.operation.values);
}
}
// Topological Sort
let output: string[] = [];
for (let vertex of Object.keys(graph)) {
if (!mark[vertex]) {
......
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