Mercurial > hg > monetdb-java
changeset 62:b66003555560 embedded
Split parsers and cleaned the MCL layer.
line wrap: on
line diff
--- a/example/SQLcopyinto.java +++ b/example/SQLcopyinto.java @@ -10,8 +10,8 @@ import java.sql.*; import java.io.*; import java.util.*; -import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader; -import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter; +import nl.cwi.monetdb.mcl.io.AbstractMCLReader; +import nl.cwi.monetdb.mcl.io.AbstractMCLWriter; import nl.cwi.monetdb.mcl.net.*; /** @@ -61,8 +61,8 @@ public class SQLcopyinto { } } - AbstractBufferedReader in = server.getReader(); - AbstractBufferedWriter out = server.getWriter(); + AbstractMCLReader in = server.getReader(); + AbstractMCLWriter out = server.getWriter(); String error = in.waitForPrompt(); if (error != null)
--- a/src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedDatabase.java +++ b/src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedDatabase.java @@ -8,7 +8,7 @@ package nl.cwi.monetdb.embedded.env; -import nl.cwi.monetdb.mcl.embedded.EmbeddedConnection; +import nl.cwi.monetdb.mcl.net.EmbeddedMonetDB; import java.util.concurrent.ConcurrentHashMap; @@ -172,7 +172,7 @@ public class MonetDBEmbeddedDatabase { return CompletableFuture.supplyAsync(() -> this.createConnectionInternal()); }*/ - public static void AddJDBCEmbeddedConnection(EmbeddedConnection con) throws MonetDBEmbeddedException { + public static void AddJDBCEmbeddedConnection(EmbeddedMonetDB con) throws MonetDBEmbeddedException { if(MonetDBEmbeddedDatabase == null) { throw new MonetDBEmbeddedException("The database is not running!"); } else { @@ -208,5 +208,5 @@ public class MonetDBEmbeddedDatabase { /** * Internal implementation to create a JDBC embeddded connection on this database. */ - private native void createJDBCConnectionInternal(EmbeddedConnection emc) throws MonetDBEmbeddedException; + private native void createJDBCConnectionInternal(EmbeddedMonetDB emc) throws MonetDBEmbeddedException; }
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java @@ -44,14 +44,14 @@ import java.util.concurrent.locks.Reentr import nl.cwi.monetdb.jdbc.types.INET; import nl.cwi.monetdb.jdbc.types.URL; import nl.cwi.monetdb.mcl.MCLException; -import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader; -import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter; -import nl.cwi.monetdb.mcl.embedded.EmbeddedConnection; +import nl.cwi.monetdb.mcl.io.AbstractMCLReader; +import nl.cwi.monetdb.mcl.io.AbstractMCLWriter; +import nl.cwi.monetdb.mcl.net.EmbeddedMonetDB; import nl.cwi.monetdb.mcl.net.MapiSocket; -import nl.cwi.monetdb.mcl.connection.AbstractMonetDBConnection; +import nl.cwi.monetdb.mcl.net.AbstractMCLConnection; import nl.cwi.monetdb.mcl.parser.HeaderLineParser; +import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser; import nl.cwi.monetdb.mcl.parser.MCLParseException; -import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser; /** * A {@link Connection} suitable for the MonetDB database. @@ -81,14 +81,13 @@ import nl.cwi.monetdb.mcl.parser.StartOf public class MonetConnection extends MonetWrapper implements Connection { /** A connection to mserver5 either through MAPI with TCP or embedded */ - private final AbstractMonetDBConnection server; + private final AbstractMCLConnection server; /** The Reader from the server */ - private final AbstractBufferedReader in; + private final AbstractMCLReader in; /** The Writer to the server */ - private final AbstractBufferedWriter out; - - /** A StartOfHeaderParser declared for reuse. */ - private StartOfHeaderParser sohp = new StartOfHeaderParser(); + private final AbstractMCLWriter out; + /** A StartOfHeaderParser declared for reuse. */ + private final StartOfHeaderParser sohp; /** Whether this Connection is closed (and cannot be used anymore) */ private boolean closed; @@ -150,7 +149,7 @@ public class MonetConnection extends Mon if (directory == null || directory.trim().isEmpty()) throw new IllegalArgumentException("directory should not be null or empty"); - server = new EmbeddedConnection("localhost", -1, database, username, debug, "sql", null, directory); + server = new EmbeddedMonetDB("localhost", -1, database, username, debug, "sql", null, directory); } else { String hostname = props.getProperty("host"); String hash = props.getProperty("hash"); @@ -220,9 +219,11 @@ public class MonetConnection extends Mon in = server.getReader(); out = server.getWriter(); - String error = in.waitForPrompt(); //TODO CHECK THIS + String error = in.waitForPrompt(); if (error != null) throw new SQLException(error.substring(6), "08001"); + + sohp = server.getStartOfHeaderParser(); } catch (IOException e) { throw new SQLException("Unable to connect (" + server.getHostname() + ":" + server.getPort() + "): " + e.getMessage(), "08006"); } catch (MCLParseException e) { @@ -238,7 +239,7 @@ public class MonetConnection extends Mon // the following initialisers are only valid when the language // is SQL... - if (server.getLang() == AbstractMonetDBConnection.LANG_SQL) { + if (server.getLang() == AbstractMCLConnection.LANG_SQL) { // enable auto commit setAutoCommit(true); // set our time zone on the server @@ -253,7 +254,7 @@ public class MonetConnection extends Mon } } - protected AbstractMonetDBConnection getServer() { + protected AbstractMCLConnection getServer() { return server; } @@ -626,7 +627,7 @@ public class MonetConnection extends Mon */ @Override public DatabaseMetaData getMetaData() throws SQLException { - if (server.getLang() != AbstractMonetDBConnection.LANG_SQL) + if (server.getLang() != AbstractMCLConnection.LANG_SQL) throw new SQLException("This method is only supported in SQL mode", "M0M04"); return new MonetDatabaseMetaData(this); @@ -1634,7 +1635,7 @@ public class MonetConnection extends Mon this.resultBlocks = new DataBlockResponse[(tuplecount / cacheSize) + 1]; - hlp = new HeaderLineParser(columncount); + hlp = server.getHeaderLineParser(columncount); resultBlocks[0] = new DataBlockResponse( rowcount, @@ -1658,7 +1659,7 @@ public class MonetConnection extends Mon return resultBlocks[0].addLine(tmpLine, linetype); } - if (linetype != AbstractBufferedReader.HEADER) + if (linetype != AbstractMCLReader.HEADER) return "header expected, got: " + tmpLine; // depending on the name of the header, we continue @@ -1992,7 +1993,7 @@ public class MonetConnection extends Mon */ @Override public String addLine(String line, int linetype) { - if (linetype != AbstractBufferedReader.RESULT) + if (linetype != AbstractMCLReader.RESULT) return "protocol violation: unexpected line in data block: " + line; // add to the backing array data[++pos] = line; @@ -2321,7 +2322,7 @@ public class MonetConnection extends Mon int size = cachesize == 0 ? DEF_FETCHSIZE : cachesize; size = maxrows != 0 ? Math.min(maxrows, size) : size; // don't do work if it's not needed - if (server.getLang() == AbstractMonetDBConnection.LANG_SQL && size != curReplySize && templ != server.getCommandHeaderTemplates()) { + if (server.getLang() == AbstractMCLConnection.LANG_SQL && size != curReplySize && templ != server.getCommandHeaderTemplates()) { sendControlCommand("reply_size " + size); // store the reply size after a successful change @@ -2354,11 +2355,11 @@ public class MonetConnection extends Mon String tmpLine = in.readLine(); int linetype = in.getLineType(); Response res = null; - while (linetype != AbstractBufferedReader.PROMPT) { + while (linetype != AbstractMCLReader.PROMPT) { // each response should start with a start of header // (or error) switch (linetype) { - case AbstractBufferedReader.SOHEADER: + case AbstractMCLReader.SOHEADER: // make the response object, and fill it try { switch (sohp.parse(tmpLine)) { @@ -2487,7 +2488,7 @@ public class MonetConnection extends Mon tmpLine = in.readLine(); linetype = in.getLineType(); break; - case AbstractBufferedReader.INFO: + case AbstractMCLReader.INFO: addWarning(tmpLine.substring(1), "01000"); // read the next line (can be prompt, new @@ -2502,7 +2503,7 @@ public class MonetConnection extends Mon // message tmpLine = "!M0M10!protocol violation, unexpected line: " + tmpLine; // don't break; fall through... - case AbstractBufferedReader.ERROR: + case AbstractMCLReader.ERROR: // read everything till the prompt (should be // error) we don't know if we ignore some // garbage here... but the log should reveal @@ -2579,7 +2580,7 @@ public class MonetConnection extends Mon private String[] templ; private String query; - private AbstractBufferedWriter out; + private AbstractMCLWriter out; private String error; private int state = WAIT; @@ -2593,7 +2594,7 @@ public class MonetConnection extends Mon * * @param out the socket to write to */ - public SendThread(AbstractBufferedWriter out) { + public SendThread(AbstractMCLWriter out) { super("SendThread"); setDaemon(true); this.out = out;
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java @@ -10,6 +10,7 @@ package nl.cwi.monetdb.jdbc; import nl.cwi.monetdb.mcl.parser.MCLParseException; import nl.cwi.monetdb.mcl.parser.TupleLineParser; + import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.Reader; @@ -134,7 +135,7 @@ public class MonetResultSet extends Mone tupleCount = header.tuplecount; // create result array - tlp = new TupleLineParser(columns.length); + tlp = ((MonetConnection)statement.getConnection()).getServer().getTupleLineParser(columns.length); JdbcSQLTypes = new int[types.length]; populateJdbcSQLtypesArray(); @@ -178,7 +179,11 @@ public class MonetResultSet extends Mone this.types = types; this.tupleCount = results; - this.tlp = new TupleLineParser(columns.length); + try { + this.tlp = ((MonetConnection)statement.getConnection()).getServer().getTupleLineParser(columns.length); + } catch (SQLException e) { + throw new IllegalArgumentException(e); + } JdbcSQLTypes = new int[types.length]; populateJdbcSQLtypesArray();
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java @@ -8,7 +8,7 @@ package nl.cwi.monetdb.jdbc; -import nl.cwi.monetdb.mcl.connection.AbstractMonetDBConnection; +import nl.cwi.monetdb.mcl.net.AbstractMCLConnection; import java.sql.BatchUpdateException; import java.sql.Connection; import java.sql.Statement; @@ -202,7 +202,7 @@ public class MonetStatement extends Mone boolean first = true; boolean error = false; - AbstractMonetDBConnection server = connection.getServer(); + AbstractMCLConnection server = connection.getServer(); BatchUpdateException e = new BatchUpdateException("Error(s) occurred while executing the batch, see next SQLExceptions for details", "22000", counts); StringBuilder tmpBatch = new StringBuilder(server.getBlockSize());
rename from src/main/java/nl/cwi/monetdb/mcl/connection/AbstractBufferedReader.java rename to src/main/java/nl/cwi/monetdb/mcl/io/AbstractMCLReader.java --- a/src/main/java/nl/cwi/monetdb/mcl/connection/AbstractBufferedReader.java +++ b/src/main/java/nl/cwi/monetdb/mcl/io/AbstractMCLReader.java @@ -1,4 +1,4 @@ -package nl.cwi.monetdb.mcl.connection; +package nl.cwi.monetdb.mcl.io; import java.io.BufferedReader; import java.io.IOException; @@ -7,7 +7,7 @@ import java.io.Reader; /** * Created by ferreira on 11/24/16. */ -public abstract class AbstractBufferedReader extends BufferedReader { +public abstract class AbstractMCLReader extends BufferedReader { /** The type of the last line read */ protected int lineType; @@ -32,7 +32,7 @@ public abstract class AbstractBufferedRe /** a line starting with # indicates INFO */ public final static int INFO = '#'; - public AbstractBufferedReader(Reader in) { + public AbstractMCLReader(Reader in) { super(in); }
rename from src/main/java/nl/cwi/monetdb/mcl/connection/AbstractBufferedWriter.java rename to src/main/java/nl/cwi/monetdb/mcl/io/AbstractMCLWriter.java --- a/src/main/java/nl/cwi/monetdb/mcl/connection/AbstractBufferedWriter.java +++ b/src/main/java/nl/cwi/monetdb/mcl/io/AbstractMCLWriter.java @@ -1,4 +1,4 @@ -package nl.cwi.monetdb.mcl.connection; +package nl.cwi.monetdb.mcl.io; import java.io.BufferedWriter; import java.io.IOException; @@ -7,11 +7,11 @@ import java.io.Writer; /** * Created by ferreira on 11/24/16. */ -public abstract class AbstractBufferedWriter extends BufferedWriter { +public abstract class AbstractMCLWriter extends BufferedWriter { - protected AbstractBufferedReader reader; + protected AbstractMCLReader reader; - public AbstractBufferedWriter(Writer out) { + public AbstractMCLWriter(Writer out) { super(out); } @@ -20,9 +20,9 @@ public abstract class AbstractBufferedWr * receives a linetype reset when a line is written from this * writer. * - * @param r an AbstractBufferedReader + * @param r an AbstractMCLReader */ - public void registerReader(AbstractBufferedReader r) { + public void registerReader(AbstractMCLReader r) { this.reader = r; }
rename from src/main/java/nl/cwi/monetdb/mcl/net/BufferedMCLReader.java rename to src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLReader.java --- a/src/main/java/nl/cwi/monetdb/mcl/net/BufferedMCLReader.java +++ b/src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLReader.java @@ -6,9 +6,7 @@ * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V. */ -package nl.cwi.monetdb.mcl.net; - -import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader; +package nl.cwi.monetdb.mcl.io; import java.io.IOException; import java.io.InputStream; @@ -42,7 +40,7 @@ import java.io.UnsupportedEncodingExcept * @see nl.cwi.monetdb.mcl.net.MapiSocket * @see BufferedMCLWriter */ -public class BufferedMCLReader extends AbstractBufferedReader { +public class BufferedMCLReader extends AbstractMCLReader { /** * Create a buffering character-input stream that uses a
rename from src/main/java/nl/cwi/monetdb/mcl/net/BufferedMCLWriter.java rename to src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLWriter.java --- a/src/main/java/nl/cwi/monetdb/mcl/net/BufferedMCLWriter.java +++ b/src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLWriter.java @@ -6,9 +6,7 @@ * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V. */ -package nl.cwi.monetdb.mcl.net; - -import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter; +package nl.cwi.monetdb.mcl.io; import java.io.*; @@ -33,7 +31,7 @@ import java.io.*; * @see nl.cwi.monetdb.mcl.net.MapiSocket * @see BufferedMCLWriter */ -public class BufferedMCLWriter extends AbstractBufferedWriter { +public class BufferedMCLWriter extends AbstractMCLWriter { /** * Create a buffered character-output stream that uses a @@ -69,6 +67,7 @@ public class BufferedMCLWriter extends A this.write('\n'); } + @Override public void writeLine(String line) throws IOException { this.write(line); this.flush();
rename from src/main/java/nl/cwi/monetdb/mcl/embedded/EmbeddedReader.java rename to src/main/java/nl/cwi/monetdb/mcl/io/EmbeddedMCLReader.java --- a/src/main/java/nl/cwi/monetdb/mcl/embedded/EmbeddedReader.java +++ b/src/main/java/nl/cwi/monetdb/mcl/io/EmbeddedMCLReader.java @@ -1,21 +1,19 @@ -package nl.cwi.monetdb.mcl.embedded; - -import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader; +package nl.cwi.monetdb.mcl.io; import java.io.*; /** * Created by ferreira on 11/24/16. */ -public class EmbeddedReader extends AbstractBufferedReader { +public class EmbeddedMCLReader extends AbstractMCLReader { - protected EmbeddedReader() { + public EmbeddedMCLReader() { super(null); } @Override public String readLine() throws IOException { - String res = this.readLineInternal(); + String res = this.readLineInternal(); //this readline will never wait!! setLineType(res); if (lineType == ERROR && !res.matches("^![0-9A-Z]{5}!.+")) res = "!22000!" + res.substring(1); @@ -25,18 +23,11 @@ public class EmbeddedReader extends Abst @Override public synchronized String waitForPrompt() throws IOException { try { - this.wait(); + this.wait(); //must mimic the socket readline with the wait/notify methods } catch (InterruptedException e) { throw new IOException(e); } - String res = this.readLine(); - if (res == null) { - throw new IOException("Connection to server lost!"); - } - if (lineType == ERROR) { - return "\n" + res.substring(1); - } - return res.trim(); + return null; } private native String readLineInternal();
rename from src/main/java/nl/cwi/monetdb/mcl/embedded/EmbeddedWriter.java rename to src/main/java/nl/cwi/monetdb/mcl/io/EmbeddedMCLWriter.java --- a/src/main/java/nl/cwi/monetdb/mcl/embedded/EmbeddedWriter.java +++ b/src/main/java/nl/cwi/monetdb/mcl/io/EmbeddedMCLWriter.java @@ -1,22 +1,21 @@ -package nl.cwi.monetdb.mcl.embedded; - -import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter; +package nl.cwi.monetdb.mcl.io; import java.io.*; /** * Created by ferreira on 11/24/16. */ -public class EmbeddedWriter extends AbstractBufferedWriter { +public class EmbeddedMCLWriter extends AbstractMCLWriter { - public EmbeddedWriter() { + public EmbeddedMCLWriter(EmbeddedMCLReader reader) { super(null); + this.reader = reader; } @Override public void writeLine(String line) throws IOException { this.writeInternal(line); - this.reader.notify(); + this.reader.notify(); //wake up the embedded reader. } private native void writeInternal(String str);
rename from src/main/java/nl/cwi/monetdb/mcl/connection/AbstractMonetDBConnection.java rename to src/main/java/nl/cwi/monetdb/mcl/net/AbstractMCLConnection.java --- a/src/main/java/nl/cwi/monetdb/mcl/connection/AbstractMonetDBConnection.java +++ b/src/main/java/nl/cwi/monetdb/mcl/net/AbstractMCLConnection.java @@ -1,7 +1,12 @@ -package nl.cwi.monetdb.mcl.connection; +package nl.cwi.monetdb.mcl.net; import nl.cwi.monetdb.mcl.MCLException; +import nl.cwi.monetdb.mcl.io.AbstractMCLReader; +import nl.cwi.monetdb.mcl.io.AbstractMCLWriter; +import nl.cwi.monetdb.mcl.parser.HeaderLineParser; import nl.cwi.monetdb.mcl.parser.MCLParseException; +import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser; +import nl.cwi.monetdb.mcl.parser.TupleLineParser; import java.io.*; import java.net.SocketException; @@ -10,7 +15,7 @@ import java.util.List; /** * Created by ferreira on 11/23/16. */ -public abstract class AbstractMonetDBConnection { +public abstract class AbstractMCLConnection { /** the SQL language */ public final static int LANG_SQL = 0; @@ -43,16 +48,16 @@ public abstract class AbstractMonetDBCon /** A template to apply to each command (like pre and post fixes) */ protected String[] commandTempl = new String[3]; // pre, post, sep - public AbstractMonetDBConnection(String hostname, int port, String database, String username, boolean debug, String language, String hash, String[] queryTempl, String[] commandTempl) { + public AbstractMCLConnection(String hostname, int port, String database, String username, boolean debug, String language, String hash, String[] queryTempl, String[] commandTempl) { this.hostname = hostname; this.port = port; this.database = database; this.username = username; this.debug = debug; this.hash = hash; - this.setLanguage(language); this.queryTempl = queryTempl; this.commandTempl = commandTempl; + this.setLanguage(language); } public String getHostname() { @@ -110,33 +115,7 @@ public abstract class AbstractMonetDBCon * * @param language the language */ - public void setLanguage(String language) { - this.language = language; - if ("sql".equals(language)) { - lang = LANG_SQL; - } else if ("mal".equals(language)) { - lang = LANG_MAL; - } else { - lang = LANG_UNKNOWN; - } - if (lang == LANG_SQL) { - queryTempl[0] = "s"; // pre - queryTempl[1] = "\n;"; // post - queryTempl[2] = "\n;\n"; // separator - - commandTempl[0] = "X"; // pre - commandTempl[1] = null; // post - commandTempl[2] = "\nX"; // separator - } else if (lang == LANG_MAL) { - queryTempl[0] = null; - queryTempl[1] = ";\n"; - queryTempl[2] = ";\n"; - - commandTempl[0] = null; // pre - commandTempl[1] = null; // post - commandTempl[2] = null; // separator - } - } + public abstract void setLanguage(String language); public int getLang() { return lang; @@ -214,7 +193,7 @@ public abstract class AbstractMonetDBCon * * @return a BufferedMCLReader connected to this MapiSocket */ - public abstract AbstractBufferedReader getReader(); + public abstract AbstractMCLReader getReader(); /** * Returns a Writer for this MapiSocket. The Writer is a @@ -223,7 +202,7 @@ public abstract class AbstractMonetDBCon * * @return a BufferedMCLWriter connected to this MapiSocket */ - public abstract AbstractBufferedWriter getWriter(); + public abstract AbstractMCLWriter getWriter(); /** * Enables logging to a file what is read and written from and to @@ -307,4 +286,10 @@ public abstract class AbstractMonetDBCon public abstract String getJDBCURL(); public abstract int getBlockSize(); + + public abstract StartOfHeaderParser getStartOfHeaderParser(); + + public abstract HeaderLineParser getHeaderLineParser(int capacity); + + public abstract TupleLineParser getTupleLineParser(int capacity); }
rename from src/main/java/nl/cwi/monetdb/mcl/embedded/EmbeddedConnection.java rename to src/main/java/nl/cwi/monetdb/mcl/net/EmbeddedMonetDB.java --- a/src/main/java/nl/cwi/monetdb/mcl/embedded/EmbeddedConnection.java +++ b/src/main/java/nl/cwi/monetdb/mcl/net/EmbeddedMonetDB.java @@ -1,13 +1,20 @@ -package nl.cwi.monetdb.mcl.embedded; +package nl.cwi.monetdb.mcl.net; import nl.cwi.monetdb.embedded.env.IEmbeddedConnection; import nl.cwi.monetdb.embedded.env.MonetDBEmbeddedDatabase; import nl.cwi.monetdb.embedded.env.MonetDBEmbeddedException; import nl.cwi.monetdb.mcl.MCLException; -import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader; -import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter; -import nl.cwi.monetdb.mcl.connection.AbstractMonetDBConnection; +import nl.cwi.monetdb.mcl.io.AbstractMCLReader; +import nl.cwi.monetdb.mcl.io.AbstractMCLWriter; +import nl.cwi.monetdb.mcl.io.EmbeddedMCLReader; +import nl.cwi.monetdb.mcl.io.EmbeddedMCLWriter; +import nl.cwi.monetdb.mcl.parser.HeaderLineParser; import nl.cwi.monetdb.mcl.parser.MCLParseException; +import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser; +import nl.cwi.monetdb.mcl.parser.TupleLineParser; +import nl.cwi.monetdb.mcl.parser.embedded.EmbeddedHeaderLineParser; +import nl.cwi.monetdb.mcl.parser.embedded.EmbeddedStartOfHeaderParser; +import nl.cwi.monetdb.mcl.parser.embedded.EmbeddedTupleLineParser; import java.io.*; import java.net.SocketException; @@ -16,7 +23,7 @@ import java.util.List; /** * Created by ferreira on 11/23/16. */ -public class EmbeddedConnection extends AbstractMonetDBConnection implements IEmbeddedConnection { +public class EmbeddedMonetDB extends AbstractMCLConnection implements IEmbeddedConnection { private long connectionPointer; @@ -24,12 +31,12 @@ public class EmbeddedConnection extends private final String directory; - private EmbeddedReader reader; + private EmbeddedMCLReader reader; - private EmbeddedWriter writer; + private EmbeddedMCLWriter writer; - public EmbeddedConnection(String hostname, int port, String database, String username, boolean debug, String language, String hash, String directory) { - super(hostname, port, database, username, debug, language, hash, new String[]{"s", "\n;", "\n;\n"}, new String[]{"X", null, "\nX"}); + public EmbeddedMonetDB(String hostname, int port, String database, String username, boolean debug, String language, String hash, String directory) { + super(hostname, port, database, username, debug, language, hash, new String[]{"", "\n;", "\n;\n"}, new String[]{"X", null, "\nX"}); this.directory = directory; } @@ -57,7 +64,6 @@ public class EmbeddedConnection extends if(this.lang != LANG_SQL) { throw new IllegalArgumentException("The embedded connection only supports the SQL language!"); } - super.setLanguage(language); } @Override @@ -83,8 +89,8 @@ public class EmbeddedConnection extends } else { MonetDBEmbeddedDatabase.StartDatabase(this.directory, true, false); } - this.reader = new EmbeddedReader(); - this.writer = new EmbeddedWriter(); + this.reader = new EmbeddedMCLReader(); + this.writer = new EmbeddedMCLWriter(this.reader); MonetDBEmbeddedDatabase.AddJDBCEmbeddedConnection(this); } catch (MonetDBEmbeddedException ex) { throw new MCLException(ex); @@ -103,12 +109,12 @@ public class EmbeddedConnection extends } @Override - public AbstractBufferedReader getReader() { + public AbstractMCLReader getReader() { return this.reader; } @Override - public AbstractBufferedWriter getWriter() { + public AbstractMCLWriter getWriter() { return this.writer; } @@ -133,6 +139,21 @@ public class EmbeddedConnection extends } @Override + public StartOfHeaderParser getStartOfHeaderParser() { + return new EmbeddedStartOfHeaderParser(); + } + + @Override + public HeaderLineParser getHeaderLineParser(int capacity) { + return new EmbeddedHeaderLineParser(capacity); + } + + @Override + public TupleLineParser getTupleLineParser(int capacity) { + return new EmbeddedTupleLineParser(capacity); + } + + @Override public long getConnectionPointer() { return connectionPointer; }
--- a/src/main/java/nl/cwi/monetdb/mcl/net/MapiSocket.java +++ b/src/main/java/nl/cwi/monetdb/mcl/net/MapiSocket.java @@ -29,10 +29,17 @@ import java.util.List; import java.util.Set; import nl.cwi.monetdb.mcl.MCLException; -import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader; -import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter; -import nl.cwi.monetdb.mcl.connection.AbstractMonetDBConnection; +import nl.cwi.monetdb.mcl.io.AbstractMCLReader; +import nl.cwi.monetdb.mcl.io.AbstractMCLWriter; +import nl.cwi.monetdb.mcl.io.BufferedMCLReader; +import nl.cwi.monetdb.mcl.io.BufferedMCLWriter; +import nl.cwi.monetdb.mcl.parser.HeaderLineParser; import nl.cwi.monetdb.mcl.parser.MCLParseException; +import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser; +import nl.cwi.monetdb.mcl.parser.TupleLineParser; +import nl.cwi.monetdb.mcl.parser.socket.SocketHeaderLineParser; +import nl.cwi.monetdb.mcl.parser.socket.SocketStartOfHeaderParser; +import nl.cwi.monetdb.mcl.parser.socket.SocketTupleLineParser; /** * A Socket for communicating with the MonetDB database in MAPI block @@ -84,7 +91,7 @@ import nl.cwi.monetdb.mcl.parser.MCLPars * @see BufferedMCLReader * @see BufferedMCLWriter */ -public final class MapiSocket extends AbstractMonetDBConnection { +public final class MapiSocket extends AbstractMCLConnection { /** The blocksize (hardcoded in compliance with stream.mx) */ private static final int BLOCK = 8 * 1024 - 2; @@ -130,7 +137,7 @@ public final class MapiSocket extends Ab private byte[] blklen = new byte[2]; public MapiSocket(String hostname, int port, String database, String username, boolean debug, String language, String hash) { - super(hostname, port, database, username, debug, language, hash, new String[]{"s", "\n;", "\n;\n"}, new String[]{"s", "\n;", "\n;\n"}); + super(hostname, port, database, username, debug, language, hash, new String[]{"", "\n;", "\n;\n"}, new String[]{"", "\n;", "\n;\n"}); } @Override @@ -165,6 +172,39 @@ public final class MapiSocket extends Ab } /** + * Sets the language to use for this connection. + * + * @param language the language + */ + public void setLanguage(String language) { + this.language = language; + if ("sql".equals(language)) { + lang = LANG_SQL; + } else if ("mal".equals(language)) { + lang = LANG_MAL; + } else { + lang = LANG_UNKNOWN; + } + if (lang == LANG_SQL) { + queryTempl[0] = "s"; // pre + queryTempl[1] = "\n;"; // post + queryTempl[2] = "\n;\n"; // separator + + commandTempl[0] = "X"; // pre + commandTempl[1] = null; // post + commandTempl[2] = "\nX"; // separator + } else if (lang == LANG_MAL) { + queryTempl[0] = null; + queryTempl[1] = ";\n"; + queryTempl[2] = ";\n"; + + commandTempl[0] = null; // pre + commandTempl[1] = null; // post + commandTempl[2] = null; // separator + } + } + + /** * Sets whether MCL redirections should be followed or not. If set * to false, an MCLException will be thrown when a redirect is * encountered during connect. The default bahaviour is to @@ -527,12 +567,12 @@ public final class MapiSocket extends Ab } @Override - public AbstractBufferedReader getReader() { + public AbstractMCLReader getReader() { return reader; } @Override - public AbstractBufferedWriter getWriter() { + public AbstractMCLWriter getWriter() { return writer; } @@ -966,7 +1006,7 @@ public final class MapiSocket extends Ab @Override public String getJDBCURL() { String language = ""; - if (this.getLang() == AbstractMonetDBConnection.LANG_MAL) + if (this.getLang() == AbstractMCLConnection.LANG_MAL) language = "?language=mal"; return "jdbc:monetdb://" + this.getHostname() + ":" + this.getPort() + "/" + this.getDatabase() + language; } @@ -975,4 +1015,19 @@ public final class MapiSocket extends Ab public int getBlockSize() { return BLOCK; } + + @Override + public StartOfHeaderParser getStartOfHeaderParser() { + return new SocketStartOfHeaderParser(); + } + + @Override + public HeaderLineParser getHeaderLineParser(int capacity) { + return new SocketHeaderLineParser(capacity); + } + + @Override + public TupleLineParser getTupleLineParser(int capacity) { + return new SocketTupleLineParser(capacity); + } }
--- a/src/main/java/nl/cwi/monetdb/mcl/parser/HeaderLineParser.java +++ b/src/main/java/nl/cwi/monetdb/mcl/parser/HeaderLineParser.java @@ -1,181 +1,25 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V. - */ - package nl.cwi.monetdb.mcl.parser; - /** - * The HeaderLineParser is a generic MCLParser that extracts values from - * a metadata header in the MCL protocol either as string or integer - * values. - * - * @author Fabian Groffen <Fabian.Groffen> + * Created by ferreira on 11/25/16. */ -public class HeaderLineParser extends MCLParser { - private int type; - - public final static int NAME = 1; - public final static int LENGTH = 2; - public final static int TABLE = 3; - public final static int TYPE = 4; - - /** - * Constructs a HeaderLineParser which expects columncount columns. - * - * @param columncount the number of columns in the to be parsed string - */ - public HeaderLineParser(int columncount) { - super(columncount); - } +public abstract class HeaderLineParser extends MCLParser { - /** - * Parses the given String source as header line. If source cannot - * be parsed, an MCLParseException is thrown. The columncount argument - * given during construction is used for allocation of the backing - * array. Parsing a header line with has more fields will therefore - * result in a crash. While this seems illogical, the caller should - * know this size, since the StartOfHeader contains this - * information. - * - * @param source a String which should be parsed - * @return the type of then parsed header line - * @throws MCLParseException if an error occurs during parsing - */ - @Override - public int parse(String source) throws MCLParseException { - char[] chrLine = source.toCharArray(); - int len = chrLine.length; - int pos = 0; - boolean foundChar = false; - boolean nameFound = false; - // find header name - for (int i = len - 1; i >= 0; i--) { - switch (chrLine[i]) { - case ' ': - case '\n': - case '\t': - case '\r': - if (!foundChar) { - len = i - 1; - } else { - pos = i + 1; - } - break; - case '#': - // found! - nameFound = true; - if (pos == 0) pos = i + 1; - i = 0; // force the loop to terminate - break; - default: - foundChar = true; - pos = 0; - break; - } - } - if (!nameFound) - throw new MCLParseException("invalid header, no header name found", pos); + public final static int NAME = 1; + public final static int LENGTH = 2; + public final static int TABLE = 3; + public final static int TYPE = 4; + + protected int type; - // depending on the name of the header, we continue - switch (chrLine[pos]) { - case 'n': - if (len - pos == 4 && - source.regionMatches(pos + 1, "name", 1, 3)) - { - getValues(chrLine, 2, pos - 3); - type = NAME; - } - break; - case 'l': - if (len - pos == 6 && - source.regionMatches(pos + 1, "length", 1, 5)) - { - getIntValues(chrLine, 2, pos - 3); - type = LENGTH; - } - break; - case 't': - if (len - pos == 4 && - source.regionMatches(pos + 1, "type", 1, 3)) - { - getValues(chrLine, 2, pos - 3); - type = TYPE; - } else if (len - pos == 10 && - source.regionMatches(pos + 1, "table_name", 1, 9)) - { - getValues(chrLine, 2, pos - 3); - type = TABLE; - } - break; - default: - throw new MCLParseException("unknown header: " + - (new String(chrLine, pos, len - pos))); - } - - // adjust colno - reset(); - - return type; - } - - /** - * Returns an array of Strings containing the values between - * ',\t' separators. Note that no quoting/dequoting is done in this - * method. - * - * @param chrLine a character array holding the input data - * @param start where the relevant data starts - * @param stop where the relevant data stops - */ - final private void getValues(char[] chrLine, int start, int stop) { - int elem = 0; - - for (int i = start + 1; i < stop; i++) { - if (chrLine[i] == '\t' && chrLine[i - 1] == ',') { - values[elem++] = - new String(chrLine, start, i - 1 - start); - start = i + 1; - } - } - // add the left over part - values[elem + 1] = new String(chrLine, start, stop - start); - } - - /** - * Returns an array of ints containing the values between - * ',\t' separators. - * - * @param chrLine a character array holding the input data - * @param start where the relevant data starts - * @param stop where the relevant data stops - */ - final private void getIntValues(char[] chrLine, int start, int stop) - throws MCLParseException - { - int elem = 0; - int tmp = 0; - - for (int i = start; i < stop; i++) { - if (chrLine[i] == ',' && chrLine[i + 1] == '\t') { - intValues[elem++] = tmp; - tmp = 0; - } else { - tmp *= 10; - // note: don't use Character.isDigit() here, because - // we only want ISO-LATIN-1 digits - if (chrLine[i] >= '0' && chrLine[i] <= '9') { - tmp += (int)chrLine[i] - (int)'0'; - } else { - throw new MCLParseException("expected a digit in " + new String(chrLine) + " at " + i); - } - } - } - // add the left over part - intValues[elem + 1] = tmp; - } + /** + * Creates an MCLParser targeted at a given number of field values. + * The lines parsed by an instance of this MCLParser should have + * exactly capacity field values. + * + * @param capacity the number of field values to expect + */ + protected HeaderLineParser(int capacity) { + super(capacity); + } }
--- a/src/main/java/nl/cwi/monetdb/mcl/parser/MCLParser.java +++ b/src/main/java/nl/cwi/monetdb/mcl/parser/MCLParser.java @@ -8,7 +8,6 @@ package nl.cwi.monetdb.mcl.parser; - /** * Interface for parsers in MCL. The parser family in MCL is set up as * a reusable object. This allows the same parser to be used again for @@ -54,13 +53,13 @@ public abstract class MCLParser { * @see #nextInt() * @see #hasNext() */ - abstract public int parse(String source) throws MCLParseException; + public abstract int parse(String source) throws MCLParseException; /** * Repositions the internal field offset to the start, such that the * next call to next() will return the first field again. */ - final public void reset() { + public final void reset() { colnr = 0; } @@ -72,7 +71,7 @@ public abstract class MCLParser { * @see #next() * @see #nextInt() */ - final public boolean hasNext() { + public final boolean hasNext() { return colnr < values.length; } @@ -86,7 +85,7 @@ public abstract class MCLParser { * @see #nextInt() * @see #hasNext() */ - final public String next() { + public final String next() { return values[colnr++]; } @@ -99,7 +98,7 @@ public abstract class MCLParser { * @return the current field value as integer * @see #next() */ - final public int nextInt() { + public final int nextInt() { return intValues[colnr++]; } }
--- a/src/main/java/nl/cwi/monetdb/mcl/parser/StartOfHeaderParser.java +++ b/src/main/java/nl/cwi/monetdb/mcl/parser/StartOfHeaderParser.java @@ -1,138 +1,45 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V. - */ - package nl.cwi.monetdb.mcl.parser; -import java.nio.CharBuffer; - /** - * The StartOfHeaderParser allows easy examination of a start of header - * line. It does not fit into the general MCLParser framework because - * it uses a different interface. While the parser is very shallow, it - * requires the caller to know about the header lines that are parsed. - * All this parser does is detect the (valid) type of a soheader, and - * allow to return the fields in it as integer or string. An extra - * bonus is that it can return if another field should be present in the - * soheader. - * - * @author Fabian Groffen <Fabian.Groffen> + * Created by ferreira on 11/25/16. */ -public class StartOfHeaderParser { - private CharBuffer soh = null; - private int len; - private int pos; - - /* Query types (copied from sql_query.mx) */ +public abstract class StartOfHeaderParser { - /** A parse response (not handled) */ - public final static int Q_PARSE = '0'; - /** A tabular response (typical ResultSet) */ - public final static int Q_TABLE = '1'; - /** A response to an update statement, contains number of affected - * rows and generated key-id */ - public final static int Q_UPDATE = '2'; - /** A response to a schema update */ - public final static int Q_SCHEMA = '3'; - /** A response to a transation statement (start, rollback, abort, - * commit) */ - public final static int Q_TRANS = '4'; - /** A tabular response in response to a PREPARE statement containing - * information about the wildcard values that need to be supplied */ - public final static int Q_PREPARE = '5'; - /** A tabular continuation response (for a ResultSet) */ - public final static int Q_BLOCK = '6'; - /** An unknown and unsupported response */ - public final static int Q_UNKNOWN = 0 ; + /* Query types (copied from sql_query.mx) */ - public final int parse(String in) throws MCLParseException { - soh = CharBuffer.wrap(in); - soh.get(); // skip the & - int type = soh.get(); - switch (type) { - default: - throw new MCLParseException("invalid or unknown header", 1); - case Q_PARSE: - case Q_SCHEMA: - len = 0; - break; - case Q_TABLE: - case Q_PREPARE: - len = 4; - soh.get(); - break; - case Q_UPDATE: - len = 2; - soh.get(); - break; - case Q_TRANS: - len = 1; - soh.get(); - break; - case Q_BLOCK: - len = 3; - soh.get(); - break; - } - pos = 0; - return type; - } - - public final boolean hasNext() { - return pos < len; - } + /** A parse response (not handled) */ + public final static int Q_PARSE = '0'; + /** A tabular response (typical ResultSet) */ + public final static int Q_TABLE = '1'; + /** A response to an update statement, contains number of affected + * rows and generated key-id */ + public final static int Q_UPDATE = '2'; + /** A response to a schema update */ + public final static int Q_SCHEMA = '3'; + /** A response to a transaction statement (start, rollback, abort, + * commit) */ + public final static int Q_TRANS = '4'; + /** A tabular response in response to a PREPARE statement containing + * information about the wildcard values that need to be supplied */ + public final static int Q_PREPARE = '5'; + /** A tabular continuation response (for a ResultSet) */ + public final static int Q_BLOCK = '6'; + /** An unknown and unsupported response */ + public final static int Q_UNKNOWN = 0; - /** - * Returns the next token in the CharBuffer as integer. The value is - * considered to end at the end of the CharBuffer or at a space. If - * a non-numeric character is encountered an MCLParseException is - * thrown. - * - * @return The next token in the CharBuffer as integer - * @throws MCLParseException if no numeric value could be read - */ - public final int getNextAsInt() throws MCLParseException { - pos++; - if (!soh.hasRemaining()) throw - new MCLParseException("unexpected end of string", soh.position() - 1); - int tmp; - char chr = soh.get(); - // note: don't use Character.isDigit() here, because - // we only want ISO-LATIN-1 digits - if (chr >= '0' && chr <= '9') { - tmp = (int)chr - (int)'0'; - } else { - throw new MCLParseException("expected a digit", soh.position() - 1); - } + protected int len; + + protected int pos; + + public StartOfHeaderParser() {} + + public abstract int parse(String in) throws MCLParseException; - while (soh.hasRemaining() && (chr = soh.get()) != ' ') { - tmp *= 10; - if (chr >= '0' && chr <= '9') { - tmp += (int)chr - (int)'0'; - } else { - throw new MCLParseException("expected a digit", soh.position() - 1); - } - } + public abstract int getNextAsInt() throws MCLParseException; - return tmp; - } + public abstract String getNextAsString() throws MCLParseException; - public final String getNextAsString() throws MCLParseException { - pos++; - if (!soh.hasRemaining()) throw - new MCLParseException("unexpected end of string", soh.position() - 1); - int cnt = 0; - soh.mark(); - while (soh.hasRemaining() && soh.get() != ' ') { - cnt++; - } - - soh.reset(); - - return soh.subSequence(0, cnt).toString(); - } + public final boolean hasNext() { + return pos < len; + } }
--- a/src/main/java/nl/cwi/monetdb/mcl/parser/TupleLineParser.java +++ b/src/main/java/nl/cwi/monetdb/mcl/parser/TupleLineParser.java @@ -1,183 +1,17 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V. - */ - package nl.cwi.monetdb.mcl.parser; /** - * The TupleLineParser extracts the values from a given tuple. The - * number of values that are expected are known upfront to speed up - * allocation and validation. - * - * @author Fabian Groffen <Fabian.Groffen> + * Created by ferreira on 11/25/16. */ -public class TupleLineParser extends MCLParser { - /** - * Constructs a TupleLineParser which expects columncount columns. - * - * @param columncount the number of columns in the to be parsed string - */ - public TupleLineParser(int columncount) { - super(columncount); - } - - /** - * Parses the given String source as tuple line. If source cannot - * be parsed, a ParseException is thrown. The columncount argument - * is used for allocation of the returned array. While this seems - * illogical, the caller should know this size, since the - * StartOfHeader contains this information. - * - * @param source a String which should be parsed - * @return 0, as there is no 'type' of TupleLine - * @throws MCLParseException if an error occurs during parsing - */ - @Override - public int parse(String source) throws MCLParseException { - int len = source.length(); - char[] chrLine = new char[len]; - source.getChars(0, len, chrLine, 0); - - // first detect whether this is a single value line (=) or a - // real tuple ([) - if (chrLine[0] == '=') { - if (values.length != 1) - throw new MCLParseException(values.length + - " columns expected, but only single value found"); - - // return the whole string but the leading = - values[0] = source.substring(1); - - // reset colnr - reset(); - - return 0; - } - - // extract separate fields by examining string, char for char - boolean inString = false, escaped = false; - int cursor = 2, column = 0, i = 2; - StringBuilder uesc = new StringBuilder(); - for (; i < len; i++) { - switch(chrLine[i]) { - default: - escaped = false; - break; - case '\\': - escaped = !escaped; - break; - case '"': - /** - * If all strings are wrapped between two quotes, a \" can - * never exist outside a string. Thus if we believe that we - * are not within a string, we can safely assume we're about - * to enter a string if we find a quote. - * If we are in a string we should stop being in a string if - * we find a quote which is not prefixed by a \, for that - * would be an escaped quote. However, a nasty situation can - * occur where the string is like "test \\" as obvious, a - * test for a \ in front of a " doesn't hold here for all - * cases. Because "test \\\"" can exist as well, we need to - * know if a quote is prefixed by an escaping slash or not. - */ - if (!inString) { - inString = true; - } else if (!escaped) { - inString = false; - } - - // reset escaped flag - escaped = false; - break; - case '\t': - if (!inString && - (i > 0 && chrLine[i - 1] == ',') || - (i + 1 == len - 1 && chrLine[++i] == ']')) // dirty - { - // split! - if (chrLine[cursor] == '"' && - chrLine[i - 2] == '"') - { - // reuse the StringBuilder by cleaning it - uesc.delete(0, uesc.length()); - // prevent capacity increasements - uesc.ensureCapacity((i - 2) - (cursor + 1)); - for (int pos = cursor + 1; pos < i - 2; pos++) { - if (chrLine[pos] == '\\' && pos + 1 < i - 2) { - pos++; - // strToStr and strFromStr in gdk_atoms.mx only - // support \t \n \\ \" and \377 - switch (chrLine[pos]) { - case '\\': - uesc.append('\\'); - break; - case 'n': - uesc.append('\n'); - break; - case 't': - uesc.append('\t'); - break; - case '"': - uesc.append('"'); - break; - case '0': case '1': case '2': case '3': - // this could be an octal number, let's check it out - if (pos + 2 < i - 2 && - chrLine[pos + 1] >= '0' && chrLine[pos + 1] <= '7' && - chrLine[pos + 2] >= '0' && chrLine[pos + 2] <= '7' - ) { - // we got the number! - try { - uesc.append((char)(Integer.parseInt("" + chrLine[pos] + chrLine[pos + 1] + chrLine[pos + 2], 8))); - pos += 2; - } catch (NumberFormatException e) { - // hmmm, this point should never be reached actually... - throw new AssertionError("Flow error, should never try to parse non-number"); - } - } else { - // do default action if number seems not to be correct - uesc.append(chrLine[pos]); - } - break; - default: - // this is wrong, just ignore the escape, and print the char - uesc.append(chrLine[pos]); - break; - } - } else { - uesc.append(chrLine[pos]); - } - } - - // put the unescaped string in the right place - values[column++] = uesc.toString(); - } else if ((i - 1) - cursor == 4 && - source.indexOf("NULL", cursor) == cursor) - { - values[column++] = null; - } else { - values[column++] = - source.substring(cursor, i - 1); - } - cursor = i + 1; - } - - // reset escaped flag - escaped = false; - break; - } - } - // check if this result is of the size we expected it to be - if (column != values.length) - throw new MCLParseException("illegal result length: " + column + "\nlast read: " + (column > 0 ? values[column - 1] : "<none>")); - - // reset colnr - reset(); - - return 0; - } +public abstract class TupleLineParser extends MCLParser { + /** + * Creates an MCLParser targeted at a given number of field values. + * The lines parsed by an instance of this MCLParser should have + * exactly capacity field values. + * + * @param capacity the number of field values to expect + */ + protected TupleLineParser(int capacity) { + super(capacity); + } }
new file mode 100644 --- /dev/null +++ b/src/main/java/nl/cwi/monetdb/mcl/parser/embedded/EmbeddedHeaderLineParser.java @@ -0,0 +1,26 @@ +package nl.cwi.monetdb.mcl.parser.embedded; + +import nl.cwi.monetdb.mcl.parser.HeaderLineParser; +import nl.cwi.monetdb.mcl.parser.MCLParseException; + +/** + * Created by ferreira on 11/25/16. + */ +public class EmbeddedHeaderLineParser extends HeaderLineParser { + + /** + * Creates an MCLParser targeted at a given number of field values. + * The lines parsed by an instance of this MCLParser should have + * exactly capacity field values. + * + * @param capacity the number of field values to expect + */ + public EmbeddedHeaderLineParser(int capacity) { + super(capacity); + } + + @Override + public int parse(String source) throws MCLParseException { + return 0; + } +}
new file mode 100644 --- /dev/null +++ b/src/main/java/nl/cwi/monetdb/mcl/parser/embedded/EmbeddedStartOfHeaderParser.java @@ -0,0 +1,25 @@ +package nl.cwi.monetdb.mcl.parser.embedded; + +import nl.cwi.monetdb.mcl.parser.MCLParseException; +import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser; + +/** + * Created by ferreira on 11/25/16. + */ +public class EmbeddedStartOfHeaderParser extends StartOfHeaderParser { + + @Override + public int parse(String in) throws MCLParseException { + return 0; + } + + @Override + public int getNextAsInt() throws MCLParseException { + return 0; + } + + @Override + public String getNextAsString() throws MCLParseException { + return null; + } +}
new file mode 100644 --- /dev/null +++ b/src/main/java/nl/cwi/monetdb/mcl/parser/embedded/EmbeddedTupleLineParser.java @@ -0,0 +1,26 @@ +package nl.cwi.monetdb.mcl.parser.embedded; + +import nl.cwi.monetdb.mcl.parser.MCLParseException; +import nl.cwi.monetdb.mcl.parser.TupleLineParser; + +/** + * Created by ferreira on 11/25/16. + */ +public class EmbeddedTupleLineParser extends TupleLineParser { + + /** + * Creates an MCLParser targeted at a given number of field values. + * The lines parsed by an instance of this MCLParser should have + * exactly capacity field values. + * + * @param capacity the number of field values to expect + */ + public EmbeddedTupleLineParser(int capacity) { + super(capacity); + } + + @Override + public int parse(String source) throws MCLParseException { + return 0; + } +}
copy from src/main/java/nl/cwi/monetdb/mcl/parser/HeaderLineParser.java copy to src/main/java/nl/cwi/monetdb/mcl/parser/socket/SocketHeaderLineParser.java --- a/src/main/java/nl/cwi/monetdb/mcl/parser/HeaderLineParser.java +++ b/src/main/java/nl/cwi/monetdb/mcl/parser/socket/SocketHeaderLineParser.java @@ -6,30 +6,28 @@ * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V. */ -package nl.cwi.monetdb.mcl.parser; +package nl.cwi.monetdb.mcl.parser.socket; +import nl.cwi.monetdb.mcl.parser.HeaderLineParser; +import nl.cwi.monetdb.mcl.parser.MCLParseException; +import nl.cwi.monetdb.mcl.parser.MCLParser; + /** - * The HeaderLineParser is a generic MCLParser that extracts values from + * The SocketHeaderLineParser is a generic MCLParser that extracts values from * a metadata header in the MCL protocol either as string or integer * values. * * @author Fabian Groffen <Fabian.Groffen> */ -public class HeaderLineParser extends MCLParser { - private int type; - - public final static int NAME = 1; - public final static int LENGTH = 2; - public final static int TABLE = 3; - public final static int TYPE = 4; +public class SocketHeaderLineParser extends HeaderLineParser { /** - * Constructs a HeaderLineParser which expects columncount columns. + * Constructs a SocketHeaderLineParser which expects columncount columns. * * @param columncount the number of columns in the to be parsed string */ - public HeaderLineParser(int columncount) { + public SocketHeaderLineParser(int columncount) { super(columncount); } @@ -88,7 +86,7 @@ public class HeaderLineParser extends MC source.regionMatches(pos + 1, "name", 1, 3)) { getValues(chrLine, 2, pos - 3); - type = NAME; + type = HeaderLineParser.NAME; } break; case 'l': @@ -96,7 +94,7 @@ public class HeaderLineParser extends MC source.regionMatches(pos + 1, "length", 1, 5)) { getIntValues(chrLine, 2, pos - 3); - type = LENGTH; + type = HeaderLineParser.LENGTH; } break; case 't': @@ -104,12 +102,12 @@ public class HeaderLineParser extends MC source.regionMatches(pos + 1, "type", 1, 3)) { getValues(chrLine, 2, pos - 3); - type = TYPE; + type = HeaderLineParser.TYPE; } else if (len - pos == 10 && source.regionMatches(pos + 1, "table_name", 1, 9)) { getValues(chrLine, 2, pos - 3); - type = TABLE; + type = HeaderLineParser.TABLE; } break; default:
copy from src/main/java/nl/cwi/monetdb/mcl/parser/StartOfHeaderParser.java copy to src/main/java/nl/cwi/monetdb/mcl/parser/socket/SocketStartOfHeaderParser.java --- a/src/main/java/nl/cwi/monetdb/mcl/parser/StartOfHeaderParser.java +++ b/src/main/java/nl/cwi/monetdb/mcl/parser/socket/SocketStartOfHeaderParser.java @@ -6,12 +6,15 @@ * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V. */ -package nl.cwi.monetdb.mcl.parser; +package nl.cwi.monetdb.mcl.parser.socket; + +import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser; +import nl.cwi.monetdb.mcl.parser.MCLParseException; import java.nio.CharBuffer; /** - * The StartOfHeaderParser allows easy examination of a start of header + * The SocketStartOfHeaderParser allows easy examination of a start of header * line. It does not fit into the general MCLParser framework because * it uses a different interface. While the parser is very shallow, it * requires the caller to know about the header lines that are parsed. @@ -22,33 +25,11 @@ import java.nio.CharBuffer; * * @author Fabian Groffen <Fabian.Groffen> */ -public class StartOfHeaderParser { - private CharBuffer soh = null; - private int len; - private int pos; - - /* Query types (copied from sql_query.mx) */ +public class SocketStartOfHeaderParser extends StartOfHeaderParser { - /** A parse response (not handled) */ - public final static int Q_PARSE = '0'; - /** A tabular response (typical ResultSet) */ - public final static int Q_TABLE = '1'; - /** A response to an update statement, contains number of affected - * rows and generated key-id */ - public final static int Q_UPDATE = '2'; - /** A response to a schema update */ - public final static int Q_SCHEMA = '3'; - /** A response to a transation statement (start, rollback, abort, - * commit) */ - public final static int Q_TRANS = '4'; - /** A tabular response in response to a PREPARE statement containing - * information about the wildcard values that need to be supplied */ - public final static int Q_PREPARE = '5'; - /** A tabular continuation response (for a ResultSet) */ - public final static int Q_BLOCK = '6'; - /** An unknown and unsupported response */ - public final static int Q_UNKNOWN = 0 ; + private CharBuffer soh = null; + @Override public final int parse(String in) throws MCLParseException { soh = CharBuffer.wrap(in); soh.get(); // skip the & @@ -82,10 +63,6 @@ public class StartOfHeaderParser { return type; } - public final boolean hasNext() { - return pos < len; - } - /** * Returns the next token in the CharBuffer as integer. The value is * considered to end at the end of the CharBuffer or at a space. If @@ -95,6 +72,7 @@ public class StartOfHeaderParser { * @return The next token in the CharBuffer as integer * @throws MCLParseException if no numeric value could be read */ + @Override public final int getNextAsInt() throws MCLParseException { pos++; if (!soh.hasRemaining()) throw @@ -121,6 +99,7 @@ public class StartOfHeaderParser { return tmp; } + @Override public final String getNextAsString() throws MCLParseException { pos++; if (!soh.hasRemaining()) throw
copy from src/main/java/nl/cwi/monetdb/mcl/parser/TupleLineParser.java copy to src/main/java/nl/cwi/monetdb/mcl/parser/socket/SocketTupleLineParser.java --- a/src/main/java/nl/cwi/monetdb/mcl/parser/TupleLineParser.java +++ b/src/main/java/nl/cwi/monetdb/mcl/parser/socket/SocketTupleLineParser.java @@ -6,22 +6,26 @@ * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V. */ -package nl.cwi.monetdb.mcl.parser; +package nl.cwi.monetdb.mcl.parser.socket; + +import nl.cwi.monetdb.mcl.parser.MCLParseException; +import nl.cwi.monetdb.mcl.parser.TupleLineParser; /** - * The TupleLineParser extracts the values from a given tuple. The + * The SocketTupleLineParser extracts the values from a given tuple. The * number of values that are expected are known upfront to speed up * allocation and validation. * * @author Fabian Groffen <Fabian.Groffen> */ -public class TupleLineParser extends MCLParser { +public class SocketTupleLineParser extends TupleLineParser { + /** - * Constructs a TupleLineParser which expects columncount columns. + * Constructs a SocketTupleLineParser which expects columncount columns. * * @param columncount the number of columns in the to be parsed string */ - public TupleLineParser(int columncount) { + public SocketTupleLineParser(int columncount) { super(columncount); }
--- a/src/main/java/nl/cwi/monetdb/merovingian/Control.java +++ b/src/main/java/nl/cwi/monetdb/merovingian/Control.java @@ -8,8 +8,8 @@ package nl.cwi.monetdb.merovingian; -import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader; -import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter; +import nl.cwi.monetdb.mcl.io.AbstractMCLReader; +import nl.cwi.monetdb.mcl.io.AbstractMCLWriter; import nl.cwi.monetdb.mcl.net.MapiSocket; import nl.cwi.monetdb.mcl.MCLException; import nl.cwi.monetdb.mcl.parser.MCLParseException; @@ -115,8 +115,8 @@ public class Control { String database, String command, boolean hasOutput) throws MerovingianException, IOException { - AbstractBufferedReader min; - AbstractBufferedWriter mout; + AbstractMCLReader min; + AbstractMCLWriter mout; MapiSocket ms = new MapiSocket(host, port, "monetdb", "monetdb", false, "sql", "SHA256"); ms.setDatabase("merovingian"); ms.setLanguage("control"); @@ -205,16 +205,16 @@ public class Control { ArrayList<String> l = new ArrayList<>(); String tmpLine = min.readLine(); int linetype = min.getLineType(); - if (linetype == AbstractBufferedReader.ERROR) + if (linetype == AbstractMCLReader.ERROR) throw new MerovingianException(tmpLine.substring(6)); - if (linetype != AbstractBufferedReader.RESULT) + if (linetype != AbstractMCLReader.RESULT) throw new MerovingianException("unexpected line: " + tmpLine); if (!tmpLine.substring(1).equals(RESPONSE_OK)) throw new MerovingianException(tmpLine.substring(1)); tmpLine = min.readLine(); linetype = min.getLineType(); - while (linetype != AbstractBufferedReader.PROMPT) { - if (linetype != AbstractBufferedReader.RESULT) + while (linetype != AbstractMCLReader.PROMPT) { + if (linetype != AbstractMCLReader.RESULT) throw new MerovingianException("unexpected line: " + tmpLine);
--- a/src/main/java/nl/cwi/monetdb/util/SQLRestore.java +++ b/src/main/java/nl/cwi/monetdb/util/SQLRestore.java @@ -15,8 +15,8 @@ import java.io.IOException; import java.util.concurrent.atomic.AtomicBoolean; import nl.cwi.monetdb.mcl.MCLException; -import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader; -import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter; +import nl.cwi.monetdb.mcl.io.AbstractMCLReader; +import nl.cwi.monetdb.mcl.io.AbstractMCLWriter; import nl.cwi.monetdb.mcl.net.MapiSocket; import nl.cwi.monetdb.mcl.parser.MCLParseException; @@ -42,11 +42,11 @@ public class SQLRestore { } private static class ServerResponseReader implements Runnable { - private final AbstractBufferedReader _is; + private final AbstractMCLReader _is; private final AtomicBoolean _errorState = new AtomicBoolean(false); private String _errorMessage = null; - ServerResponseReader(AbstractBufferedReader is) { + ServerResponseReader(AbstractMCLReader is) { _is = is; } @@ -58,7 +58,7 @@ public class SQLRestore { break; int result = _is.getLineType(); switch (result) { - case AbstractBufferedReader.ERROR: + case AbstractMCLReader.ERROR: _errorMessage = line; _errorState.set(true); return; @@ -108,8 +108,8 @@ public class SQLRestore { try { ms.connect(_user, _password); - AbstractBufferedWriter os = ms.getWriter(); - AbstractBufferedReader reader = ms.getReader(); + AbstractMCLWriter os = ms.getWriter(); + AbstractMCLReader reader = ms.getReader(); ServerResponseReader srr = new ServerResponseReader(reader);