Add "Describe" command, with support for describing both (a) specific table(s) and...
authorChris Jaekl <cejaekl@yahoo.com>
Wed, 22 Jun 2016 12:38:50 +0000 (21:38 +0900)
committerChris Jaekl <cejaekl@yahoo.com>
Wed, 22 Jun 2016 12:38:50 +0000 (21:38 +0900)
16 files changed:
src/main/java/net/jaekl/squelch/Squelch.java
src/main/java/net/jaekl/squelch/db/DbDriver.java
src/main/java/net/jaekl/squelch/db/PostgresqlDriver.java
src/main/java/net/jaekl/squelch/sql/Row.java
src/main/java/net/jaekl/squelch/stmt/Describe.java [new file with mode: 0644]
src/main/java/net/jaekl/squelch/stmt/Select.java
src/main/java/net/jaekl/squelch/stmt/Stmt.java
src/main/java/net/jaekl/squelch/stmt/Tabular.java
src/main/java/net/jaekl/squelch/stmt/TabularColumnInfo.java [new file with mode: 0644]
src/test/java/net/jaekl/squelch/SquelchTest.java
src/test/java/net/jaekl/squelch/db/DbDriverMock.java [new file with mode: 0644]
src/test/java/net/jaekl/squelch/sql/ConnectionMock.java
src/test/java/net/jaekl/squelch/sql/DatabaseMetaDataMock.java
src/test/java/net/jaekl/squelch/sql/ResultSetMock.java
src/test/java/net/jaekl/squelch/stmt/DescribeTest.java [new file with mode: 0644]
src/test/java/net/jaekl/squelch/stmt/TabularTest.java

index 88515e0bd6502b11ed87f9429bdc573991478ebf..848ede7db05c9a5d88c783f66bd250a7c4211e55 100644 (file)
@@ -11,6 +11,7 @@ import net.jaekl.squelch.db.MsSqlDriver;
 import net.jaekl.squelch.db.MySqlDriver;
 import net.jaekl.squelch.db.OracleDriver;
 import net.jaekl.squelch.db.PostgresqlDriver;
+import net.jaekl.squelch.stmt.Describe;
 import net.jaekl.squelch.stmt.Select;
 import net.jaekl.squelch.stmt.Stmt;
 import net.jaekl.squelch.util.ConsoleInput;
@@ -26,6 +27,7 @@ public class Squelch {
                new PostgresqlDriver()
        };
        private static final Stmt[] READ_ONLY_STATEMENTS = {
+               new Describe(),
                new Select()
        };
        
@@ -76,11 +78,9 @@ public class Squelch {
                return false;
        }
        
-       Connection getConnection() throws ClassNotFoundException, SQLException, SquelchException 
+       Connection getConnection(DbDriver driver, String jdbcUrl) 
+               throws ClassNotFoundException, SQLException, SquelchException 
        {
-               String jdbcUrl = m_args.getUrl();
-               DbDriver driver = getDriverFor(jdbcUrl);
-
                return driver.connect(jdbcUrl, m_args.getUser(), m_args.getPass());
        }
        
@@ -97,7 +97,10 @@ public class Squelch {
        void pumpLines(PrintWriter pw, ConsoleInput ci) throws IOException, ClassNotFoundException, SQLException, SquelchException 
        {
                String line = null;
-               try (Connection conn = getConnection())
+               String jdbcUrl = m_args.getUrl();
+               DbDriver driver = getDriverFor(jdbcUrl);
+
+               try (Connection conn = getConnection(driver, jdbcUrl))
                {
                        while (true) {
                                boolean processed = false;
@@ -105,7 +108,12 @@ public class Squelch {
                                
                                for (Stmt statement : m_statements) {
                                        if (statement.handles(line)) {
-                                               statement.exec(conn, pw, line);
+                                               try {
+                                                       statement.exec(driver, conn, pw, line);
+                                               }
+                                               catch (SQLException exc) {
+                                                       exc.printStackTrace(pw);
+                                               }
                                                processed = true;
                                                break;
                                        }
@@ -118,8 +126,8 @@ public class Squelch {
                                        // Unrecognized command
                                        // TODO:  add a string table, and a natural-language error message.
                                        pw.println("??? \"" + line + "\"");
-                                       pw.flush();
                                }
+                               pw.flush();
                        }
                }
        }       
index 5e73885033e4d06ae2b17c13ec27c7d7597f57f3..931fcf19908bf872306bb2bd384dbd40bc3b48c4 100644 (file)
@@ -3,6 +3,7 @@ package net.jaekl.squelch.db;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.SQLException;
+import java.util.Locale;
 
 public abstract class DbDriver {
        // Returns true iff. this DbDriver knows how to connect to the given JDBC URL
@@ -17,4 +18,14 @@ public abstract class DbDriver {
                Class.forName(getJdbcDriverClassName());
                return DriverManager.getConnection(jdbcUrl, userName, password);
        }
+       
+       // If this database uses case-insensitive collation, then return an upper-cased version of the passed string.
+       // Otherwise (if this database is case-sensitive), return the string unchanged.
+       // Note that the default implementation assumes a case-insensitive DB.
+       public String adjustCase(String input) {
+               if (null == input) {
+                       return "";      // Convert nulls to empty strings, so that we can safely use .equals() on the result
+               }
+               return input.toUpperCase(Locale.CANADA);
+       }
 }
index 9020064c90117d03c3c850260b814d2f81681a97..97fd12cf2976b2f95873e611799e86468b5aa671 100644 (file)
@@ -14,4 +14,9 @@ public class PostgresqlDriver extends DbDriver {
        public String getJdbcDriverClassName() {
                return "org.postgresql.Driver";
        }
+
+       @Override
+       public String adjustCase(String input) {
+               return (null == input) ? "" : input;
+       }
 }
index fd47301307e908e3122922ac367eab538155c4e8..88e87e2baaa3c773300797f7bcf7d0c97e263056 100644 (file)
@@ -7,6 +7,10 @@ public class Row {
                m_args = new Object[numCols];
        }
        
+       public Row(Object[] values) {
+               m_args = values.clone();
+       }
+       
        // 1-based index, like JDBC
        public void setValue(int idx, Object value) {
                m_args[idx - 1] = value;
diff --git a/src/main/java/net/jaekl/squelch/stmt/Describe.java b/src/main/java/net/jaekl/squelch/stmt/Describe.java
new file mode 100644 (file)
index 0000000..a76e5f0
--- /dev/null
@@ -0,0 +1,129 @@
+package net.jaekl.squelch.stmt;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Locale;
+
+import net.jaekl.squelch.db.DbDriver;
+
+public class Describe extends Stmt {
+
+       @Override
+       public boolean handles(String line) 
+       {
+               if (null == line) {
+                       return false;
+               }
+               
+               String trimmed = line.trim();
+               if (trimmed.equals("\\d")) {
+                       return true;
+               }
+               if (trimmed.startsWith("\\d ")) {
+                       return true;
+               }
+               
+               String upper = trimmed.toUpperCase(Locale.CANADA);
+               if (upper.equals("DESCRIBE")) {
+                       return true;
+               }
+               if (upper.startsWith("DESCRIBE ")) {
+                       return true;
+               }
+               
+               return false;
+       }
+
+       @Override
+       public int exec(DbDriver driver, Connection conn, PrintWriter pw, String line)
+                       throws IOException, SQLException 
+       {
+               DatabaseMetaData metaData = conn.getMetaData();
+               
+               String trimmed = line.trim();
+               String tablePattern;
+               if (trimmed.startsWith("\\d")) {
+                       tablePattern = trimmed.substring(2).trim();
+               }
+               else {
+                       assert (trimmed.toUpperCase(Locale.CANADA).startsWith("DESCRIBE"));
+                       tablePattern = trimmed.substring(8).trim();
+               }
+               tablePattern = driver.adjustCase(tablePattern);
+               
+               if (tablePattern.length() < 1) {
+                       return describeAll(pw, metaData);
+               }
+               else {
+                       return describeTable(pw, metaData, tablePattern);
+               }
+       }
+
+       int describeAll(PrintWriter pw, DatabaseMetaData metaData)
+               throws SQLException
+       {
+               try (ResultSet rs = metaData.getTables(null, null, "%", null))
+               {
+                       TabularResultSet tabular = new TabularResultSet(rs);
+                       // TODO:  StringTable i18n
+                       tabular.printTable(pw, "???");
+               }
+               
+               return 0;
+       }
+
+       int describeTable(PrintWriter pw, DatabaseMetaData metaData, String tablePattern) 
+               throws SQLException
+       {
+               boolean found = false;
+               String trimmed = tablePattern.trim();
+               
+               try (ResultSet rs = metaData.getTables(null, null, trimmed, null))
+               {
+                       while (rs.next()) {
+                               found = true;
+                               describe(pw, metaData, rs);
+                       }
+               }
+               
+               if (!found) {
+                       // TODO:  StringTable i18n
+                       pw.println("??? " + trimmed);
+               }
+               return 0;
+       }
+       
+       void describe(PrintWriter pw, DatabaseMetaData metaData, ResultSet tableRs)
+               throws SQLException
+       {
+               String catalogueName = tableRs.getString(1);
+               String schemaName = tableRs.getString(2);
+               String tableName = tableRs.getString(3);
+               String tableType = tableRs.getString(4);
+               String remarks = tableRs.getString(5);
+               
+               pw.print("" + tableType + " ");
+               if (null != catalogueName) {
+                       pw.print(catalogueName + ".");
+               }
+               if (null != schemaName) {
+                       pw.print(schemaName + ".");
+               }
+               pw.print("" + tableName);
+               if ((null != remarks) && (remarks.length() > 0)) {
+                       pw.print(" (" + remarks + ")");
+               }
+               pw.println("");
+               
+               try (ResultSet colsRs = metaData.getColumns(catalogueName, schemaName, tableName, null))
+               {
+                       TabularColumnInfo tabular = new TabularColumnInfo(colsRs);
+                       // TODO:  StringTable i18n
+                       tabular.printTable(pw, "???");
+               }
+       }
+}
index f34b8c9392014b4e210972f3f1dae4b5be10befe..c5f785e5a3d6acd651bc30b3822f362a255f5f30 100644 (file)
@@ -8,6 +8,8 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.Locale;
 
+import net.jaekl.squelch.db.DbDriver;
+
 public class Select extends Query {
 
        @Override
@@ -21,11 +23,17 @@ public class Select extends Query {
        }
 
        @Override
-       public int exec(Connection conn, PrintWriter pw, String line) throws IOException, SQLException 
+       public int exec(DbDriver driver, Connection conn, PrintWriter pw, String line) throws IOException, SQLException 
        {
                int rowCount = 0;
                
-               try (PreparedStatement ps = conn.prepareStatement(line)) 
+               // If there's a ';' on the end of this line, remove it.
+               String trimmed = line.trim();
+               if (trimmed.endsWith(";")) {
+                       trimmed = trimmed.substring(0, trimmed.length() - 1);
+               }
+               
+               try (PreparedStatement ps = conn.prepareStatement(trimmed)) 
                {
                        try (ResultSet rs = ps.executeQuery()) 
                        {
@@ -38,7 +46,8 @@ public class Select extends Query {
        private int printFormatted(PrintWriter pw, ResultSet rs) throws IOException, SQLException
        {
                TabularResultSet trs = new TabularResultSet(rs);
-               int rowCount = trs.printTable(pw);
+               // TODO:  StringTable i18n
+               int rowCount = trs.printTable(pw, "No rows returned.");
                pw.flush();
                
                return rowCount;
index fc090d4e96f458ef114673744f15129c207d27b2..893cfddfbea63b4687cc558bcbcd99c505a46277 100644 (file)
@@ -5,6 +5,8 @@ import java.io.PrintWriter;
 import java.sql.Connection;
 import java.sql.SQLException;
 
+import net.jaekl.squelch.db.DbDriver;
+
 /**
  * Abstract base class for all statements (e.g., Insert, Create, Delete, Describe)
  */
@@ -14,5 +16,5 @@ public abstract class Stmt {
        abstract public boolean handles(String line);
        
        // Execute line as a statement of this type
-       abstract public int exec(Connection conn, PrintWriter pw, String line) throws IOException, SQLException;
+       abstract public int exec(DbDriver driver, Connection conn, PrintWriter pw, String line) throws IOException, SQLException;
 }
index af3d5da360933f8c37e48c216187236fd047bdde..130f4a563eefaef9977c7e56ccc12ea597368557 100644 (file)
@@ -41,7 +41,9 @@ abstract public class Tabular {
        abstract Row getNext() throws SQLException;
        
        // Returns the number of (data) rows that were output
-       public int printTable(PrintWriter pw) throws SQLException {
+       public int printTable(PrintWriter pw, String noRowsMessage) 
+               throws SQLException 
+       {
                int rowCount = 0;
                Column[] cols = getCols();
                RowBuffer rowBuf;
@@ -68,10 +70,13 @@ abstract public class Tabular {
                
                if (rowCount > 0) {
                        writeDivider(pw, colWidths);
+                       // TODO:  Implement a String table for i18n
+                       pw.println("" + rowCount + " row(s) returned.");
+               }
+               else {
+                       pw.println(noRowsMessage);
                }
                
-               // TODO:  Implement a String table for i18n
-               pw.println("" + rowCount + " row(s) returned.");
                pw.flush();
                
                return rowCount;
@@ -206,7 +211,7 @@ abstract public class Tabular {
                }
                return Object.class;
        }
-
+       
        String repChar(char chr, int times)
        {
                StringBuffer sb = new StringBuffer();
diff --git a/src/main/java/net/jaekl/squelch/stmt/TabularColumnInfo.java b/src/main/java/net/jaekl/squelch/stmt/TabularColumnInfo.java
new file mode 100644 (file)
index 0000000..ff9fc62
--- /dev/null
@@ -0,0 +1,78 @@
+package net.jaekl.squelch.stmt;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import net.jaekl.squelch.sql.Column;
+import net.jaekl.squelch.sql.Row;
+
+public class TabularColumnInfo extends Tabular {
+       private static final Column[] COLUMNS = {
+               new Column("Column", String.class, 32),
+               new Column("Type", String.class, 16),
+               new Column("Modifiers", String.class, 16)
+       };
+       private ResultSet m_rs;
+       
+       public TabularColumnInfo(ResultSet rs) {
+               m_rs = rs;
+       }
+       
+       @Override
+       Column[] getCols() throws SQLException {
+               return COLUMNS;
+       }
+
+       @Override
+       Row getNext() throws SQLException {
+               if (!m_rs.next()) {
+                       return null;
+               }
+               
+               Row row = new Row(COLUMNS.length);
+               
+               String columnName = m_rs.getString(4);
+               
+               String typeName = m_rs.getString(6);
+               int columnSize = m_rs.getInt(7);
+               if (columnSize > 0) {
+                       int decimalDigits = m_rs.getInt(8);     // digits after the decimal point
+                       if (decimalDigits > 0) {
+                               typeName += "(" + columnSize + "." + decimalDigits + ")";
+                       }
+                       else {
+                               typeName += "(" + columnSize + ")";
+                       }
+               }
+               
+               String remarks = m_rs.getString(12);
+               String isNullable = m_rs.getString(18);
+               String isAutoIncrement = m_rs.getString(23);
+               String notes = "";
+               if ("YES".equals(isNullable)) {
+                       notes += "NULL";
+               }
+               else if ("NO".equals(isNullable)) {
+                       notes += "NOT NULL";
+               }
+               if ("YES".equals(isAutoIncrement)) {
+                       if (notes.length() > 0) {
+                               notes += " ";
+                       }
+                       notes += "AUTOINCREMENT";
+               }
+               if ((null != remarks) && (remarks.length() > 0)) {
+                       if (notes.length() > 0) {
+                               notes += " ";
+                       }
+                       notes += "(" + remarks + ")";
+               }
+               
+               row.setValue(1, columnName);
+               row.setValue(2, typeName);
+               row.setValue(3, notes);
+               
+               return row;
+       }
+
+}
index be533d875a56bbf73a8f21f601c131f4423f2ff3..44b7de96c854819adc16cd49521ef6faa53c39b4 100644 (file)
@@ -32,7 +32,8 @@ public class SquelchTest {
                }
                
                @Override
-               Connection getConnection() throws ClassNotFoundException, SQLException, SquelchException 
+               Connection getConnection(DbDriver driver, String jdbcUrl) 
+                       throws ClassNotFoundException, SQLException, SquelchException 
                {
                        return m_conn;
                }
@@ -140,11 +141,11 @@ public class SquelchTest {
                String[] simpleSelect = { "SELECT * FROM Fred WHERE wife='Wilma';", "QUIT" };
                consoleOutput = runPump(squelch, simpleSelect);
                assertEquals(  Squelch.PROMPT + simpleSelect[0] + "\n"
-                                        + "0 row(s) returned.\n"
+                                        + "No rows returned.\n"
                                     + Squelch.PROMPT + simpleSelect[1] + "\n", consoleOutput);
                
                ConnectionMock cm = squelch.mock_getConnectionMock();
-               assertTrue(cm.mock_queryWasExecuted(simpleSelect[0]));
+               assertTrue(cm.mock_queryWasExecuted(simpleSelect[0].substring(0, simpleSelect[0].length() - 1)));
        }
        
        private String runPump(Squelch squelch, String[] lines) throws IOException, ClassNotFoundException, SQLException, SquelchException
diff --git a/src/test/java/net/jaekl/squelch/db/DbDriverMock.java b/src/test/java/net/jaekl/squelch/db/DbDriverMock.java
new file mode 100644 (file)
index 0000000..1434d8a
--- /dev/null
@@ -0,0 +1,22 @@
+package net.jaekl.squelch.db;
+
+public class DbDriverMock extends DbDriver {
+
+       @Override
+       public boolean handles(String jdbcUrl) {
+               return true;
+       }
+
+       @Override
+       String getJdbcDriverClassName() {
+               return getClass().getCanonicalName();
+       }
+
+       @Override
+       public String adjustCase(String input) {
+               if (null == input) {
+                       return "";      // Convert nulls to empty strings, so that we can safely use .equals() on the result
+               }
+               return input;
+       }
+}
index 22b686fb89666b95b7d0ecbf23eb8cd9f0ce8317..40e6229d9eb0509bdb3a38ed7d3b0a81e30157a0 100644 (file)
@@ -22,22 +22,29 @@ import java.util.concurrent.Executor;
 
 
 public class ConnectionMock implements Connection {
-       private ArrayList<String> m_executedQueries;
+       private ArrayList<String> mock_executedQueries;
+       private DatabaseMetaDataMock mock_databaseMetaData;
        
        public ConnectionMock() {
-               m_executedQueries = new ArrayList<String>();
+               mock_executedQueries = new ArrayList<String>();
+               mock_databaseMetaData = new DatabaseMetaDataMock();
        }
        
        public ResultSetMock mock_executeQuery(PreparedStatementMock psm)
        {
-               m_executedQueries.add(psm.toString());
+               mock_executedQueries.add(psm.toString());
                return new ResultSetMock();
        }
        
        public boolean mock_queryWasExecuted(String sql) {
                // There's an assumption here that we don't try a large number of queries in a single test.
                // If that assumption is false, then we should change this to be more efficient.
-               return m_executedQueries.contains(sql);
+               return mock_executedQueries.contains(sql);
+       }
+       
+       public void mock_setDatabaseMetaData(DatabaseMetaDataMock dbmdm)
+       {
+               mock_databaseMetaData = dbmdm;
        }
 
        @Override
@@ -167,8 +174,7 @@ public class ConnectionMock implements Connection {
 
        @Override
        public DatabaseMetaData getMetaData() throws SQLException {
-               DatabaseMetaData result = new DatabaseMetaDataMock();
-               return result;
+               return mock_databaseMetaData;
        }
 
        @Override
index b8ecded2ee23c57b97b38580db3b18f515021241..7b12a804200643039b0a0e6331377a0847c54fe6 100644 (file)
@@ -5,1098 +5,1139 @@ import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
 import java.sql.RowIdLifetime;
 import java.sql.SQLException;
+import java.util.HashMap;
 
 
 public class DatabaseMetaDataMock implements DatabaseMetaData {
+       private HashMap<String, ResultSetMock> mock_colMap;
+       private HashMap<String, ResultSetMock> mock_tableMap;
+       
+       public DatabaseMetaDataMock() {
+               mock_colMap = new HashMap<String, ResultSetMock>();
+               mock_tableMap = new HashMap<String, ResultSetMock>();
+       }
+
+       private String mock_colRSKey(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) {
+               return "" + catalog + ":" + schemaPattern + ":" + tableNamePattern + ":" + columnNamePattern;
+       }
+       
+       public void mock_setColRS(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern, ResultSetMock value) {
+               String key = mock_colRSKey(catalog, schemaPattern, tableNamePattern, columnNamePattern);
+               mock_colMap.put(key, value);
+       }
+       
+       public void mock_setTableRS(String catalog, String schemaPattern, String tableNamePattern, String[] types, ResultSetMock value) {
+               String key = mock_tableKey(catalog, schemaPattern, tableNamePattern, types);
+               mock_tableMap.put(key, value);
+       }
 
+       private String mock_tableKey(String catalog, String schemaPattern, String tableNamePattern, String[] types) {
+               StringBuilder sb = new StringBuilder();
+               sb.append("" + catalog + ":" + schemaPattern + ":" + tableNamePattern);
+               if (null != types) {
+                       for (String s : types) {
+                               sb.append(":" + s);
+                       }
+               }
+               return sb.toString();
+       }
+       
        @Override
        public boolean isWrapperFor(Class<?> iface) throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public <T> T unwrap(Class<T> iface) throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean allProceduresAreCallable() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean allTablesAreSelectable() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean autoCommitFailureClosesAllResultSets() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean dataDefinitionCausesTransactionCommit() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean deletesAreDetected(int type) throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean generatedKeyAlwaysReturned() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getAttributes(String catalog, String schemaPattern,
                        String typeNamePattern, String attributeNamePattern)
                        throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getBestRowIdentifier(String catalog, String schema,
                        String table, int scope, boolean nullable) throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getCatalogSeparator() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getCatalogTerm() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getCatalogs() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getClientInfoProperties() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getColumnPrivileges(String catalog, String schema,
                        String table, String columnNamePattern) throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
-       public ResultSet getColumns(String catalog, String schemaPattern,
-                       String tableNamePattern, String columnNamePattern)
-                       throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+       public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
+               throws SQLException 
+       {
+               String key = mock_colRSKey(catalog, schemaPattern, tableNamePattern, columnNamePattern);
+               ResultSetMock rsm = mock_colMap.get(key);
+               if (null == rsm) {
+                       rsm = new ResultSetMock();
+               }
+               return rsm;
        }
 
        @Override
        public Connection getConnection() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getCrossReference(String parentCatalog,
                        String parentSchema, String parentTable, String foreignCatalog,
                        String foreignSchema, String foreignTable) throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getDatabaseMajorVersion() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getDatabaseMinorVersion() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getDatabaseProductName() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getDatabaseProductVersion() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getDefaultTransactionIsolation() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getDriverMajorVersion() {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getDriverMinorVersion() {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getDriverName() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getDriverVersion() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getExportedKeys(String catalog, String schema, String table)
                        throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getExtraNameCharacters() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getFunctionColumns(String catalog, String schemaPattern,
                        String functionNamePattern, String columnNamePattern)
                        throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getFunctions(String catalog, String schemaPattern,
                        String functionNamePattern) throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getIdentifierQuoteString() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getImportedKeys(String catalog, String schema, String table)
                        throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getIndexInfo(String catalog, String schema, String table,
                        boolean unique, boolean approximate) throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getJDBCMajorVersion() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getJDBCMinorVersion() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxBinaryLiteralLength() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxCatalogNameLength() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxCharLiteralLength() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxColumnNameLength() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxColumnsInGroupBy() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxColumnsInIndex() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxColumnsInOrderBy() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxColumnsInSelect() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxColumnsInTable() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxConnections() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxCursorNameLength() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxIndexLength() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxProcedureNameLength() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxRowSize() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxSchemaNameLength() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxStatementLength() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxStatements() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxTableNameLength() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxTablesInSelect() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getMaxUserNameLength() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getNumericFunctions() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getPrimaryKeys(String catalog, String schema, String table)
                        throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getProcedureColumns(String catalog, String schemaPattern,
                        String procedureNamePattern, String columnNamePattern)
                        throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getProcedureTerm() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getProcedures(String catalog, String schemaPattern,
                        String procedureNamePattern) throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getPseudoColumns(String catalog, String schemaPattern,
                        String tableNamePattern, String columnNamePattern)
                        throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getResultSetHoldability() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public RowIdLifetime getRowIdLifetime() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getSQLKeywords() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public int getSQLStateType() throws SQLException {
-               // TODO Auto-generated method stub
-               return 0;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getSchemaTerm() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getSchemas() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getSchemas(String catalog, String schemaPattern)
                        throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getSearchStringEscape() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getStringFunctions() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getSuperTables(String catalog, String schemaPattern,
                        String tableNamePattern) throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getSuperTypes(String catalog, String schemaPattern,
                        String typeNamePattern) throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getSystemFunctions() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getTablePrivileges(String catalog, String schemaPattern,
                        String tableNamePattern) throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getTableTypes() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) 
                throws SQLException 
        {
-               ResultSetMock result = new ResultSetMock();
+               String key = mock_tableKey(catalog, schemaPattern, tableNamePattern, types);
+               ResultSetMock result = mock_tableMap.get(key);
+               if (null == result) {
+                       result = new ResultSetMock();
+               }
                return result;
        }
 
        @Override
        public String getTimeDateFunctions() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getTypeInfo() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getUDTs(String catalog, String schemaPattern,
                        String typeNamePattern, int[] types) throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getURL() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public String getUserName() throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public ResultSet getVersionColumns(String catalog, String schema,
                        String table) throws SQLException {
-               // TODO Auto-generated method stub
-               return null;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean insertsAreDetected(int type) throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean isCatalogAtStart() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean isReadOnly() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean locatorsUpdateCopy() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean nullPlusNonNullIsNull() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean nullsAreSortedAtEnd() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean nullsAreSortedAtStart() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean nullsAreSortedHigh() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean nullsAreSortedLow() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean othersDeletesAreVisible(int type) throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean othersInsertsAreVisible(int type) throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean othersUpdatesAreVisible(int type) throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean ownDeletesAreVisible(int type) throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean ownInsertsAreVisible(int type) throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean ownUpdatesAreVisible(int type) throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean storesLowerCaseIdentifiers() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean storesMixedCaseIdentifiers() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean storesUpperCaseIdentifiers() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsANSI92EntryLevelSQL() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsANSI92FullSQL() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsANSI92IntermediateSQL() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsAlterTableWithAddColumn() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsAlterTableWithDropColumn() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsBatchUpdates() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsCatalogsInDataManipulation() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsCatalogsInIndexDefinitions() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsCatalogsInProcedureCalls() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsCatalogsInTableDefinitions() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsColumnAliasing() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsConvert() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsConvert(int fromType, int toType)
                        throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsCoreSQLGrammar() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsCorrelatedSubqueries() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsDataDefinitionAndDataManipulationTransactions()
                        throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsDataManipulationTransactionsOnly()
                        throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsDifferentTableCorrelationNames() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsExpressionsInOrderBy() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsExtendedSQLGrammar() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsFullOuterJoins() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsGetGeneratedKeys() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsGroupBy() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsGroupByBeyondSelect() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsGroupByUnrelated() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsIntegrityEnhancementFacility() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsLikeEscapeClause() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsLimitedOuterJoins() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsMinimumSQLGrammar() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsMixedCaseIdentifiers() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsMultipleOpenResults() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsMultipleResultSets() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsMultipleTransactions() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsNamedParameters() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsNonNullableColumns() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsOpenCursorsAcrossRollback() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsOpenStatementsAcrossRollback() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsOrderByUnrelated() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsOuterJoins() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsPositionedDelete() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsPositionedUpdate() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsResultSetConcurrency(int type, int concurrency)
                        throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsResultSetHoldability(int holdability)
                        throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsResultSetType(int type) throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsSavepoints() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsSchemasInDataManipulation() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsSchemasInIndexDefinitions() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsSchemasInProcedureCalls() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsSchemasInTableDefinitions() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsSelectForUpdate() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsStatementPooling() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsStoredProcedures() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsSubqueriesInComparisons() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsSubqueriesInExists() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsSubqueriesInIns() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsSubqueriesInQuantifieds() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsTableCorrelationNames() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsTransactionIsolationLevel(int level)
                        throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsTransactions() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsUnion() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean supportsUnionAll() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean updatesAreDetected(int type) throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean usesLocalFilePerTable() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
        @Override
        public boolean usesLocalFiles() throws SQLException {
-               // TODO Auto-generated method stub
-               return false;
+               throw new UnsupportedOperationException("Not yet implemented");
+               
        }
 
 }
index b398e24c05ca80af41c3f2dc70688526fd9bd4ac..a2f8a99f4b6c842ea5601d90458acc98317148bf 100644 (file)
@@ -25,18 +25,24 @@ import java.util.Map;
 
 
 public class ResultSetMock implements ResultSet {
-       private ResultSetMetaDataMock m_metaDataMock;
-       private ArrayList<Row> m_rows;
-       private int m_rowNum;
+       private ResultSetMetaDataMock mock_metaDataMock;
+       private ArrayList<Row> mock_rows;
+       private int mock_rowIdx;
        
        public ResultSetMock() {
-               m_metaDataMock = new ResultSetMetaDataMock();
-               m_rows = new ArrayList<Row>();
-               m_rowNum = -1;
+               mock_metaDataMock = new ResultSetMetaDataMock();
+               mock_rows = new ArrayList<Row>();
+               mock_rowIdx = -1;
        }
        
        public void mock_addRow(Row row) {
-               m_rows.add(row);
+               mock_rows.add(row);
+       }
+       
+       public void mock_addRows(Row[] rows) {
+               for (Row row : rows) {
+                       mock_addRow(row);
+               }
        }
 
        @Override
@@ -317,9 +323,17 @@ public class ResultSetMock implements ResultSet {
        }
 
        @Override
-       public int getInt(int arg0) throws SQLException {
-               throw new UnsupportedOperationException("Not yet implemented.");
-               
+       public int getInt(int idx) throws SQLException {
+               Row row = mock_rows.get(mock_rowIdx);
+               Object obj = row.getValue(idx);
+               if (null == obj) {
+                       return 0;
+               }
+               if (obj instanceof Number) {
+                       Number num = (Number)obj;
+                       return num.intValue();
+               }
+               throw new SQLException("Invalid type");
        }
 
        @Override
@@ -330,7 +344,7 @@ public class ResultSetMock implements ResultSet {
 
        @Override
        public long getLong(int idx) throws SQLException {
-               Row row = m_rows.get(m_rowNum);
+               Row row = mock_rows.get(mock_rowIdx);
                return (Long)(row.getValue(idx));
        }
 
@@ -342,7 +356,7 @@ public class ResultSetMock implements ResultSet {
 
        @Override
        public ResultSetMetaData getMetaData() throws SQLException {
-               return m_metaDataMock;
+               return mock_metaDataMock;
        }
 
        @Override
@@ -383,7 +397,7 @@ public class ResultSetMock implements ResultSet {
 
        @Override
        public Object getObject(int idx) throws SQLException {
-               Row row = m_rows.get(m_rowNum);
+               Row row = mock_rows.get(mock_rowIdx);
                return row.getValue(idx);
        }
 
@@ -481,7 +495,7 @@ public class ResultSetMock implements ResultSet {
 
        @Override
        public String getString(int idx) throws SQLException {
-               Row row = m_rows.get(m_rowNum);
+               Row row = mock_rows.get(mock_rowIdx);
                return (String)(row.getValue(idx));
        }
 
@@ -493,7 +507,7 @@ public class ResultSetMock implements ResultSet {
 
        @Override
        public Time getTime(int idx) throws SQLException {
-               Row row = m_rows.get(m_rowNum);
+               Row row = mock_rows.get(mock_rowIdx);
                return new Time(((java.util.Date)row.getValue(idx)).getTime());
        }
 
@@ -634,7 +648,12 @@ public class ResultSetMock implements ResultSet {
 
        @Override
        public boolean next() throws SQLException {
-               return false;
+               if (null == mock_rows) {
+                       return false;
+               }
+               
+               mock_rowIdx++;
+               return (mock_rowIdx < mock_rows.size());
        }
 
        @Override
diff --git a/src/test/java/net/jaekl/squelch/stmt/DescribeTest.java b/src/test/java/net/jaekl/squelch/stmt/DescribeTest.java
new file mode 100644 (file)
index 0000000..f211105
--- /dev/null
@@ -0,0 +1,270 @@
+package net.jaekl.squelch.stmt;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+
+import net.jaekl.squelch.db.DbDriverMock;
+import net.jaekl.squelch.sql.ConnectionMock;
+import net.jaekl.squelch.sql.DatabaseMetaDataMock;
+import net.jaekl.squelch.sql.ResultSetMock;
+import net.jaekl.squelch.sql.Row;
+
+import org.junit.Test;
+
+public class DescribeTest {
+
+       @Test
+       public void testHandles() {
+               final String[] AFFIRMATIVE = {
+                               "\\d", "\\d ", " \\d", " \\d ", 
+                               "describe", "describe ", " describe", " describe ",
+                               "DESCRIBE", "DESCRIBE ", " DESCRIBE", " DESCRIBE ",
+                               "descRIbe", "DEscribE ", " DEScribe", " DEscRIbE ",
+                               "\\d tablename", "\\d tablename ", " \\d tablename", " \\d tableName ",
+                               "describe tablename", "DESCRIBE tablename ", " DesCrIbE tablename", " DESCribE fred "
+               };
+               final String[] NEGATIVE = {
+                               "\\d\\q", "", null, "    ", "select * from foo", "  select * from foo ",
+                               "DESCRIBEQ", "describeFOO", " describeJackAndDianne "
+               };
+
+               Describe describe = new Describe();
+               for (String s : AFFIRMATIVE) {
+                       assertTrue("handles " + s, describe.handles(s));
+               }
+               for (String s : NEGATIVE) {
+                       assertFalse("does not handle " + s, describe.handles(s));
+               }
+       }
+
+       @Test
+       public void testDescribeAll_noTables() throws IOException, SQLException 
+       {
+               DatabaseMetaDataMock dbmdm = new DatabaseMetaDataMock();
+               Describe describe = new Describe();
+               
+               try (
+                               ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                               PrintWriter pw = new PrintWriter(new OutputStreamWriter(baos, StandardCharsets.UTF_8));
+                       )
+               {
+                       describe.describeAll(pw, dbmdm);
+                       pw.close();
+                       baos.close();
+                       String actual = baos.toString();
+                       final String EXPECTED = "???\n";
+                       assertEquals(EXPECTED, actual);
+               }
+       }
+
+       @Test
+       public void testDescribeTable_noColumns()
+               throws IOException, SQLException
+       {
+               DatabaseMetaDataMock dbmdm = new DatabaseMetaDataMock();
+               Describe describe = new Describe();
+               
+               try (
+                               ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                               PrintWriter pw = new PrintWriter(new OutputStreamWriter(baos, StandardCharsets.UTF_8));
+                       )
+               {
+                       describe.describeTable(pw, dbmdm, "%");
+                       pw.close();
+                       baos.close();
+                       String actual = baos.toString();
+                       final String EXPECTED = "??? %\n";
+                       assertEquals(EXPECTED, actual);
+               }
+       }
+       
+       private DatabaseMetaDataMock construct_runs_dbmdm()
+       {
+               ResultSetMock rsmCols = new ResultSetMock();
+               ResultSetMock rsmTables = new ResultSetMock();
+
+               DatabaseMetaDataMock dbmdm = new DatabaseMetaDataMock();
+               Row[] rows = {
+                               new Row(new Object[]{
+                                               null,           // 1) table_cat
+                                               "public",       // 2) table schema
+                                               "runs",         // 3) table name
+                                               "runid",        // 4) column name
+                                               Integer.valueOf(4),             // 5) data type
+                                               "int4",         // 6) type name
+                                               Integer.valueOf(10),    // 7) column size
+                                               null,           // 8) buffer length
+                                               null,           // 9) decimal digits
+                                               Integer.valueOf(10),    // 10) num_prec_radix
+                                               Integer.valueOf(DatabaseMetaData.columnNoNulls),        // 11) nullable
+                                               null,           // 12) remarks
+                                               null,           // 13) default value for the column
+                                               Integer.valueOf(0),     // 14) sql_data_type
+                                               Integer.valueOf(0),     // 15) sql_datetime_sub
+                                               null,           // 16) char_octet_length
+                                               Integer.valueOf(1),     // 17) ordinal_position
+                                               "NO",           // 18) is_nullable
+                                               null,           // 19) scope_catalog
+                                               null,           // 20) scope_schema
+                                               null,           // 21) scope_table
+                                               null,           // 22) source_data_type
+                                               "NO",           // 23) is_autoincrement
+                                               "NO"            // 24) is_generated_column
+                               }),
+                               new Row(new Object[]{
+                                               null,           // 1) table_cat
+                                               "public",       // 2) table schema
+                                               "runs",         // 3) table name
+                                               "projname",     // 4) column name
+                                               Integer.valueOf(12),    // 5) data type
+                                               "varchar",      // 6) type name
+                                               Integer.valueOf(80),    // 7) column size
+                                               null,           // 8) buffer length
+                                               null,           // 9) decimal digits
+                                               Integer.valueOf(10),    // 10) num_prec_radix
+                                               Integer.valueOf(DatabaseMetaData.columnNoNulls),        // 11) nullable
+                                               null,           // 12) remarks
+                                               null,           // 13) default value for the column
+                                               Integer.valueOf(0),     // 14) sql_data_type
+                                               Integer.valueOf(0),     // 15) sql_datetime_sub
+                                               null,           // 16) char_octet_length
+                                               Integer.valueOf(2),     // 17) ordinal_position
+                                               "NO",           // 18) is_nullable
+                                               null,           // 19) scope_catalog
+                                               null,           // 20) scope_schema
+                                               null,           // 21) scope_table
+                                               null,           // 22) source_data_type
+                                               "NO",           // 23) is_autoincrement
+                                               "NO"            // 24) is_generated_column
+                               }),
+                               new Row(new Object[]{
+                                               null,           // 1) table_cat
+                                               "public",       // 2) table schema
+                                               "runs",         // 3) table name
+                                               "version",      // 4) column name
+                                               Integer.valueOf(12),    // 5) data type
+                                               "varchar",      // 6) type name
+                                               Integer.valueOf(10),    // 7) column size
+                                               null,           // 8) buffer length
+                                               null,           // 9) decimal digits
+                                               Integer.valueOf(10),    // 10) num_prec_radix
+                                               Integer.valueOf(DatabaseMetaData.columnNullable),       // 11) nullable
+                                               null,           // 12) remarks
+                                               null,           // 13) default value for the column
+                                               Integer.valueOf(0),     // 14) sql_data_type
+                                               Integer.valueOf(0),     // 15) sql_datetime_sub
+                                               null,           // 16) char_octet_length
+                                               Integer.valueOf(1),     // 17) ordinal_position
+                                               "YES",          // 18) is_nullable
+                                               null,           // 19) scope_catalog
+                                               null,           // 20) scope_schema
+                                               null,           // 21) scope_table
+                                               null,           // 22) source_data_type
+                                               "NO",           // 23) is_autoincrement
+                                               "NO"            // 24) is_generated_column
+                               })
+               };
+               rsmCols.mock_addRows(rows);
+               
+               rows = new Row[] {
+                       new Row(new Object[]{
+                               null,    // TABLE_CAT String => table catalog (may be null)
+                               null,    // TABLE_SCHEM String => table schema (may be null)
+                               "runs",  // TABLE_NAME String => table name
+                               "TABLE", // TABLE_TYPE String => table type. Typical types are "TABLE", "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
+                               "",     // REMARKS String => explanatory comment on the table
+                               null,   // TYPE_CAT String => the types catalog (may be null)
+                               null,   // TYPE_SCHEM String => the types schema (may be null)
+                               null,   // TYPE_NAME String => type name (may be null)
+                               null,   // SELF_REFERENCING_COL_NAME String => name of the designated "identifier" column of a typed table (may be null)
+                               null    // REF_GENERATION String => specifies how values in SELF_REFERENCING_COL_NAME are created. Values are "SYSTEM", "USER", "DERIVED". (may be null) 
+                       })      
+               };
+               rsmTables.mock_addRows(rows);
+               
+               dbmdm.mock_setColRS(null, null, "runs", null, rsmCols);
+               dbmdm.mock_setTableRS(null, null, "runs", null, rsmTables);
+               
+               return dbmdm;
+       }
+       
+       private String construct_runs_expected() {
+               return   "TABLE runs\n"
+                  + "+--------+-----------+---------+\n"
+                  + "| Column |   Type    |Modifiers|\n"
+                  + "+--------+-----------+---------+\n"
+                  + "|runid   |int4(10)   |NOT NULL |\n"
+                  + "|projname|varchar(80)|NOT NULL |\n"
+                  + "|version |varchar(10)|NULL     |\n"
+                  + "+--------+-----------+---------+\n"
+                  + "3 row(s) returned.\n";
+       }
+
+       @Test
+       public void testDescribeTable_threeColumns()
+               throws IOException, SQLException
+       {
+               DatabaseMetaDataMock dbmdm = construct_runs_dbmdm();
+               Describe describe = new Describe();
+               
+               try (
+                               ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                               PrintWriter pw = new PrintWriter(new OutputStreamWriter(baos, StandardCharsets.UTF_8));
+                       )
+               {
+                       describe.describeTable(pw, dbmdm, "runs");
+                       pw.close();
+                       baos.close();
+                       String actual = baos.toString();
+                       String expected = construct_runs_expected();
+                       
+                       assertEquals(expected, actual);
+               }
+       }
+       
+       @Test
+       public void testExec() throws IOException, SQLException
+       {
+               final String[] SUCCESSFUL = { 
+                               "\\d runs", " \\d runs", "\\d runs ", " \\d runs ",
+                               "DESCRIBE runs", " DescRIBe runs", "describe runs ", " describe runs "
+               };
+               String expected = construct_runs_expected();
+               for (String stmt : SUCCESSFUL) {
+                       String actual = doExec(stmt);
+                       assertEquals("doExec():  " + stmt, expected, actual);
+               }
+       }
+       
+       public String doExec(String stmt) throws IOException, SQLException
+       {
+               DatabaseMetaDataMock dbmdm = construct_runs_dbmdm();
+               DbDriverMock driver = new DbDriverMock();
+               ConnectionMock cm = new ConnectionMock();
+               cm.mock_setDatabaseMetaData(dbmdm);
+               
+               Describe describe = new Describe();
+
+               try (
+                               ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                               PrintWriter pw = new PrintWriter(new OutputStreamWriter(baos, StandardCharsets.UTF_8));
+                       )
+               {
+                       describe.exec(driver, cm, pw, stmt);
+                       pw.close();
+                       baos.close();
+                       String actual = baos.toString();
+                       
+                       return actual;
+               }
+       }
+}
index f6749f29293218d6c93464f438ea371fdb2c9ebd..f0e05bffd1f0e8500e96fc767f350dd257e84997 100644 (file)
@@ -106,7 +106,7 @@ public class TabularTest {
                                PrintWriter pw = new PrintWriter(new OutputStreamWriter(baos, StandardCharsets.UTF_8));
                        )
                {
-                       tabular.printTable(pw);
+                       tabular.printTable(pw, "No rows returned.");
                        pw.close();
                        baos.close();
                        String actual = baos.toString();