/* Copyright (c) 2001-2008, 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;
import org.hsqldb.Trace;
import org.hsqldb.Types;
// fredt@users 20040412 - removed DITypeInfo dependencies
// TODO: implement internal support for at least OUT return parameter
/**
* An object that can be used to get information about the types and
* properties of the parameters in a PreparedStatement object.
*
* @author boucherb@users
* @version 1.7.2
* @since JDK 1.4, HSQLDB 1.7.2
*/
public class jdbcParameterMetaData implements ParameterMetaData {
/** The metadata object with which this object is constructed */
Result.ResultMetaData rmd;
/** The numeric data type codes of the parameters. */
int[] types;
/** Parameter mode values */
int[] modes;
/** whether param is assigned directly to identity column */
boolean[] isIdentity;
/** nullability code for site to which param is bound */
int[] nullability;
/**
* The fully-qualified name of the Java class whose instances should
* be passed to the method PreparedStatement.setObject. <p>
*
* Note that changes to Function.java and Types.java allow passing
* objects of any class implementing java.io.Serializable and that,
* as such, the parameter expression resolution mechanism has been
* upgraded to provide the precise FQN for SQL function and stored
* procedure arguments, rather than the more generic
* org.hsqldb.JavaObject class that is used internally to represent
* and transport objects whose class is not in the standard mapping.
*/
String[] classNames;
/** The number of parameters in the described statement */
int parameterCount;
/**
* Creates a new instance of jdbcParameterMetaData. <p>
*
* @param r A Result object describing the statement parameters
* @throws SQLException never - reserved for future use
*/
jdbcParameterMetaData(Result r) throws SQLException {
if (r == null) {
parameterCount = 0;
return;
}
rmd = r.metaData;
types = rmd.colTypes;
parameterCount = types.length;
nullability = rmd.colNullable;
isIdentity = rmd.isIdentity;
classNames = rmd.classNames;
modes = rmd.paramMode;
}
/**
* 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 Util.sqlException(Trace.INVALID_JDBC_ARGUMENT, msg);
}
}
/**
* Retrieves the fully-qualified name of the Java class whose instances
* should be passed to the method PreparedStatement.setObject. <p>
*
* @param param the first parameter is 1, the second is 2, ...
* @throws SQLException if a database access error occurs
* @return 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
*/
public String getParameterClassName(int param) throws SQLException {
checkRange(param);
return classNames[--param];
}
/**
* Retrieves the number of parameters in the PreparedStatement object for
* which this ParameterMetaData object provides information. <p>
*
* @throws SQLException if a database access error occurs
* @return the number of parameters
* @since JDK 1.4, HSQLDB 1.7.2
*/
public int getParameterCount() throws SQLException {
return parameterCount;
}
/**
* Retrieves the designated parameter's mode. <p>
*
* @param param the first parameter is 1, the second is 2, ...
* @throws SQLException if a database access error occurs
* @return mode of the parameter; one of
* ParameterMetaData.parameterModeIn,
* ParameterMetaData.parameterModeOut,
* ParameterMetaData.parameterModeInOut,
* ParameterMetaData.parameterModeUnknown
* @since JDK 1.4, HSQLDB 1.7.2
*/
public int getParameterMode(int param) throws SQLException {
checkRange(param);
return modes[--param];
}
/**
* Retrieves the designated parameter's SQL type. <p>
*
* @param param the first parameter is 1, the second is 2, ...
* @throws SQLException if a database access error occurs
* @return SQL type from java.sql.Types
* @since JDK 1.4, HSQLDB 1.7.2
* @see java.sql.Types
*/
public int getParameterType(int param) throws SQLException {
int t;
checkRange(param);
t = types[--param];
return t == Types.VARCHAR_IGNORECASE ? Types.VARCHAR
: t;
}
/**
* Retrieves the designated parameter's database-specific type name. <p>
*
* @param param the first parameter is 1, the second is 2, ...
* @throws SQLException if a database access error occurs
* @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.
* @since JDK 1.4, HSQLDB 1.7.2
*/
public String getParameterTypeName(int param) throws SQLException {
int t;
int ts;
checkRange(param);
return Types.getTypeName(types[--param]);
}
/**
* Retrieves the designated parameter's number of decimal digits. <p>
*
* @param param the first parameter is 1, the second is 2, ...
* @throws SQLException if a database access error occurs
* @return precision
* @since JDK 1.4, HSQLDB 1.7.2
*/
public int getPrecision(int param) throws SQLException {
checkRange(param);
// TODO:
// parameters assigned directly to table columns
// should report the precision of the column if it is
// defined, otherwise the default (intrinsic) precision
// of the undecorated type
return Types.getPrecision(types[--param]);
}
/**
* Retrieves the designated parameter's number of digits to right of
* the decimal point. <p>
*
* @param param the first parameter is 1, the second is 2, ...
* @throws SQLException if a database access error occurs
* @return scale
* @since JDK 1.4, HSQLDB 1.7.2
*/
public int getScale(int param) throws SQLException {
checkRange(param);
// TODO:
// parameters assigned directly to DECIMAL/NUMERIC columns
// should report the declared scale of the column
// For now, to be taken as "default or unknown"
return 0;
}
/**
* Retrieves whether null values are allowed in the designated parameter. <p>
*
* @param param the first parameter is 1, the second is 2, ...
* @throws SQLException if a database access error occurs
* @return the nullability status of the given parameter; one of
* ParameterMetaData.parameterNoNulls,
* ParameterMetaData.parameterNullable or
* ParameterMetaData.parameterNullableUnknown
* @since JDK 1.4, HSQLDB 1.7.2
*/
public int isNullable(int param) throws SQLException {
checkRange(param);
return nullability[--param];
}
/**
* Retrieves whether values for the designated parameter can be
* signed numbers. <p>
*
* @param param the first parameter is 1, the second is 2, ...
* @throws SQLException if a database access error occurs
* @return true if so; false otherwise
* @since JDK 1.4, HSQLDB 1.7.2
*/
public boolean isSigned(int param) throws SQLException {
checkRange(param);
Boolean b = Types.isUnsignedAttribute(types[--param]);
return b != null &&!b.booleanValue() &&!isIdentity[param];
}
/**
* Retrieves a String repsentation of this object. <p>
*
* @return a String repsentation 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. <p>
*
* @return a String representation of this object
* @throws Exception if a reflection error occurs
*/
private String toStringImpl() throws Exception {
StringBuffer sb;
Method[] methods;
Method method;
int count;
sb = new StringBuffer();
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[]{ new Integer(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();
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
// TODO Auto-generated method stub
return false;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
// TODO Auto-generated method stub
return null;
}
//#ifdef JAVA6
/*
public <T> T unwrap(Class<T> iface) throws SQLException
{
throw new UnsupportedOperationException("Not supported yet.");
}
public boolean isWrapperFor(Class<?> iface) throws SQLException
{
throw new UnsupportedOperationException("Not supported yet.");
}
*/
//#endif JAVA6
}