All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.firebirdsql.jdbc.FBParameterMetaData Maven / Gradle / Ivy

There is a newer version: 2.2.7
Show newest version
/*
 * $Id: FBParameterMetaData.java 58482 2013-08-10 14:37:31Z mrotteveel $
 * 
 * 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);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy