|
HSQLDB example source code file (DIProcedureInfo.java)
The HSQLDB DIProcedureInfo.java source code/* 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; import java.io.Serializable; import java.lang.reflect.Method; import org.hsqldb.lib.HashMap; import org.hsqldb.lib.HsqlArrayList; import org.hsqldb.resources.BundleHandler; import org.hsqldb.store.ValuePool; import org.hsqldb.types.Binary; /**@todo fredt - move Trace.doAssert() literals to Trace*/ /** * Provides information about HSQLDB SQL-invoked routines and SQL functions. <p> * * In particular, this class provides information about Java Methods in a form * compatible with presentation via the related HSQLDB system tables, * SYSTEM_PROCEDURES and SYSTEM_PROCEDURECOLUMNS, involved in the production of * the DatabaseMetaData getProcedures and getProcedureColumns result sets. * * @author boucherb@users * @version 1.7.2 * @since 1.7.2 */ final class DIProcedureInfo { // java.sql dependencies mostly removed static final String conClsName = "java.sql.Connection"; static final int procedureResultUnknown = 0; static final int procedureNoResult = 1; static final int procedureReturnsResult = 2; static final int procedureColumnUnknown = 0; static final int procedureColumnIn = 1; static final int procedureColumnInOut = 2; static final int procedureColumnResult = 3; static final int procedureColumnOut = 4; static final int procedureColumnReturn = 5; static final int procedureNoNulls = 0; static final int procedureNullable = 1; static final int procedureNullableUnknown = 2; private Class clazz; private Class[] colClasses; private int[] colTypes; private int colOffset; private int colCount; private boolean colsResolved; private String fqn; private String specificName; private int hnd_remarks; private Method method; private String sig; private DINameSpace nameSpace; private final HashMap typeMap = new HashMap(); public DIProcedureInfo(DINameSpace ns) throws HsqlException { setNameSpace(ns); } private int colOffset() { if (!colsResolved) { resolveCols(); } return colOffset; } HsqlArrayList getAliases() { return (HsqlArrayList) nameSpace.getInverseAliasMap().get(getFQN()); } Class getColClass(int i) { return colClasses[i + colOffset()]; } int getColCount() { if (!colsResolved) { resolveCols(); } return colCount; } Integer getColDataType(int i) { return ValuePool.getInt(getColTypeCode(i)); } Integer getColLen(int i) { int size; int type; type = getColTypeCode(i); switch (type) { case Types.BINARY : case Types.LONGVARBINARY : case Types.VARBINARY : { size = Integer.MAX_VALUE; break; } case Types.BIGINT : case Types.DOUBLE : case Types.DATE : case Types.FLOAT : case Types.TIME : { size = 8; break; } case Types.TIMESTAMP : { size = 12; break; } case Types.REAL : case Types.INTEGER : { size = 4; break; } case Types.SMALLINT : { size = 2; break; } case Types.TINYINT : case Types.BOOLEAN : { size = 1; break; } default : size = 0; } return (size == 0) ? null : ValuePool.getInt(size); } String getColName(int i) { return CompiledStatement.PCOL_PREFIX + (i + colOffset()); } Integer getColNullability(int i) { int cn; cn = getColClass(i).isPrimitive() ? procedureNoNulls : procedureNullable; return ValuePool.getInt(cn); } String getColRemark(int i) { String key; StringBuffer sb; sb = new StringBuffer(getSignature()); key = sb.append('@').append(i + colOffset()).toString(); return BundleHandler.getString(hnd_remarks, key); } // JDBC sort-contract: // out return value column, then in/in out/out parameter columns // in formal order, then result columns in column order // // Currently, we materialize the java method return value, if // any, as a result column, not as an OUT return value column, so // it should actually appear _after_ the other procedure columns // in the row order returned by the JDBC getProcedureColumns() method int getColSequence(int i) { // colOffset has the side-effect of setting colCount properly return (i + colOffset() == 0) ? colCount : i; } int getColTypeCode(int i) { i += colOffset(); return colTypes[i]; } Integer getColUsage(int i) { switch (i + colOffset()) { case 0 : { // Currently, we materialize the java method return value, if // any, as a result column, not as an OUT return column return ValuePool.getInt(procedureColumnResult); } // todo: registration and reporting on result columns for routines // that generate real" result sets default : { // We could get religious here and maybe report IN OUT // for newRow of before update for each row trigger methods, // but there's not really any added value return ValuePool.getInt(procedureColumnIn); } } } Class getDeclaringClass() { return this.clazz; } String getFQN() { StringBuffer sb; if (fqn == null) { sb = new StringBuffer(); fqn = sb.append(clazz.getName()).append('.').append( method.getName()).toString(); } return fqn; } String getSpecificName() { if (specificName == null) { specificName = clazz.getName() + "." + getSignature(); } return specificName; } Integer getInputParmCount() { return ValuePool.getInt(method.getParameterTypes().length); } Method getMethod() { return this.method; } String getOrigin(String srcType) { return (nameSpace.isBuiltin(clazz) ? "BUILTIN " : "USER DEFINED ") + srcType; } Integer getOutputParmCount() { // no support for IN OUT or OUT columns yet return ValuePool.getInt(0); } String getRemark() { return BundleHandler.getString(hnd_remarks, getSignature()); } Integer getResultSetCount() { return (method.getReturnType() == Void.TYPE) ? ValuePool.getInt(0) : ValuePool.getInt(1); } Integer getResultType(String origin) { int type; type = !"ROUTINE".equals(origin) ? procedureResultUnknown : method.getReturnType() == Void.TYPE ? procedureNoResult : procedureReturnsResult; return ValuePool.getInt(type); } String getSignature() { if (sig == null) { sig = DINameSpace.getSignature(method); } return sig; } /** * Retrieves the specific name of the given Method object. <p> * * @param m The Method object for which to retreive the specific name * @return the specific name of the specified Method object. */ static String getMethodSpecificName(Method m) { return m == null ? null : m.getDeclaringClass().getName() + '.' + DINameSpace.getSignature(m); } DINameSpace getNameSpace() { return nameSpace; } void setNameSpace(DINameSpace ns) throws HsqlException { nameSpace = ns; Class c; Integer type; // can only speed up test significantly for java.lang.Object, // final classes, primitive types and hierachy parents. // Must still check later if assignable from candidate classes, where // hierarchy parent is not final. //ARRAY try { c = nameSpace.classForName("org.hsqldb.jdbc.jdbcArray"); typeMap.put(c, ValuePool.getInt(Types.ARRAY)); } catch (Exception e) {} // BIGINT type = ValuePool.getInt(Types.BIGINT); typeMap.put(Long.TYPE, type); typeMap.put(Long.class, type); // BOOLEAN type = ValuePool.getInt(Types.BOOLEAN); typeMap.put(Boolean.TYPE, type); typeMap.put(Boolean.class, type); // BLOB type = ValuePool.getInt(Types.BLOB); try { c = nameSpace.classForName("org.hsqldb.jdbc.jdbcBlob"); typeMap.put(c, type); } catch (Exception e) {} // CHAR type = ValuePool.getInt(Types.CHAR); typeMap.put(Character.TYPE, type); typeMap.put(Character.class, type); typeMap.put(Character[].class, type); typeMap.put(char[].class, type); // CLOB type = ValuePool.getInt(Types.CLOB); try { c = nameSpace.classForName("org.hsqldb.jdbc.jdbcClob"); typeMap.put(c, type); } catch (Exception e) {} // DATALINK type = ValuePool.getInt(Types.DATALINK); typeMap.put(java.net.URL.class, type); // DATE type = ValuePool.getInt(Types.DATE); typeMap.put(java.util.Date.class, type); typeMap.put(java.sql.Date.class, type); // DECIMAL type = ValuePool.getInt(Types.DECIMAL); try { c = nameSpace.classForName("java.math.BigDecimal"); typeMap.put(c, type); } catch (Exception e) {} // DISTINCT try { c = nameSpace.classForName("org.hsqldb.jdbc.jdbcDistinct"); typeMap.put(c, ValuePool.getInt(Types.DISTINCT)); } catch (Exception e) {} // DOUBLE type = ValuePool.getInt(Types.DOUBLE); typeMap.put(Double.TYPE, type); typeMap.put(Double.class, type); // FLOAT : Not actually a legal IN parameter type yet type = ValuePool.getInt(Types.FLOAT); typeMap.put(Float.TYPE, type); typeMap.put(Float.class, type); // INTEGER type = ValuePool.getInt(Types.INTEGER); typeMap.put(Integer.TYPE, type); typeMap.put(Integer.class, type); // JAVA_OBJECT type = ValuePool.getInt(Types.JAVA_OBJECT); typeMap.put(Object.class, type); // LONGVARBINARY type = ValuePool.getInt(Types.LONGVARBINARY); typeMap.put(byte[].class, type); typeMap.put(Binary.class, type); // LONGVARCHAR type = ValuePool.getInt(Types.LONGVARCHAR); typeMap.put(String.class, type); // NULL type = ValuePool.getInt(Types.NULL); typeMap.put(Void.TYPE, type); typeMap.put(Void.class, type); // REF type = ValuePool.getInt(Types.REF); try { c = nameSpace.classForName("org.hsqldb.jdbc.jdbcRef"); typeMap.put(c, type); } catch (Exception e) {} // SMALLINT : Not actually a legal IN parameter type yet type = ValuePool.getInt(Types.SMALLINT); typeMap.put(Short.TYPE, type); typeMap.put(Short.class, type); // STRUCT : type = ValuePool.getInt(Types.STRUCT); try { c = nameSpace.classForName("org.hsqldb.jdbc.jdbcStruct"); typeMap.put(c, type); } catch (Exception e) {} // TIME type = ValuePool.getInt(Types.TIME); typeMap.put(java.sql.Time.class, type); // TIMESTAMP type = ValuePool.getInt(Types.TIMESTAMP); typeMap.put(java.sql.Timestamp.class, type); // TINYINT : Not actually a legal IN parameter type yet type = ValuePool.getInt(Types.TINYINT); typeMap.put(Byte.TYPE, type); typeMap.put(Byte.class, type); // XML : Not actually a legal IN parameter type yet type = ValuePool.getInt(Types.XML); try { c = nameSpace.classForName("org.w3c.dom.Document"); typeMap.put(c, type); c = nameSpace.classForName("org.w3c.dom.DocumentFragment"); typeMap.put(c, type); } catch (Exception e) {} } private void resolveCols() { Class rType; Class[] pTypes; Class clazz; int ptlen; int pclen; boolean isFPCON; rType = method.getReturnType(); pTypes = method.getParameterTypes(); ptlen = pTypes.length; isFPCON = ptlen > 0 && pTypes[0].getName().equals(conClsName); pclen = 1 + ptlen - (isFPCON ? 1 : 0); colClasses = new Class[pclen]; colTypes = new int[pclen]; colClasses[0] = rType; colTypes[0] = typeForClass(rType); for (int i = isFPCON ? 1 : 0, idx = 1; i < ptlen; i++, idx++) { clazz = pTypes[i]; colClasses[idx] = clazz; colTypes[idx] = typeForClass(clazz); } colOffset = rType == Void.TYPE ? 1 : 0; colCount = pclen - colOffset; } /** * This requires the following properties files: * * org_hsqldb_Library.properties * java_math.properties */ void setMethod(Method m) { String remarkKey; method = m; clazz = method.getDeclaringClass(); fqn = null; specificName = null; sig = null; colsResolved = false; remarkKey = clazz.getName().replace('.', '_'); hnd_remarks = BundleHandler.getBundleHandle(remarkKey, null); } int typeForClass(Class c) { Class to; Integer type = (Integer) typeMap.get(c); if (type != null) { return type.intValue(); } // ARRAY (dimension 1) // HSQLDB does not yet support ARRAY for SQL, but // Trigger.fire takes Object[] row, which we report. // Also, it's just friendly to show what "would" // be required if/when we support ARRAY in a broader // sense if (c.isArray() &&!c.getComponentType().isArray()) { return Types.ARRAY; } try { to = Class.forName("java.sql.Array"); if (to.isAssignableFrom(c)) { return Types.ARRAY; } } catch (Exception e) {} // NUMERIC // All java.lang.Number impls and BigDecimal have // already been covered by lookup in typeMap. // They are all final, so this is OK. if (Number.class.isAssignableFrom(c)) { return Types.NUMERIC; } // TIMESTAMP try { to = Class.forName("java.sql.Timestamp"); if (to.isAssignableFrom(c)) { return Types.TIMESTAMP; } } catch (Exception e) {} // TIME try { to = Class.forName("java.sql.Time"); if (to.isAssignableFrom(c)) { return Types.TIMESTAMP; } } catch (Exception e) {} // DATE try { to = Class.forName("java.sql.Date"); if (to.isAssignableFrom(c)) { return Types.DATE; } } catch (Exception e) {} // BLOB try { to = Class.forName("java.sql.Blob"); if (to.isAssignableFrom(c)) { return Types.BLOB; } } catch (Exception e) {} // CLOB try { to = Class.forName("java.sql.Clob"); if (to.isAssignableFrom(c)) { return Types.CLOB; } } catch (Exception e) {} // REF try { to = Class.forName("java.sql.Ref"); if (to.isAssignableFrom(c)) { return Types.REF; } } catch (Exception e) {} // STRUCT try { to = Class.forName("java.sql.Struct"); if (to.isAssignableFrom(c)) { return Types.STRUCT; } } catch (Exception e) {} // LONGVARBINARY : org.hsqldb.Binary is not final if (Binary.class.isAssignableFrom(c)) { return Types.LONGVARBINARY; } // LONGVARCHAR : really OTHER at this point try { // @since JDK1.4 to = Class.forName("java.lang.CharSequence"); if (to.isAssignableFrom(c)) { return Types.LONGVARCHAR; } } catch (Exception e) {} // we have no standard mapping for the specified class // at this point...is it even storable? if (Serializable.class.isAssignableFrom(c)) { // Yes: it is storable, as an OTHER. return Types.OTHER; } // It may (in future, say using bean contract) or may not be storable // (by HSQLDB)... // but then it may be possible to pass to an in-process routine, // so be lenient and just return the most generic type. return Types.JAVA_OBJECT; } } Other HSQLDB examples (source code examples)Here is a short list of links related to this HSQLDB DIProcedureInfo.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.