org.firebirdsql.jdbc.FBParameterMetaData Maven / Gradle / Ivy
/*
* $Id$
*
* Firebird Open Source J2ee connector - jdbc driver
*
* Distributable under LGPL license.
* You may obtain a copy of the License at http://www.gnu.org/copyleft/lgpl.html
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* LGPL License for more details.
*
* This file was created by members of the firebird development team.
* All individual contributions remain the Copyright (C) of those
* individuals. Contributors to this file are either listed here or
* can be obtained from a CVS history command.
*
* All rights reserved.
*/
package org.firebirdsql.jdbc;
import java.math.BigDecimal;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Date;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import org.firebirdsql.encodings.EncodingFactory;
import org.firebirdsql.gds.ISCConstants;
import org.firebirdsql.gds.XSQLVAR;
import org.firebirdsql.gds.impl.GDSHelper;
/**
* Describe class FBParameterMetaData
here.
*
* @author Nickolay Samofatov
* @version 1.0
*/
public class FBParameterMetaData implements FirebirdParameterMetaData {
private final XSQLVAR[] xsqlvars;
private final GDSHelper connection;
/**
* Creates a new FBParameterMetaData
instance.
*
* @param xsqlvars a XSQLVAR[]
value
* @param connection a AbstractConnection
value
* @exception SQLException if an error occurs
*
*/
protected FBParameterMetaData(XSQLVAR[] xsqlvars, GDSHelper connection) throws SQLException {
this.xsqlvars = xsqlvars;
this.connection = connection;
}
private String getIscEncoding() {
if (connection != null)
return connection.getIscEncoding();
else
return "NONE";
}
/**
* Retrieves the number of parameters in the PreparedStatement
* object for which this ParameterMetaData
object contains
* information.
*
* @return the number of parameters
* @exception SQLException if a database access error occurs
* @since 1.4
*/
public int getParameterCount() {
return xsqlvars.length;
}
/**
* Retrieves whether null values are allowed in the designated parameter.
*
* @param parameter 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
* @exception SQLException if a database access error occurs
* @since 1.4
*/
public int isNullable(int parameter) throws SQLException {
if ((getXsqlvar(parameter).sqltype & 1) == 1) {
return parameterNullable;
}
else {
return parameterNoNulls;
}
}
/**
* Retrieves whether values for the designated parameter can be signed numbers.
*
* @param parameter the first parameter is 1, the second is 2, ...
* @return true
if so; false
otherwise
* @exception SQLException if a database access error occurs
* @since 1.4
*/
public boolean isSigned(int parameter) throws SQLException {
switch (getXsqlvar(parameter).sqltype & ~1) {
case ISCConstants.SQL_SHORT:
case ISCConstants.SQL_LONG:
case ISCConstants.SQL_FLOAT:
case ISCConstants.SQL_DOUBLE:
case ISCConstants.SQL_D_FLOAT:
case ISCConstants.SQL_INT64:
return true;
default:
return false;
}
}
/**
* Retrieves the designated parameter's number of decimal digits.
*
* @param parameter the first parameter is 1, the second is 2, ...
* @return precision
* @exception SQLException if a database access error occurs
* @since 1.4
*/
public int getPrecision(int parameter) throws SQLException {
int colType = getParameterType(parameter);
switch (colType){
case Types.DECIMAL:
case Types.NUMERIC:
return estimatePrecision(parameter);
case Types.CHAR:
case Types.VARCHAR: {
XSQLVAR var = getXsqlvar(parameter);
int charset = var.sqlsubtype & 0xFF;
int charSetSize = charset == 127 /* CS_dynamic */ ?
EncodingFactory.getIscEncodingSize(getIscEncoding()) :
EncodingFactory.getCharacterSetSize(charset);
return var.sqllen / charSetSize;
}
case Types.FLOAT:
return 7;
case Types.DOUBLE:
return 15;
case Types.BIGINT:
return 19;
case Types.INTEGER:
return 10;
case Types.SMALLINT:
return 5;
case Types.DATE:
return 10;
case Types.TIME:
return 8;
case Types.TIMESTAMP:
return 19;
case Types.BOOLEAN:
return 1;
default:
return 0;
}
}
/**
* Retrieves the designated parameter's number of digits to right of the decimal point.
*
* @param parameter the first parameter is 1, the second is 2, ...
* @return scale
* @exception SQLException if a database access error occurs
* @since 1.4
*/
public int getScale(int parameter) throws SQLException {
return getXsqlvar(parameter).sqlscale * (-1);
}
/**
* Retrieves the designated parameter's SQL type.
*
* @param parameter the first parameter is 1, the second is 2, ...
* @return SQL type from java.sql.Types
* @exception SQLException if a database access error occurs
* @since 1.4
* @see Types
*/
public int getParameterType(int parameter) throws SQLException {
int sqltype = getXsqlvar(parameter).sqltype & ~1;
int sqlscale = getXsqlvar(parameter).sqlscale;
int sqlsubtype = getXsqlvar(parameter).sqlsubtype;
if (sqlscale < 0) {
switch (sqltype) {
case ISCConstants.SQL_SHORT:
case ISCConstants.SQL_LONG:
case ISCConstants.SQL_INT64:
case ISCConstants.SQL_DOUBLE:
if (sqlsubtype == 2)
return Types.DECIMAL;
else
return Types.NUMERIC;
default:
break;
}
}
switch (sqltype) {
case ISCConstants.SQL_SHORT:
return Types.SMALLINT;
case ISCConstants.SQL_LONG:
return Types.INTEGER;
case ISCConstants.SQL_DOUBLE:
case ISCConstants.SQL_D_FLOAT:
return Types.DOUBLE;
case ISCConstants.SQL_FLOAT:
return Types.FLOAT;
case ISCConstants.SQL_TEXT:
return Types.CHAR;
case ISCConstants.SQL_VARYING:
return Types.VARCHAR;
case ISCConstants.SQL_TIMESTAMP:
return Types.TIMESTAMP;
case ISCConstants.SQL_TYPE_TIME:
return Types.TIME;
case ISCConstants.SQL_TYPE_DATE:
return Types.DATE;
case ISCConstants.SQL_INT64:
if (sqlsubtype == 1)
return Types.NUMERIC;
else
if (sqlsubtype == 2)
return Types.DECIMAL;
else
return Types.BIGINT;
case ISCConstants.SQL_BLOB:
if (sqlsubtype < 0)
return Types.BLOB;
else if (sqlsubtype == 0 || sqlsubtype > 1)
return Types.LONGVARBINARY;
else if (sqlsubtype == 1)
return Types.LONGVARCHAR;
else
return Types.OTHER;
case ISCConstants.SQL_QUAD:
return Types.OTHER;
case ISCConstants.SQL_BOOLEAN:
return Types.BOOLEAN;
default:
return Types.NULL;
}
}
/**
* Retrieves the designated parameter's database-specific type name.
*
* @param parameter 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 1.4
*/
public String getParameterTypeName(int parameter) throws SQLException {
// Must return the same value as DatamaseMetaData getColumns Type_Name
int sqltype = getXsqlvar(parameter).sqltype & ~1;
int sqlscale = getXsqlvar(parameter).sqlscale;
int sqlsubtype = getXsqlvar(parameter).sqlsubtype;
if (sqlscale < 0) {
switch (sqltype) {
case ISCConstants.SQL_SHORT:
case ISCConstants.SQL_LONG:
case ISCConstants.SQL_INT64:
case ISCConstants.SQL_DOUBLE:
if (sqlsubtype == 2)
return "DECIMAL";
else
return "NUMERIC";
default:
break;
}
}
switch (sqltype) {
case ISCConstants.SQL_SHORT:
return "SMALLINT";
case ISCConstants.SQL_LONG:
return "INTEGER";
case ISCConstants.SQL_DOUBLE:
case ISCConstants.SQL_D_FLOAT:
return "DOUBLE PRECISION";
case ISCConstants.SQL_FLOAT:
return "FLOAT";
case ISCConstants.SQL_TEXT:
return "CHAR";
case ISCConstants.SQL_VARYING:
return "VARCHAR";
case ISCConstants.SQL_TIMESTAMP:
return "TIMESTAMP";
case ISCConstants.SQL_TYPE_TIME:
return "TIME";
case ISCConstants.SQL_TYPE_DATE:
return "DATE";
case ISCConstants.SQL_INT64:
if (sqlsubtype == 1)
return "NUMERIC";
else if (sqlsubtype == 2)
return "DECIMAL";
else
return "BIGINT";
case ISCConstants.SQL_BLOB:
if (sqlsubtype < 0)
return "BLOB SUB_TYPE " + sqlsubtype;
else if (sqlsubtype == 0)
return "BLOB SUB_TYPE 0";
else if (sqlsubtype == 1)
return "BLOB SUB_TYPE 1";
else
return "BLOB SUB_TYPE " + sqlsubtype;
case ISCConstants.SQL_QUAD:
return "ARRAY";
case ISCConstants.SQL_BOOLEAN:
return "BOOLEAN";
default:
return "NULL";
}
}
/**
* Retrieves the fully-qualified name of the Java class whose instances
* should be passed to the method PreparedStatement.setObject
.
*
* @param parameter 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
* PreparedStatement.setObject
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 1.4
*/
public String getParameterClassName(int parameter) throws SQLException {
switch (getXsqlvar(parameter).sqltype & ~1) {
case ISCConstants.SQL_TEXT:
case ISCConstants.SQL_VARYING:
return String.class.getName();
case ISCConstants.SQL_SHORT:
case ISCConstants.SQL_LONG:
return Integer.class.getName();
case ISCConstants.SQL_FLOAT:
case ISCConstants.SQL_DOUBLE:
case ISCConstants.SQL_D_FLOAT:
return Double.class.getName();
case ISCConstants.SQL_TIMESTAMP:
return Timestamp.class.getName();
case ISCConstants.SQL_BLOB:
XSQLVAR field = getXsqlvar(parameter);
if (field.sqlsubtype < 0)
return Blob.class.getName();
if (field.sqlsubtype == 1)
return String.class.getName();
else
return byte[].class.getName();
case ISCConstants.SQL_ARRAY:
return Array.class.getName();
case ISCConstants.SQL_QUAD:
return Long.class.getName();
case ISCConstants.SQL_TYPE_TIME:
return Time.class.getName();
case ISCConstants.SQL_TYPE_DATE:
return Date.class.getName();
case ISCConstants.SQL_INT64:
if (getXsqlvar(parameter).sqlscale == 0) {
return Long.class.getName();
}
else {
return BigDecimal.class.getName();
}
case ISCConstants.SQL_BOOLEAN:
return Boolean.class.getName();
default:
throw new SQLException("Unknown SQL type",
FBSQLException.SQL_STATE_INVALID_PARAM_TYPE);
}
}
/**
* Retrieves the designated parameter's mode.
*
* @param param the first parameter is 1, the second is 2, ...
* @return mode of the parameter; one of
* ParameterMetaData.parameterModeIn
,
* ParameterMetaData.parameterModeOut
, or
* ParameterMetaData.parameterModeInOut
* ParameterMetaData.parameterModeUnknown
.
* @exception SQLException if a database access error occurs
* @since 1.4
*/
public int getParameterMode(int param) throws SQLException {
return parameterModeIn;
}
//private methods
private XSQLVAR getXsqlvar(int parameterIndex) {
return xsqlvars[parameterIndex - 1];
}
// TODO: Exact duplicate of method in AbstractResultSetMetaData
private int estimatePrecision(int parameterIndex) {
int sqltype = getXsqlvar(parameterIndex).sqltype & ~1;
// TODO Why unused
int sqlscale = getXsqlvar(parameterIndex).sqlscale;
switch(sqltype) {
case ISCConstants.SQL_SHORT : return 5;
case ISCConstants.SQL_LONG : return 10;
case ISCConstants.SQL_INT64 : return 19;
case ISCConstants.SQL_DOUBLE : return 19;
default : return 0;
}
}
public boolean isWrapperFor(Class iface) throws SQLException {
return iface != null && iface.isAssignableFrom(getClass());
}
public T unwrap(Class iface) throws SQLException {
if (!isWrapperFor(iface))
throw new FBDriverNotCapableException();
return iface.cast(this);
}
}