Changeset: 2f42195e9c58 for monetdb-java
URL: https://dev.monetdb.org/hg/monetdb-java/rev/2f42195e9c58
Added Files:
        src/main/java/org/monetdb/jdbc/MonetParameterMetaData.java
Modified Files:
        src/main/java/org/monetdb/jdbc/MonetPreparedStatement.java
        tests/JDBC_API_Tester.java
Branch: default
Log Message:

Improved implementation of PreparedStatement.getParameterMetaData().
The previous implementation created a new ParameterMetaData object each time 
this method is called which is quite costly if it is called from inside a loop.
As the ParameterMetaData is static for a PreparedStatement it is better to 
create it once,
cache it in the PreparedStatement object and return the cached object for next 
calls to PreparedStatement.getParameterMetaData().
We also now create dedicated 1-based meta data arrays, such that we no longer 
have to call getParamIdx(param) in methods of ParameterMetaData.


diffs (truncated from 780 to 300 lines):

diff --git a/src/main/java/org/monetdb/jdbc/MonetParameterMetaData.java 
b/src/main/java/org/monetdb/jdbc/MonetParameterMetaData.java
new file mode 100644
--- /dev/null
+++ b/src/main/java/org/monetdb/jdbc/MonetParameterMetaData.java
@@ -0,0 +1,376 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0.  If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 1997 - July 2008 CWI, August 2008 - 2023 MonetDB B.V.
+ */
+
+package org.monetdb.jdbc;
+
+import java.sql.ParameterMetaData;
+import java.sql.SQLDataException;
+import java.sql.SQLException;
+import java.sql.Types;
+
+/**
+ *<pre>
+ * A {@link ParameterMetaData} suitable for the MonetDB database.
+ *
+ * An object that can be used to get information about the types and properties
+ * for each parameter marker in a PreparedStatement or CallableStatement 
object.
+ *</pre>
+ *
+ * @author Martin van Dinther
+ * @version 1.0
+ */
+final class MonetParameterMetaData
+       extends MonetWrapper
+       implements ParameterMetaData
+{
+       /** The parental Connection object */
+       private final MonetConnection conn;
+
+       /** The number of parameters, it can be zero !! */
+       private final int paramCount;
+
+       /** The MonetDB type names of the parameters in the PreparedStatement */
+       private final String[] monetdbTypes;
+       /** The JDBC SQL type codes of the parameters in the PreparedStatement 
*/
+       private final int[] JdbcSQLTypes;
+       /** The precisions of the parameters in the PreparedStatement */
+       private final int[] precisions;
+       /** The scales of the parameters in the PreparedStatement */
+       private final int[] scales;
+
+       /**
+        * Constructor backed by the given connection and metadata arrays.
+        * It is used by MonetPreparedStatement.
+        *
+        * @param connection the parent connection
+        * @param paramCount the number of parameters, it can be zero !!
+        * @param types the MonetDB type names
+        * @param jdbcTypes the JDBC SQL type codes
+        * @param precisions the precision for each parameter
+        * @param scales the scale for each parameter
+        * @throws IllegalArgumentException if called with null for one of the 
arguments
+        */
+       MonetParameterMetaData(
+               final MonetConnection connection,
+               final int paramcount,
+               final String[] types,
+               final int[] jdbcTypes,
+               final int[] precisions,
+               final int[] scales)
+               throws IllegalArgumentException
+       {
+               if (connection == null) {
+                       throw new IllegalArgumentException("Connection may not 
be null!");
+               }
+               if (types == null) {
+                       throw new IllegalArgumentException("MonetDB Types may 
not be null!");
+               }
+               if (jdbcTypes == null) {
+                       throw new IllegalArgumentException("JDBC Types may not 
be null!");
+               }
+               if (precisions == null) {
+                       throw new IllegalArgumentException("Precisions may not 
be null!");
+               }
+               if (scales == null) {
+                       throw new IllegalArgumentException("Scales may not be 
null!");
+               }
+               if (types.length != precisions.length || types.length != 
(paramcount +1)) {
+                       throw new IllegalArgumentException("Inconsistent 
Parameters metadata");
+               }
+               this.conn = connection;
+               this.paramCount = paramcount;
+               this.monetdbTypes = types;
+               this.JdbcSQLTypes = jdbcTypes;
+               this.precisions = precisions;
+               this.scales = scales;
+       }
+
+       /**
+        * Retrieves the number of parameters in the PreparedStatement object
+        * for which this ParameterMetaData object contains information.
+        *
+        * @return the number of parameters
+        */
+       @Override
+       public int getParameterCount() {
+               return paramCount;
+       }
+
+       /**
+        * Retrieves whether null values are allowed in the
+        * designated parameter.
+        *
+        * This is currently always unknown for MonetDB/SQL.
+        *
+        * @param param - the first parameter is 1, the second is 2, ...
+        * @return the nullability status of the given parameter;
+        *         one of ParameterMetaData.parameterNoNulls,
+        *         ParameterMetaData.parameterNullable, or
+        *         ParameterMetaData.parameterNullableUnknown
+        */
+       @Override
+       public int isNullable(final int param) throws SQLException {
+               checkParameterIndexValidity(param);
+               return ParameterMetaData.parameterNullableUnknown;
+       }
+
+       /**
+        * Retrieves whether values for the designated parameter can
+        * be signed numbers.
+        *
+        * @param param - the first parameter is 1, the second is 2, ...
+        * @return true if so; false otherwise
+        * @throws SQLException if a database access error occurs
+        */
+       @Override
+       public boolean isSigned(final int param) throws SQLException {
+               // we can hardcode this, based on the parameter type
+               switch (getParameterType(param)) {
+                       case Types.TINYINT:
+                       case Types.SMALLINT:
+                       case Types.INTEGER:
+                       case Types.REAL:
+                       case Types.FLOAT:
+                       case Types.DOUBLE:
+                       case Types.DECIMAL:
+                       case Types.NUMERIC:
+                               return true;
+                       case Types.BIGINT:
+                               final String monettype = 
getParameterTypeName(param);
+                               if (monettype != null && monettype.length() == 
3) {
+                                       // data of type oid or ptr is not signed
+                                       if ("oid".equals(monettype)
+                                        || "ptr".equals(monettype))
+                                               return false;
+                               }
+                               return true;
+               //      All other types should return false
+               //      case Types.BOOLEAN:
+               //      case Types.DATE:        // can year be negative?
+               //      case Types.TIME:        // can time be negative?
+               //      case Types.TIME_WITH_TIMEZONE:
+               //      case Types.TIMESTAMP:   // can year be negative?
+               //      case Types.TIMESTAMP_WITH_TIMEZONE:
+                       default:
+                               return false;
+               }
+       }
+
+       /**
+        * Retrieves the designated parameter's specified column size.
+        * The returned value represents the maximum column size for
+        * the given parameter.
+        * For numeric data, this is the maximum precision.
+        * For character data, this is the length in characters.
+        * For datetime datatypes, this is the length in characters
+        * of the String representation (assuming the maximum allowed
+        * precision of the fractional seconds component).
+        * For binary data, this is the length in bytes.
+        * For the ROWID datatype, this is the length in bytes.
+        * 0 is returned for data types where the column size is not applicable.
+        *
+        * @param param - the first parameter is 1, the second is 2, ...
+        * @return precision
+        * @throws SQLException if a database access error occurs
+        */
+       @Override
+       public int getPrecision(final int param) throws SQLException {
+               switch (getParameterType(param)) {
+                       case Types.BIGINT:
+                               return 19;
+                       case Types.INTEGER:
+                               return 10;
+                       case Types.SMALLINT:
+                               return 5;
+                       case Types.TINYINT:
+                               return 3;
+                       case Types.REAL:
+                               return 7;
+                       case Types.FLOAT:
+                       case Types.DOUBLE:
+                               return 15;
+                       case Types.DECIMAL:
+                       case Types.NUMERIC:
+                               // these data types have a variable precision 
(max precision is 38)
+                               try {
+                                       return precisions[param];
+                               } catch (IndexOutOfBoundsException e) {
+                                       throw 
newSQLInvalidParameterIndexException(param);
+                               }
+                       case Types.CHAR:
+                       case Types.VARCHAR:
+                       case Types.LONGVARCHAR: // MonetDB doesn't use type 
LONGVARCHAR, it's here for completeness
+                       case Types.CLOB:
+                               // these data types have a variable length
+                               try {
+                                       return precisions[param];
+                               } catch (IndexOutOfBoundsException e) {
+                                       throw 
newSQLInvalidParameterIndexException(param);
+                               }
+                       case Types.BINARY:
+                       case Types.VARBINARY:
+                       case Types.BLOB:
+                               // these data types have a variable length
+                               // It expect number of bytes, not number of hex 
chars
+                               try {
+                                       return precisions[param];
+                               } catch (IndexOutOfBoundsException e) {
+                                       throw 
newSQLInvalidParameterIndexException(param);
+                               }
+                       case Types.DATE:
+                               return 10;      // 2020-10-08
+                       case Types.TIME:
+                               return 15;      // 21:51:34.399753
+                       case Types.TIME_WITH_TIMEZONE:
+                               return 21;      // 21:51:34.399753+02:00
+                       case Types.TIMESTAMP:
+                               return 26;      // 2020-10-08 21:51:34.399753
+                       case Types.TIMESTAMP_WITH_TIMEZONE:
+                               return 32;      // 2020-10-08 
21:51:34.399753+02:00
+                       case Types.BOOLEAN:
+                               return 1;
+                       default:
+                               // All other types should return 0
+                               return 0;
+               }
+       }
+
+       /**
+        * Retrieves the designated parameter's number of digits to
+        * right of the decimal point.
+        * 0 is returned for data types where the scale is not applicable.
+        *
+        * @param param - the first parameter is 1, the second is 2, ...
+        * @return scale
+        * @throws SQLException if a database access error occurs
+        */
+       @Override
+       public int getScale(final int param) throws SQLException {
+               checkParameterIndexValidity(param);
+               try {
+                       return scales[param];
+               } catch (IndexOutOfBoundsException e) {
+                       throw newSQLInvalidParameterIndexException(param);
+               }
+       }
+
+       /**
+        * Retrieves the designated parameter's SQL type.
+        *
+        * @param param - the first parameter is 1, the second is 2, ...
+        * @return SQL type from java.sql.Types
+        * @throws SQLException if a database access error occurs
+        */
+       @Override
+       public int getParameterType(final int param) throws SQLException {
+               checkParameterIndexValidity(param);
+               try {
+                       return JdbcSQLTypes[param];
+               } catch (IndexOutOfBoundsException e) {
+                       throw newSQLInvalidParameterIndexException(param);
+               }
+       }
+
+       /**
+        * Retrieves the designated parameter's database-specific type name.
+        *
+        * @param param - the first parameter is 1, the second is 2, ...
+        * @return type the name used by the database.  If the
+        *         parameter type is a user-defined type, then a
+        *         fully-qualified type name is returned.
+        * @throws SQLException if a database access error occurs
+        */
+       @Override
+       public String getParameterTypeName(final int param) throws SQLException 
{
+               checkParameterIndexValidity(param);
+               try {
+                       final String monettype = monetdbTypes[param];
+                       if (monettype.endsWith("_interval")) {
+                               /* convert the interval type names to valid SQL 
data type names */
+                               if ("day_interval".equals(monettype))
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to