001: /*
002:
003: Derby - Class org.apache.derby.catalog.GetProcedureColumns
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to You under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.catalog;
023:
024: import java.sql.Types;
025: import java.lang.reflect.*;
026: import java.sql.ResultSetMetaData;
027: import java.sql.SQLException;
028: import java.sql.DatabaseMetaData;
029: import org.apache.derby.catalog.TypeDescriptor;
030:
031: import org.apache.derby.iapi.types.DataTypeDescriptor;
032: import org.apache.derby.iapi.types.DataTypeUtilities;
033: import org.apache.derby.iapi.sql.ResultColumnDescriptor;
034: import org.apache.derby.impl.jdbc.EmbedResultSetMetaData;
035: import org.apache.derby.catalog.types.RoutineAliasInfo;
036:
037: import org.apache.derby.shared.common.reference.JDBC40Translation;
038:
039: /**
040: <P>Use of VirtualTableInterface to provide support for
041: DatabaseMetaData.getProcedureColumns().
042:
043:
044: <P>This class is called from a Query constructed in
045: java/org.apache.derby.impl.jdbc/metadata.properties:
046: <PRE>
047:
048:
049: <P>The VTI will return columns 3-14, an extra column to the specification
050: METHOD_ID is returned to distinguish between overloaded methods.
051:
052: <OL>
053: <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
054: <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
055: <LI><B>PROCEDURE_NAME</B> String => procedure name
056: <LI><B>COLUMN_NAME</B> String => column/parameter name
057: <LI><B>COLUMN_TYPE</B> Short => kind of column/parameter:
058: <UL>
059: <LI> procedureColumnUnknown - nobody knows
060: <LI> procedureColumnIn - IN parameter
061: <LI> procedureColumnInOut - INOUT parameter
062: <LI> procedureColumnOut - OUT parameter
063: <LI> procedureColumnReturn - procedure return value
064: <LI> procedureColumnResult - result column in ResultSet
065: </UL>
066: <LI><B>DATA_TYPE</B> int => SQL type from java.sql.Types
067: <LI><B>TYPE_NAME</B> String => SQL type name, for a UDT type the
068: type name is fully qualified
069: <LI><B>PRECISION</B> int => precision
070: <LI><B>LENGTH</B> int => length in bytes of data
071: <LI><B>SCALE</B> short => scale
072: <LI><B>RADIX</B> short => radix
073: <LI><B>NULLABLE</B> short => can it contain NULL?
074: <UL>
075: <LI> procedureNoNulls - does not allow NULL values
076: <LI> procedureNullable - allows NULL values
077: <LI> procedureNullableUnknown - nullability unknown
078: </UL>
079: <LI><B>REMARKS</B> String => comment describing parameter/column
080: <LI><B>METHOD_ID</B> Short => cloudscape extra column (overloading)
081: <LI><B>PARAMETER_ID</B> Short => cloudscape extra column (output order)
082: </OL>
083:
084: */
085:
086: public class GetProcedureColumns extends
087: org.apache.derby.vti.VTITemplate {
088: private boolean isFunction;
089:
090: private int translate(int val) {
091: if (!isFunction) {
092: return val;
093: }
094: switch (val) {
095: case DatabaseMetaData.procedureColumnUnknown:
096: return JDBC40Translation.FUNCTION_PARAMETER_UNKNOWN;
097: case DatabaseMetaData.procedureColumnIn:
098: return JDBC40Translation.FUNCTION_PARAMETER_IN;
099: case DatabaseMetaData.procedureColumnInOut:
100: return JDBC40Translation.FUNCTION_PARAMETER_INOUT;
101: case DatabaseMetaData.procedureColumnOut:
102: return JDBC40Translation.FUNCTION_PARAMETER_OUT;
103: case DatabaseMetaData.procedureColumnReturn:
104: return JDBC40Translation.FUNCTION_RETURN;
105: default:
106: return JDBC40Translation.FUNCTION_PARAMETER_UNKNOWN;
107: }
108: }
109:
110: private boolean isProcedure;
111: // state for procedures.
112: private RoutineAliasInfo procedure;
113: private int paramCursor;
114: private short method_count;
115: private short param_number;
116:
117: private TypeDescriptor sqlType;
118: private String columnName;
119: private short columnType;
120: private final short nullable;
121:
122: public ResultSetMetaData getMetaData() {
123: return metadata;
124: }
125:
126: //
127: // Instantiates the vti given a class name and methodname.
128: //
129: // @exception SQLException Thrown if there is a SQL error.
130: //
131: //
132: public GetProcedureColumns(AliasInfo aliasInfo, String aliasType)
133: throws SQLException {
134: // compile time aliasInfo will be null.
135: if (aliasInfo != null) {
136: isProcedure = aliasType.equals("P");
137: isFunction = aliasType.equals("F");
138: procedure = (RoutineAliasInfo) aliasInfo;
139: method_count = (short) procedure.getParameterCount();
140: }
141: if (aliasType == null) {
142: nullable = 0;
143: return;
144: }
145:
146: if (isFunction) {
147: nullable = (short) JDBC40Translation.FUNCTION_NULLABLE;
148: sqlType = procedure.getReturnType();
149: columnName = ""; // COLUMN_NAME is VARCHAR NOT NULL
150: columnType = (short) JDBC40Translation.FUNCTION_RETURN;
151: paramCursor = -2;
152: return;
153: }
154: nullable = (short) DatabaseMetaData.procedureNullable;
155:
156: paramCursor = -1;
157: }
158:
159: public boolean next() throws SQLException {
160: if (++paramCursor >= procedure.getParameterCount())
161: return false;
162:
163: if (paramCursor > -1) {
164: sqlType = procedure.getParameterTypes()[paramCursor];
165: columnName = procedure.getParameterNames()[paramCursor];
166: columnType = (short) translate(procedure
167: .getParameterModes()[paramCursor]);
168: }
169: param_number = (short) paramCursor;
170: return true;
171: }
172:
173: //
174: // Get the value of the specified data type from a column.
175: //
176: // @exception SQLException Thrown if there is a SQL error.
177: //
178: //
179: public String getString(int column) throws SQLException {
180: switch (column) {
181: case 1: // COLUMN_NAME:
182: return columnName;
183:
184: case 4: //_TYPE_NAME:
185: return sqlType.getTypeName();
186:
187: case 10: // REMARKS:
188: return null;
189:
190: default:
191: return super .getString(column); // throw exception
192: }
193: }
194:
195: //
196: // Get the value of the specified data type from a column.
197: //
198: // @exception SQLException Thrown if there is a SQL error.
199: //
200: //
201: public int getInt(int column) throws SQLException {
202: switch (column) {
203: case 3: // DATA_TYPE:
204: if (sqlType != null) {
205: return sqlType.getJDBCTypeId();
206: }
207: return java.sql.Types.JAVA_OBJECT;
208:
209: case 5: // PRECISION:
210: if (sqlType != null) {
211: int type = sqlType.getJDBCTypeId();
212: if (DataTypeDescriptor.isNumericType(type))
213: return sqlType.getPrecision();
214: else if (type == Types.DATE || type == Types.TIME
215: || type == Types.TIMESTAMP)
216: return DataTypeUtilities.getColumnDisplaySize(type,
217: -1);
218: else
219: return sqlType.getMaximumWidth();
220: }
221:
222: // No corresponding SQL type
223: return 0;
224:
225: case 6: // LENGTH (in bytes):
226: if (sqlType != null)
227: return sqlType.getMaximumWidthInBytes();
228:
229: // No corresponding SQL type
230: return 0;
231:
232: default:
233: return super .getInt(column); // throw exception
234: }
235: }
236:
237: //
238: // Get the value of the specified data type from a column.
239: //
240: // @exception SQLException Thrown if there is a SQL error.
241: //
242: //
243: public short getShort(int column) throws SQLException {
244: switch (column) {
245: case 2: // COLUMN_TYPE:
246: return columnType;
247:
248: case 7: // SCALE:
249: if (sqlType != null)
250: return (short) sqlType.getScale();
251:
252: // No corresponding SQL type
253: return 0;
254:
255: case 8: // RADIX:
256: if (sqlType != null) {
257: int sqlTypeID = sqlType.getJDBCTypeId();
258: if (sqlTypeID == java.sql.Types.REAL
259: || sqlTypeID == java.sql.Types.FLOAT
260: || sqlTypeID == java.sql.Types.DOUBLE) {
261: return 2;
262: }
263: return 10;
264: }
265:
266: // No corresponding SQL type
267: return 0;
268:
269: //FIXME
270: case 9: // NULLABLE:
271: return nullable;
272:
273: case 11: // METHOD_ID:
274: return method_count;
275:
276: case 12: // PARAMETER_ID:
277: return param_number;
278:
279: default:
280: return super .getShort(column); // throw exception
281: }
282: }
283:
284: public void close() {
285: }
286:
287: /*
288: ** Metadata
289: */
290: private static final ResultColumnDescriptor[] columnInfo = {
291:
292: EmbedResultSetMetaData.getResultColumnDescriptor(
293: "COLUMN_NAME", Types.VARCHAR, false, 128),
294: EmbedResultSetMetaData.getResultColumnDescriptor(
295: "COLUMN_TYPE", Types.SMALLINT, false),
296: EmbedResultSetMetaData.getResultColumnDescriptor(
297: "DATA_TYPE", Types.INTEGER, false),
298: EmbedResultSetMetaData.getResultColumnDescriptor(
299: "TYPE_NAME", Types.VARCHAR, false, 22),
300: EmbedResultSetMetaData.getResultColumnDescriptor(
301: "PRECISION", Types.INTEGER, false),
302: EmbedResultSetMetaData.getResultColumnDescriptor("LENGTH",
303: Types.INTEGER, false),
304: EmbedResultSetMetaData.getResultColumnDescriptor("SCALE",
305: Types.SMALLINT, false),
306:
307: EmbedResultSetMetaData.getResultColumnDescriptor("RADIX",
308: Types.SMALLINT, false),
309: EmbedResultSetMetaData.getResultColumnDescriptor(
310: "NULLABLE", Types.SMALLINT, false),
311: EmbedResultSetMetaData.getResultColumnDescriptor("REMARKS",
312: Types.VARCHAR, true, 22),
313: EmbedResultSetMetaData.getResultColumnDescriptor(
314: "METHOD_ID", Types.SMALLINT, false),
315: EmbedResultSetMetaData.getResultColumnDescriptor(
316: "PARAMETER_ID", Types.SMALLINT, false), };
317: private static final ResultSetMetaData metadata = new EmbedResultSetMetaData(
318: columnInfo);
319: }
|