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

org.apache.openjpa.jdbc.sql.StoredProcedure Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openjpa.jdbc.sql;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.schema.Schemas;
import org.apache.openjpa.meta.MultiQueryMetaData;

/**
 * Holds metadata about a Database Stored Procedure.
 * This is different than {@link MultiQueryMetaData} which holds the metadata
 * about what the user has specified.
 * 
* An instance of this class can be constructed either by reading from database meta data * or by programatic assignment. If an instance if created programmatically, then * its SQL body or parameters can be added. *
* This class can generate the SQL statement to create, drop or delete this procedure. * * * @author Pinaki Poddar * */ public class StoredProcedure { private DBIdentifier _catalog; private DBIdentifier _schema; private DBIdentifier _name; private List _cols = new ArrayList<>(); private List _params = new ArrayList<>(); private List _sql = new ArrayList<>(); private final boolean _fromDatabase; /** * An enumeration on type of parameter for a Stored Procedure. * The enumerted values has the same ordinal numbers as found * in corresponding integer values in {@link DatabaseMetaData}. */ public enum PARAM {UNKNOW, IN, INOUT, RESULT, OUT, RETURN} public enum SQL {NONE,MODIFY,READ, CONTAINS} /** * Create a procedure of the given name. */ public StoredProcedure(String name) { _name = DBIdentifier.newProcedure(name); _fromDatabase = false; } /** *
     *
     * 	1. PROCEDURE_CAT - String - the procedure catalog name
     * 	2. PROCEDURE_SCHEM - String - the procedure schema name (possibly null)
     * 	3. PROCEDURE_NAME - String - the procedure name
     * 	4. COLUMN_NAME - String - the name of the column
     * 	5. COLUMN_TYPE - short - the kind of column or parameter, as follows:
     * 			DatabaseMetaData.procedureColumnUnknown - type unknown
     * 			DatabaseMetaData.procedureColumnIn - an IN parameter
     * 			DatabaseMetaData.procedureColumnInOut - an INOUT parameter
     * 			DatabaseMetaData.procedureColumnOut - an OUT parameter
     * 			DatabaseMetaData.procedureColumnReturn - a return value
     * 			DatabaseMetaData.procedureReturnsResult - a result column in a result set
     * 	6. DATA_TYPE - int - the SQL type of the data, as in java.sql.Types
     * 	7. TYPE_NAME - String - the SQL type name, for a UDT it is fully qualified
     * 	8. PRECISION - int - the precision
     * 	9. LENGTH - int - the length of the data in bytes
     * 	10.SCALE - short - the scale for numeric types
     * 	11.RADIX - short - the Radix for numeric data (typically 2 or 10)
     * 	12.NULLABLE - short - can the data contain null:
     * 			DatabaseMetaData.procedureNoNulls - NULLs not permitted
     * 			DatabaseMetaData.procedureNullable - NULLs are permitted
     * 			DatabaseMetaData.procedureNullableUnknown - NULL status unknown
     * 	13.REMARKS - String - an explanatory comment about the data item
     * 
**/ public StoredProcedure(ResultSet rs) throws SQLException { _fromDatabase = true; int i = 0; do { if (i == 0) { // get stored procedure metadata _catalog = DBIdentifier.newCatalog(rs.getString(1)); _schema = DBIdentifier.newSchema(rs.getString(2)); _name = DBIdentifier.newIdentifier(rs.getString(3), DBIdentifier.DBIdentifierType.PROCEDURE, false); } Column col = new Column(); _cols.add(col); col.setIdentifier(DBIdentifier.newColumn(rs.getString(4))); col.setFlag(rs.getShort(5), true); col.setType(rs.getInt(6)); col.setTypeIdentifier(DBIdentifier.newConstant(rs.getString(7))); col.setPrecision(rs.getInt(8)); col.setSize(rs.getInt(9)); col.setScale(rs.getInt(10)); col.setRadix(rs.getShort(11)); col.setNullability(rs.getShort(12)); col.setComment(rs.getString(13)); col.setIndex(i); _params.add(col.getIdentifier().getName() + " " + col.getTypeIdentifier().getName()); i++; } while (rs.next()); } public void setCatalog(DBIdentifier catalog) { this._catalog = catalog; } public void setSchema(DBIdentifier schema) { this._schema = schema; } public void setName(String name) { this._name = DBIdentifier.newIdentifier(name, DBIdentifier.DBIdentifierType.PROCEDURE, false); } public Column[] getInColumns() { return getColumns((short)DatabaseMetaData.procedureColumnIn); } public Column[] getInOutColumns() { return getColumns((short)DatabaseMetaData.procedureColumnInOut); } public Column[] getOutColumns() { return getColumns((short)DatabaseMetaData.procedureColumnOut); } public Column[] getReturnColumns() { return getColumns((short)DatabaseMetaData.procedureColumnReturn); } public Column[] getResultColumns() { return getColumns((short)DatabaseMetaData.procedureColumnResult); } public Column[] getColumns() { return _cols.toArray(new Column[_cols.size()]); } /** * Counts the number of columns with the given flag. * @param flag * @return */ int countColumn(short flag) { int count = 0; for (Column col : _cols) { if (col.getFlag(flag)) count++; } return count; } Column[] getColumns(short flag) { // TODO: cache? List cols = null; for (Column col : _cols) { if (col.getFlag(flag)) { if (cols == null) cols = new ArrayList<>(); cols.add(col); } } return cols == null ? Schemas.EMPTY_COLUMNS : cols.toArray(new Column[cols.size()]); } /** * Gets the name of this procedure. */ public String getName() { return _name.getName(); } /** * Adds an {@code IN} parameter of the given name and type. * @param var name of the variable * @param typeName name of the SQL type e.g. {@code VARCAR(32)} * @return this procedure instance */ public StoredProcedure addParameter(String var, String typeName) { return addParameter(PARAM.IN, var, typeName); } /** * Adds the given parameter declaration. * * @param param type of parameter. * @param var name of the variable * @param typeName name of the SQL type e.g. {@code VARCAR(32)} * @return this procedure instance */ public StoredProcedure addParameter(PARAM param, String var, String typeName) { assertMutable(); _params.add(param + " " + var + " " + typeName); return this; } public StoredProcedure setLanguage(String language) { _sql.add("LANGUAGE " + language); return this; } /** * Gets the SQL for creating this procedure. */ public String getCreateSQL() { StringBuilder buf = new StringBuilder(); buf.append("CREATE PROCEDURE "); buf.append(_name); buf.append(" ("); for (Iterator p = _params.iterator(); p.hasNext();) { buf.append(p.next()); buf.append(p.hasNext() ? "," : ""); } buf.append(") "); //buf.append("("); for (String s : _sql) { buf.append(s).append(" "); } //buf.append(")"); return buf.toString().trim(); } /** * Gets the SQL for dropping this procedure. */ public String getDropSQL() { return "DROP PROCEDURE " + _name; } /** * Gets the SQL for calling this procedure. */ public String getCallSQL() { StringBuilder buf = new StringBuilder(); buf.append("CALL "); buf.append(_name); buf.append(" ("); for (Iterator p = _params.iterator(); p.hasNext();) { p.next(); buf.append("?"); if (p.hasNext()) buf.append(","); } buf.append(")"); return buf.toString().trim(); } /** * Adds a read SQL statement via an external method. */ public StoredProcedure setSQL(SQL sql) { switch (sql) { case CONTAINS : _sql.add("CONTAINS SQL"); break; case NONE : _sql.add("NO SQL"); break; case MODIFY : _sql.add("MODIFIES SQL DATA"); break; case READ : _sql.add("READS SQL DATA"); break; } return this; } /** * Sets the language whose parameter passing convention will be used to pass paramater values. * @param lang * @return */ public StoredProcedure setParameterStyle(String lang) { _sql.add("PARAMETER STYLE " + lang); return this; } public StoredProcedure setExternalName(Class cls, String method, Class... paramTypes) { assertStaticMethod(cls, method, paramTypes); _sql.add("EXTERNAL NAME '" + cls.getName() + '.' + method + "'"); return this; } public StoredProcedure setResult(int i) { return setResult(i, false); } public StoredProcedure setResult(int i, boolean dynamic) { assertMutable(); _sql.add((dynamic ? "DYNAMIC " : "") + "RESULT SETS " + i); return this; } private void assertStaticMethod(Class cls, String method, Class...paramTypes) { try { Method m = cls.getMethod(method, paramTypes); if (m == null || !Modifier.isStatic(m.getModifiers())) { throw new RuntimeException("No static method " + method + " with arguments " + Arrays.toString(paramTypes) + " in " + cls); } } catch (Exception ex) { throw new RuntimeException("No static method " + method + " with arguments " + Arrays.toString(paramTypes) + " in " + cls, ex); } } private void assertMutable() { if (_fromDatabase) { throw new IllegalStateException(this + " is not mutable"); } } @Override public String toString() { return getName(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy