Skip to content
Snippets Groups Projects
Commit 50638ac8 authored by Paolo Guagliardo's avatar Paolo Guagliardo
Browse files

Handle BaseTable in schemas

parent e0cd5027
No related branches found
No related tags found
No related merge requests found
......@@ -9,18 +9,16 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.SetUtils;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import uk.ac.ed.pguaglia.real.db.engine.BaseTable;
import uk.ac.ed.pguaglia.real.db.engine.DataValue.DataType;
import uk.ac.ed.pguaglia.real.lang.Expression;
public class Schema {
private Map<String,List<String>> tables;
private Map<String,File> datafiles;
private Map<String,BaseTable> tables;
private Map<String,Expression> views;
private Map<String,Set<String>> isUsedBy;
......@@ -28,46 +26,14 @@ public class Schema {
tables = new HashMap<>();
views = new HashMap<>();
isUsedBy = new HashMap<>();
datafiles = new HashMap<>();
}
public static Schema fromJSON(File src) throws JsonParseException, JsonMappingException, IOException {
return SchemaMapper.getInstance().readValue(src, Schema.class);
}
protected Schema(Map<String, List<String>> tables, Map<String, File> datafiles, Map<String, Expression> views)
throws IllegalArgumentException {
Set<String> tableNames = tables.keySet();
Set<String> viewNames = views.keySet();
if (SetUtils.isEqualSet(tableNames, datafiles.keySet()) == false) {
throw new IllegalArgumentException();
}
if (CollectionUtils.containsAny(tableNames, viewNames)) {
throw new IllegalArgumentException();
}
Set<String> baseNames = SetUtils.union(tableNames, viewNames);
this.tables = new HashMap<>(tables);
this.datafiles = new HashMap<>(datafiles);
this.views = new HashMap<>();
this.isUsedBy = new HashMap<>();
for (String name : views.keySet()) {
Expression expr = views.get(name);
if (baseNames.containsAll(expr.getBaseNames()) == false) {
throw new IllegalArgumentException();
}
this.views.put(name, expr);
updateDeps(name, expr);
}
}
public File getTableDatafile(String name) throws IOException {
if (datafiles.containsKey(name) == false) {
String msg = String.format("ERROR: \"%s\" (No such table)", name);
throw new IOException(msg);
}
return datafiles.get(name);
return tables.get(name).datafile().toFile();
}
public boolean hasTable(String name) {
......@@ -79,19 +45,18 @@ public class Schema {
}
public List<String> getTableAttributes(String name) {
return tables.get(name);
return tables.get(name).attributes();
}
public Expression getViewDefinition(String name) {
return views.get(name);
}
public void addTable(String name, List<String> attributes, File data) throws Exception {
public void addTable(String name, BaseTable table) throws Exception {
if (tables.containsKey(name)) {
throw new Exception(String.format("ERROR: Table %s already exists", name));
}
tables.put(name, attributes);
datafiles.put(name, data.getAbsoluteFile());
tables.put(name, table);
}
public void dropTable(String name) throws Exception {
......@@ -101,11 +66,6 @@ public class Schema {
throw new Exception(msg);
}
tables.remove(name);
datafiles.remove(name);
}
public List<String> addTable(String name, List<String> attributes) {
return tables.put(name, attributes);
}
public Expression addView(String name, Expression def) throws SchemaException {
......@@ -160,6 +120,10 @@ public class Schema {
return tables.keySet();
}
public DataType getDataType(String tbl, String attr) {
return tables.get(tbl).getDataType(attr);
}
public Set<String> getTableNames(Expression expr) throws SchemaException {
Set<String> base = new HashSet<>();
for (String name : expr.getBaseNames()) {
......
......@@ -2,11 +2,10 @@ package uk.ac.ed.pguaglia.real.db;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.antlr.v4.runtime.RecognitionException;
......@@ -22,6 +21,8 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import uk.ac.ed.pguaglia.real.db.engine.BaseTable;
import uk.ac.ed.pguaglia.real.db.engine.DataValue.DataType;
import uk.ac.ed.pguaglia.real.lang.Expression;
import uk.ac.ed.pguaglia.real.lang.ReplacementException;
......@@ -54,7 +55,7 @@ public final class SchemaMapper extends ObjectMapper {
gen.writeObjectFieldStart(TABLE_ATTRIBUTES); // start attributes
for (String attrName : sch.getTableAttributes(tableName)) {
gen.writeObjectFieldStart(attrName);
gen.writeObjectField(ATTRIBUTE_TYPE,"STRING");
gen.writeObjectField(ATTRIBUTE_TYPE, sch.getDataType(tableName, attrName));
gen.writeEndObject();
}
gen.writeEndObject(); // end attributes
......@@ -84,40 +85,51 @@ public final class SchemaMapper extends ObjectMapper {
@Override
public Schema deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
Schema sch = new Schema();
JsonNode tables = node.get(TABLES);
Iterator<String> tableNames = tables.fieldNames();
Map<String,List<String>> tableMap = new HashMap<>();
Map<String,File> dataMap = new HashMap<>();
while (tableNames.hasNext()) {
String name = tableNames.next();
JsonNode tbl = tables.get(name);
List<String> attributes = new ArrayList<>();
List<DataType> types = new ArrayList<>();
Iterator<String> attrNames = tbl.get(TABLE_ATTRIBUTES).fieldNames();
while (attrNames.hasNext()) {
attributes.add(attrNames.next());
String attr = attrNames.next();
String type = tbl.get(TABLE_ATTRIBUTES).get(attr).get(ATTRIBUTE_TYPE).textValue();
switch (type) {
case "TEXT":
types.add(DataType.TEXT);
break;
case "NUMBER":
types.add(DataType.NUMBER);
break;
default:
throw new IllegalStateException();
}
attributes.add(attr);
}
Path p = new File(tbl.get(TABLE_DATAFILE).textValue()).toPath();
BaseTable bt = new BaseTable(p, attributes.toArray(new String[0]), types.toArray(new DataType[0]));
try {
sch.addTable(name, bt);
} catch (Exception e) {
throw new JsonProcessingException(e) {};
}
tableMap.put(name, attributes);
dataMap.put(name, new File(tbl.get(TABLE_DATAFILE).textValue()));
}
JsonNode views = node.get(VIEWS);
Iterator<String> viewNames = views.fieldNames();
Map<String,Expression> viewsMap = new HashMap<>();
while (viewNames.hasNext()) {
String name = viewNames.next();
try {
viewsMap.put(name, Expression.parse(views.get(name).textValue()));
} catch (RecognitionException | ReplacementException e) {
sch.addView(name, Expression.parse(views.get(name).textValue()));
} catch (RecognitionException | ReplacementException | SchemaException e) {
throw new JsonProcessingException(e) {};
}
}
try {
return new Schema(tableMap, dataMap, viewsMap);
} catch (IllegalArgumentException e) {
throw new JsonProcessingException(e) {};
}
return sch;
}
}
......
......@@ -3,17 +3,20 @@ package uk.ac.ed.pguaglia.real.db.engine;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import uk.ac.ed.pguaglia.real.db.engine.DataValue.DataType;
public class BaseTable {
private String[] attributes; // in fetch order
private DataType[] types; // in fetch order
private Path datafile;
private final String[] attributes; // in fetch order
private final DataType[] types; // in fetch order
private final Path datafile;
public BaseTable(Path data, String[] attributes, DataType[] types) {
// TODO: check sizes match
this.datafile = data;
this.types = types;
this.attributes = attributes;
......@@ -22,4 +25,21 @@ public class BaseTable {
public Stream<Record> fetch() throws IOException {
return Files.lines(datafile).map(s -> Record.of(s.split(","), types));
}
public List<String> attributes() {
return Arrays.asList(attributes);
}
public List<DataType> types() {
return Arrays.asList(types);
}
public DataType getDataType(String attr) {
int pos = Arrays.asList(attributes).indexOf(attr);
return types[pos];
}
public Path datafile() {
return datafile;
}
}
......@@ -3,6 +3,7 @@ package uk.ac.ed.pguaglia.real.runtime;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
......@@ -15,6 +16,7 @@ import org.apache.commons.cli.MissingOptionException;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.lang3.ArrayUtils;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.terminal.Terminal;
......@@ -27,6 +29,8 @@ import uk.ac.ed.pguaglia.real.db.Schema;
import uk.ac.ed.pguaglia.real.db.SchemaException;
import uk.ac.ed.pguaglia.real.db.SchemaMapper;
import uk.ac.ed.pguaglia.real.db.Table;
import uk.ac.ed.pguaglia.real.db.engine.BaseTable;
import uk.ac.ed.pguaglia.real.db.engine.DataValue.DataType;
import uk.ac.ed.pguaglia.real.lang.Expression;
import uk.ac.ed.pguaglia.real.lang.ReplacementException;
......@@ -322,8 +326,11 @@ public final class CommandLineApp {
for (String attr : spec.substring(start+1,end).split(",")) {
attributes.add(attr.strip());
}
DataType[] dt = new DataType[attributes.size()]; // TODO: add support for types
Arrays.fill(dt, DataType.TEXT);
BaseTable bt = new BaseTable(new File(filename).toPath(), attributes.toArray(new String[0]), dt);
try {
sch.addTable(tableName, attributes, new File(filename));
sch.addTable(tableName, bt);
} catch (Exception e) {
System.err.println("ERROR: " + e.getMessage());
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment