diff --git a/src/main/java/uk/ac/ed/pguaglia/real/db/Database.java b/src/main/java/uk/ac/ed/pguaglia/real/db/Database.java index dd83fbcb3aeea6153447aafec05e574bf12d316e..c6b4b51f428e146f02925eb700d83e046cc6d695 100644 --- a/src/main/java/uk/ac/ed/pguaglia/real/db/Database.java +++ b/src/main/java/uk/ac/ed/pguaglia/real/db/Database.java @@ -3,10 +3,11 @@ package uk.ac.ed.pguaglia.real.db; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.FileReader; import java.io.IOException; +import java.io.InputStreamReader; import java.io.Reader; import java.util.ArrayList; +import java.util.Enumeration; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -37,6 +38,49 @@ public class Database { db.close(); } + // Inefficient: rewrites the whole database zip file to a new one + // TODO: find a better to solution for appending to a db file (change format?) + public void addTable(String name, List<String> attributes, File data) throws DatabaseException { + try { + if (schema.addTable(name, attributes) == false) { + throw new DatabaseException(String.format("ERROR: Table %s already exists", name)); + } + if (dbFile == null) { + // TODO + } + File tmpFile = File.createTempFile(dbFile.getName(), ".copy"); + ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(tmpFile)); + if (dbFile.length() > 0) { + ZipFile dbZip = new ZipFile(dbFile); + Enumeration<? extends ZipEntry> entries = dbZip.entries(); + while (entries.hasMoreElements()) { + ZipEntry e = entries.nextElement(); + System.out.println("copy: " + e.getName()); + zipOut.putNextEntry(e); + zipOut.closeEntry(); + } + dbZip.close(); + } + FileInputStream dataInput = new FileInputStream(data); + String dataFile = schema.getTableDatafile(name); + System.out.println(">>>>>>>>>" + dataFile); + zipOut.putNextEntry(new ZipEntry(dataFile)); + zipOut.write(dataInput.readAllBytes()); + dataInput.close(); + zipOut.closeEntry(); + zipOut.close(); + // move temporary file to original file + FileInputStream src = new FileInputStream(tmpFile); + FileOutputStream dst = new FileOutputStream(dbFile); + dst.write(src.readAllBytes()); + src.close(); + dst.close(); + //tmpFile.delete(); + } catch (Exception e) { + throw new DatabaseException(e); + } + } + public boolean save() throws IOException { return save(dbFile, true); } @@ -73,7 +117,7 @@ public class Database { zipOut.closeEntry(); // write data files to database archive for (String tbl : schema.getTableNames()) { - File data = schema.getTableDatafile(tbl); + String data = schema.getTableDatafile(tbl); FileInputStream dataInput = new FileInputStream(data); zipOut.putNextEntry(new ZipEntry(tbl + ".csv")); zipOut.write(dataInput.readAllBytes()); @@ -97,11 +141,12 @@ public class Database { } public Table fetchTable(String name) throws DatabaseException { - try { + try (ZipFile db = new ZipFile(dbFile)) { List<String[]> records = new ArrayList<>(); - File datafile = schema.getTableDatafile(name); - Reader in = new FileReader(datafile); - CSVParser csv = CSVFormat.RFC4180.parse(in); + String dataFile = schema.getTableDatafile(name); + System.out.println(dataFile); + Reader reader = new InputStreamReader(db.getInputStream(db.getEntry(dataFile))); + CSVParser csv = CSVFormat.RFC4180.parse(reader); List<String> attributes = schema.getTableAttributes(name); for (CSVRecord r : csv.getRecords()) { diff --git a/src/main/java/uk/ac/ed/pguaglia/real/db/Schema.java b/src/main/java/uk/ac/ed/pguaglia/real/db/Schema.java index 29b2a12bfdacc4b6d9a54f0e940311beadb9c3fa..ced558793ca04a36e022ff0e0b315001b4c4a5d5 100644 --- a/src/main/java/uk/ac/ed/pguaglia/real/db/Schema.java +++ b/src/main/java/uk/ac/ed/pguaglia/real/db/Schema.java @@ -1,6 +1,5 @@ package uk.ac.ed.pguaglia.real.db; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; @@ -21,7 +20,7 @@ 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,String> datafiles; private Map<String,Expression> views; private Map<String,Set<String>> isUsedBy; @@ -36,7 +35,7 @@ public class Schema { return SchemaMapper.getInstance().readValue(src, Schema.class); } - protected Schema(Map<String, List<String>> tables, Map<String, File> datafiles, Map<String, Expression> views) + protected Schema(Map<String, List<String>> tables, Map<String, String> datafiles, Map<String, Expression> views) throws IllegalArgumentException { Set<String> tableNames = tables.keySet(); Set<String> viewNames = views.keySet(); @@ -63,7 +62,7 @@ public class Schema { } } - public File getTableDatafile(String name) throws IOException { + public String getTableDatafile(String name) throws IOException { if (datafiles.containsKey(name) == false) { String msg = String.format("ERROR: \"%s\" (No such table)", name); throw new IOException(msg); @@ -87,16 +86,13 @@ public class Schema { return views.get(name); } - public void addTable(String name, List<String> attributes, File data) throws Exception { + protected boolean addTable(String name, List<String> attributes) { if (tables.containsKey(name)) { - throw new Exception(String.format("ERROR: Table %s already exists", name)); + return false; } tables.put(name, attributes); - datafiles.put(name, data.getAbsoluteFile()); - } - - public List<String> addTable(String name, List<String> attributes) { - return tables.put(name, attributes); + datafiles.put(name, name + ".csv"); + return true; } public Expression addView(String name, Expression def) throws SchemaException { diff --git a/src/main/java/uk/ac/ed/pguaglia/real/db/SchemaMapper.java b/src/main/java/uk/ac/ed/pguaglia/real/db/SchemaMapper.java index 351ad9a9d1a3e9c329a73ff6168abcb8ada15ee9..6371344f1c5ed936070962c008ba1f41568606d6 100644 --- a/src/main/java/uk/ac/ed/pguaglia/real/db/SchemaMapper.java +++ b/src/main/java/uk/ac/ed/pguaglia/real/db/SchemaMapper.java @@ -1,6 +1,5 @@ package uk.ac.ed.pguaglia.real.db; -import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -61,13 +60,13 @@ public final class SchemaMapper extends ObjectMapper { gen.writeObjectField(TABLE_DATAFILE, sch.getTableDatafile(tableName)); gen.writeEndObject(); // end table } - gen.writeEndObject(); //end tables + gen.writeEndObject(); // end tables gen.writeObjectFieldStart(VIEWS); // start views for (String viewName : sch.getViewNames()) { gen.writeObjectField(viewName, sch.getViewDefinition(viewName).toString()); } gen.writeEndObject(); // end views - gen.writeEndObject(); //end schema + gen.writeEndObject(); // end schema } } @@ -88,7 +87,7 @@ public final class SchemaMapper extends ObjectMapper { JsonNode tables = node.get(TABLES); Iterator<String> tableNames = tables.fieldNames(); Map<String,List<String>> tableMap = new HashMap<>(); - Map<String,File> dataMap = new HashMap<>(); + Map<String,String> dataMap = new HashMap<>(); while (tableNames.hasNext()) { String name = tableNames.next(); JsonNode tbl = tables.get(name); @@ -98,7 +97,7 @@ public final class SchemaMapper extends ObjectMapper { attributes.add(attrNames.next()); } tableMap.put(name, attributes); - dataMap.put(name, new File(tbl.get(TABLE_DATAFILE).textValue())); + dataMap.put(name, tbl.get(TABLE_DATAFILE).textValue()); } JsonNode views = node.get(VIEWS); diff --git a/src/main/java/uk/ac/ed/pguaglia/real/runtime/CommandLineApp.java b/src/main/java/uk/ac/ed/pguaglia/real/runtime/CommandLineApp.java index a7882dd16e0e61c79bef7baf7607af1db2bb38e0..20c74d38be965489aeec20bf63603976ea69822d 100644 --- a/src/main/java/uk/ac/ed/pguaglia/real/runtime/CommandLineApp.java +++ b/src/main/java/uk/ac/ed/pguaglia/real/runtime/CommandLineApp.java @@ -218,7 +218,7 @@ public final class CommandLineApp { save(db, line, false); continue mainLoop; case ADD: - addTable(line, db.schema()); + addTable(line, db); continue mainLoop; } continue mainLoop; @@ -307,7 +307,7 @@ public final class CommandLineApp { return false; } - private static void addTable(String line, Schema sch) { + private static void addTable(String line, Database db) { String[] lines = line.split(":"); String filename = lines[1].strip(); String spec = lines[0]; @@ -319,8 +319,9 @@ public final class CommandLineApp { attributes.add(attr.strip()); } try { - sch.addTable(tableName, attributes, new File(filename)); + db.addTable(tableName, attributes, new File(filename)); } catch (Exception e) { + e.printStackTrace(); System.err.println("ERROR: " + e.getMessage()); } }