Support for SQL generation.

master
Oliver Kennedy 2016-06-25 02:02:04 -07:00
parent afdf9f7042
commit 9a1116c376
6 changed files with 297 additions and 2 deletions

6
bin/runTest Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
BASE=`dirname $0`/..
CLASSPATH=`echo $BASE/target/vizier-db/WEB-INF/lib/* | tr ' ' ':'`
java -cp $CLASSPATH:$BASE/target/classes:$BASE/target/test-classes org.vizier.test.$1

View File

@ -45,7 +45,7 @@ public class ColumnList implements Iterable<Column> {
_columnList.add(column);
_columnIndex.put(column.getIdentifier(), _columnIndex.size());
}
/**
* Check if the list contains a column with the given identifier.
*
@ -83,6 +83,19 @@ public class ColumnList implements Iterable<Column> {
return null;
}
}
public void renameColumn(int columnId, String newName)
{
int index = this.getIndexOf(columnId);
Column col = _columnList.get(index);
String oldName = col.getName();
_nameCount.put(oldName, _nameCount.get(oldName) - 1);
if (_nameCount.containsKey(newName)) {
_nameCount.put(newName, _nameCount.get(newName) + 1);
} else {
_nameCount.put(newName, 1);
}
_columnList.set(index, new Column(columnId, newName, index, this));
}
/**
* The column identifier of the column with given name. Is UNKNOWN if either

View File

@ -51,6 +51,18 @@ public class VizUALScript {
_ops.addFirst(new ScriptOp(operation, stmt, snapshotIdentifier));
}
/**
* Add an operation to the end of the script.
*
* @param operation
* @param stmt
* @param snapshotIdentifier
*/
public void addAtEnd(Operation operation, VizUALStatement stmt, int snapshotIdentifier) {
_ops.add(new ScriptOp(operation, stmt, snapshotIdentifier));
}
/**
* Operation at the given position in the script's operation sequence.

View File

@ -283,7 +283,6 @@ public class CellUpdate extends Operation {
* @return
*/
public String getValue() {
return _value;
}

View File

@ -0,0 +1,163 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vizierdb.sql;
import java.util.*;
import scala.Enumeration;
import org.vizierdb.database.*;
import org.vizierdb.database.script.*;
import org.vizierdb.database.script.op.*;
import mimir.algebra.Table;
import mimir.algebra.Project;
import mimir.algebra.ProjectArg;
import mimir.algebra.Select;
import mimir.algebra.Union;
/**
* A script in VizUAL is a sequence of operations. Each operation generates a
* new snapshot. Operations and generated snapshot identifiers are recorded as
* part of the script.
*
* @author Oliver Kennedy
*/
public class MimirAdaptor {
public static <A, B> scala.collection.immutable.Map<A, B> toScalaMap(Map<A, B> m) {
return scala.collection.JavaConverters.mapAsScalaMapConverter(m).asScala().toMap(
scala.Predef.<scala.Tuple2<A, B>>conforms()
);
}
public static scala.collection.immutable.List<scala.Tuple2<String,scala.Enumeration.Value>> makeMimirSchema(Collection<String> cols)
{
return makeMimirSchema(cols, mimir.algebra.Type.withName("TString"));
}
public static scala.collection.immutable.List<scala.Tuple2<String,scala.Enumeration.Value>> makeMimirSchema(Collection<String> cols, scala.Enumeration.Value t)
{
scala.collection.immutable.List<scala.Tuple2<String,scala.Enumeration.Value>> ret =
scala.collection.immutable.List$.MODULE$.empty();
for(String col : cols){
ret = new scala.collection.immutable.$colon$colon<scala.Tuple2<String,scala.Enumeration.Value>>(
new scala.Tuple2<String,scala.Enumeration.Value>(col, t), ret
);
}
return ret;
}
public static mimir.algebra.Operator compileToRA(VizUALScript script, Map<String, List<String>> schemas)
{
mimir.algebra.Operator raTree = null;
ColumnList cols = new ColumnList();
int colIdx = 0;
BitSet deleted = new BitSet();
for(int x = 0; x < script.size(); x++){
Operation step = script.getOperation(x);
// System.out.println("CONVERT: "+step);
if(step instanceof CellUpdate){
CellUpdate update = (CellUpdate)step;
String targetCol = cols.get(update.getColumnId()).getName();
raTree = mimir.algebra.OperatorUtils$.MODULE$.replaceColumn(
targetCol,
(mimir.algebra.Expression)(new mimir.algebra.Conditional(
new mimir.algebra.Comparison(
mimir.algebra.Cmp.withName("Eq"),
new mimir.algebra.Var("ROWID_MIMIR"),
new mimir.algebra.RowIdPrimitive(""+update.getRowId())
),
new mimir.algebra.StringPrimitive(update.getValue()),
new mimir.algebra.Var(targetCol)
)),
raTree
);
} else if(step instanceof ColumnDelete){
ColumnDelete delete = (ColumnDelete)step;
String targetCol = cols.get(delete.getColumnId()).getName();
// System.out.println("Deleting "+ targetCol);
raTree = mimir.algebra.OperatorUtils$.MODULE$.projectAwayColumn(targetCol, raTree);
deleted.set(delete.getColumnId());
} else if(step instanceof ColumnInsert){
ColumnInsert insert = (ColumnInsert)step;
raTree = mimir.algebra.OperatorUtils$.MODULE$.projectInColumn(insert.getName(), new mimir.algebra.NullPrimitive(), raTree);
cols.add(colIdx++, insert.getName());
} else if(step instanceof ColumnMove){
//ignore positions for now
} else if(step instanceof ColumnRename){
ColumnRename rename = (ColumnRename)step;
String targetCol = cols.get(rename.getColumnId()).getName();
raTree = mimir.algebra.OperatorUtils$.MODULE$.renameColumn(targetCol, rename.getName(), raTree);
cols.renameColumn(rename.getColumnId(), rename.getName());
} else if(step instanceof CSVFileLoad){
String relName = ((CSVFileLoad)step).getFileName().replaceFirst("\\..*$", "");
colIdx = 0;
cols = new ColumnList();
for(String col : schemas.get(relName)){
cols.add(colIdx++, col);
}
raTree = new mimir.algebra.Table(relName,
makeMimirSchema(schemas.get(relName)),
makeMimirSchema(Arrays.asList("ROWID_MIMIR"), mimir.algebra.Type.withName("TRowId"))
);
} else if(step instanceof RowDelete){
RowDelete delete = (RowDelete)step;
raTree = new mimir.algebra.Select(
(mimir.algebra.Expression)(new mimir.algebra.Comparison(
mimir.algebra.Cmp.withName("Neq"),
new mimir.algebra.Var("ROWID_MIMIR"),
new mimir.algebra.RowIdPrimitive(""+delete.getRowId())
)),
raTree
);
} else if(step instanceof RowInsert){
mimir.algebra.Operator dual = new mimir.algebra.Table("dual",
makeMimirSchema(schemas.get("dual")),
makeMimirSchema(Arrays.asList("ROWID_MIMIR"), mimir.algebra.Type.withName("TRowId"))
);
for(int i = 0; i < colIdx; i++){
if(!deleted.get(i)){
dual = mimir.algebra.OperatorUtils$.MODULE$.projectInColumn(cols.getColumn(i).getName(), new mimir.algebra.NullPrimitive(), dual);
}
}
dual = mimir.optimizer.InlineProjections$.MODULE$.optimize(dual);
raTree = new mimir.algebra.Union(dual, raTree);
} else if(step instanceof RowMove){
} else {
}
}
return mimir.algebra.OperatorUtils$.MODULE$.projectAwayColumn("ROWID_MIMIR", raTree);
}
public static String compileToSQL(mimir.algebra.Operator raTree, Map<String, List<String>> schemas)
{
Map<String,
scala.collection.immutable.List<
scala.Tuple2<String,scala.Enumeration.Value>>> scalaSchemas = new HashMap<>();
for(Map.Entry<String, List<String>> table : schemas.entrySet()){
scalaSchemas.put(table.getKey(), makeMimirSchema(table.getValue()));
}
mimir.Database db = new mimir.Database("Test DB",
new mimir.sql.NullBackend(toScalaMap(scalaSchemas)));
return db.convert(raTree).toString();
}
public static class UnsupportedFeature extends Exception {
public UnsupportedFeature(String msg) { super(msg); }
}
}

View File

@ -0,0 +1,102 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vizier.test.database;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import java.io.File;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import org.vizierdb.database.Notebook;
import org.vizierdb.database.SimpleVizierDBM;
import org.vizierdb.database.VizierDB;
import org.vizierdb.database.history.VersionGraph;
import org.vizierdb.database.script.VizUALScript;
import org.vizierdb.database.script.op.*;
import org.vizierdb.resources.ResourceManager;
import org.vizierdb.sql.MimirAdaptor;
import mimir.sql.SqlToRA;
/**
*
* @author oliver
*/
public class ConstructSQL {
public static final Map<String, List<String>> schemas = new HashMap<>();
public static void main(String[] args) {
JsonObject op;
// JsonObject opMoveRow = new JsonParser().parse("{\"type\":\"MoveRow\", \"parameters\": [{\"name\" : \"position\", \"value\" : \"0\"}, {\"name\" : \"row\", \"value\" : \"2\"}]}").getAsJsonObject();;
schemas.put("dual", new ArrayList<String>());
schemas.put("simple", Arrays.asList("Name","Age","Department"));
try {
SimpleVizierDBM vdb = new SimpleVizierDBM(new ResourceManager(new File("/Users/okennedy/Documents/Mimir/Vizier/src/main/webapp/WEB-INF/resources")));
Notebook nb = vdb.createNotebook("My Notebook");
// 0 - LoadFile
op = new JsonParser().parse("{\"type\":\"LoadFile\", \"parameters\": [{\"name\" : \"file\", \"value\" : \"simple.csv\"}, {\"name\" : \"format\", \"value\" : \"RFC4180\"}, {\"name\" : \"headline\", \"value\" : \"true\"}]}").getAsJsonObject();
vdb.executeOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), vdb.createOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), VizierDB.UNKNOWN_SNAPSHOT, op));
printSQL(nb);
// 1 - UpdateCell
op = new JsonParser().parse("{\"type\":\"UpdateCell\", \"parameters\": [{\"name\" : \"row\", \"value\" : \"0\"}, {\"name\" : \"column\", \"value\" : \"0\"}, {\"name\" : \"value\", \"value\" : \"99\" }]}").getAsJsonObject();
vdb.executeOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), vdb.createOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), VizierDB.UNKNOWN_SNAPSHOT, op));
printSQL(nb);
// 2 - DeleteColumn
op = new JsonParser().parse("{\"type\":\"DeleteColumn\", \"parameters\": [{\"name\" : \"column\", \"value\" : \"1\"}]}").getAsJsonObject();
vdb.executeOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), vdb.createOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), VizierDB.UNKNOWN_SNAPSHOT, op));
printSQL(nb);
// 3 - InsertColumn
op = new JsonParser().parse("{\"type\":\"InsertColumn\", \"parameters\": [{\"name\" : \"name\", \"value\" : \"Derived\"},{\"name\" : \"position\", \"value\" : 2}]}").getAsJsonObject();
vdb.executeOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), vdb.createOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), VizierDB.UNKNOWN_SNAPSHOT, op));
printSQL(nb);
// 4 - ColumnRename
op = new JsonParser().parse("{\"type\":\"RenameColumn\", \"parameters\": [{\"name\" : \"column\", \"value\" : \"1\"},{\"name\" : \"name\", \"value\" : \"Steve\"}]}").getAsJsonObject();
vdb.executeOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), vdb.createOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), VizierDB.UNKNOWN_SNAPSHOT, op));
printSQL(nb);
// 5 - RowDelete
op = new JsonParser().parse("{\"type\":\"DeleteRow\", \"parameters\": [{\"name\" : \"row\", \"value\" : \"2\"}]}").getAsJsonObject();
vdb.executeOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), vdb.createOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), VizierDB.UNKNOWN_SNAPSHOT, op));
printSQL(nb);
// 6 - RowInsert
op = new JsonParser().parse("{\"type\":\"InsertRow\", \"parameters\": [{\"name\" : \"position\", \"value\" : \"1\"}]}").getAsJsonObject();
vdb.executeOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), vdb.createOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), VizierDB.UNKNOWN_SNAPSHOT, op));
printSQL(nb);
} catch (Exception exception) {
exception.printStackTrace();
}
}
private static void printSQL(Notebook notebook) {
VersionGraph history = notebook.getHistory();
VizUALScript script = notebook.getHistory().getScript(history.getCurrentBranch().getIdentifier());
System.out.println("------------");
mimir.algebra.Operator raTree = MimirAdaptor.compileToRA(script, schemas);
System.out.println(raTree.toString());
String sql = MimirAdaptor.compileToSQL(raTree, schemas);
System.out.println(sql);
}
}