Commit c3fef89e authored by rafaelatc3sl's avatar rafaelatc3sl

Issue #93: Add option to select name for view

Signed-off-by: 's avatarrafaelatc3sl <rpd17@c3sl>
parent d0763d60
Pipeline #18516 passed with stages
in 1 minute and 1 second
......@@ -6,9 +6,10 @@ views:
- config/market_views.yaml.example
obj:
-
alias: "Seller"
alias: "view:Seller"
data: "test/postgres/fixtures/seller.json"
origin: true
aliasAsName: true
dimensions:
- "dim:seller:name"
- "dim:seller:sex"
......
......@@ -6,7 +6,7 @@ views:
- config/market_views.yaml.example
obj:
-
alias: "Seller"
alias: "view:Seller"
data: "test/postgres/fixtures/seller.json"
origin: true
dimensions:
......
......@@ -3,7 +3,7 @@ views:
- config/market_views.yaml.example
obj:
-
alias: "Seller"
alias: "view:Seller"
data: "test/postgres/fixtures/seller.json"
origin: true
dimensions:
......
-
alias: "Product"
alias: "view:Product"
data: "test/postgres/fixtures/product.json"
origin: true
aliasAsName: true
dimensions:
- "dim:product:name"
- "dim:product:validity"
......@@ -14,17 +15,19 @@
- "met:product:max:priceout"
- "met:product:min:priceout"
-
alias: "Client"
alias: "view:Client"
data: "test/postgres/fixtures/client.json"
origin: true
aliasAsName: true
dimensions:
- "dim:client:name"
- "dim:client:cpf"
- "dim:client:id"
-
alias: "Sell"
alias: "view:Sell"
data: "test/postgres/fixtures/sell.json"
origin: true
aliasAsName: true
dimensions:
- "dim:sell:registered"
- "dim:product:id"
......@@ -36,9 +39,10 @@
- "met:sell:avg:quantity"
- "met:sell:count:quantity"
-
alias: "Buyout"
alias: "view:Buyout"
data: "test/postgres/fixtures/buyout.json"
origin: true
aliasAsName: true
dimensions:
- "dim:buyout:datein"
- "dim:provider:id"
......@@ -48,23 +52,26 @@
- "met:buyout:max:quantity"
- "met:buyout:min:quantity"
-
alias: "Provider"
alias: "view:Provider"
data: "test/postgres/fixtures/provider.json"
origin: true
aliasAsName: true
dimensions:
- "dim:provider:name"
- "dim:provider:id"
-
alias: "Distribute"
alias: "view:Distribute"
data: "test/postgres/fixtures/distribute.json"
origin: true
aliasAsName: true
dimensions:
- "dim:provider:id"
- "dim:product:id"
-
alias: "ActiveSeller"
alias: "view:ActiveSeller"
data: "test/postgres/fixtures/activeseller.json"
origin: true
aliasAsName: true
dimensions:
- "dim:seller:name"
- "dim:seller:status"
......
......@@ -53,13 +53,13 @@ for (let i = 0; i < config.buildViews.length; ++i) {
// Cria uma tabela
let output = "-- View: " + alias + "\n";
if (process.env.BLENDB_ADAPTER === "postgres") {
output += "DROP VIEW IF EXISTS view_" + view.id + " CASCADE;\n";
output += "CREATE OR REPLACE VIEW view_" + view.id + " AS\n";
output += "DROP VIEW IF EXISTS " + view.name + " CASCADE;\n";
output += "CREATE OR REPLACE VIEW " + view.name + " AS\n";
}
else if (process.env.BLENDB_ADAPTER === "monet") {
output += "DROP VIEW view_" + view.id + " CASCADE;\n";
output += "CREATE VIEW view_" + view.id + " AS\n";
output += "DROP VIEW " + view.name + " CASCADE;\n";
output += "CREATE VIEW " + view.name + " AS\n";
}
else {
......
......@@ -37,7 +37,6 @@ describe("Sql adapter", () => {
// Arrow function not used to get acces to this and skip the test
const configPath = process.env.BLENDB_SCHEMA_FILE;
config = ConfigParser.parse(configPath);
if (config.adapter === "postgres") {
fixture = new FixPostgres(config.connection);
fixture.load(config.loadViews, (err) => {
......
......@@ -111,7 +111,7 @@ export abstract class SQLAdapter extends Adapter {
sort = " ORDER BY " + order;
}
return withClause + "SELECT * FROM " + this.viewName(view) + sort + ";";
return withClause + "SELECT * FROM " + view.name + sort + ";";
}
/**
......@@ -126,7 +126,7 @@ export abstract class SQLAdapter extends Adapter {
let queue: View[] = op.values.map((i) => i);
const output: QueryAndName[] = [{
query: this.operation(op, view),
name: this.viewName(view)
name: view.name,
}];
const map: {[key: string]: boolean } = {};
......@@ -139,7 +139,7 @@ export abstract class SQLAdapter extends Adapter {
map[partial.id] = true;
output.unshift({
query: query,
name: this.viewName(partial)
name: partial.name
});
queue = queue.concat(partial.operation.values);
}
......@@ -149,14 +149,6 @@ export abstract class SQLAdapter extends Adapter {
return output;
}
/**
* The translated name of a view into SQL databases.
* @param view - View which the name will be built.
*/
protected viewName(view: View): string {
return "view_" + view.id;
}
/**
* Constructs a query from a view based in a given operation
* @param op - Operation used to construct the view.
......@@ -221,9 +213,9 @@ export abstract class SQLAdapter extends Adapter {
if (dimMap[i].views.length > 1) {
const views = dimMap[i].views;
const dim = dimMap[i].dim;
const leftSide = this.buildColumn(dim, views.shift().id);
const leftSide = this.buildColumn(dim, views.shift().name);
while (views.length > 0) {
const rightSide = this.buildColumn(dim, views.shift().id);
const rightSide = this.buildColumn(dim, views.shift().name);
conds.push("(" + leftSide + "=" + rightSide + ")");
}
}
......@@ -232,7 +224,7 @@ export abstract class SQLAdapter extends Adapter {
// Assembly
const projection = "SELECT " + projElem.join(", ");
const sources = "FROM " + partials.map((i) => this.viewName(i)).join(", ");
const sources = "FROM " + partials.map((i) => (i.name)).join(", ");
const selection = (conds.length > 0) ? " WHERE " + conds.join(" AND ") : "";
let grouping = "";
......@@ -371,11 +363,11 @@ export abstract class SQLAdapter extends Adapter {
/**
* Add quotes and the proper view name to a attribute in a SQL query.
* @param item - Attribute to get the name quoted.
* @param id - View id used to build the view name.
* @param viewName - View name used to build the view name.
*/
private buildColumn (item: Metric|Dimension, id: string): string {
private buildColumn (item: Metric|Dimension, viewName: string): string {
const quotedName = "\"" + item.name + "\"";
return "view_" + id + "." + quotedName;
return viewName + "." + quotedName;
}
/**
......@@ -404,8 +396,8 @@ export abstract class SQLAdapter extends Adapter {
return "";
}
const viewId = map[filter.target.name].id;
const leftSide = this.buildColumn(filter.target, viewId);
const viewName = map[filter.target.name].name;
const leftSide = this.buildColumn(filter.target, viewName);
const quotedValue = "'" + filter.value + "'";
const castedValue = this.typeCast(quotedValue, filter.target.dataType);
return this.applyOperator(leftSide, castedValue, filter.operator);
......@@ -419,7 +411,7 @@ export abstract class SQLAdapter extends Adapter {
private translateMetric(metric: Metric, view: View): string {
const func = this.getAggregateFunction(metric.aggregation, view.origin);
const quotedName = "\"" + metric.name + "\"";
const extMetric = func + "(" + this.buildColumn(metric, view.id) + ")";
const extMetric = func + "(" + this.buildColumn(metric, view.name) + ")";
return extMetric + " AS " + quotedName;
}
......@@ -434,7 +426,7 @@ export abstract class SQLAdapter extends Adapter {
ancestor: Dimension,
view: View): DimTranslation {
const quotedName = "\"" + dimension.name + "\"";
let extDimension = this.buildColumn(ancestor, view.id);
let extDimension = this.buildColumn(ancestor, view.name);
let aux = dimension;
let expanded = false;
while (aux.name !== ancestor.name) {
......
......@@ -46,6 +46,10 @@ export interface ViewOptions {
sort?: (Metric|Dimension)[];
/** Definition of how to create this view using other views. */
operation?: Operation;
/** Defines if views's name will be its alias or automatically generated. */
aliasAsName?: boolean;
/** Fake identifier (human understandable) of the view. */
alias?: string;
}
/**
......@@ -54,7 +58,7 @@ export interface ViewOptions {
* these objects can only be found in views.
*/
export class View {
/** Hash of components that unique identify the clause. */
/** Hash of components that unique identify the view. */
public readonly id: string;
/** Set of metrics contained into the view. */
public readonly metrics: Metric[];
......@@ -68,6 +72,8 @@ export class View {
public readonly origin: boolean;
/** Definition of how to create this view using other views. */
public readonly operation: Operation;
/** View identifier, used on query generation as "table" name */
public readonly name: string;
/**
* Create a view.
......@@ -96,5 +102,13 @@ export class View {
const clausesIds = this.clauses.map((clause) => clause.id);
const join = metNames.concat(dimNames).concat(clausesIds).sort();
this.id = Hash.sha1(join);
if ( options.aliasAsName ) {
this.name = "\"" + options.alias + "\"";
} else {
this.name = "view_" + this.id;
}
}
}
......@@ -50,6 +50,8 @@ export interface ViewParsingOptions {
metrics: string[];
/** Set of (stringified) clauses applied to the view. */
clauses?: string[];
/** Inform if the view's name will be it's alias or id */
aliasAsName?: boolean;
}
/**
......@@ -300,7 +302,9 @@ export class ConfigParser {
metrics: [],
dimensions: [],
origin: opts.origin,
alias: (opts.alias) ? opts.alias : "",
clauses: [],
aliasAsName: (opts.aliasAsName) ? opts.aliasAsName : false,
operation: {
opcode: Opcode.PUSH,
values: []
......
......@@ -112,7 +112,7 @@ export class Fixture {
}
private extractDataView(view: View, filePath: string): string[]{
let name = "view_" + view.id;
let name = view.name;
let data: string[] = [];
let rows = JSON.parse(fs.readFileSync(filePath, {encoding : "utf8"}));
for (let i = 0; i < rows.length; ++i) {
......@@ -132,7 +132,7 @@ export class Fixture {
}
private createTransSet(view: View, filePath: string, create: boolean): string {
let name = "view_" + view.id;
let name = view.name;
let init: string = "";
let props = [];
for (let i = 0; i < view.metrics.length; ++i) {
......
......@@ -122,7 +122,7 @@ export class Fixture {
}
private extractDataView(view: View, filePath: string): string[]{
let name = "view_" + view.id;
let name = view.name;
let data: string[] = [];
let rows = JSON.parse(fs.readFileSync(filePath, {encoding : "utf8"}));
for (let i = 0; i < rows.length; ++i) {
......@@ -142,7 +142,7 @@ export class Fixture {
}
private createTransSet(view: View, filePath: string, create: boolean): string {
let name = "view_" + view.id;
let name = view.name;
let init: string = "";
let props = [];
for (let i = 0; i < view.metrics.length; ++i) {
......
......@@ -163,19 +163,19 @@ const JoinWithAncestors = ViewHandler.growView({
metrics: [mets["met:sell:count:quantity"]],
dimensions: [dims["dim:seller:id"],dims["dim:provider:id"]],
clauses: []
},[views["Sell"]]);
},[views["view:Sell"]]);
const joinWithNoMetrics = ViewHandler.growView({
metrics: [],
dimensions: [dims["dim:product:name"],dims["dim:seller:name"]],
clauses: []
}, [views["Product"],views["Sell"],views["Seller"]]);
}, [views["view:Product"],views["view:Sell"],views["view:Seller"]]);
const growOneView = ViewHandler.growView({
metrics: [mets["met:seller:min:age"]],
dimensions: [dims["dim:seller:name"],dims["dim:seller:sex"]],
clauses: []
}, [views["Seller"]]);
}, [views["view:Seller"]]);
const multipleClause = ViewHandler.growView({
metrics: [mets["met:sell:avg:quantity"]],
......@@ -183,20 +183,20 @@ const multipleClause = ViewHandler.growView({
dims["dim:client:name"]],
// and between filters => (A) and (B)
clauses: [clauses["expired"],clauses["averageBought"]]
}, [views["Sell"],views["Seller"],views["Client"],views["Product"]]);
}, [views["view:Sell"],views["view:Seller"],views["view:Client"],views["view:Product"]]);
const singleClause = ViewHandler.growView({
metrics: [mets["met:sell:avg:quantity"]],
dimensions: [dims["dim:sell:datein"],dims["dim:seller:name"],
dims["dim:client:name"]],
clauses: [clauses["expiredAndAverage"]]
}, [views["Sell"],views["Seller"],views["Client"],views["Product"]]);
}, [views["view:Sell"],views["view:Seller"],views["view:Client"],views["view:Product"]]);
const equalfilter = ViewHandler.queryJoin({
metrics: [],
dimensions: [dims["dim:client:name"],dims["dim:product:validity"]],
clauses: [clauses["lastDay"]]
},[views["Sell"],views["Client"],views["Product"]]);
},[views["view:Sell"],views["view:Client"],views["view:Product"]]);
const withSortView = ViewHandler.queryJoin({
metrics: [mets["met:sell:sum:quantity"]],
......@@ -205,7 +205,7 @@ const withSortView = ViewHandler.queryJoin({
},[ViewHandler.queryReduce({
metrics: [mets["met:sell:sum:quantity"]],
dimensions: [dims["dim:client:id"]]
},views["Sell"]),views["Client"]]);
},views["view:Sell"]),views["view:Client"]]);
const subDimView = ViewHandler.queryJoin({
metrics : [],
......@@ -214,13 +214,13 @@ const subDimView = ViewHandler.queryJoin({
[ViewHandler.queryReduce({
metrics: [],
dimensions: [dims["dim:sell:datein"]]
},views["Sell"]),views["Sell"]]);
},views["view:Sell"]),views["view:Sell"]]);
const joinOneView = ViewHandler.queryJoin({
metrics: [mets["met:product:avg:pricein"]],
dimensions: []
},[views["Product"]]);
},[views["view:Product"]]);
const reduceAsView = ViewHandler.queryReduce({
metrics: [mets["met:sell:sum:quantity"],mets["met:sell:avg:quantity"],
......@@ -228,7 +228,7 @@ 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"]]
},views["Sell"]);
},views["view:Sell"]);
const clientAverageBought = ViewHandler.queryReduce({
metrics: [mets["met:sell:avg:quantity"]],
......@@ -237,12 +237,12 @@ const clientAverageBought = ViewHandler.queryReduce({
},ViewHandler.queryJoin({
metrics: [mets["met:sell:avg:quantity"]],
dimensions: [dims["dim:client:name"], dims["dim:seller:id"]]
},[views["Sell"],views["Client"]]));
},[views["view:Sell"],views["view:Client"]]));
const viewProduct = views["Product"];
const viewProduct = views["view:Product"];
const viewActiveSeller = views["ActiveSeller"];
const viewActiveSeller = views["view:ActiveSeller"];
const wrongMet = new Metric({
name: "met:this:is:just:a:test",
......@@ -318,7 +318,7 @@ export const engineScenario: EngineScenario = {
};
export const adapterScenario: AdapterScenario = {
materializedView: views["Product"],
materializedView: views["view:Product"],
sortView: withSortView,
joinWithOneView: joinOneView,
singleClause: singleClause,
......
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