support SQL commands returning more ResultSets + remove COMMAND_TYPE (type is now derived from result returned from SQL – it is not needed to specify the type on CLI) v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Mon, 23 Dec 2013 11:50:24 +0100
branchv_0
changeset 379e6f8e5d5f98
parent 36 025fbe816bbf
child 38 ff5bbc06ed29
support SQL commands returning more ResultSets + remove COMMAND_TYPE (type is now derived from result returned from SQL – it is not needed to specify the type on CLI)
java/sql-dk/src/info/globalcode/sql/dk/CLIOptions.java
java/sql-dk/src/info/globalcode/sql/dk/CLIParser.java
java/sql-dk/src/info/globalcode/sql/dk/ColorfulPrintWriter.java
java/sql-dk/src/info/globalcode/sql/dk/DatabaseConnection.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/formatting/AbstractFormatter.java
java/sql-dk/src/info/globalcode/sql/dk/formatting/ColumnDescriptor.java
java/sql-dk/src/info/globalcode/sql/dk/formatting/ColumnsHeader.java
java/sql-dk/src/info/globalcode/sql/dk/formatting/TabularFormatter.java
     1.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/CLIOptions.java	Mon Dec 23 00:14:29 2013 +0100
     1.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/CLIOptions.java	Mon Dec 23 11:50:24 2013 +0100
     1.3 @@ -20,7 +20,6 @@
     1.4  import static info.globalcode.sql.dk.Functions.isNotEmpty;
     1.5  import static info.globalcode.sql.dk.Functions.isEmpty;
     1.6  import static info.globalcode.sql.dk.Functions.equalz;
     1.7 -import info.globalcode.sql.dk.SQLCommand.COMMAND_TYPE;
     1.8  import java.io.OutputStream;
     1.9  import java.util.ArrayList;
    1.10  import java.util.Collection;
    1.11 @@ -59,7 +58,6 @@
    1.12  		DATABASES,
    1.13  		CONNECTION
    1.14  	}
    1.15 -	private COMMAND_TYPE commandType;
    1.16  	private final List<NamedParameter> namedParameters = new ArrayList<>();
    1.17  	private final List<Parameter> numberedParameters = new ArrayList<>();
    1.18  	private final EnumSet<INFO_TYPE> showInfo = EnumSet.noneOf(INFO_TYPE.class);
    1.19 @@ -153,14 +151,6 @@
    1.20  		this.batch = batch;
    1.21  	}
    1.22  
    1.23 -	public COMMAND_TYPE getCommandType() {
    1.24 -		return commandType;
    1.25 -	}
    1.26 -
    1.27 -	public void setCommandType(COMMAND_TYPE commandType) {
    1.28 -		this.commandType = commandType;
    1.29 -	}
    1.30 -
    1.31  	public Collection<NamedParameter> getNamedParameters() {
    1.32  		return namedParameters;
    1.33  	}
    1.34 @@ -211,9 +201,9 @@
    1.35  
    1.36  	public SQLCommand getSQLCommand() {
    1.37  		if (namedParameters.isEmpty()) {
    1.38 -			return new SQLCommandNumbered(commandType, sql, numberedParameters);
    1.39 +			return new SQLCommandNumbered(sql, numberedParameters);
    1.40  		} else {
    1.41 -			return new SQLCommandNamed(commandType, sql, namedParameters);
    1.42 +			return new SQLCommandNamed(sql, namedParameters);
    1.43  		}
    1.44  	}
    1.45  
     2.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/CLIParser.java	Mon Dec 23 00:14:29 2013 +0100
     2.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/CLIParser.java	Mon Dec 23 11:50:24 2013 +0100
     2.3 @@ -17,7 +17,6 @@
     2.4   */
     2.5  package info.globalcode.sql.dk;
     2.6  
     2.7 -import info.globalcode.sql.dk.SQLCommand.COMMAND_TYPE;
     2.8  import java.sql.Types;
     2.9  import java.util.ArrayList;
    2.10  import java.util.Collections;
    2.11 @@ -76,12 +75,6 @@
    2.12  					break;
    2.13  				case Tokens.SQL:
    2.14  					options.setSql(fetchNext(args, ++i));
    2.15 -					options.setCommandType(COMMAND_TYPE.QUERY);
    2.16 -					break;
    2.17 -				case Tokens.SQL_UPDATE:
    2.18 -				case Tokens.SQL_INSERT:
    2.19 -					options.setSql(fetchNext(args, ++i));
    2.20 -					options.setCommandType(COMMAND_TYPE.UPDATE);
    2.21  					break;
    2.22  				case Tokens.BATCH:
    2.23  					options.setBatch(true);
    2.24 @@ -158,8 +151,6 @@
    2.25  
    2.26  		public static final String DB = "--db";
    2.27  		public static final String SQL = "--sql";
    2.28 -		public static final String SQL_UPDATE = "--sql-update";
    2.29 -		public static final String SQL_INSERT = "--sql-insert";
    2.30  		public static final String BATCH = "--batch";
    2.31  		public static final String DATA = "--data";
    2.32  		public static final String NAME_PREFIX = "--name-prefix";
     3.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/ColorfulPrintWriter.java	Mon Dec 23 00:14:29 2013 +0100
     3.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/ColorfulPrintWriter.java	Mon Dec 23 11:50:24 2013 +0100
     3.3 @@ -166,6 +166,26 @@
     3.4  		println();
     3.5  	}
     3.6  
     3.7 +	public void print(EnumSet<TerminalStyle> styles, String string) {
     3.8 +		setStyle(styles);
     3.9 +		print(string);
    3.10 +		resetAll();
    3.11 +	}
    3.12 +
    3.13 +	public void println(EnumSet<TerminalStyle> styles, String string) {
    3.14 +		print(styles, string);
    3.15 +		println();
    3.16 +	}
    3.17 +
    3.18 +	public void print(TerminalStyle style, String string) {
    3.19 +		print(EnumSet.of(style), string);
    3.20 +	}
    3.21 +
    3.22 +	public void println(TerminalStyle style, String string) {
    3.23 +		print(style, string);
    3.24 +		println();
    3.25 +	}
    3.26 +
    3.27  	public void resetAll() {
    3.28  		printCodes(0);
    3.29  	}
     4.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/DatabaseConnection.java	Mon Dec 23 00:14:29 2013 +0100
     4.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/DatabaseConnection.java	Mon Dec 23 11:50:24 2013 +0100
     4.3 @@ -57,68 +57,58 @@
     4.4  	}
     4.5  
     4.6  	private void processCommand(SQLCommand sqlCommand, Formatter formatter) throws SQLException {
     4.7 -		SQLCommand.COMMAND_TYPE commandType = sqlCommand.getCommandType();
     4.8 -		switch (commandType) {
     4.9 -			case QUERY:
    4.10 -				processQueryCommand(sqlCommand, formatter);
    4.11 -				break;
    4.12 -			case UPDATE:
    4.13 -				processUpdateCommand(sqlCommand, formatter);
    4.14 -				break;
    4.15 -			default:
    4.16 -				throw new IllegalArgumentException("Unexpected command type: " + commandType);
    4.17 -		}
    4.18 -	}
    4.19 -
    4.20 -	private void processQueryCommand(SQLCommand sqlCommand, Formatter formatter) throws SQLException {
    4.21 -		formatter.writeStartResultSet();
    4.22 -		formatter.writeQuery(sqlCommand.getQuery());
    4.23 -		formatter.writeParameters(sqlCommand.getParameters());
    4.24  		try (PreparedStatement ps = sqlCommand.prepareStatement(connection)) {
    4.25  			sqlCommand.parametrize(ps);
    4.26  
    4.27  			boolean isRS = ps.execute();
    4.28  			if (isRS) {
    4.29  				try (ResultSet rs = ps.getResultSet()) {
    4.30 -					processResultSet(rs, formatter);
    4.31 +					processResultSet(sqlCommand, rs, formatter);
    4.32  				}
    4.33  			} else {
    4.34 -				/**
    4.35 -				 * TODO: process UPDATE command
    4.36 -				 */
    4.37 +				processUpdateResult(sqlCommand, ps, formatter);
    4.38  			}
    4.39  
    4.40  			while (ps.getMoreResults() || ps.getUpdateCount() > -1) {
    4.41 -				/**
    4.42 -				 * TODO: process more RS or UPDATEs
    4.43 -				 */
    4.44 +				ResultSet rs = ps.getResultSet();
    4.45 +				if (rs == null) {
    4.46 +					processUpdateResult(sqlCommand, ps, formatter);
    4.47 +				} else {
    4.48 +					processResultSet(sqlCommand, rs, formatter);
    4.49 +					rs.close();
    4.50 +				}
    4.51  			}
    4.52  		}
    4.53 +	}
    4.54 +
    4.55 +	private void processUpdateResult(SQLCommand sqlCommand, PreparedStatement ps, Formatter formatter) throws SQLException {
    4.56 +		formatter.writeStartUpdatesResult();
    4.57 +		formatter.writeQuery(sqlCommand.getQuery());
    4.58 +		formatter.writeParameters(sqlCommand.getParameters());
    4.59 +
    4.60 +		int updatedRowsCount = ps.getUpdateCount();
    4.61 +		formatter.writeUpdatedRowsCount(updatedRowsCount);
    4.62 +
    4.63 +		formatter.writeStartGeneratedKeys();
    4.64 +		try (ResultSet rs = ps.getGeneratedKeys()) {
    4.65 +			processResultSetRows(rs, formatter);
    4.66 +		}
    4.67 +		formatter.writeEndGeneratedKeys();
    4.68 +
    4.69 +		formatter.writeEndUpdatesResult();
    4.70 +	}
    4.71 +
    4.72 +	private void processResultSet(SQLCommand sqlCommand, ResultSet rs, Formatter formatter) throws SQLException {
    4.73 +		formatter.writeStartResultSet();
    4.74 +		formatter.writeQuery(sqlCommand.getQuery());
    4.75 +		formatter.writeParameters(sqlCommand.getParameters());
    4.76 +
    4.77 +		processResultSetRows(rs, formatter);
    4.78  
    4.79  		formatter.writeEndResultSet();
    4.80  	}
    4.81  
    4.82 -	private void processUpdateCommand(SQLCommand sqlCommand, Formatter formatter) throws SQLException {
    4.83 -		formatter.writeStartUpdatesResult();
    4.84 -		formatter.writeQuery(sqlCommand.getQuery());
    4.85 -		formatter.writeParameters(sqlCommand.getParameters());
    4.86 -		try (PreparedStatement ps = sqlCommand.prepareStatement(connection)) {
    4.87 -			sqlCommand.parametrize(ps);
    4.88 -			int updatedRowsCount = ps.executeUpdate();
    4.89 -			formatter.writeUpdatedRowsCount(updatedRowsCount);
    4.90 -
    4.91 -			formatter.writeStartGeneratedKeys();
    4.92 -			try (ResultSet rs = ps.getGeneratedKeys()) {
    4.93 -				processResultSet(rs, formatter);
    4.94 -			}
    4.95 -			formatter.writeEndGeneratedKeys();
    4.96 -
    4.97 -		}
    4.98 -
    4.99 -		formatter.writeEndUpdatesResult();
   4.100 -	}
   4.101 -
   4.102 -	private void processResultSet(ResultSet rs, Formatter formatter) throws SQLException {
   4.103 +	private void processResultSetRows(ResultSet rs, Formatter formatter) throws SQLException {
   4.104  		formatter.writeColumnsHeader(new ColumnsHeader(rs.getMetaData()));
   4.105  		int columnCount = rs.getMetaData().getColumnCount();
   4.106  
     5.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/SQLCommand.java	Mon Dec 23 00:14:29 2013 +0100
     5.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/SQLCommand.java	Mon Dec 23 11:50:24 2013 +0100
     5.3 @@ -28,11 +28,9 @@
     5.4   */
     5.5  public abstract class SQLCommand {
     5.6  
     5.7 -	private COMMAND_TYPE commandType;
     5.8  	private String query;
     5.9  
    5.10 -	public SQLCommand(COMMAND_TYPE commandType, String query) {
    5.11 -		this.commandType = commandType;
    5.12 +	public SQLCommand(String query) {
    5.13  		this.query = query;
    5.14  	}
    5.15  
    5.16 @@ -44,23 +42,7 @@
    5.17  
    5.18  	public abstract List<? extends Parameter> getParameters();
    5.19  
    5.20 -	public COMMAND_TYPE getCommandType() {
    5.21 -		return commandType;
    5.22 -	}
    5.23 -
    5.24 -	public void setCommandType(COMMAND_TYPE commandType) {
    5.25 -		this.commandType = commandType;
    5.26 -	}
    5.27 -
    5.28  	public String getQuery() {
    5.29  		return query;
    5.30  	}
    5.31 -
    5.32 -	public enum COMMAND_TYPE {
    5.33 -
    5.34 -		/** SELECT */
    5.35 -		QUERY,
    5.36 -		/** INSERT, UPDATE, DELETE */
    5.37 -		UPDATE
    5.38 -	};
    5.39  }
     6.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/SQLCommandNamed.java	Mon Dec 23 00:14:29 2013 +0100
     6.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/SQLCommandNamed.java	Mon Dec 23 11:50:24 2013 +0100
     6.3 @@ -17,7 +17,6 @@
     6.4   */
     6.5  package info.globalcode.sql.dk;
     6.6  
     6.7 -import java.sql.Connection;
     6.8  import java.sql.PreparedStatement;
     6.9  import java.sql.SQLException;
    6.10  import java.util.List;
    6.11 @@ -30,8 +29,8 @@
    6.12  
    6.13  	private List<NamedParameter> parameters;
    6.14  
    6.15 -	public SQLCommandNamed(COMMAND_TYPE commandType, String query, List<NamedParameter> parameters) {
    6.16 -		super(commandType, query);
    6.17 +	public SQLCommandNamed(String query, List<NamedParameter> parameters) {
    6.18 +		super(query);
    6.19  		this.parameters = parameters;
    6.20  	}
    6.21  
     7.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/SQLCommandNumbered.java	Mon Dec 23 00:14:29 2013 +0100
     7.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/SQLCommandNumbered.java	Mon Dec 23 11:50:24 2013 +0100
     7.3 @@ -18,7 +18,6 @@
     7.4  package info.globalcode.sql.dk;
     7.5  
     7.6  import static info.globalcode.sql.dk.Functions.notNull;
     7.7 -import java.sql.Connection;
     7.8  import java.sql.PreparedStatement;
     7.9  import java.sql.SQLException;
    7.10  import java.util.List;
    7.11 @@ -31,8 +30,8 @@
    7.12  
    7.13  	private List<Parameter> parameters;
    7.14  
    7.15 -	public SQLCommandNumbered(COMMAND_TYPE commandType, String query, List<Parameter> parameters) {
    7.16 -		super(commandType, query);
    7.17 +	public SQLCommandNumbered(String query, List<Parameter> parameters) {
    7.18 +		super(query);
    7.19  		this.parameters = parameters;
    7.20  	}
    7.21  
     8.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/formatting/AbstractFormatter.java	Mon Dec 23 00:14:29 2013 +0100
     8.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/formatting/AbstractFormatter.java	Mon Dec 23 11:50:24 2013 +0100
     8.3 @@ -170,7 +170,7 @@
     8.4  
     8.5  	@Override
     8.6  	public void writeColumnsHeader(ColumnsHeader header) {
     8.7 -		peekState(EnumSet.of(State.RESULT_SET, State.UPDATES_RESULT));
     8.8 +		peekState(EnumSet.of(State.RESULT_SET, State.GENERATED_KEYS));
     8.9  
    8.10  		if (currentColumnsHeader == null) {
    8.11  			currentColumnsHeader = header;
    8.12 @@ -204,7 +204,7 @@
    8.13  
    8.14  	@Override
    8.15  	public void writeStartUpdatesResult() {
    8.16 -		pushState(State.RESULT_SET, EnumSet.of(State.DATABASE));
    8.17 +		pushState(State.UPDATES_RESULT, EnumSet.of(State.DATABASE));
    8.18  	}
    8.19  
    8.20  	@Override
     9.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/formatting/ColumnDescriptor.java	Mon Dec 23 00:14:29 2013 +0100
     9.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/formatting/ColumnDescriptor.java	Mon Dec 23 11:50:24 2013 +0100
     9.3 @@ -27,7 +27,13 @@
     9.4  	private String label;
     9.5  	private int type;
     9.6  	private String typeName;
     9.7 +	private boolean firstColumn;
     9.8 +	private boolean lastColumn;
     9.9  
    9.10 +	/**
    9.11 +	 * @return column name
    9.12 +	 * @see #getLabel()
    9.13 +	 */
    9.14  	public String getName() {
    9.15  		return name;
    9.16  	}
    9.17 @@ -36,6 +42,9 @@
    9.18  		this.name = name;
    9.19  	}
    9.20  
    9.21 +	/**
    9.22 +	 * @return label specified by the SQL AS clause
    9.23 +	 */
    9.24  	public String getLabel() {
    9.25  		return label;
    9.26  	}
    9.27 @@ -59,4 +68,20 @@
    9.28  	public void setTypeName(String typeName) {
    9.29  		this.typeName = typeName;
    9.30  	}
    9.31 +
    9.32 +	public boolean isFirstColumn() {
    9.33 +		return firstColumn;
    9.34 +	}
    9.35 +
    9.36 +	public void setFirstColumn(boolean firstColumn) {
    9.37 +		this.firstColumn = firstColumn;
    9.38 +	}
    9.39 +
    9.40 +	public boolean isLastColumn() {
    9.41 +		return lastColumn;
    9.42 +	}
    9.43 +
    9.44 +	public void setLastColumn(boolean lastColumn) {
    9.45 +		this.lastColumn = lastColumn;
    9.46 +	}
    9.47  }
    10.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/formatting/ColumnsHeader.java	Mon Dec 23 00:14:29 2013 +0100
    10.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/formatting/ColumnsHeader.java	Mon Dec 23 11:50:24 2013 +0100
    10.3 @@ -28,7 +28,7 @@
    10.4   */
    10.5  public class ColumnsHeader {
    10.6  
    10.7 -	ResultSetMetaData metaData;
    10.8 +	private ResultSetMetaData metaData;
    10.9  
   10.10  	public ColumnsHeader(ResultSetMetaData metaData) {
   10.11  		this.metaData = metaData;
   10.12 @@ -49,6 +49,8 @@
   10.13  
   10.14  			for (int i = 1; i <= count; i++) {
   10.15  				ColumnDescriptor cd = new ColumnDescriptor();
   10.16 +				cd.setFirstColumn(i == 1);
   10.17 +				cd.setLastColumn(i == count);
   10.18  				cd.setLabel(metaData.getColumnLabel(i));
   10.19  				cd.setName(metaData.getColumnName(i));
   10.20  				cd.setType(metaData.getColumnType(i));
    11.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/formatting/TabularFormatter.java	Mon Dec 23 00:14:29 2013 +0100
    11.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/formatting/TabularFormatter.java	Mon Dec 23 11:50:24 2013 +0100
    11.3 @@ -18,6 +18,7 @@
    11.4  package info.globalcode.sql.dk.formatting;
    11.5  
    11.6  import info.globalcode.sql.dk.ColorfulPrintWriter;
    11.7 +import static info.globalcode.sql.dk.ColorfulPrintWriter.*;
    11.8  
    11.9  /**
   11.10   *
   11.11 @@ -27,6 +28,7 @@
   11.12  
   11.13  	public static final String NAME = "tabular";
   11.14  	private ColorfulPrintWriter out;
   11.15 +	private boolean firstResult = true;
   11.16  
   11.17  	public TabularFormatter(FormatterContext formatterContext) {
   11.18  		super(formatterContext);
   11.19 @@ -34,14 +36,37 @@
   11.20  	}
   11.21  
   11.22  	@Override
   11.23 +	public void writeStartResultSet() {
   11.24 +		super.writeStartResultSet();
   11.25 +		printResultSeparator();
   11.26 +	}
   11.27 +
   11.28 +	@Override
   11.29 +	public void writeColumnsHeader(ColumnsHeader header) {
   11.30 +		super.writeColumnsHeader(header);
   11.31 +
   11.32 +		for (ColumnDescriptor cd : header.getColumnDescriptors()) {
   11.33 +			out.print(TerminalStyle.Bright, cd.getLabel());
   11.34 +			out.print(" (");
   11.35 +			out.print(cd.getTypeName());
   11.36 +			out.print(")");
   11.37 +			if (!cd.isLastColumn()) {
   11.38 +				out.print(TerminalColor.Green, " | ");
   11.39 +			}
   11.40 +		}
   11.41 +		out.println();
   11.42 +		out.flush();
   11.43 +	}
   11.44 +
   11.45 +	@Override
   11.46  	public void writeColumnValue(Object value) {
   11.47  		super.writeColumnValue(value);
   11.48  
   11.49  		if (!isCurrentColumnFirst()) {
   11.50 -			out.print(ColorfulPrintWriter.TerminalColor.Green, " | ");
   11.51 +			out.print(TerminalColor.Green, " | ");
   11.52  		}
   11.53 -		
   11.54 -		out.print(ColorfulPrintWriter.TerminalColor.Cyan, String.valueOf(value));
   11.55 +
   11.56 +		out.print(TerminalColor.Cyan, String.valueOf(value));
   11.57  	}
   11.58  
   11.59  	@Override
   11.60 @@ -50,4 +75,40 @@
   11.61  		out.println();
   11.62  		out.flush();
   11.63  	}
   11.64 +
   11.65 +	@Override
   11.66 +	public void writeEndResultSet() {
   11.67 +		super.writeEndResultSet();
   11.68 +		out.print(TerminalColor.Yellow, "Record count: ");
   11.69 +		out.println(getCurrentRowCount());
   11.70 +		out.flush();
   11.71 +	}
   11.72 +
   11.73 +	@Override
   11.74 +	public void writeStartUpdatesResult() {
   11.75 +		super.writeStartUpdatesResult();
   11.76 +		printResultSeparator();
   11.77 +	}
   11.78 +
   11.79 +	@Override
   11.80 +	public void writeUpdatedRowsCount(int updatedRowsCount) {
   11.81 +		super.writeUpdatedRowsCount(updatedRowsCount);
   11.82 +		out.print(TerminalColor.Red, "Updated records: ");
   11.83 +		out.println(updatedRowsCount);
   11.84 +		out.flush();
   11.85 +	}
   11.86 +
   11.87 +	@Override
   11.88 +	public void writeEndDatabase() {
   11.89 +		super.writeEndDatabase();
   11.90 +		out.flush();
   11.91 +	}
   11.92 +
   11.93 +	private void printResultSeparator() {
   11.94 +		if (firstResult) {
   11.95 +			firstResult = false;
   11.96 +		} else {
   11.97 +			out.println();
   11.98 +		}
   11.99 +	}
  11.100  }