first working version v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sun, 22 Dec 2013 23:31:55 +0100
branchv_0
changeset 34 9335cf31c0f2
parent 33 04db6ccd6c48
child 35 b2ff3b2d58b2
first working version
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/Functions.java
java/sql-dk/src/info/globalcode/sql/dk/SQLCommand.java
java/sql-dk/src/info/globalcode/sql/dk/SQLCommandNamed.java
java/sql-dk/src/info/globalcode/sql/dk/SQLCommandNumbered.java
java/sql-dk/src/info/globalcode/sql/dk/configuration/FormatterDefinition.java
java/sql-dk/src/info/globalcode/sql/dk/formatting/AbstractFormatter.java
java/sql-dk/src/info/globalcode/sql/dk/formatting/Formatter.java
java/sql-dk/src/info/globalcode/sql/dk/formatting/FormatterException.java
java/sql-dk/src/info/globalcode/sql/dk/formatting/TabularFormatter.java
--- a/java/sql-dk/src/info/globalcode/sql/dk/CLIOptions.java	Sun Dec 22 22:02:44 2013 +0100
+++ b/java/sql-dk/src/info/globalcode/sql/dk/CLIOptions.java	Sun Dec 22 23:31:55 2013 +0100
@@ -21,6 +21,7 @@
 import static info.globalcode.sql.dk.Functions.isEmpty;
 import static info.globalcode.sql.dk.Functions.equalz;
 import info.globalcode.sql.dk.SQLCommand.COMMAND_TYPE;
+import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.EnumSet;
@@ -59,7 +60,7 @@
 		CONNECTION
 	}
 	private COMMAND_TYPE commandType;
-	private final Collection<NamedParameter> namedParameters = new ArrayList<>();
+	private final List<NamedParameter> namedParameters = new ArrayList<>();
 	private final List<Parameter> numberedParameters = new ArrayList<>();
 	private final EnumSet<INFO_TYPE> showInfo = EnumSet.noneOf(INFO_TYPE.class);
 
@@ -207,4 +208,16 @@
 	public void setDatabaseNameToTest(String databaseNameToTest) {
 		this.databaseNameToTest = databaseNameToTest;
 	}
+
+	public SQLCommand getSQLCommand() {
+		if (namedParameters.isEmpty()) {
+			return new SQLCommandNumbered(commandType, sql, numberedParameters);
+		} else {
+			return new SQLCommandNamed(commandType, sql, namedParameters);
+		}
+	}
+
+	public OutputStream getOutputStream() {
+		return System.out;
+	}
 }
--- a/java/sql-dk/src/info/globalcode/sql/dk/CLIStarter.java	Sun Dec 22 22:02:44 2013 +0100
+++ b/java/sql-dk/src/info/globalcode/sql/dk/CLIStarter.java	Sun Dec 22 23:31:55 2013 +0100
@@ -21,7 +21,13 @@
 import info.globalcode.sql.dk.CLIOptions.MODE;
 import info.globalcode.sql.dk.configuration.Configuration;
 import info.globalcode.sql.dk.configuration.ConfigurationException;
+import info.globalcode.sql.dk.configuration.DatabaseDefinition;
+import info.globalcode.sql.dk.configuration.FormatterDefinition;
+import info.globalcode.sql.dk.formatting.Formatter;
+import info.globalcode.sql.dk.formatting.FormatterContext;
+import info.globalcode.sql.dk.formatting.FormatterException;
 import java.io.IOException;
+import java.sql.SQLException;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import javax.xml.bind.JAXBContext;
@@ -54,6 +60,12 @@
 			log.log(Level.SEVERE, "Unable to parse CLI options", e);
 		} catch (InvalidOptionsException e) {
 			log.log(Level.SEVERE, "Invalid CLI options", e);
+		} catch (ConfigurationException e) {
+			log.log(Level.SEVERE, "Configuration problem", e);
+		} catch (SQLException e) {
+			log.log(Level.SEVERE, "SQL problem", e);
+		} catch (FormatterException e) {
+			log.log(Level.SEVERE, "Formatting problem", e);
 		}
 	}
 
@@ -61,7 +73,7 @@
 		this.options = options;
 	}
 
-	private void process() {
+	private void process() throws ConfigurationException, SQLException, FormatterException {
 		/** Show info */
 		if (!options.getShowInfo().isEmpty()) {
 			InfoLister infoLister = new InfoLister(System.err, this);
@@ -71,10 +83,13 @@
 		MODE mode = options.getMode();
 		switch (mode) {
 			case QUERY_NOW:
+				processQueryNow();
 				break;
 			case PREPARE_BATCH:
+				processPrepareBatch();
 				break;
 			case EXECUTE_BATCH:
+				processExecuteBatch();
 				break;
 			case JUST_SHOW_INFO:
 				// already done above
@@ -85,6 +100,28 @@
 		}
 	}
 
+	private void processQueryNow() throws ConfigurationException, SQLException, FormatterException {
+		DatabaseDefinition dd = getConfiguration().getDatabase(options.getDatabaseName());
+		if (dd == null) {
+			throw new ConfigurationException("Database is not configured: " + options.getDatabaseName());
+		} else {
+			FormatterDefinition fd = configuration.getFormatter(options.getFormatterName());
+			if (fd == null) {
+				throw new ConfigurationException("Formatter is not configured: " + options.getDatabaseName());
+			} else {
+				DatabaseConnection c = dd.connect();
+				Formatter f = fd.getInstance(new FormatterContext(options.getOutputStream()));
+				c.executeQuery(options.getSQLCommand(), f);
+			}
+		}
+	}
+
+	private void processPrepareBatch() {
+	}
+
+	private void processExecuteBatch() {
+	}
+
 	@Override
 	public Configuration getConfiguration() throws ConfigurationException {
 		if (configuration == null) {
@@ -93,7 +130,7 @@
 		return configuration;
 	}
 
-	private void installDefaultConfiguration() {
+	private void installDefaultConfiguration() throws ConfigurationException {
 		Constants.DIR.mkdir();
 
 		if (Constants.CONFIG_FILE.exists()) {
@@ -102,10 +139,9 @@
 			try {
 				Functions.installResource(Constants.EXAMPLE_CONFIG_FILE, Constants.CONFIG_FILE);
 			} catch (IOException e) {
-				log.log(Level.SEVERE, "Unable to write example configuration to " + Constants.CONFIG_FILE, e);
+				throw new ConfigurationException("Unable to write example configuration to " + Constants.CONFIG_FILE, e);
 			}
 		}
-
 	}
 
 	private Configuration loadConfiguration() throws ConfigurationException {
--- a/java/sql-dk/src/info/globalcode/sql/dk/DatabaseConnection.java	Sun Dec 22 22:02:44 2013 +0100
+++ b/java/sql-dk/src/info/globalcode/sql/dk/DatabaseConnection.java	Sun Dec 22 23:31:55 2013 +0100
@@ -19,6 +19,7 @@
 
 import info.globalcode.sql.dk.batch.Batch;
 import info.globalcode.sql.dk.configuration.DatabaseDefinition;
+import info.globalcode.sql.dk.formatting.ColumnsHeader;
 import info.globalcode.sql.dk.formatting.Formatter;
 import java.sql.Connection;
 import java.sql.DriverManager;
@@ -38,7 +39,7 @@
 	public DatabaseConnection(DatabaseDefinition databaseDefinition) throws SQLException {
 		this.databaseDefinition = databaseDefinition;
 
-		connection = DriverManager.getConnection(databaseDefinition.getUrl(), databaseDefinition.getName(), databaseDefinition.getPassword());
+		connection = DriverManager.getConnection(databaseDefinition.getUrl(), databaseDefinition.getUserName(), databaseDefinition.getPassword());
 	}
 
 	public void executeQuery(SQLCommand sqlCommand, Formatter formatter) throws SQLException {
@@ -72,7 +73,7 @@
 	private void processQueryCommand(SQLCommand sqlCommand, Formatter formatter) throws SQLException {
 		formatter.writeStartResultSet();
 		formatter.writeQuery(sqlCommand.getQuery());
-		/** TODO: formatter.writeParameters(null); */
+		formatter.writeParameters(sqlCommand.getParameters());
 		try (PreparedStatement ps = sqlCommand.prepareStatement(connection)) {
 			sqlCommand.parametrize(ps);
 			try (ResultSet rs = ps.executeQuery()) {
@@ -86,7 +87,7 @@
 	private void processUpdateCommand(SQLCommand sqlCommand, Formatter formatter) throws SQLException {
 		formatter.writeStartUpdatesResult();
 		formatter.writeQuery(sqlCommand.getQuery());
-		/** TODO: formatter.writeParameters(null); */
+		formatter.writeParameters(sqlCommand.getParameters());
 		try (PreparedStatement ps = sqlCommand.prepareStatement(connection)) {
 			sqlCommand.parametrize(ps);
 			int updatedRowsCount = ps.executeUpdate();
@@ -104,12 +105,18 @@
 	}
 
 	private void processResultSet(ResultSet rs, Formatter formatter) throws SQLException {
-		/** TODO: formatter.writeColumnsHeader(null); */
+		formatter.writeColumnsHeader(new ColumnsHeader(rs.getMetaData()));
+		int columnCount = rs.getMetaData().getColumnCount();
+
 		while (rs.next()) {
 			formatter.writeStartRow();
 
-			/** TODO: formatter.writeColumnValue(rs.get); */
+			for (int i = 1; i <= columnCount; i++) {
+				formatter.writeColumnValue(rs.getObject(i));
+			}
+
 			formatter.writeEndRow();
 		}
+
 	}
 }
--- a/java/sql-dk/src/info/globalcode/sql/dk/Functions.java	Sun Dec 22 22:02:44 2013 +0100
+++ b/java/sql-dk/src/info/globalcode/sql/dk/Functions.java	Sun Dec 22 23:31:55 2013 +0100
@@ -26,7 +26,6 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Map;
-import java.util.logging.Level;
 
 /**
  *
--- a/java/sql-dk/src/info/globalcode/sql/dk/SQLCommand.java	Sun Dec 22 22:02:44 2013 +0100
+++ b/java/sql-dk/src/info/globalcode/sql/dk/SQLCommand.java	Sun Dec 22 23:31:55 2013 +0100
@@ -19,6 +19,8 @@
 
 import java.sql.Connection;
 import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.List;
 
 /**
  *
@@ -29,9 +31,16 @@
 	private COMMAND_TYPE commandType;
 	private String query;
 
-	public abstract PreparedStatement prepareStatement(Connection c);
+	public SQLCommand(COMMAND_TYPE commandType, String query) {
+		this.commandType = commandType;
+		this.query = query;
+	}
 
-	public abstract void parametrize(PreparedStatement ps);
+	public abstract PreparedStatement prepareStatement(Connection c) throws SQLException;
+
+	public abstract void parametrize(PreparedStatement ps) throws SQLException;
+
+	public abstract List<? extends Parameter> getParameters();
 
 	public COMMAND_TYPE getCommandType() {
 		return commandType;
--- a/java/sql-dk/src/info/globalcode/sql/dk/SQLCommandNamed.java	Sun Dec 22 22:02:44 2013 +0100
+++ b/java/sql-dk/src/info/globalcode/sql/dk/SQLCommandNamed.java	Sun Dec 22 23:31:55 2013 +0100
@@ -19,6 +19,8 @@
 
 import java.sql.Connection;
 import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.List;
 
 /**
  *
@@ -26,13 +28,25 @@
  */
 public class SQLCommandNamed extends SQLCommand {
 
+	private List<NamedParameter> parameters;
+
+	public SQLCommandNamed(COMMAND_TYPE commandType, String query, List<NamedParameter> parameters) {
+		super(commandType, query);
+		this.parameters = parameters;
+	}
+
 	@Override
-	public PreparedStatement prepareStatement(Connection c) {
+	public PreparedStatement prepareStatement(Connection c) throws SQLException {
 		throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
 	}
 
 	@Override
-	public void parametrize(PreparedStatement ps) {
+	public void parametrize(PreparedStatement ps) throws SQLException {
 		throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
 	}
+
+	@Override
+	public List<NamedParameter> getParameters() {
+		return parameters;
+	}
 }
--- a/java/sql-dk/src/info/globalcode/sql/dk/SQLCommandNumbered.java	Sun Dec 22 22:02:44 2013 +0100
+++ b/java/sql-dk/src/info/globalcode/sql/dk/SQLCommandNumbered.java	Sun Dec 22 23:31:55 2013 +0100
@@ -17,8 +17,11 @@
  */
 package info.globalcode.sql.dk;
 
+import static info.globalcode.sql.dk.Functions.notNull;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.List;
 
 /**
  *
@@ -26,13 +29,28 @@
  */
 public class SQLCommandNumbered extends SQLCommand {
 
+	private List<Parameter> parameters;
+
+	public SQLCommandNumbered(COMMAND_TYPE commandType, String query, List<Parameter> parameters) {
+		super(commandType, query);
+		this.parameters = parameters;
+	}
+
 	@Override
-	public PreparedStatement prepareStatement(Connection c) {
-		throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+	public PreparedStatement prepareStatement(Connection c) throws SQLException {
+		return c.prepareStatement(getQuery());
 	}
 
 	@Override
-	public void parametrize(PreparedStatement ps) {
-		throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+	public void parametrize(PreparedStatement ps) throws SQLException {
+		int i = 1;
+		for (Parameter p : notNull(parameters)) {
+			ps.setObject(i++, p.getValue(), p.getType());
+		}
+	}
+
+	@Override
+	public List<Parameter> getParameters() {
+		return parameters;
 	}
 }
--- a/java/sql-dk/src/info/globalcode/sql/dk/configuration/FormatterDefinition.java	Sun Dec 22 22:02:44 2013 +0100
+++ b/java/sql-dk/src/info/globalcode/sql/dk/configuration/FormatterDefinition.java	Sun Dec 22 23:31:55 2013 +0100
@@ -21,6 +21,7 @@
 import info.globalcode.sql.dk.DKException;
 import info.globalcode.sql.dk.formatting.Formatter;
 import info.globalcode.sql.dk.formatting.FormatterContext;
+import info.globalcode.sql.dk.formatting.FormatterException;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import javax.xml.bind.annotation.XmlElement;
@@ -76,7 +77,7 @@
 	 * @return
 	 * @throws DKException
 	 */
-	public Formatter getInstance(FormatterContext context) throws DKException {
+	public Formatter getInstance(FormatterContext context) throws FormatterException {
 		try {
 			Constructor constructor = Class.forName(className).getConstructor(context.getClass());
 
@@ -84,14 +85,14 @@
 			if (instance instanceof Formatter) {
 				return (Formatter) instance;
 			} else {
-				throw new DKException("Formatter " + instance + " does not implement the " + Formatter.class.getName() + " interface");
+				throw new FormatterException("Formatter " + instance + " does not implement the " + Formatter.class.getName() + " interface");
 			}
 		} catch (ClassNotFoundException e) {
-			throw new DKException("No formatter class with name: " + className, e);
+			throw new FormatterException("No formatter class with name: " + className, e);
 		} catch (NoSuchMethodException e) {
-			throw new DKException("Formatter class with no valid constructor: " + className, e);
+			throw new FormatterException("Formatter class with no valid constructor: " + className, e);
 		} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
-			throw new DKException("Formatter's constructor caused an error: " + className, e);
+			throw new FormatterException("Formatter's constructor caused an error: " + className, e);
 		}
 	}
 }
--- a/java/sql-dk/src/info/globalcode/sql/dk/formatting/AbstractFormatter.java	Sun Dec 22 22:02:44 2013 +0100
+++ b/java/sql-dk/src/info/globalcode/sql/dk/formatting/AbstractFormatter.java	Sun Dec 22 23:31:55 2013 +0100
@@ -110,7 +110,8 @@
 	 */
 	private State popState(EnumSet expected) {
 		try {
-			State superior = state.pop();
+			state.pop();
+			State superior = state.peek();
 			if (expected.contains(superior)) {
 				return superior;
 			} else {
@@ -155,7 +156,7 @@
 	}
 
 	@Override
-	public void writeParameters(List<Parameter> parameters) {
+	public void writeParameters(List<? extends Parameter> parameters) {
 		peekState(EnumSet.of(State.RESULT_SET, State.UPDATES_RESULT));
 
 		if (currentColumnsHeader != null) {
@@ -242,6 +243,14 @@
 		return currentColumnsCount;
 	}
 
+	protected boolean isCurrentColumnFirst() {
+		return currentColumnsCount == 1;
+	}
+
+	protected boolean isCurrentColumnLast() {
+		return currentColumnsCount == currentColumnsHeader.getColumnCount();
+	}
+
 	/**
 	 * @return row number, 1 = first
 	 */
--- a/java/sql-dk/src/info/globalcode/sql/dk/formatting/Formatter.java	Sun Dec 22 22:02:44 2013 +0100
+++ b/java/sql-dk/src/info/globalcode/sql/dk/formatting/Formatter.java	Sun Dec 22 23:31:55 2013 +0100
@@ -37,7 +37,7 @@
 
 	void writeQuery(String sql);
 
-	void writeParameters(List<Parameter> parameters);
+	void writeParameters(List<? extends Parameter> parameters);
 
 	void writeColumnsHeader(ColumnsHeader header);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/sql-dk/src/info/globalcode/sql/dk/formatting/FormatterException.java	Sun Dec 22 23:31:55 2013 +0100
@@ -0,0 +1,42 @@
+/**
+ * SQL-DK
+ * Copyright © 2013 František Kučera (frantovo.cz)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package info.globalcode.sql.dk.formatting;
+
+import info.globalcode.sql.dk.DKException;
+
+/**
+ *
+ * @author Ing. František Kučera (frantovo.cz)
+ */
+public class FormatterException extends DKException {
+
+	public FormatterException() {
+	}
+
+	public FormatterException(String message) {
+		super(message);
+	}
+
+	public FormatterException(Throwable cause) {
+		super(cause);
+	}
+
+	public FormatterException(String message, Throwable cause) {
+		super(message, cause);
+	}
+}
--- a/java/sql-dk/src/info/globalcode/sql/dk/formatting/TabularFormatter.java	Sun Dec 22 22:02:44 2013 +0100
+++ b/java/sql-dk/src/info/globalcode/sql/dk/formatting/TabularFormatter.java	Sun Dec 22 23:31:55 2013 +0100
@@ -17,6 +17,8 @@
  */
 package info.globalcode.sql.dk.formatting;
 
+import info.globalcode.sql.dk.ColorfulPrintWriter;
+
 /**
  *
  * @author Ing. František Kučera (frantovo.cz)
@@ -24,8 +26,28 @@
 public class TabularFormatter extends AbstractFormatter {
 
 	public static final String NAME = "tabular";
+	private ColorfulPrintWriter out;
 
 	public TabularFormatter(FormatterContext formatterContext) {
 		super(formatterContext);
+		out = new ColorfulPrintWriter(formatterContext.getOutputStream());
+	}
+
+	@Override
+	public void writeColumnValue(Object value) {
+		super.writeColumnValue(value);
+
+		if (!isCurrentColumnFirst()) {
+			out.print(ColorfulPrintWriter.TerminalColor.Green, " | ");
+		}
+		
+		out.print(ColorfulPrintWriter.TerminalColor.Cyan, String.valueOf(value));
+	}
+
+	@Override
+	public void writeEndRow() {
+		super.writeEndRow();
+		out.println();
+		out.flush();
 	}
 }