BatchDecoder: basic decoder v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Wed, 08 Jan 2014 19:18:52 +0100
branchv_0
changeset 1464f4f515df807
parent 145 5f90decd3b59
child 147 4a704c1669f4
BatchDecoder: basic decoder
java/sql-dk/src/info/globalcode/sql/dk/CLIOptions.java
java/sql-dk/src/info/globalcode/sql/dk/CLIStarter.java
java/sql-dk/src/info/globalcode/sql/dk/DatabaseConnection.java
java/sql-dk/src/info/globalcode/sql/dk/SQLType.java
java/sql-dk/src/info/globalcode/sql/dk/batch/Batch.java
java/sql-dk/src/info/globalcode/sql/dk/batch/BatchConstants.java
java/sql-dk/src/info/globalcode/sql/dk/batch/BatchDecoder.java
java/sql-dk/src/info/globalcode/sql/dk/batch/BatchEncoder.java
     1.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/CLIOptions.java	Wed Jan 08 14:50:26 2014 +0100
     1.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/CLIOptions.java	Wed Jan 08 19:18:52 2014 +0100
     1.3 @@ -22,6 +22,7 @@
     1.4  import info.globalcode.sql.dk.InfoLister.InfoType;
     1.5  import info.globalcode.sql.dk.configuration.Properties;
     1.6  import info.globalcode.sql.dk.configuration.Property;
     1.7 +import java.io.InputStream;
     1.8  import java.io.OutputStream;
     1.9  import java.util.ArrayList;
    1.10  import java.util.Collection;
    1.11 @@ -250,4 +251,8 @@
    1.12  	public OutputStream getOutputStream() {
    1.13  		return System.out;
    1.14  	}
    1.15 +
    1.16 +	public InputStream getInputStream() {
    1.17 +		return System.in;
    1.18 +	}
    1.19  }
     2.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/CLIStarter.java	Wed Jan 08 14:50:26 2014 +0100
     2.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/CLIStarter.java	Wed Jan 08 19:18:52 2014 +0100
     2.3 @@ -19,6 +19,8 @@
     2.4  
     2.5  import info.globalcode.sql.dk.configuration.ConfigurationProvider;
     2.6  import info.globalcode.sql.dk.CLIOptions.MODE;
     2.7 +import info.globalcode.sql.dk.batch.Batch;
     2.8 +import info.globalcode.sql.dk.batch.BatchDecoder;
     2.9  import info.globalcode.sql.dk.batch.BatchException;
    2.10  import info.globalcode.sql.dk.batch.BatchEncoder;
    2.11  import info.globalcode.sql.dk.configuration.Configuration;
    2.12 @@ -158,7 +160,18 @@
    2.13  		log.log(Level.FINE, "Prepared batch size: {0} bytes", length);
    2.14  	}
    2.15  
    2.16 -	private void processExecuteBatch() {
    2.17 +	private void processExecuteBatch() throws ConfigurationException, SQLException, FormatterException, BatchException {
    2.18 +		BatchDecoder dec = new BatchDecoder();
    2.19 +		Batch b = dec.decode(options.getInputStream());
    2.20 +
    2.21 +		DatabaseDefinition dd = getConfiguration().getDatabase(options.getDatabaseName());
    2.22 +		FormatterDefinition fd = configuration.getFormatter(options.getFormatterName());
    2.23 +		try (DatabaseConnection c = dd.connect(options.getDatabaseProperties())) {
    2.24 +			log.log(Level.FINE, "Database connected");
    2.25 +			try (Formatter f = fd.getInstance(new FormatterContext(options.getOutputStream(), options.getFormatterProperties()))) {
    2.26 +				c.executeBatch(b, f);
    2.27 +			}
    2.28 +		}
    2.29  	}
    2.30  
    2.31  	@Override
     3.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/DatabaseConnection.java	Wed Jan 08 14:50:26 2014 +0100
     3.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/DatabaseConnection.java	Wed Jan 08 19:18:52 2014 +0100
     3.3 @@ -18,6 +18,7 @@
     3.4  package info.globalcode.sql.dk;
     3.5  
     3.6  import info.globalcode.sql.dk.batch.Batch;
     3.7 +import info.globalcode.sql.dk.batch.BatchException;
     3.8  import info.globalcode.sql.dk.configuration.DatabaseDefinition;
     3.9  import info.globalcode.sql.dk.configuration.Properties;
    3.10  import info.globalcode.sql.dk.configuration.Property;
    3.11 @@ -75,7 +76,7 @@
    3.12  		formatter.writeEndBatch();
    3.13  	}
    3.14  
    3.15 -	public void executeBatch(Batch batch, Formatter formatter) throws SQLException {
    3.16 +	public void executeBatch(Batch batch, Formatter formatter) throws SQLException, BatchException {
    3.17  		formatter.writeStartBatch();
    3.18  		formatter.writeStartDatabase(databaseDefinition);
    3.19  		while (batch.hasNext()) {
     4.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/SQLType.java	Wed Jan 08 14:50:26 2014 +0100
     4.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/SQLType.java	Wed Jan 08 19:18:52 2014 +0100
     4.3 @@ -83,7 +83,7 @@
     4.4  	 * @return found SQLType
     4.5  	 * @throws IllegalArgumentException if no data type has given code
     4.6  	 */
     4.7 -	public SQLType valueOf(int code) {
     4.8 +	public static SQLType valueOf(int code) {
     4.9  		for (SQLType t : values()) {
    4.10  			if (t.code == code) {
    4.11  				return t;
     5.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/batch/Batch.java	Wed Jan 08 14:50:26 2014 +0100
     5.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/batch/Batch.java	Wed Jan 08 19:18:52 2014 +0100
     5.3 @@ -18,28 +18,14 @@
     5.4  package info.globalcode.sql.dk.batch;
     5.5  
     5.6  import info.globalcode.sql.dk.SQLCommand;
     5.7 -import java.util.Iterator;
     5.8  
     5.9  /**
    5.10   *
    5.11   * @author Ing. František Kučera (frantovo.cz)
    5.12   */
    5.13 -public class Batch implements Iterator<SQLCommand> {
    5.14 +public interface Batch {
    5.15  
    5.16 -	@Override
    5.17 -	public boolean hasNext() {
    5.18 -		/** TODO: implement iterator */
    5.19 -		throw new UnsupportedOperationException("Not supported yet.");
    5.20 -	}
    5.21 +	public boolean hasNext() throws BatchException;
    5.22  
    5.23 -	@Override
    5.24 -	public SQLCommand next() {
    5.25 -		/** TODO: implement iterator */
    5.26 -		throw new UnsupportedOperationException("Not supported yet.");
    5.27 -	}
    5.28 -
    5.29 -	@Override
    5.30 -	public void remove() {
    5.31 -		throw new UnsupportedOperationException("remove() is not supported");
    5.32 -	}
    5.33 +	public SQLCommand next() throws BatchException;
    5.34  }
     6.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/batch/BatchConstants.java	Wed Jan 08 14:50:26 2014 +0100
     6.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/batch/BatchConstants.java	Wed Jan 08 19:18:52 2014 +0100
     6.3 @@ -28,7 +28,7 @@
     6.4  
     6.5  	public static final Charset CHARSET = StandardCharsets.UTF_8;
     6.6  	public static final byte VERSION = 0x01;
     6.7 -	public static final byte[] BATCH_START = {0x00, 0x53, 0x51, 0x4C, VERSION};
     6.8 +	public static final byte[] BATCH_HEADER = {0x00, 0x53, 0x51, 0x4C, VERSION};
     6.9  
    6.10  	private BatchConstants() {
    6.11  	}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/batch/BatchDecoder.java	Wed Jan 08 19:18:52 2014 +0100
     7.3 @@ -0,0 +1,110 @@
     7.4 +/**
     7.5 + * SQL-DK
     7.6 + * Copyright © 2014 František Kučera (frantovo.cz)
     7.7 + *
     7.8 + * This program is free software: you can redistribute it and/or modify
     7.9 + * it under the terms of the GNU General Public License as published by
    7.10 + * the Free Software Foundation, either version 3 of the License, or
    7.11 + * (at your option) any later version.
    7.12 + *
    7.13 + * This program is distributed in the hope that it will be useful,
    7.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    7.16 + * GNU General Public License for more details.
    7.17 + *
    7.18 + * You should have received a copy of the GNU General Public License
    7.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
    7.20 + */
    7.21 +package info.globalcode.sql.dk.batch;
    7.22 +
    7.23 +import info.globalcode.sql.dk.Parameter;
    7.24 +import info.globalcode.sql.dk.SQLCommand;
    7.25 +import info.globalcode.sql.dk.SQLCommandNumbered;
    7.26 +import java.io.DataInputStream;
    7.27 +import java.io.InputStream;
    7.28 +import static info.globalcode.sql.dk.batch.BatchConstants.*;
    7.29 +import static info.globalcode.sql.dk.Functions.toHex;
    7.30 +import info.globalcode.sql.dk.SQLType;
    7.31 +import java.io.IOException;
    7.32 +import java.util.ArrayList;
    7.33 +import java.util.Arrays;
    7.34 +import java.util.List;
    7.35 +
    7.36 +/**
    7.37 + *
    7.38 + * @author Ing. František Kučera (frantovo.cz)
    7.39 + */
    7.40 +public class BatchDecoder {
    7.41 +
    7.42 +	public Batch decode(InputStream in) throws BatchException {
    7.43 +		return new BatchFromStream(new DataInputStream(in));
    7.44 +
    7.45 +	}
    7.46 +
    7.47 +	private class BatchFromStream implements Batch {
    7.48 +
    7.49 +		private DataInputStream in;
    7.50 +		private boolean hasNext;
    7.51 +
    7.52 +		public BatchFromStream(DataInputStream in) throws BatchException {
    7.53 +			this.in = in;
    7.54 +			hasNext = verifyHeader();
    7.55 +		}
    7.56 +
    7.57 +		@Override
    7.58 +		public boolean hasNext() throws BatchException {
    7.59 +			return hasNext;
    7.60 +		}
    7.61 +
    7.62 +		@Override
    7.63 +		public SQLCommand next() throws BatchException {
    7.64 +			try {
    7.65 +				String sql = readNextString();
    7.66 +
    7.67 +				int paramCount = in.readInt();
    7.68 +				List<Parameter> parameters = new ArrayList<>(paramCount);
    7.69 +
    7.70 +				for (int i = 0; i < paramCount; i++) {
    7.71 +					SQLType type = SQLType.valueOf(in.readInt());
    7.72 +					String value = readNextString();
    7.73 +					parameters.add(new Parameter(value, type));
    7.74 +				}
    7.75 +
    7.76 +				hasNext = verifyHeader();
    7.77 +
    7.78 +				SQLCommand sqlCommand = new SQLCommandNumbered(sql, parameters);
    7.79 +				return sqlCommand;
    7.80 +			} catch (IOException e) {
    7.81 +				throw new BatchException("Unable to read batch", e);
    7.82 +			}
    7.83 +		}
    7.84 +
    7.85 +		private String readNextString() throws IOException {
    7.86 +			byte[] buffer = new byte[in.readInt()];
    7.87 +			in.read(buffer);
    7.88 +			return new String(buffer, CHARSET);
    7.89 +		}
    7.90 +
    7.91 +		/**
    7.92 +		 * @return true if correct batch header was found | false if EOF was found
    7.93 +		 * @throws BatchException if unexpected data was found (not batch header nor EOF)
    7.94 +		 */
    7.95 +		private boolean verifyHeader() throws BatchException {
    7.96 +			try {
    7.97 +				byte[] buffer = new byte[BATCH_HEADER.length];
    7.98 +				int bytesRead = in.read(buffer);
    7.99 +
   7.100 +				if (bytesRead == BATCH_HEADER.length && Arrays.equals(buffer, BATCH_HEADER)) {
   7.101 +					return true;
   7.102 +				} else if (bytesRead == -1) {
   7.103 +					return false;
   7.104 +				} else {
   7.105 +					throw new BatchException("This is not SQL-DK batch: " + toHex(buffer));
   7.106 +				}
   7.107 +			} catch (IOException e) {
   7.108 +				throw new BatchException("Unable to read batch header", e);
   7.109 +			}
   7.110 +
   7.111 +		}
   7.112 +	}
   7.113 +}
     8.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/batch/BatchEncoder.java	Wed Jan 08 14:50:26 2014 +0100
     8.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/batch/BatchEncoder.java	Wed Jan 08 19:18:52 2014 +0100
     8.3 @@ -39,7 +39,7 @@
     8.4  			ByteArrayOutputStream bufferAOS = new ByteArrayOutputStream();
     8.5  			DataOutputStream buffer = new DataOutputStream(bufferAOS);
     8.6  
     8.7 -			buffer.write(BATCH_START);
     8.8 +			buffer.write(BATCH_HEADER);
     8.9  
    8.10  			if (sqlCommand instanceof SQLCommandNamed) {
    8.11  				sqlCommand = ((SQLCommandNamed) sqlCommand).getSQLCommandNumbered();