diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f0748346158196aac0e7bd9e9503d70fd4247287..893848c6b8fe1ec7e2c1a9df780bf9095f5d9e24 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,5 +1,13 @@
 image: node:6.2
 
+services:
+    - postgres:latest
+
+variables:
+    POSTGRES_DB: 'blendb_fixture'
+    POSTGRES_USER: 'runner'
+    POSTGRES_PASSWORD: ''
+
 cache:
     paths:
         - node_modules
@@ -9,6 +17,8 @@ before_script:
 
 run_tests:
     script:
+        - mv config/ci_test.yaml.example config/test.yaml
         - npm test
     tags:
         - node
+        - postgres
diff --git a/config/ci_test.yaml.example b/config/ci_test.yaml.example
new file mode 100644
index 0000000000000000000000000000000000000000..2c49af1a1850ca344038e4505444fb91cb13597e
--- /dev/null
+++ b/config/ci_test.yaml.example
@@ -0,0 +1,176 @@
+# gitignore ignores files.yaml in this folder
+# however a config file for tests in CI is required
+# so this example file in fact is the CI test file
+connection:
+    database: 'blendb_fixture'
+    user: 'runner'
+    password: ''
+    host: 'postgres'
+    port: 5432
+    max: 10
+    idleTimeoutMillis: 30000
+struct:
+    create: true
+    insert: true
+schema:
+    views:
+        -
+            alias: "View 1"
+            data: "test/postgres/fixtures/view1.json"
+            dimensions:
+                - "dim:1"
+                - "dim:2"
+            metrics:
+                - "met:1"
+                - "met:2"
+                - "met:3"
+        -
+            alias: "View 2"
+            data: "test/postgres/fixtures/view2.json"
+            dimensions:
+                - "dim:1"
+                - "dim:2"
+            metrics:
+                - "met:1"
+                - "met:3"
+                - "met:5"
+        -
+            alias: "View 3"
+            data: "test/postgres/fixtures/view3.json"
+            dimensions:
+                - "dim:4"
+                - "dim:5"
+            metrics:
+                - "met:3"
+                - "met:4"
+                - "met:7"
+        -
+            alias: "View 4"
+            data: "test/postgres/fixtures/view4.json"
+            dimensions:
+                - "dim:3"
+                - "dim:4"
+                - "dim:5"
+                - "dim:6"
+            metrics:
+                - "met:6"
+                - "met:7"
+        -
+            alias: "View 5"
+            data: "test/postgres/fixtures/view5.json"
+            dimensions:
+                - "dim:1"
+                - "dim:2"
+                - "dim:7"
+            metrics:
+                - "met:2"
+                - "met:3"
+                - "met:8"
+        -
+            alias: "View 6"
+            data: "test/postgres/fixtures/view6.json"
+            dimensions:
+                - "dim:1"
+                - "dim:2"
+            metrics:
+                - "met:1"
+                - "met:4"
+        -
+            alias: "View 7"
+            data: "test/postgres/fixtures/view7.json"
+            dimensions:
+                - "dim:8"
+                - "dim:9"
+                - "dim:10"
+            metrics:
+                - "met:8"
+        -
+            alias: "View 8"
+            data: "test/postgres/fixtures/view8.json"
+            dimensions:
+                - "dim:8"
+                - "dim:9"
+                - "dim:10"
+            metrics:
+                - "met:9"
+        -
+            alias: "View 9"
+            data: "test/postgres/fixtures/view9.json"
+            dimensions:
+                - "dim:8"
+                - "dim:9"
+                - "dim:10"
+            metrics:
+                - "met:10"
+    metrics:
+        -
+            name: "met:1"
+            dataType: "integer"
+            aggregation: "sum"
+        -
+            name: "met:2"
+            dataType: "integer"
+            aggregation: "avg"
+        -
+            name: "met:3"
+            dataType: "integer"
+            aggregation: "avg"
+        -
+            name: "met:4"
+            dataType: "integer"
+            aggregation: "sum"
+        -
+            name: "met:5"
+            dataType: "integer"
+            aggregation: "sum"
+        -
+            name: "met:6"
+            dataType: "integer"
+            aggregation: "avg"
+        -
+            name: "met:7"
+            dataType: "integer"
+            aggregation: "count"
+        -
+            name: "met:8"
+            dataType: "integer"
+            aggregation: "count"
+        -
+            name: "met:9"
+            dataType: "integer"
+            aggregation: "sum"
+        -
+            name: "met:10"
+            dataType: "integer"
+            aggregation: "count"
+    dimensions:
+        -
+            name: "dim:1"
+            dataType: "date"
+        -
+            name: "dim:2"
+            dataType: "date"
+        -
+            name: "dim:3"
+            dataType: "integer"
+        -
+            name: "dim:4"
+            dataType: "string"
+        -
+            name: "dim:5"
+            dataType: "string"
+        -
+            name: "dim:6"
+            dataType: "boolean"
+        -
+            name: "dim:7"
+            dataType: "integer"
+        -
+            name: "dim:8"
+            dataType: "integer"
+        -
+            name: "dim:9"
+            dataType: "date"
+        -
+            name: "dim:10"
+            dataType: "string"
diff --git a/config/config.yaml.example b/config/config.yaml.example
new file mode 100644
index 0000000000000000000000000000000000000000..f97ea97db5adb4daf21d7011aa78bbaa50e61803
--- /dev/null
+++ b/config/config.yaml.example
@@ -0,0 +1,15 @@
+connection:
+    user: 'blendb'
+    database: 'blendb-test'
+    password: 'secret'
+    host: 'localhost'
+    port: 5432
+    max: 10
+    idleTimeoutMillis: 30000
+struct:
+    create: false
+    insert: false
+schema:
+    views:
+    metrics:
+    dimensions:
diff --git a/database/config.ts b/database/config.ts
index e138ee60c67a8de25fbd39ad05044050525337fc..5bf471c97ada9c60263c244d541c2483dd1bf208 100755
--- a/database/config.ts
+++ b/database/config.ts
@@ -83,7 +83,7 @@ function createView(view: View): string {
     let keys = [];
     for (let field in view.fields) {
         props.push("\"" + field + "\" " + typeConvertion(view.fields[field]));
-        keys.push(field);
+        keys.push(field.name);
     }
     keys.sort();
     let name = "view_" + Hash.sha1(keys);
diff --git a/package.json b/package.json
index 488e010a664ce248e32a484514b241819625dcba..af5e12d36e5e1f62168eb4b034b36401b8c6003c 100644
--- a/package.json
+++ b/package.json
@@ -18,15 +18,21 @@
   "author": "Centro de Computação Científica e Software Livre (C3SL)",
   "license": "GPL-3.0",
   "dependencies": {
+    "@types/async": "^2.0.40",
     "@types/chai": "^3.4.33",
     "@types/d3": "^3.5.36",
     "@types/express": "^4.0.33",
+    "@types/js-yaml": "^3.5.29",
     "@types/mocha": "^2.2.32",
+    "@types/pg": "^6.1.38",
     "@types/pug": "^2.0.1",
+    "async": "^2.3.0",
     "express": "^4.0.33",
+    "js-yaml": "^3.8.2",
     "mississippi": "^1.2.0",
     "node-uuid": "^1.4.7",
     "osprey": "^0.3.2",
+    "pg": "^6.1.5",
     "pug": "^2.0.0-beta6",
     "ts-node": "^1.3.0",
     "typescript": "^2.0.3"
diff --git a/src/adapter/postgres.spec.ts b/src/adapter/postgres.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..adc09ec8c04ed8e3fe27cbd4984439741264c6ee
--- /dev/null
+++ b/src/adapter/postgres.spec.ts
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2017 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana
+ *
+ * This file is part of blendb.
+ *
+ * blendb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * blendb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with blendb.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import { expect } from "chai";
+
+import { PostgresAdapter } from "./postgres";
+import { Adapter } from "../core/adapter";
+import { Fixture } from "../../test/postgres/fixture";
+
+import { ConfigParser } from "../util/configParser";
+import { adapterScenario } from "../../test/scenario";
+
+describe("postgres adapter", () => {
+
+    // Initializing
+    let config: any;
+    let adapter: Adapter;
+    let fixture;
+    before((done) => {
+        config = ConfigParser.parse("config/test.yaml");
+        fixture = new Fixture(config.connection);
+        fixture.load(config.loadViews, config.struct.create, (err) => {
+            if (err) {
+                throw err;
+            }
+            adapter = new PostgresAdapter(config.connection);
+            done();
+        });
+    });
+    // Tests
+    it("should get data from single materialized view", (done) => {
+        let view = adapterScenario.materializedView;
+        adapter.getDataFromView(view, (err, result) => {
+            expect(err).to.be.a("null");
+            expect(result).to.be.an("array");
+            expect(result).to.have.length(5);
+            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);
+            });
+            done();
+        });
+    });
+    it("should get data from join of 2 views (without selection)", (done) => {
+        let view = adapterScenario.noSelectionView;
+        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);
+            });
+            done();
+        });
+    });
+    it("should get data from join of 2 views (with selection)", (done) => {
+        let view = adapterScenario.withSelectionView;
+        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[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);
+            });
+            done();
+        });
+    });
+    it("should get data from single view (with sub-dimension)", (done) => {
+        let view = adapterScenario.subDimensionView;
+        adapter.getDataFromView(view, (err, result) => {
+            expect(err).to.be.a("null");
+            expect(result).to.be.an("array");
+            expect(result).to.have.length(25);
+            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);
+            });
+            done();
+        });
+    });
+    it("should get data from join of 4 views (with selection)", (done) => {
+        let view = adapterScenario.join4View;
+        adapter.getDataFromView(view, (err, result) => {
+            expect(err).to.be.a("null");
+            expect(result).to.be.an("array");
+            expect(result).to.have.length(125);
+            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);
+            });
+            done();
+        });
+    });
+
+    it("should get data from different sub dimensions with same parent", (done) => {
+        let view = adapterScenario.dateView;
+        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[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(row).to.have.property("dim:2:year", 2017);
+            });
+            done();
+        });
+    });
+});
diff --git a/src/adapter/postgres.ts b/src/adapter/postgres.ts
index 4c7e8b9996b7b05c219153dfe35e69eda626bd1e..7e133dd8393bb3ad24958fec79a09fd5328e1d29 100644
--- a/src/adapter/postgres.ts
+++ b/src/adapter/postgres.ts
@@ -19,136 +19,171 @@
  */
 
 import { Adapter } from "../core/adapter";
+import { Metric } from "../core/metric";
+import { Dimension } from "../core/dimension";
 import { AggregationType, RelationType } from "../common/types";
 import { View, ChildView } from "../core/view";
+import { Pool, PoolConfig } from "pg";
 
-interface ParsedView {
+interface ParsedChild {
     query: string;
     view: View;
+    dimensions: Dimension[];
+    metrics: Metric[];
+    alias: string;
 };
 
-export class PostgresAdapter extends Adapter{
-    public getDataFromView(view: View): string {
+export class PostgresAdapter extends Adapter {
+    private pool: Pool;
+
+    constructor (config: PoolConfig) {
+        super();
+        this.pool = new Pool(config);
+    }
+    public getDataFromView(view: View, cb: (error: Error, result?: any[]) => void): void {
         // buildQueryFromView does not put the final ;, it need to be put apart
-        return this.buildQueryFromView(view, view.metrics, view.dimensions) + ";\n";
+        let query =  this.buildQueryFromView(view, view.metrics, view.dimensions) + ";\n";
+        this.pool.connect((err, client, done) => {
+            if (err) {
+                cb (err);
+            }
+
+            client.query(query, [], (error, result) => {
+                // call 'done()' to release client back to pool
+                done();
+                cb(error, (result) ? result.rows : null);
+            });
+        });
     }
 
-    public materializeView(view: View): string {
-        return null;
+    public materializeView(view: View): boolean {
+        return false;
     }
 
-    private buildQueryFromView (view: View, metrics: Metric[], dimensions: Dimession[]): string {
+    private buildQueryFromView (view: View, metrics: Metric[], dimensions: Dimension[]): string {
         /*
             Reduce metrics and dimensions array to the intersection with the
              view. So is possible only get useful data in the sub-querys.
         */
         let strMetrics = metrics.map((metric) => {
             let func = this.getAggregateFunction(metric.aggregation);
-            let extMetric = func + "(" + metric.name + ")";
+            let quotedName = "\"" + metric.name + "\"";
+            let extMetric = func + "(" + quotedName + ") AS " + quotedName;
             return extMetric;
         });
 
         if (view.materialized) {
-            let strDimensions = dimensions.map((dimmension) => dimension.name );
-            let sql = "(SELECT " + strMetrics.join(", ") + ", " + strDimensions.join(", ");
+            let strDimensions = dimensions.map((dimension) => "\"" + dimension.name + "\"");
+            let sql = "(SELECT " + strMetrics.concat(strDimensions).join(", ");
             sql += " FROM " + "view_" + view.id;
-            sql += " GROUP BY " + strDimensions.join(", ");
-            sql += ")\n";
+            if (strDimensions.length > 0 && strMetrics.length > 0) {
+                sql += " GROUP BY " + strDimensions.join(", ");
+            }
+            sql += ")";
             return sql;
         }
 
         else {
-            let children: ParsedView[] = view.childViews.map((item: ChildView) => {
-                return {
-                    query: this.buildQueryFromView(item.view, item.metrics, item.dimensions),
-                    view: item.view
-                };
-            });
 
             let covered = new Map();
-            dimensions.forEach((item) => covered.set(item.name, ""));
+            let matchable: any[] = [] ;
+            dimensions.forEach((item) => {
+                covered.set(item.name, "");
+                /*
+                    For each dimension that must be covered
+                    create a match in the array.
+                    If a more than onde view match to the same
+                    dimension, cretes a WHERE clause
+                */
+                matchable.push({match: item.name, sub: item});
+                let dim = item;
+                /*
+                    Sub dimensions also have parents that can match
+                    with then too.
+                */
+                while (dim.relation !== RelationType.NONE) {
+                    dim = dim.parent;
+                    matchable.push({
+                        match: dim.name,
+                        sub: item,
+                    });
+                }
+            });
             metrics.forEach((item) => covered.set(item.name, ""));
 
-            let projection = "SELECT ";
-            let viewsFrom = "FROM ";
-            let selection = "WHERE ";
-            let grouping = "GROUP BY ";
-
-            let elements = [];
-            let group = [];
+            let elements: string[] = [];
+            let group: string[] = [];
+            let viewsQuery: string[] = [];
+            let selected: string[] = [];
 
-            children.forEach((child: ParsedView) => {
-                let selected = [];
-                let matchable = child.dimensions.map((item) => {
-                    return { match: item, sub: item, viewId: child.view.id };
+            let children: ParsedChild[] = view.childViews.map((item: ChildView) => {
+                let dims = item.view.dimensions.filter((dim) => {
+                    return matchable.some((match) => match.match === dim.name);
                 });
 
-                // Running over the dimensions that cover some part of the query
-                child.dimensions.forEach((dimension: Dimension) => {
-                    /*
-                        If a dimension has a parent, the parent must match with
-                        the sub dimension, so must be added in the matchable
-                        array, for the selection (WHERE statement).
-                    */
-                    let dim = dimension;
-                    while (dim.relation !== RelationType.NONE) {
-                        matchable.push({
-                            match: dim.name,
-                            sub: dimension,
-                            viewId: child.view.id
-                        });
-                        dim = dim.parent;
-                    }
-
-                    dim = dimension;
-                    let extDimension = "view_" + child.view.id + ".\"" + dim.name + "\"";
-
-                    // If the view dimension does not match, search for parent
-                    while (!child.dimensions.some((item) => item.name === dim.name)) {
-                        dim = dim.parent;
-                        extDimension = this.translateRelation(dim.relation, extDimension);
-                    }
-                    covered.set(dimension.name, extDimension);
-                    elements.push(extDimension + " AS " + dimension.name);
-                    group.push(dimension.name);
+                let mets = item.metrics.filter((met) => {
+                    return metrics.some((elem) => elem.name === met.name);
                 });
+                let query = "";
+                if (dims.length !== 0 || mets.length !== 0) {
+                    query = this.buildQueryFromView(item.view, mets, dims);
+                }
+                return {
+                    query: query,
+                    view: item.view,
+                    dimensions : dims,
+                    metrics: mets,
+                    alias: "alias_" + item.view.id
+                };
+            }).filter ((item) => item.query !== "");
+
+            children.forEach((child: ParsedChild) => {
                 child.view.dimensions.forEach((dimension: Dimension) => {
                     /*
                         Make selection. Search for dimensions, that are in
                         matchable array.
                     */
                     matchable.filter((item) => {
-                        return item.viewId !== child.view.id &&
-                                 item.match === dimension.name;
+                        return item.match === dimension.name;
                     })
                     .forEach((item) => {
                         // Expand the sub-dimension until match with a parent
                         let dim = item.sub;
-                        let extDimension = "view_" + child.view.id + ".\"" + dimension.name + "\"";
+                        let extDimension = child.alias + ".\"" + dimension.name + "\"";
                         while (dim.name !== item.match) {
+                            extDimension = this.translateRelation(dim.relation, extDimension);
                             dim = dim.parent;
-                            extDimension = this.translateRelation(dim, extDimension);
                         }
-                        selected.push(extDimension + " = " + covered.get(item.sub.name));
+
+                        if (covered.get(item.sub.name) === "") {
+                            elements.push(extDimension + " AS \"" + item.sub.name + "\"");
+                            covered.set(item.sub.name, extDimension);
+                            group.push(extDimension);
+                        }
+                        else {
+                            selected.push(extDimension + " = " + covered.get(item.sub.name));
+                        }
                     });
                 });
 
                 child.metrics.forEach((metric: Metric) => {
-                    let func = this.geAggregateFunction(metric.aggregation);
-                    let extMetric = func + "(view_" + child.view.id + "." + metric.name + ")";
+                    let func = this.getAggregateFunction(metric.aggregation);
+                    let quotedName = "\"" + metric.name + "\"";
+                    let extMetric = func + "(" + child.alias + "." + quotedName + ") AS " + quotedName;
                     elements.push(extMetric);
                 });
 
-                viewsFrom += "\n" + child.query;
+                viewsQuery.push(child.query + " AS " + child.alias);
 
-                if (selected.length > 0) {
-                    selection += selected.join(" AND ");
-                }
             });
 
-            projection += elements.join(", ") + "\n";
-            selection += "\n";
-            grouping += group.join(", ") + "\n";
+            let projection = "SELECT " + elements.join(", ") + "\n";
+            let viewsFrom = "FROM " + viewsQuery.join(", ") + "\n";
+            let selection = (selected.length > 0) ? "WHERE " + selected.join(" AND ") + "\n" : "";
+            let grouping =  "";
+            if (group.length > 0 && metrics.length > 0) {
+                grouping = "GROUP BY " + group.join(", ") + "\n";
+            }
 
             return "(" +  projection + viewsFrom + selection + grouping + ")";
         }
@@ -184,7 +219,7 @@ export class PostgresAdapter extends Adapter{
 
     }
 
-    private applyRelation(name, args, values): string {
+    private applyRelation(name: string, args: string[], values: string[]): string {
         /*
             This adapter uses the concept of functions in Postgres to
             implement BLENDB sub-dimention relations, this functions
diff --git a/src/core/adapter.ts b/src/core/adapter.ts
index f2981953b9f362da9e07cdab004454865facc304..20cb90cfa5b995959f0aa7fb6b1d9381d97e0cdf 100644
--- a/src/core/adapter.ts
+++ b/src/core/adapter.ts
@@ -21,6 +21,6 @@
 import { View } from "./view";
 
 export abstract class Adapter {
-    public abstract getDataFromView(view: View): string;
-    public abstract materializeView(view: View): string;
+    public abstract getDataFromView(view: View, cb: (err: Error, result: any[]) =>  void): void;
+    public abstract materializeView(view: View): boolean;
 }
diff --git a/src/core/dimension.ts b/src/core/dimension.ts
index 386d0b5011c84f35b1189b771a1f2be1e31e6181..bf75265a66839a5dafc0385f0d74ca4c989c45b0 100644
--- a/src/core/dimension.ts
+++ b/src/core/dimension.ts
@@ -22,17 +22,20 @@ import { RelationType } from "../common/types";
 
 export interface DimensionOptions {
     name: string;
+    dataType: string;
     parent?: Dimension;
     relation?: RelationType;
 }
 
 export class Dimension {
     public readonly name: string;
+    public readonly dataType: string;
     public readonly parent: Dimension;
     public readonly relation: RelationType;
 
     constructor(options: DimensionOptions) {
         this.name = options.name;
+        this.dataType = options.dataType;
         this.relation = (options.relation) ? options.relation : RelationType.NONE;
         this.parent = (options.parent) ? options.parent : null;
     }
diff --git a/src/core/engine.spec.ts b/src/core/engine.spec.ts
index fc954355b1182d4cc5bf088c8d8ecb4ec097bb92..13f64fcba079781958e8aa3a171572e37be8b581 100644
--- a/src/core/engine.spec.ts
+++ b/src/core/engine.spec.ts
@@ -24,120 +24,30 @@ import { Engine } from "./engine";
 import { Metric } from "./metric";
 import { Dimension } from "./dimension";
 import { View } from "./view";
-import { AggregationType } from "../common/types";
-import { RelationType } from "../common/types";
+import { engineScenario } from "../../test/scenario";
 
 describe("engine class", () => {
     const engine = new Engine();
 
-    const met1 = new Metric({ name: "met:1", aggregation: AggregationType.SUM });
-    const met2 = new Metric({ name: "met:2", aggregation: AggregationType.AVG });
-    const met3 = new Metric({ name: "met:3", aggregation: AggregationType.AVG });
-    const met4 = new Metric({ name: "met:4", aggregation: AggregationType.SUM });
-    const met5 = new Metric({ name: "met:5", aggregation: AggregationType.SUM });
-    const met6 = new Metric({ name: "met:6", aggregation: AggregationType.AVG });
-    const met7 = new Metric({ name: "met:7", aggregation: AggregationType.COUNT });
-    const met8 = new Metric({ name: "met:8", aggregation: AggregationType.COUNT });
-    const met9 = new Metric({ name: "met:9", aggregation: AggregationType.SUM });
-    const met10 = new Metric({ name: "met:10", aggregation: AggregationType.COUNT });
-    const met11 = new Metric({ name: "met:11", aggregation: AggregationType.COUNT });
+    const met = engineScenario.metrics;
+    const dim = engineScenario.dimensions;
+    const subdim = engineScenario.subDimensions;
+    const views = engineScenario.views;
 
-    const dim1 = new Dimension({ name: "dim:1" });
-    const dim2 = new Dimension({ name: "dim:2" });
-    const dim3 = new Dimension({ name: "dim:3" });
-    const dim4 = new Dimension({ name: "dim:4" });
-    const dim5 = new Dimension({ name: "dim:5" });
-    const dim6 = new Dimension({ name: "dim:6" });
-    const dim7 = new Dimension({ name: "dim:7" });
-    const dim8 = new Dimension({ name: "dim:8" });
-    const dim9 = new Dimension({ name: "dim:9" });
-    const dim10 = new Dimension({ name: "dim:10" });
-    const dim11 = new Dimension({ name: "dim:11" });
-
-    const subdim1 = new Dimension({ name: "sub:1", parent: dim1, relation: RelationType.DAY });
-    const subdim2 = new Dimension({ name: "sub:2", parent: dim9, relation: RelationType.DAY });
-    const subdim3 = new Dimension({ name: "sub:3", parent: subdim1, relation: RelationType.DAY });
-    const subdim4 = new Dimension({ name: "sub:4", parent: null, relation: RelationType.DAY });
-    const subdim5 = new Dimension({ name: "sub:5", parent: dim2, relation: RelationType.DAY });
-
-    engine.addMetric(met1);
-    engine.addMetric(met2);
-    engine.addMetric(met3);
-    engine.addMetric(met4);
-    engine.addMetric(met5);
-    engine.addMetric(met6);
-    engine.addMetric(met7);
-    engine.addMetric(met8);
-    engine.addMetric(met9);
-    engine.addMetric(met10);
-
-    engine.addDimension(dim1);
-    engine.addDimension(dim2);
-    engine.addDimension(dim3);
-    engine.addDimension(dim4);
-    engine.addDimension(dim5);
-    engine.addDimension(dim6);
-    engine.addDimension(dim7);
-    engine.addDimension(dim8);
-    engine.addDimension(dim9);
-    engine.addDimension(dim10);
-
-    engine.addDimension(subdim1);
-    engine.addDimension(subdim2);
-    engine.addDimension(subdim3);
-    engine.addDimension(subdim4);
-    engine.addDimension(subdim5);
-
-    let views: View[] = [
-        new View({ metrics: [met1, met2, met3], dimensions: [dim1, dim2]}),
-        new View({ metrics: [met1, met3, met5], dimensions: [dim1, dim2]}),
-        new View({ metrics: [met3, met4, met7], dimensions: [dim4, dim5]}),
-        new View({ metrics: [met6, met7], dimensions: [dim3, dim4, dim5, dim6]}),
-        new View({ metrics: [met8, met2, met3], dimensions: [dim1, dim2, dim7]}),
-        new View({ metrics: [met2, met4], dimensions: [dim1, dim2]}),
-        new View({ metrics: [met8], dimensions: [dim8, dim9, dim10]}),
-        new View({ metrics: [met9], dimensions: [dim8, dim9, dim10]}),
-        new View({ metrics: [met10], dimensions: [dim8, dim9, dim10]})
-    ];
-
-    views.push(new View({
-        metrics: [met1, met2, met3, met4, met5],
-        dimensions: [dim1, dim2],
-        materialized: false,
-        childViews: [
-            { view: views[0], metrics: [met1, met2, met3], dimensions: [dim1, dim2]},
-            { view: views[6], metrics: [met4], dimensions: []},
-            { view: views[1], metrics: [met5], dimensions: []}
-        ]
-    }));
-
-    views.push(new View({
-        metrics: [met8, met9, met10],
-        dimensions: [dim8, dim9, dim10],
-        materialized: false,
-        childViews: [
-            { view: views[7], metrics: [met8], dimensions: [dim8, dim9, dim10]},
-            { view: views[8], metrics: [met9], dimensions: []},
-            { view: views[9], metrics: [met10], dimensions: []}
-        ]
-    }));
-
-    views.push(new View({
-        metrics: [met1],
-        dimensions: [subdim1, subdim2],
-        materialized: false,
-        childViews: [
-            { view: views[0], metrics: [met1], dimensions: [dim1]},
-            { view: views[9], metrics: [], dimensions: [dim9]}
-        ]
-    }));
+    for (let i = 0; i < 10; ++i) {
+        engine.addMetric(met[i]);
+        engine.addDimension(dim[i]);
+        if (i < 5) {
+            engine.addDimension(subdim[i]);
+        }
+    }
 
     views.forEach((view) => engine.addView(view));
 
     it("should be create a fill that cover the query and has 4 children", () => {
         let query = {
-            metrics : [met1, met2, met3, met4, met5, met6, met7, met8, met9, met10]
-            , dimensions : [dim1, dim2, dim3, dim4, dim5, dim6, dim7, dim8, dim9, dim10]
+            metrics : met.slice(0, 10)
+            , dimensions : dim.slice(0, 10)
         };
         let optimalView = engine.query(query);
         expect(optimalView).to.be.an("object");
@@ -150,22 +60,22 @@ describe("engine class", () => {
         expect(optimalView.metrics).to.have.length(10);
         expect(optimalView.dimensions).to.have.length(10);
         expect(optimalView.childViews).to.have.length(4);
-        let metAux: number[] = optimalView.metrics.sort().map((met: Metric) => {
-            return Number(met.name.split(":")[1]);
+        let metAux: number[] = optimalView.metrics.sort().map((item: Metric) => {
+            return Number(item.name.split(":")[1]);
         });
-        let dimAux: number[] = optimalView.dimensions.sort().map((dim: Dimension) => {
-            return Number(dim.name.split(":")[1]);
+        let dimAux: number[] = optimalView.dimensions.sort().map((item: Dimension) => {
+            return Number(item.name.split(":")[1]);
         });
 
         for (let i: number = 0; i < 10; ++i) {
-            expect(dimAux[i]).to.be.equal(i+1);
-            expect(metAux[i]).to.be.equal(i+1);
+            expect(dimAux[i]).to.be.equal(i + 1);
+            expect(metAux[i]).to.be.equal(i + 1);
         }
     });
     it("should throw an exception, query with non-existent metric", () => {
         let error: boolean = false;
         try {
-            engine.query({metrics: [met11], dimensions: [dim1]});
+            engine.query({metrics: [met[10]], dimensions: [dim[0]]});
         }
         catch (e){
             error = true;
@@ -178,7 +88,7 @@ describe("engine class", () => {
     it("should throw an exception, query with non-existent dimension", () => {
         let error: boolean = false;
         try {
-            engine.query({metrics: [met1], dimensions: [dim11]});
+            engine.query({metrics: [met[0]], dimensions: [dim[10]]});
         }
         catch (e){
             error = true;
@@ -190,8 +100,8 @@ describe("engine class", () => {
 
     it("should be create a fill that cover the query, that match perfectly with a existent view", () => {
         let query = {
-            metrics : [met1, met2, met3]
-            , dimensions : [dim1, dim2]
+            metrics : met.slice(0, 3)
+            , dimensions : dim.slice(0, 2)
         };
         let optimalView = engine.query(query);
         expect(optimalView).to.be.an("object");
@@ -212,7 +122,7 @@ describe("engine class", () => {
         let emptyMetrics: Metric[] = [];
         let query = {
             metrics : emptyMetrics
-            , dimensions : [subdim1, subdim2]
+            , dimensions : subdim.slice(0, 2)
         };
         let optimalView = engine.query(query);
         expect(optimalView).to.be.an("object");
@@ -227,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 === subdim1.name);
+            return optView.childViews[0].dimensions.some((item) => item.name === subdim[0].name);
         });
         expect(optimalView).satisfy((optView: View) => {
-            return optView.childViews[0].dimensions.some((item) => item.name === subdim1.name);
+            return optView.childViews[0].dimensions.some((item) => item.name === subdim[0].name);
         });
     });
 
@@ -238,7 +148,7 @@ describe("engine class", () => {
         let emptyMetrics: Metric[] = [];
         let query = {
             metrics : emptyMetrics
-            , dimensions : [subdim3, subdim5]
+            , dimensions : [subdim[2], subdim[4]]
         };
         let optimalView = engine.query(query);
         expect(optimalView).to.be.an("object");
@@ -253,21 +163,21 @@ describe("engine class", () => {
         expect(optimalView.childViews).to.have.length(1);
 
         expect(optimalView).satisfy((optView: View) => {
-            return optView.childViews[0].dimensions.some((item) => item.name === subdim3.name);
+            return optView.childViews[0].dimensions.some((item) => item.name === subdim[2].name);
         });
         expect(optimalView).satisfy((optView: View) => {
-            return optView.childViews[0].dimensions.some((item) => item.name === subdim5.name);
+            return optView.childViews[0].dimensions.some((item) => item.name === subdim[4].name);
         });
     });
 
     it("should throw an exception, sub-dimension with non-existent parent", () => {
         let error: boolean = false;
         try {
-            engine.query({metrics: [met11], dimensions: [subdim4]});
+            engine.query({metrics: [met[10]], dimensions: [subdim[3]]});
         }
         catch (e){
             error = true;
-            expect(e.message).to.be.equal("Engine sub-dimention " + subdim4.name + " with no parent");
+            expect(e.message).to.be.equal("Engine sub-dimention " + subdim[3].name + " with no parent");
 
         }
         expect(error).to.be.true;
diff --git a/src/core/metric.ts b/src/core/metric.ts
index adbabeaf3f577ce51c6824709ed7279877b351d6..4f0d1c4579d2fc9a83c97ea2cbbccd4545f15f28 100644
--- a/src/core/metric.ts
+++ b/src/core/metric.ts
@@ -23,14 +23,17 @@ import { AggregationType } from "../common/types";
 export interface MetricOptions {
     name: string;
     aggregation: AggregationType;
+    dataType: string;
 }
 
 export class Metric {
     public readonly name: string;
     public readonly aggregation: AggregationType;
+    public readonly dataType: string;
 
     constructor(options: MetricOptions) {
         this.name = options.name;
         this.aggregation = options.aggregation;
+        this.dataType = options.dataType;
     }
 }
diff --git a/src/core/view.ts b/src/core/view.ts
index 66fd11d447a87591610d1039f305565044cf895b..6de687e4cf7bf098e6568cf4b253cacd3cd9b8a5 100644
--- a/src/core/view.ts
+++ b/src/core/view.ts
@@ -22,6 +22,11 @@ import { Dimension } from "./dimension";
 import { Metric } from "./metric";
 import { Hash } from "../util/hash";
 
+export interface LoadView {
+    view: View;
+    data: string;
+}
+
 export interface ChildView {
     metrics: Metric[];
     dimensions: Dimension[];
@@ -45,8 +50,8 @@ export class View {
     constructor (options: ViewOptions) {
         this.metrics = options.metrics.sort();
         this.dimensions = options.dimensions.sort();
-        this.materialized = options.materialized || true;
-        this.childViews = options.childViews || [];
+        this.materialized = options.materialized || false;
+        this.childViews = (options.childViews) ? options.childViews : [];
 
         // calculate the id of the view based on it's metrics and dimensions
         let metricsNames = options.metrics.map(metric => metric.name);
diff --git a/src/util/configParser.spec.ts b/src/util/configParser.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bb13d67ab39a79550e372efecd5ba811014a18a0
--- /dev/null
+++ b/src/util/configParser.spec.ts
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana
+ *
+ * This file is part of blendb.
+ *
+ * blendb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * blendb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with blendb.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import { expect } from "chai";
+
+import { ConfigParser, ViewParsingOptions } from "./configParser";
+
+describe("configParser utility library", () => {
+    let metMap = new Map();
+    let dimMap = new Map();
+    it("should throw expection for inexistent metric", () => {
+        let opts: ViewParsingOptions =  {
+            alias: "Test",
+            data: "test",
+            dimensions: [],
+            metrics: ["met:-1"]
+        };
+
+        let error: boolean = false;
+        try {
+            ConfigParser.parseViewOpt(opts, metMap, dimMap);
+        }
+        catch (e) {
+            error = true;
+            expect(e.message).to.be
+            .equal("[Parsing error] Non exist metric set to view " + opts.alias);
+        }
+
+        expect(error).to.be.true;
+    });
+
+    it("should throw expection for inexistent metric", () => {
+        let opts: ViewParsingOptions =  {
+            alias: "Test",
+            data: "test",
+            dimensions: ["dim:-1"],
+            metrics: []
+        };
+
+        let error: boolean = false;
+        try {
+            ConfigParser.parseViewOpt(opts, metMap, dimMap);
+        }
+        catch (e) {
+            error = true;
+            expect(e.message).to.be
+            .equal("[Parsing error] Non exist dimension set to view " + opts.alias);
+        }
+
+        expect(error).to.be.true;
+    });
+
+});
diff --git a/src/util/configParser.ts b/src/util/configParser.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c6490e0660417f3fe0a14a10dcfc1c7e3d7bf972
--- /dev/null
+++ b/src/util/configParser.ts
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2017 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana
+ *
+ * This file is part of blendb.
+ *
+ * blendb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * blendb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with blendb.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import { Metric, MetricOptions } from "../core/metric";
+import { Dimension, DimensionOptions } from "../core/dimension";
+import { View, ViewOptions, LoadView } from "../core/view";
+import { PoolConfig } from "pg";
+import * as fs from "fs";
+import * as yaml from "js-yaml";
+
+export interface ViewParsingOptions {
+    alias: string;
+    data: string;
+    dimensions: string[];
+    metrics: string[];
+}
+
+interface ConfigSchema {
+    views: ViewParsingOptions[];
+    metrics: MetricOptions[];
+    dimensions: DimensionOptions[];
+}
+
+interface ConfigFile {
+    connection: PoolConfig;
+    struct: LoadStruct;
+    schema: ConfigSchema;
+}
+
+export interface LoadStruct{
+    create: boolean;
+    insert: boolean;
+}
+
+export interface ParsedConfig {
+    connection: PoolConfig;
+    views: View[];
+    metrics: Metric[];
+    dimensions: Dimension[];
+    struct: LoadStruct;
+    loadViews: LoadView[];
+}
+
+export class ConfigParser {
+    public static parse(configPath: string): ParsedConfig {
+        let config: ConfigFile = yaml.safeLoad(fs.readFileSync(configPath, {
+            encoding: "utf-8"
+        }));
+
+        let metricsOpts = config.schema.metrics;
+        let viewsOpts = config.schema.views;
+        let dimensionsOpts = config.schema.dimensions;
+        let parsed: ParsedConfig = {
+            connection: config.connection,
+            views: [],
+            metrics: [],
+            dimensions: [],
+            struct: config.struct,
+            loadViews: []
+        };
+
+        let metMap: Map<string, Metric> = new Map();
+        let dimMap: Map<string, Dimension> = new Map();
+
+        for (let i = 0; i < metricsOpts.length; ++i) {
+            let met = new Metric(metricsOpts[i]);
+            parsed.metrics.push(met);
+            metMap.set(met.name, met);
+        }
+
+        for (let i = 0; i < dimensionsOpts.length; ++i) {
+            let dim = new Dimension(dimensionsOpts[i]);
+            parsed.dimensions.push(dim);
+            dimMap.set(dim.name, dim);
+        }
+
+        for (let i = 0; i < viewsOpts.length; ++i) {
+            let viewOpts = ConfigParser.parseViewOpt(viewsOpts[i], metMap, dimMap);
+            let view = new View(viewOpts);
+            parsed.views.push(view);
+            let loadView: LoadView = {view: view, data: viewsOpts[i].data};
+            parsed.loadViews.push(loadView);
+        }
+
+        return parsed;
+    }
+
+    public static parseViewOpt(opts: ViewParsingOptions,
+                                metMap: Map<string, Metric>,
+                                dimMap: Map<string, Dimension>): ViewOptions {
+
+        let viewOpt: ViewOptions = {
+            metrics: [],
+            dimensions: [],
+            materialized: true,
+            childViews: [],
+        };
+
+        for (let i = 0; i < opts.metrics.length; ++i) {
+            if (metMap.has(opts.metrics[i])) {
+                viewOpt.metrics.push(metMap.get(opts.metrics[i]));
+            }
+
+            else {
+                throw new Error("[Parsing error] Non exist metric set to view " + opts.alias);
+            }
+        }
+
+        for (let i = 0; i < opts.dimensions.length; ++i) {
+            if (dimMap.has(opts.dimensions[i])) {
+                viewOpt.dimensions.push(dimMap.get(opts.dimensions[i]));
+            }
+
+            else {
+                throw new Error("[Parsing error] Non exist dimension set to view " + opts.alias);
+            }
+        }
+        return viewOpt;
+    }
+}
diff --git a/test/postgres/fixture.ts b/test/postgres/fixture.ts
new file mode 100644
index 0000000000000000000000000000000000000000..111bda10cd75c08400606aed11f4a63a21e281aa
--- /dev/null
+++ b/test/postgres/fixture.ts
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2017 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana
+ *
+ * This file is part of blend.
+ *
+ * blend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * blend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with blend.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import { Client, PoolConfig } from "pg";
+import { View, LoadView } from "../../src/core/view";
+import { each, series } from "async";
+import * as fs from "fs";
+
+interface TransSet {
+    init: string;
+    data: string[];
+}
+
+export interface Schema {
+    alias?: string;
+    query?: string;
+    data?: string;
+    fields: any[];
+}
+
+export class Fixture {
+    private database: string;
+    private config: PoolConfig;
+
+    constructor(config: PoolConfig) {
+        this.config = config;
+        this.database = config.database;
+    }
+
+    public load(schemas: LoadView[], create: boolean, cb: (err: Error) => void) {
+        let client = new Client(this.config);
+
+        /*
+            Loading data has 2 steps:
+            1 - Create a table or truncate a existing one.
+                Create or truncate dependes from a parameter in the configure
+                file, this parameter reaches this function as the create
+                parameter.
+            2 - Insert data.
+        */
+        let init: string[] = [];
+        let data: string[] = [];
+        for (let i = 0; i < schemas.length; ++i) {
+            let table: TransSet = this.createTransSet(schemas[i].view, schemas[i].data, create);
+            init.push(table.init);
+            data = data.concat(table.data);
+        }
+
+        client.connect((error) => {
+            if (error) {
+                cb(error);
+                return;
+            }
+
+            /*
+                Tables must be creates before data could be inserted, so the
+                queries that create and insert are splited in 2 arrays.
+                To garantee that tables exists before start insert data, series
+                is used. Inside series each query is executed, using each;
+            */
+            series([(callback) => {
+                each(init, (query, cback) => {
+                    return client.query(query, [], (err: Error) => cback(err));
+                }, (errQuery: Error) => callback(errQuery));
+            }, (callback) => {
+                each(data, (query, cback) => {
+                    return client.query(query, [], (err: Error) => cback(err));
+                }, (errQuery: Error) => callback(errQuery));
+            }], (errQuery: Error) => {
+                if (errQuery) {
+                    client.end();
+                    cb(errQuery);
+                }
+                client.end((err) => {
+                    cb(err);
+                });
+            });
+
+        });
+    }
+
+    private typeConvertion(t: string) {
+        switch (t) {
+            case "integer":
+                return "INTEGER";
+            case "date":
+                return "DATE";
+            case "string":
+                return "TEXT";
+            case "boolean":
+                return "BOOLEAN";
+            default:
+                return "";
+        }
+    }
+
+    private createTransSet(view: View, filePath: string, create: boolean) {
+        let props = [];
+
+        for (let i = 0; i < view.metrics.length; ++i) {
+            let met = view.metrics[i];
+            props.push("\"" + met.name + "\" " + this.typeConvertion(met.dataType));
+        }
+
+        for (let i = 0; i < view.dimensions.length; ++i) {
+            let dim = view.dimensions[i];
+            props.push("\"" + dim.name + "\" " + this.typeConvertion(dim.dataType));
+        }
+
+        let name = "view_" + view.id;
+        let transaction: TransSet = {init: "", data: []};
+        if (create) {
+            transaction.init = "CREATE TABLE " + name + "(" + props.join(", ") + ")";
+        }
+        else {
+            transaction.init = "TRUNCATE TABLE " + name;
+        }
+
+        transaction.data = [];
+        let rows = JSON.parse(fs.readFileSync(filePath, {encoding : "utf8"}));
+        for (let i = 0; i < rows.length; ++i) {
+            let values = [];
+            let keys = [];
+            for (let key in rows[i]) {
+                keys.push("\"" + key + "\"");
+                values.push("'" + rows[i][key] + "'");
+            }
+            transaction.data.push("INSERT INTO " + name +
+                                    "(" + keys.join(", ") + ") " +
+                                    "VALUES (" + values.join(", ") + ")");
+        }
+        return transaction;
+    }
+}
diff --git a/test/postgres/fixtures/view1.json b/test/postgres/fixtures/view1.json
new file mode 100644
index 0000000000000000000000000000000000000000..ee901bd78333d518094fcdb3fa1b2f8b5e6eec70
--- /dev/null
+++ b/test/postgres/fixtures/view1.json
@@ -0,0 +1,7 @@
+[
+{"dim:1":"2017-01-01","dim:2":"2017-01-01","met:1":"1","met:2":"1","met:3":"1"},
+{"dim:1":"2017-01-02","dim:2":"2017-01-02","met:1":"2","met:2":"2","met:3":"2"},
+{"dim:1":"2017-01-03","dim:2":"2017-01-03","met:1":"3","met:2":"3","met:3":"3"},
+{"dim:1":"2017-01-04","dim:2":"2017-01-04","met:1":"4","met:2":"4","met:3":"4"},
+{"dim:1":"2017-01-05","dim:2":"2017-01-05","met:1":"5","met:2":"5","met:3":"5"}
+]
diff --git a/test/postgres/fixtures/view2.json b/test/postgres/fixtures/view2.json
new file mode 100644
index 0000000000000000000000000000000000000000..b49410e0a3c58c0a19e4931db55c7d4142a9da63
--- /dev/null
+++ b/test/postgres/fixtures/view2.json
@@ -0,0 +1,7 @@
+[
+{"dim:1":"2017-01-01","dim:2":"2017-01-01","met:1":"1","met:3":"1","met:5":"1"},
+{"dim:1":"2017-01-02","dim:2":"2017-01-02","met:1":"2","met:3":"2","met:5":"2"},
+{"dim:1":"2017-01-03","dim:2":"2017-01-03","met:1":"3","met:3":"3","met:5":"3"},
+{"dim:1":"2017-01-04","dim:2":"2017-01-04","met:1":"4","met:3":"4","met:5":"4"},
+{"dim:1":"2017-01-05","dim:2":"2017-01-05","met:1":"5","met:3":"5","met:5":"5"}
+]
diff --git a/test/postgres/fixtures/view3.json b/test/postgres/fixtures/view3.json
new file mode 100644
index 0000000000000000000000000000000000000000..a45a44119ba3b1011327859d3b6f2cf9a7eda2ed
--- /dev/null
+++ b/test/postgres/fixtures/view3.json
@@ -0,0 +1,7 @@
+[
+{"dim:4":"dim:4:1","dim:5":"dim:5:1","met:3":"1","met:4":"1","met:7":"1"},
+{"dim:4":"dim:4:2","dim:5":"dim:5:2","met:3":"2","met:4":"2","met:7":"2"},
+{"dim:4":"dim:4:3","dim:5":"dim:5:3","met:3":"3","met:4":"3","met:7":"3"},
+{"dim:4":"dim:4:4","dim:5":"dim:5:4","met:3":"4","met:4":"4","met:7":"4"},
+{"dim:4":"dim:4:5","dim:5":"dim:5:5","met:3":"5","met:4":"5","met:7":"5"}
+]
diff --git a/test/postgres/fixtures/view4.json b/test/postgres/fixtures/view4.json
new file mode 100644
index 0000000000000000000000000000000000000000..7dbaad02ce12c5d452cb2b1071d1407082588d15
--- /dev/null
+++ b/test/postgres/fixtures/view4.json
@@ -0,0 +1,7 @@
+[
+{"dim:3":"1","dim:4":"dim:4:1","dim:5":"dim:5:1","dim:6":"t","met:6":"1","met:7":"1"},
+{"dim:3":"2","dim:4":"dim:4:2","dim:5":"dim:5:2","dim:6":"t","met:6":"2","met:7":"2"},
+{"dim:3":"3","dim:4":"dim:4:3","dim:5":"dim:5:3","dim:6":"f","met:6":"3","met:7":"3"},
+{"dim:3":"4","dim:4":"dim:4:4","dim:5":"dim:5:4","dim:6":"f","met:6":"4","met:7":"4"},
+{"dim:3":"5","dim:4":"dim:4:5","dim:5":"dim:5:5","dim:6":"f","met:6":"5","met:7":"5"}
+]
diff --git a/test/postgres/fixtures/view5.json b/test/postgres/fixtures/view5.json
new file mode 100644
index 0000000000000000000000000000000000000000..3f76ce6e4a3bffffe0e68e79dc45addcc71f51ba
--- /dev/null
+++ b/test/postgres/fixtures/view5.json
@@ -0,0 +1,7 @@
+[
+{"dim:1":"2017-01-01","dim:2":"2017-01-01","dim:7":"1","met:2":"1","met:3":"1","met:8":"1"},
+{"dim:1":"2017-01-02","dim:2":"2017-01-02","dim:7":"2","met:2":"2","met:3":"2","met:8":"2"},
+{"dim:1":"2017-01-03","dim:2":"2017-01-03","dim:7":"3","met:2":"3","met:3":"3","met:8":"3"},
+{"dim:1":"2017-01-04","dim:2":"2017-01-04","dim:7":"4","met:2":"4","met:3":"4","met:8":"4"},
+{"dim:1":"2017-01-05","dim:2":"2017-01-05","dim:7":"5","met:2":"5","met:3":"5","met:8":"5"}
+]
diff --git a/test/postgres/fixtures/view6.json b/test/postgres/fixtures/view6.json
new file mode 100644
index 0000000000000000000000000000000000000000..a810edb99a0efde8151a9c784fba3043c527aadf
--- /dev/null
+++ b/test/postgres/fixtures/view6.json
@@ -0,0 +1,7 @@
+[
+{"dim:1":"2017-01-01","dim:2":"2017-01-01","met:1":"1","met:4":"1"},
+{"dim:1":"2017-01-02","dim:2":"2017-01-02","met:1":"2","met:4":"2"},
+{"dim:1":"2017-01-03","dim:2":"2017-01-03","met:1":"3","met:4":"3"},
+{"dim:1":"2017-01-04","dim:2":"2017-01-04","met:1":"4","met:4":"4"},
+{"dim:1":"2017-01-05","dim:2":"2017-01-05","met:1":"5","met:4":"5"}
+]
diff --git a/test/postgres/fixtures/view7.json b/test/postgres/fixtures/view7.json
new file mode 100644
index 0000000000000000000000000000000000000000..bc4f17dee3fc46baadab5372f8b261c5eedebf1d
--- /dev/null
+++ b/test/postgres/fixtures/view7.json
@@ -0,0 +1,7 @@
+[
+{"dim:8":"1","dim:9":"2017-01-01","dim:10":"dim:5:1","met:8":"1"},
+{"dim:8":"2","dim:9":"2017-01-02","dim:10":"dim:5:2","met:8":"2"},
+{"dim:8":"3","dim:9":"2017-01-03","dim:10":"dim:5:3","met:8":"3"},
+{"dim:8":"4","dim:9":"2017-01-04","dim:10":"dim:5:4","met:8":"4"},
+{"dim:8":"5","dim:9":"2017-01-05","dim:10":"dim:5:5","met:8":"5"}
+]
diff --git a/test/postgres/fixtures/view8.json b/test/postgres/fixtures/view8.json
new file mode 100644
index 0000000000000000000000000000000000000000..db33365b4780efabe114f1a85b65139978852ff9
--- /dev/null
+++ b/test/postgres/fixtures/view8.json
@@ -0,0 +1,7 @@
+[
+{"dim:8":"1","dim:9":"2017-01-01","dim:10":"dim:5:1","met:9":"1"},
+{"dim:8":"2","dim:9":"2017-01-02","dim:10":"dim:5:2","met:9":"2"},
+{"dim:8":"3","dim:9":"2017-01-03","dim:10":"dim:5:3","met:9":"3"},
+{"dim:8":"4","dim:9":"2017-01-04","dim:10":"dim:5:4","met:9":"4"},
+{"dim:8":"5","dim:9":"2017-01-05","dim:10":"dim:5:5","met:9":"5"}
+]
diff --git a/test/postgres/fixtures/view9.json b/test/postgres/fixtures/view9.json
new file mode 100644
index 0000000000000000000000000000000000000000..c6ef8937a25975af513a957f8e7f5ea9d32e1266
--- /dev/null
+++ b/test/postgres/fixtures/view9.json
@@ -0,0 +1,7 @@
+[
+{"dim:8":"1","dim:9":"2017-01-01","dim:10":"dim:5:1","met:10":"1"},
+{"dim:8":"2","dim:9":"2017-01-02","dim:10":"dim:5:2","met:10":"2"},
+{"dim:8":"3","dim:9":"2017-01-03","dim:10":"dim:5:3","met:10":"3"},
+{"dim:8":"4","dim:9":"2017-01-04","dim:10":"dim:5:4","met:10":"4"},
+{"dim:8":"5","dim:9":"2017-01-05","dim:10":"dim:5:5","met:10":"5"}
+]
diff --git a/test/scenario.ts b/test/scenario.ts
new file mode 100644
index 0000000000000000000000000000000000000000..24185847b66e7aeddd6b615142a2b9e6bee1baa2
--- /dev/null
+++ b/test/scenario.ts
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2017 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana
+ *
+ * This file is part of blendb.
+ *
+ * blendb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * blendb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with blendb.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import { Metric } from "../src/core/metric";
+import { Dimension } from "../src/core/dimension";
+import { View } from "../src/core/view";
+import { AggregationType, RelationType } from "../src/common/types";
+
+interface EngineScenario {
+    metrics: Metric[];
+    dimensions: Dimension[];
+    subDimensions: Dimension[];
+    views: View[];
+}
+
+interface AdapterScenario {
+    materializedView: View;
+    noSelectionView: View;
+    withSelectionView: View;
+    subDimensionView: View;
+    join4View: View;
+    dateView: View;
+}
+
+const mets = [
+    new Metric({ name: "met:1", aggregation: AggregationType.SUM, dataType: "integer" }),
+    new Metric({ name: "met:2", aggregation: AggregationType.AVG, dataType: "integer" }),
+    new Metric({ name: "met:3", aggregation: AggregationType.AVG, dataType: "integer" }),
+    new Metric({ name: "met:4", aggregation: AggregationType.SUM, dataType: "integer" }),
+    new Metric({ name: "met:5", aggregation: AggregationType.SUM, dataType: "integer" }),
+    new Metric({ name: "met:6", aggregation: AggregationType.AVG, dataType: "integer" }),
+    new Metric({ name: "met:7", aggregation: AggregationType.COUNT, dataType: "integer" }),
+    new Metric({ name: "met:8", aggregation: AggregationType.COUNT, dataType: "integer" }),
+    new Metric({ name: "met:9", aggregation: AggregationType.SUM, dataType: "integer" }),
+    new Metric({ name: "met:10", aggregation: AggregationType.COUNT, dataType: "integer" }),
+];
+
+const dims = [
+    new Dimension({ name: "dim:1", dataType: "date" }),
+    new Dimension({ name: "dim:2", dataType: "date" }),
+    new Dimension({ name: "dim:3", dataType: "integer" }),
+    new Dimension({ name: "dim:4", dataType: "string" }),
+    new Dimension({ name: "dim:5", dataType: "string" }),
+    new Dimension({ name: "dim:6", dataType: "boolean" }),
+    new Dimension({ name: "dim:7", dataType: "integer" }),
+    new Dimension({ name: "dim:8", dataType: "integer" }),
+    new Dimension({ name: "dim:9", dataType: "date" }),
+    new Dimension({ name: "dim:10", dataType: "string" }),
+];
+
+const wrongMet = new Metric({
+    name: "met:11",
+    aggregation: AggregationType.COUNT,
+    dataType: "integer"
+});
+const wrongDim = new Dimension({ name: "dim:11", dataType: "integer" });
+
+const subdimAux = new Dimension({
+    name: "sub:1",
+    dataType: "integer",
+    parent: dims[0],
+    relation: RelationType.DAY
+});
+
+const subdims = [
+    subdimAux,
+    new Dimension({
+        name: "sub:2",
+        dataType: "integer",
+        parent: dims[8],
+        relation: RelationType.DAY
+    }),
+    new Dimension({
+        name: "sub:3",
+        dataType: "integer",
+        parent: subdimAux,
+        relation: RelationType.DAY
+    }),
+    new Dimension({
+        name: "sub:4",
+        dataType: "integer",
+        parent: null,
+        relation: RelationType.DAY
+    }),
+    new Dimension({
+        name: "sub:5",
+        dataType: "integer",
+        parent: dims[1],
+        relation: RelationType.DAY
+    })
+];
+
+const dateSubDim = [
+    new Dimension ({
+        name: "dim:2:month",
+        dataType: "integer",
+        parent: dims[1],
+        relation: RelationType.MONTH
+    }),
+    new Dimension ({
+        name: "dim:2:day",
+        dataType: "integer",
+        parent: dims[1],
+        relation: RelationType.DAY
+    }),
+    new Dimension ({
+        name: "dim:2:year",
+        dataType: "integer",
+        parent: dims[1],
+        relation: RelationType.YEAR
+    }),
+    new Dimension ({
+        name: "dim:2:dow",
+        dataType: "integer",
+        parent: dims[1],
+        relation: RelationType.DAYOFWEEK
+    }),
+];
+
+const views = [
+    new View({
+        metrics: [mets[0], mets[1], mets[2]],
+        dimensions: [dims[0], dims[1]],
+        materialized: true
+    }),
+    new View({
+        metrics: [mets[0], mets[2], mets[4]],
+        dimensions: [dims[0], dims[1]],
+        materialized: true
+    }),
+    new View({
+        metrics: [mets[2], mets[3], mets[6]],
+        dimensions: [dims[3], dims[4]],
+        materialized: true
+    }),
+    new View({
+        metrics: [mets[5], mets[6]],
+        dimensions: [dims[2], dims[3], dims[4], dims[5]],
+        materialized: true
+    }),
+    new View({
+        metrics: [mets[7], mets[1], mets[2]],
+        dimensions: [dims[0], dims[1], dims[6]],
+        materialized: true
+    }),
+    new View({
+        metrics: [mets[0], mets[3]],
+        dimensions: [dims[0], dims[1]],
+        materialized: true
+    }),
+    new View({
+        metrics: [mets[7]],
+        dimensions: [dims[7], dims[8], dims[9]],
+        materialized: true
+    }),
+    new View({
+        metrics: [mets[8]],
+        dimensions: [dims[7], dims[8], dims[9]],
+        materialized: true
+    }),
+    new View({
+        metrics: [mets[9]],
+        dimensions: [dims[7], dims[8], dims[9]],
+        materialized: true
+    })
+];
+
+const engAuxView = [
+    new View({
+        metrics: [mets[0], mets[1], mets[2], mets[3], mets[4]],
+        dimensions: [dims[0], dims[1]],
+        materialized: false,
+        childViews: [
+            {
+                view: views[0],
+                metrics: [mets[0], mets[1], mets[2]],
+                dimensions: [dims[0], dims[1]]
+            },
+            {
+                view: views[5],
+                metrics: [mets[3]],
+                dimensions: []
+            },
+            {
+                view: views[1],
+                metrics: [mets[4]],
+                dimensions: []
+            }
+        ]
+    }),
+
+    new View({
+        metrics: [mets[7], mets[8], mets[9]],
+        dimensions: [dims[7], dims[8], dims[9]],
+        materialized: false,
+        childViews: [
+            {
+                view: views[6],
+                metrics: [mets[7]],
+                dimensions: [dims[7], dims[8], dims[9]]
+            },
+            {
+                view: views[7],
+                metrics: [mets[8]],
+                dimensions: []
+            },
+            {
+                view: views[8],
+                metrics: [mets[9]],
+                dimensions: []
+            }
+        ]
+    }),
+
+    new View({
+        metrics: [mets[0]],
+        dimensions: [subdims[0], subdims[1]],
+        materialized: false,
+        childViews: [
+            {
+                view: views[0],
+                metrics: [mets[0]],
+                dimensions: [dims[0]]
+            },
+            {
+                view: views[9],
+                metrics: [],
+                dimensions: [dims[8]]
+            }
+        ]
+    })
+];
+
+const dateView = new View({
+    metrics: [],
+    dimensions: dateSubDim,
+    materialized: false,
+    childViews: [{
+        view: views[0],
+        metrics: [],
+        dimensions: [dims[1]]
+    }]
+});
+
+const subDimView = new View({
+    metrics: [mets[0]],
+    dimensions: [subdims[0], subdims[1]],
+    materialized: false,
+    childViews: [
+        {
+            view: views[0],
+            metrics: [mets[0]],
+            dimensions: [dims[0]]
+        },
+        {
+            view: views[8],
+            metrics: [],
+            dimensions: [dims[8]]
+        }
+    ]
+});
+
+const join4View = new View({
+    metrics: mets,
+    dimensions: dims,
+    materialized: false,
+    childViews: [
+        {
+            view: engAuxView[0],
+            metrics: [mets[0], mets[1], mets[2], mets[3], mets[4]],
+            dimensions: [dims[0], dims[1]]
+        },
+        {
+            view: engAuxView[1],
+            metrics: [mets[7], mets[8], mets[9]],
+            dimensions: [dims[7], dims[8], dims[9]]
+        },
+        {
+            view: views[3],
+            metrics: [mets[5], mets[6]],
+            dimensions: [dims[2], dims[3], dims[4], dims[5]]
+        },
+        {
+            view: views[4],
+            metrics: [],
+            dimensions: [dims[6]]
+        }
+    ]
+});
+
+const noSelView = new View({
+    metrics: [mets[0], mets[3]],
+    dimensions: [],
+    materialized: false,
+    childViews: [
+        {
+            view: views[0],
+            metrics: [mets[0]],
+            dimensions: []
+        },
+        {
+            view: views[2],
+            metrics: [mets[3]],
+            dimensions: []
+        }
+    ]
+});
+
+const withSelView = new View({
+    metrics: [mets[0], mets[1], mets[4]],
+    dimensions: [dims[0], dims[1]],
+    materialized: false,
+    childViews: [
+        {
+            view: views[0],
+            metrics: [mets[0], mets[1]],
+            dimensions: [dims[0], dims[1]]
+        },
+        {
+            view: views[1],
+            metrics: [mets[4]],
+            dimensions: []
+        }
+    ]
+});
+
+export const engineScenario: EngineScenario = {
+    metrics: mets.concat([wrongMet]),
+    dimensions: dims.concat([wrongDim]),
+    subDimensions: subdims,
+    views: views.concat(engAuxView)
+};
+
+export const adapterScenario: AdapterScenario = {
+    materializedView: views[0],
+    noSelectionView: noSelView,
+    withSelectionView: withSelView,
+    subDimensionView: subDimView,
+    join4View: join4View,
+    dateView: dateView
+};