Changeset: 56ca5fe0526b for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=56ca5fe0526b
Modified Files:
        java/ChangeLog.Dec2011
        java/src/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java
Branch: Dec2011
Log Message:

PreparedStatement: use PREPARERESULT to obtain info about result columns

Implemented extra ResultSetMetaData for PreparedStatement with use of
the extra data emitted by PREPARERESULT.

Drawback of this commit is that it makes the server segfault for two
tests at least, compared to using plain PREPARE.
Backwards-compatability is prepared for once we rename PREPARERESULT to
PREPARE.


diffs (truncated from 495 to 300 lines):

diff --git a/java/ChangeLog.Dec2011 b/java/ChangeLog.Dec2011
--- a/java/ChangeLog.Dec2011
+++ b/java/ChangeLog.Dec2011
@@ -1,6 +1,9 @@
 # ChangeLog file for java
 # This file is updated with Maddlog
 
+* Mon Jan  2 2012 Fabian Groffen <[email protected]>
+- Implemented getMetaData() method of PreparedStatement.
+
 * Tue Dec 27 2011 Fabian Groffen <[email protected]>
 - Fixed an AssertionError for special results from e.g. EXPLAIN queries.
 
diff --git a/java/src/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java 
b/java/src/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java
--- a/java/src/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java
+++ b/java/src/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java
@@ -58,8 +58,12 @@ public class MonetPreparedStatement
        private final int[] javaType;
        private final int[] digits;
        private final int[] scale;
+       private final String[] schema;
+       private final String[] table;
+       private final String[] column;
        private final int id;
        private final int size;
+       private final int rscolcnt;
 
        private final String[] values;
        private final StringBuffer buf;
@@ -111,18 +115,22 @@ public class MonetPreparedStatement
                        resultSetHoldability
                );
 
-               if (!super.execute("PREPARE " + prepareQuery))
+               if (!super.execute("PREPARERESULT " + prepareQuery))
                        throw new SQLException("Unexpected server response", 
"M0M10");
 
                // cheat a bit to get the ID and the number of columns
                id = ((MonetConnection.ResultSetResponse)header).id;
                size = ((MonetConnection.ResultSetResponse)header).tuplecount;
+               rscolcnt = 
((MonetConnection.ResultSetResponse)header).columncount;
 
                // initialise blank finals
                monetdbType = new String[size];
                javaType = new int[size];
                digits = new int[size];
                scale = new int[size];
+               schema = new String[size];
+               table = new String[size];
+               column = new String[size];
                values = new String[size];
                buf = new StringBuffer(6 + 12 * size);
 
@@ -135,6 +143,11 @@ public class MonetPreparedStatement
                        javaType[i] = MonetDriver.getJavaType(monetdbType[i]);
                        digits[i] = rs.getInt("digits");
                        scale[i] = rs.getInt("scale");
+                       if (rscolcnt == 3)
+                               continue;
+                       schema[i] = rs.getString("schema");
+                       table[i] = rs.getString("table");
+                       column[i] = rs.getString("column");
                }
                rs.close();
 
@@ -169,10 +182,14 @@ public class MonetPreparedStatement
                javaType = null;
                digits = null;
                scale = null;
+               schema = null;
+               table = null;
+               column = null;
                values = null;
                buf = null;
                id = -1;
                size = -1;
+               rscolcnt = -1;
 
                this.connection = connection;
        }
@@ -279,6 +296,24 @@ public class MonetPreparedStatement
        }
 
        /**
+        * Returns the index in the backing arrays for the given
+        * resultset column number
+        */
+       private int getColumnIdx(int colnr) throws SQLException {
+               int curcol = 0;
+               for (int i = 0; i < size; i++) {
+                       if (!column[i].equals(""))
+                               continue;
+                       curcol++;
+                       if (curcol == colnr)
+                               return(i);
+               }
+               throw new SQLException("No such column with index: " + colnr, 
"M1M05");
+       }
+
+       /* helper for the anonymous class inside getMetaData */
+       private abstract class rsmdw extends MonetWrapper implements 
ResultSetMetaData {}
+       /**
         * Retrieves a ResultSetMetaData object that contains information
         * about the columns of the ResultSet object that will be returned
         * when this PreparedStatement object is executed.
@@ -289,16 +324,354 @@ public class MonetPreparedStatement
         * method getMetaData on a PreparedStatement object rather than
         * waiting to execute it and then invoking the ResultSet.getMetaData
         * method on the ResultSet object that is returned.
-        * <br /><br />
-        * NOTE: Using this method is expensive for this driver due to the
-        * lack of underlying DBMS support.  Currently not implemented
         *
         * @return the description of a ResultSet object's columns or null if 
the
         *         driver cannot return a ResultSetMetaData object
         * @throws SQLException if a database access error occurs
         */
-       public ResultSetMetaData getMetaData() throws SQLException {
-               return(null);
+       public ResultSetMetaData getMetaData() {
+               if (rscolcnt == 3)
+                       return(null); // not sufficient data with pre-Dec2011 
PREPARE
+
+               // return inner class which implements the ResultSetMetaData 
interface
+               return(new rsmdw() {
+                       // for the more expensive methods, we provide a simple 
cache
+                       // for the most expensive part; getting the ResultSet 
which
+                       // contains the data
+                       private DatabaseMetaData dbmd = null;
+                       private Map colrs = new HashMap();
+
+                       /**
+                        * Returns the number of columns in this ResultSet 
object.
+                        *
+                        * @returns the number of columns
+                        */
+                       public int getColumnCount() {
+                               int cnt = 0;
+
+                               for (int i = 0; i < size; i++) {
+                                       if (!column[i].equals(""))
+                                               cnt++;
+                               }
+                               
+                               return(cnt);
+                       }
+
+                       /**
+                        * Indicates whether the designated column is 
automatically
+                        * numbered, thus read-only.
+                        * 
+                        * @param column the first column is 1, the second is 
2, ...
+                        * @return true if so; false otherwise
+                        * @throws SQLException if a database access error 
occurs
+                        */
+                       public boolean isAutoIncrement(int column) throws 
SQLException {
+                               // the only column I know of is a 'secret' 
column called rowid
+                               // with datatype oid
+                               // avoid nullpointer exception here
+                               if 
("oid".equals(monetdbType[getColumnIdx(column)])) {
+                                       return(true);
+                               } else {
+                                       return(false);
+                               }
+                       }
+
+                       /**
+                        * Indicates whether a column's case matters. This 
holds for all
+                        * columns in MonetDB resultsets since the mapping is 
done case
+                        * insensitive, therefore this method will always 
return false.
+                        *
+                        * @param column the first column is 1, the second is 
2, ...
+                        * @returns false
+                        */
+                       public boolean isCaseSensitive(int column) {
+                               return(false);
+                       }
+
+                       /**
+                        * Indicates whether the designated column can be used 
in a
+                        * where clause.
+                        * It is unknown to me what kind ot columns they regard 
to,
+                        * as I think all columns are useable in a where clause.
+                        * Returning true for all here, for the time being.
+                        * Possible thought; maybe they want to know here if 
it's a
+                        * real column existing in a table or not...
+                        *
+                        * @param column the first column is 1, the second is 
2, ...
+                        * @returns true
+                        */
+                       public boolean isSearchable(int column) {
+                               return(true);
+                       }
+
+                       /**
+                        * Indicates whether the designated column is a cash 
value.
+                        * From the MonetDB database perspective it is by 
definition
+                        * unknown whether the value is a currency, because 
there are
+                        * no currency datatypes such as MONEY.  With this 
knowledge
+                        * we can always return false here.
+                        *
+                        * @param column the first column is 1, the second is 
2, ...
+                        * @returns false
+                        */
+                       public boolean isCurrency(int column) {
+                               return(false);
+                       }
+                       
+                       /**
+                        * Indicates whether values in the designated column 
are signed
+                        * numbers.
+                        * Within MonetDB all numeric types are signed.
+                        *
+                        * @param column the first column is 1, the second is 
2, ...
+                        * @return true if so; false otherwise
+                        */
+                       public boolean isSigned(int column) throws SQLException 
{
+                               // we can hardcode this, based on the colum type
+                               switch (javaType[getColumnIdx(column)]) {
+                                       case Types.NUMERIC:
+                                       case Types.DECIMAL:
+                                       case Types.TINYINT:
+                                       case Types.SMALLINT:
+                                       case Types.INTEGER:
+                                       case Types.BIGINT:
+                                       case Types.REAL:
+                                       case Types.FLOAT:
+                                       case Types.DOUBLE:
+                                               return(true);
+                                       case Types.BIT: // we don't use type 
BIT, it's here for completeness
+                                       case Types.BOOLEAN:
+                                       case Types.DATE:
+                                       case Types.TIME:
+                                       case Types.TIMESTAMP:
+                                       default:
+                                               return(false);
+                               }
+                       }
+
+                       /**
+                        * Indicates the designated column's normal maximum 
width in
+                        * characters.
+                        *
+                        * @param column the first column is 1, the second is 
2, ...
+                        * @return the normal maximum number of characters 
allowed as the
+                        *         width of the designated column
+                        * @throws SQLException if there is no such column
+                        */
+                       public int getColumnDisplaySize(int column) throws 
SQLException {
+                               return(digits[getColumnIdx(column)]);
+                       }
+
+                       /**
+                        * Get the designated column's table's schema.
+                        *
+                        * @param column the first column is 1, the second is 
2, ...
+                        * @return schema name or "" if not applicable
+                        * @throws SQLException if a database access error 
occurs
+                        */
+                       public String getSchemaName(int column) throws 
SQLException {
+                               return(schema[getColumnIdx(column)]);
+                       }
+
+                       /**
+                        * Gets the designated column's table name.
+                        *
+                        * @param column the first column is 1, the second is 
2, ...
+                        * @return table name or "" if not applicable
+                        */
+                       public String getTableName(int col) throws SQLException 
{
+                               return(column[getColumnIdx(col)]);
+                       }
+
+                       /**
+                        * Get the designated column's number of decimal digits.
+                        * This method is currently very expensive as it needs 
to
+                        * retrieve the information from the database using an 
SQL
+                        * query.
+                        *
+                        * @param column the first column is 1, the second is 
2, ...
+                        * @return precision
+                        * @throws SQLException if a database access error 
occurs
+                        */
+                       public int getPrecision(int column) throws SQLException 
{
+                               return(digits[getColumnIdx(column)]);
+                       }
+
+                       /**
+                        * Gets the designated column's number of digits to 
right of
+                        * the decimal point.  This method is currently very
+                        * expensive as it needs to retrieve the information 
from
+                        * the database using an SQL query.
+                        *
+                        * @param column the first column is 1, the second is 
2, ...
+                        * @return scale
+                        * @throws SQLException if a database access error 
occurs
+                        */
+                       public int getScale(int column) throws SQLException {
+                               return(scale[getColumnIdx(column)]);
+                       }
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to