/* Copyright (c) 2001-2019, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


package org.hsqldb.jdbc;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.ParameterMetaData;
import java.sql.SQLException;

import org.hsqldb.result.ResultMetaData;
import org.hsqldb.types.IntervalType;
import org.hsqldb.types.Type;

/* $Id: JDBCParameterMetaData.java 5968 2019-04-27 12:55:27Z fredt $ */

/* @todo 1.9.0 - implement internal support for INOUT, OUT return parameter */

// fredt@users 20040412 - removed DITypeInfo dependencies
// fredt@users 1.9.0 - utilise the new type support
// campbell-burnet@users 20051207 - patch 1.8.0.x initial JDBC 4.0 support work
// campbell-burnet@users 20060522 - doc   1.9.0 full synch up to Mustang Build 84
// Revision 1.14  2006/07/12 12:20:49  boucherb
// - remove unused imports
// - full synch up to Mustang b90

An object that can be used to get information about the types and properties for each parameter marker in a PreparedStatement object. (JDBC4 Clarification:) For some queries and driver implementations, the data that would be returned by a ParameterMetaData object may not be available until the PreparedStatement has been executed.

Some driver implementations may not be able to provide information about the types and properties for each parameter marker in a CallableStatement object.

Author:Campbell Burnet (campbell-burnet@users dot sourceforge.net)
Version:2.3.4
Since:JDK 1.4, HSQLDB 1.7.2
@revisedJDK 1.6, HSQLDB 2.0
/** * An object that can be used to get information about the types * and properties for each parameter marker in a * <code>PreparedStatement</code> object. (JDBC4 Clarification:) For some queries and driver * implementations, the data that would be returned by a <code>ParameterMetaData</code> * object may not be available until the <code>PreparedStatement</code> has * been executed. * <p> * Some driver implementations may not be able to provide information about the * types and properties for each parameter marker in a <code>CallableStatement</code> * object. * * @author Campbell Burnet (campbell-burnet@users dot sourceforge.net) * @version 2.3.4 * @since JDK 1.4, HSQLDB 1.7.2 * @revised JDK 1.6, HSQLDB 2.0 */
public class JDBCParameterMetaData implements ParameterMetaData, java.sql.Wrapper {
Retrieves the number of parameters in the PreparedStatement object for which this ParameterMetaData object contains information.
Throws:
Returns:the number of parameters
Since:JDK 1.4, HSQLDB 1.7.2
/** * Retrieves the number of parameters in the <code>PreparedStatement</code> * object for which this <code>ParameterMetaData</code> object contains * information. * * @return the number of parameters * @exception SQLException if a database access error occurs * @since JDK 1.4, HSQLDB 1.7.2 */
public int getParameterCount() throws SQLException { return parameterCount; }
Retrieves whether null values are allowed in the designated parameter.
Params:
  • param – the first parameter is 1, the second is 2, ...
Throws:
Returns:the nullability status of the given parameter; one of ParameterMetaData.parameterNoNulls, ParameterMetaData.parameterNullable, or ParameterMetaData.parameterNullableUnknown
Since:JDK 1.4, HSQLDB 1.7.2
/** * Retrieves whether null values are allowed in the designated parameter. * * @param param the first parameter is 1, the second is 2, ... * @return the nullability status of the given parameter; one of * <code>ParameterMetaData.parameterNoNulls</code>, * <code>ParameterMetaData.parameterNullable</code>, or * <code>ParameterMetaData.parameterNullableUnknown</code> * @exception SQLException if a database access error occurs * @since JDK 1.4, HSQLDB 1.7.2 */
public int isNullable(int param) throws SQLException { checkRange(param); return ParameterMetaData.parameterNullableUnknown; }
Retrieves whether values for the designated parameter can be signed numbers.
Params:
  • param – the first parameter is 1, the second is 2, ...
Throws:
Returns:true if so; false otherwise
Since:JDK 1.4, HSQLDB 1.7.2
/** * Retrieves whether values for the designated parameter can be signed numbers. * * @param param the first parameter is 1, the second is 2, ... * @return <code>true</code> if so; <code>false</code> otherwise * @exception SQLException if a database access error occurs * @since JDK 1.4, HSQLDB 1.7.2 */
public boolean isSigned(int param) throws SQLException { checkRange(param); Type type = translateType(rmd.columnTypes[--param]); return type.isNumberType(); }
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.

Params:
  • param – the first parameter is 1, the second is 2, ...
Throws:
Returns:precision
Since:JDK 1.4, HSQLDB 1.7.2
/** * Retrieves the designated parameter's specified column size. * * <P>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 * @exception SQLException if a database access error occurs * @since JDK 1.4, HSQLDB 1.7.2 */
public int getPrecision(int param) throws SQLException { checkRange(param); Type type = translateType(rmd.columnTypes[--param]); if (type.isDateTimeType()) { return type.displaySize(); } else { long size = type.precision; if (size > Integer.MAX_VALUE) { size = 0; } return (int) size; } }
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.
Params:
  • param – the first parameter is 1, the second is 2, ...
Throws:
Returns:scale
Since:JDK 1.4, HSQLDB 1.7.2
/** * 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 * @exception SQLException if a database access error occurs * @since JDK 1.4, HSQLDB 1.7.2 */
public int getScale(int param) throws SQLException { checkRange(param); Type type = translateType(rmd.columnTypes[--param]); return type.scale; }
Retrieves the designated parameter's SQL type.
Params:
  • param – the first parameter is 1, the second is 2, ...
Throws:
See Also:
Returns:SQL type from java.sql.Types
Since:JDK 1.4, HSQLDB 1.7.2
/** * Retrieves the designated parameter's SQL type. * * @param param the first parameter is 1, the second is 2, ... * @return SQL type from <code>java.sql.Types</code> * @exception SQLException if a database access error occurs * @since JDK 1.4, HSQLDB 1.7.2 * @see java.sql.Types */
public int getParameterType(int param) throws SQLException { checkRange(param); Type type = translateType(rmd.columnTypes[--param]); return type.getJDBCTypeCode(); }
Retrieves the designated parameter's database-specific type name.
Params:
  • param – the first parameter is 1, the second is 2, ...
Throws:
Returns:type the name used by the database. If the parameter type is a user-defined type, then a fully-qualified type name is returned.
Since:JDK 1.4, HSQLDB 1.7.2
/** * 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. * @exception SQLException if a database access error occurs * @since JDK 1.4, HSQLDB 1.7.2 */
public String getParameterTypeName(int param) throws SQLException { checkRange(param); Type type = translateType(rmd.columnTypes[--param]); return type.getNameString(); }
Retrieves the fully-qualified name of the Java class whose instances should be passed to the method PreparedStatement.setObject.
Params:
  • param – the first parameter is 1, the second is 2, ...
Throws:
Returns:the fully-qualified name of the class in the Java programming language that would be used by the method PreparedStatement.setObject to set the value in the specified parameter. This is the class name used for custom mapping.
Since:JDK 1.4, HSQLDB 1.7.2
/** * Retrieves the fully-qualified name of the Java class whose instances * should be passed to the method <code>PreparedStatement.setObject</code>. * * @param param the first parameter is 1, the second is 2, ... * @return the fully-qualified name of the class in the Java programming * language that would be used by the method * <code>PreparedStatement.setObject</code> to set the value * in the specified parameter. This is the class name used * for custom mapping. * @exception SQLException if a database access error occurs * @since JDK 1.4, HSQLDB 1.7.2 */
public String getParameterClassName(int param) throws SQLException { checkRange(param); Type type = translateType(rmd.columnTypes[--param]); return type.getJDBCClassName(); }
Retrieves the designated parameter's mode.
Params:
  • param – the first parameter is 1, the second is 2, ...
Throws:
Returns:mode of the parameter; one of ParameterMetaData.parameterModeIn, ParameterMetaData.parameterModeOut, or ParameterMetaData.parameterModeInOut ParameterMetaData.parameterModeUnknown.
Since:JDK 1.4, HSQLDB 1.7.2
/** * Retrieves the designated parameter's mode. * * @param param the first parameter is 1, the second is 2, ... * @return mode of the parameter; one of * <code>ParameterMetaData.parameterModeIn</code>, * <code>ParameterMetaData.parameterModeOut</code>, or * <code>ParameterMetaData.parameterModeInOut</code> * <code>ParameterMetaData.parameterModeUnknown</code>. * @exception SQLException if a database access error occurs * @since JDK 1.4, HSQLDB 1.7.2 */
public int getParameterMode(int param) throws SQLException { checkRange(param); return rmd.paramModes[--param]; } //----------------------------- JDBC 4.0 ----------------------------------- // ------------------- java.sql.Wrapper implementation ---------------------
Returns an object that implements the given interface to allow access to non-standard methods, or standard methods not exposed by the proxy. If the receiver implements the interface then the result is the receiver or a proxy for the receiver. If the receiver is a wrapper and the wrapped object implements the interface then the result is the wrapped object or a proxy for the wrapped object. Otherwise return the the result of calling unwrap recursively on the wrapped object or a proxy for that result. If the receiver is not a wrapper and does not implement the interface, then an SQLException is thrown.
Params:
  • iface – A Class defining an interface that the result must implement.
Throws:
  • SQLException – If no object found that implements the interface
Returns:an object that implements the interface. May be a proxy for the actual implementing object.
Since:JDK 1.6, HSQLDB 2.0
/** * Returns an object that implements the given interface to allow access to * non-standard methods, or standard methods not exposed by the proxy. * * If the receiver implements the interface then the result is the receiver * or a proxy for the receiver. If the receiver is a wrapper * and the wrapped object implements the interface then the result is the * wrapped object or a proxy for the wrapped object. Otherwise return the * the result of calling <code>unwrap</code> recursively on the wrapped object * or a proxy for that result. If the receiver is not a * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown. * * @param iface A Class defining an interface that the result must implement. * @return an object that implements the interface. May be a proxy for the actual implementing object. * @throws java.sql.SQLException If no object found that implements the interface * @since JDK 1.6, HSQLDB 2.0 */
@SuppressWarnings("unchecked") public <T>T unwrap(Class<T> iface) throws java.sql.SQLException { if (isWrapperFor(iface)) { return (T) this; } throw JDBCUtil.invalidArgument("iface: " + iface); }
Returns true if this either implements the interface argument or is directly or indirectly a wrapper for an object that does. Returns false otherwise. If this implements the interface then return true, else if this is a wrapper then return the result of recursively calling isWrapperFor on the wrapped object. If this does not implement the interface and is not a wrapper, return false. This method should be implemented as a low-cost operation compared to unwrap so that callers can use this method to avoid expensive unwrap calls that may fail. If this method returns true then calling unwrap with the same argument should succeed.
Params:
  • iface – a Class defining an interface.
Throws:
  • SQLException – if an error occurs while determining whether this is a wrapper for an object with the given interface.
Returns:true if this implements the interface or directly or indirectly wraps an object that does.
Since:JDK 1.6, HSQLDB 2.0
/** * Returns true if this either implements the interface argument or is directly or indirectly a wrapper * for an object that does. Returns false otherwise. If this implements the interface then return true, * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped * object. If this does not implement the interface and is not a wrapper, return false. * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method * returns true then calling <code>unwrap</code> with the same argument should succeed. * * @param iface a Class defining an interface. * @return true if this implements the interface or directly or indirectly wraps an object that does. * @throws java.sql.SQLException if an error occurs while determining whether this is a wrapper * for an object with the given interface. * @since JDK 1.6, HSQLDB 2.0 */
public boolean isWrapperFor( Class<?> iface) throws java.sql.SQLException { return (iface != null && iface.isAssignableFrom(this.getClass())); } // -------------------------- Internal Implementation ----------------------
The metadata object with which this object is constructed
/** The metadata object with which this object is constructed */
ResultMetaData rmd;
The number of parameters in the described statement
/** The number of parameters in the described statement */
int parameterCount; private boolean translateTTIType;
Creates a new instance of JDBCParameterMetaData.

Params:
  • metaData – A ResultMetaData object describing the statement parameters
Throws:
/** * Creates a new instance of JDBCParameterMetaData. <p> * * @param metaData A ResultMetaData object describing the statement parameters * @throws SQLException never - reserved for future use */
JDBCParameterMetaData(JDBCConnection conn, ResultMetaData metaData) throws SQLException { rmd = metaData; parameterCount = rmd.getColumnCount(); translateTTIType = conn.isTranslateTTIType; }
Translates an INTERVAL type to VARCHAR. Removes time zone from datetime types.
/** * Translates an INTERVAL type to VARCHAR. * Removes time zone from datetime types. * */
private Type translateType(Type type) { if (this.translateTTIType) { if (type.isIntervalType()) { type = ((IntervalType) type).getCharacterType(); } } return type; }
Checks if the value of the param argument is a valid parameter position.

Params:
  • param – position to check
Throws:
  • SQLException – if the value of the param argument is not a valid parameter position
/** * Checks if the value of the param argument is a valid parameter * position. <p> * * @param param position to check * @throws SQLException if the value of the param argument is not a * valid parameter position */
void checkRange(int param) throws SQLException { if (param < 1 || param > parameterCount) { String msg = param + " is out of range"; throw JDBCUtil.outOfRangeArgument(msg); } }
Retrieves a String representation of this object.

Returns:a String representation of this object
/** * Retrieves a String representation of this object. <p> * * @return a String representation of this object */
public String toString() { try { return toStringImpl(); } catch (Throwable t) { return super.toString() + "[toStringImpl_exception=" + t + "]"; } }
Provides the implementation of the toString() method.

Throws:
Returns:a String representation of this object
/** * Provides the implementation of the toString() method. <p> * * @return a String representation of this object * @throws Exception if a reflection error occurs */
private String toStringImpl() throws Exception { StringBuilder sb; Method[] methods; Method method; int count; sb = new StringBuilder(); sb.append(super.toString()); count = getParameterCount(); if (count == 0) { sb.append("[parameterCount=0]"); return sb.toString(); } methods = getClass().getDeclaredMethods(); sb.append('['); int len = methods.length; for (int i = 0; i < count; i++) { sb.append('\n'); sb.append(" parameter_"); sb.append(i + 1); sb.append('='); sb.append('['); for (int j = 0; j < len; j++) { method = methods[j]; if (!Modifier.isPublic(method.getModifiers())) { continue; } if (method.getParameterTypes().length != 1) { continue; } sb.append(method.getName()); sb.append('='); sb.append(method.invoke(this, new Object[] { Integer.valueOf(i + 1) })); if (j + 1 < len) { sb.append(','); sb.append(' '); } } sb.append(']'); if (i + 1 < count) { sb.append(','); sb.append(' '); } } sb.append('\n'); sb.append(']'); return sb.toString(); } }