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)
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 }