Author: ppoddar
Date: Tue Apr 30 00:41:14 2013
New Revision: 1477430
URL: http://svn.apache.org/r1477430
Log:
support Stored Procedure
Added:
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/StoredProcedure.java
(with props)
Removed:
openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/StoredProcedure.java
Modified:
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/SQLStoreQuery.java
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Column.java
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/AbstractProcedureList.java
openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/DerbyProcedureList.java
openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/ProcedureList.java
Modified:
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/SQLStoreQuery.java
URL:
http://svn.apache.org/viewvc/openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/SQLStoreQuery.java?rev=1477430&r1=1477429&r2=1477430&view=diff
==============================================================================
---
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/SQLStoreQuery.java
(original)
+++
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/SQLStoreQuery.java
Tue Apr 30 00:41:14 2013
@@ -30,6 +30,7 @@ import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.StringTokenizer;
import org.apache.commons.lang.StringUtils;
import org.apache.openjpa.jdbc.meta.ClassMapping;
@@ -39,7 +40,9 @@ import org.apache.openjpa.jdbc.sql.DBDic
import org.apache.openjpa.jdbc.sql.ResultSetResult;
import org.apache.openjpa.jdbc.sql.SQLBuffer;
import org.apache.openjpa.jdbc.sql.SQLExceptions;
+import org.apache.openjpa.jdbc.sql.StoredProcedure;
import org.apache.openjpa.kernel.AbstractStoreQuery;
+import org.apache.openjpa.kernel.Query;
import org.apache.openjpa.kernel.QueryContext;
import org.apache.openjpa.kernel.StoreQuery;
import org.apache.openjpa.lib.rop.RangeResultObjectProvider;
@@ -58,8 +61,7 @@ import org.apache.openjpa.util.UserExcep
public class SQLStoreQuery
extends AbstractStoreQuery {
- private static final Localizer _loc = Localizer.forPackage
- (SQLStoreQuery.class);
+ private static final Localizer _loc =
Localizer.forPackage(SQLStoreQuery.class);
private transient final JDBCStore _store;
@@ -102,8 +104,8 @@ public class SQLStoreQuery
extends AbstractExecutor {
private final ClassMetaData _meta;
- private final boolean _select;
- private final boolean _call; // native call stored procedure
+ private boolean _select;
+ private boolean _call; // native call stored procedure
private final QueryResultMapping _resultMapping;
public SQLExecutor(SQLStoreQuery q, ClassMetaData candidate) {
@@ -116,19 +118,42 @@ public class SQLStoreQuery
MappingRepository repos = q.getStore().getConfiguration().
getMappingRepositoryInstance();
_resultMapping = repos.getQueryResultMapping
- (ctx.getResultMappingScope(), resultMapping, envLoader,
- true);
+ (ctx.getResultMappingScope(), resultMapping, envLoader,
true);
}
_meta = candidate;
String sql = StringUtils.trimToNull(ctx.getQueryString());
if (sql == null)
throw new UserException(_loc.get("no-sql"));
- _select = q.getStore().getDBDictionary().isSelect(sql);
- _call = sql.length() > 4
- && sql.substring(0, 4).equalsIgnoreCase("call");
+ DBDictionary dict = q.getStore().getDBDictionary();
+ _select = dict.isSelect(sql);
+ if (!_select) {
+ String verb = getSQLVerb(sql);
+
+ _call = "call".equalsIgnoreCase(verb);
+ if (!_call && !("drop".equalsIgnoreCase(verb) ||
"create".equalsIgnoreCase(verb))) {
+
+ Connection conn = q.getStore().getConnection();
+ try {
+ StoredProcedure sp =
dict.getStoredProcedure(conn.getMetaData(), null, null,
+
q.getContext().getQueryString());
+ q.setQuery(sp.getCallSQL());
+ _call = sp != null;
+
((Query)q.getContext()).setQuery(sp.getCallSQL());
+ System.err.println("Call [" + sp.getCallSQL() +
"]");
+ } catch (SQLException ex) {
+ throw new RuntimeException(ex);
+ } finally {
+ try {
+ conn.close();
+ } catch (SQLException ex) {
+
+ }
+ }
+ }
+ }
}
-
+
public int getOperation(StoreQuery q) {
return _select ? OP_SELECT :
(q.getContext().getCandidateType() != null
@@ -141,16 +166,15 @@ public class SQLStoreQuery
public Number executeUpdate(StoreQuery q, Object[] params) {
JDBCStore store = ((SQLStoreQuery) q).getStore();
DBDictionary dict = store.getDBDictionary();
+ // we need to make sure we have an active store connection
+ store.getContext().beginStore();
+ Connection conn = store.getConnection();
String sql = q.getContext().getQueryString();
-
+
List paramList = new ArrayList(Arrays.asList(params));
SQLBuffer buf = new SQLBuffer(dict).append(sql);
- // we need to make sure we have an active store connection
- store.getContext().beginStore();
- Connection conn = store.getConnection();
- JDBCFetchConfiguration fetch = (JDBCFetchConfiguration)
- q.getContext().getFetchConfiguration();
+ JDBCFetchConfiguration fetch =
(JDBCFetchConfiguration)q.getContext().getFetchConfiguration();
PreparedStatement stmnt = null;
try {
@@ -162,7 +186,7 @@ public class SQLStoreQuery
buf.setParameters(paramList);
if (stmnt != null)
buf.setParameters(stmnt);
-
+
dict.setTimeouts(stmnt, fetch, true);
int count = executeUpdate(store, conn, stmnt, buf);
@@ -252,6 +276,7 @@ public class SQLStoreQuery
return q.getContext().getCandidateType() == null;
}
+
/**
* This method is to provide override for non-JDBC or JDBC-like
* implementation of preparing call statement.
@@ -344,16 +369,22 @@ public class SQLStoreQuery
int idx = 0;
for (Integer key : paramOrder) {
if (!userParams.containsKey(key))
- throw new UserException(_loc.get("uparam-missing",
- key, sql, userParams));
+ throw new UserException(_loc.get("uparam-missing", key,
sql, userParams));
result[idx++] = userParams.get(key);
}
// modify original JPA-style SQL to proper SQL
q.getContext().getQuery().setQuery(sql);
return result;
}
+
+ String getSQLVerb(String s) {
+ if (s == null || s.trim().isEmpty())
+ throw new RuntimeException("No SQL verb in [" + s +
"]");
+ return new StringTokenizer(s).nextToken();
+ }
}
-
+ private static final char SINGLE_QUOTE = '\'';
+ private static final char QUESTION_MARK = '?';
/**
* Utility method to substitute '?num' for parameters in the given SQL
* statement, and fill-in the order of the parameter tokens
@@ -362,25 +393,24 @@ public class SQLStoreQuery
throws IOException {
// if there's no "?" parameter marker, then we don't need to
// perform the parsing process
- if (sql.indexOf("?") == -1)
+ if (sql.indexOf(QUESTION_MARK) == -1)
return sql;
paramOrder.clear();
StreamTokenizer tok = new StreamTokenizer(new StringReader(sql));
tok.resetSyntax();
- tok.quoteChar('\'');
+ tok.quoteChar(SINGLE_QUOTE);
tok.wordChars('0', '9');
- tok.wordChars('?', '?');
+ tok.wordChars(QUESTION_MARK, QUESTION_MARK);
StringBuilder buf = new StringBuilder(sql.length());
- for (int ttype; (ttype = tok.nextToken()) !=
- StreamTokenizer.TT_EOF;) {
+ for (int ttype; (ttype = tok.nextToken()) !=
StreamTokenizer.TT_EOF;) {
switch (ttype) {
case StreamTokenizer.TT_WORD:
// a token is a positional parameter if it starts with
// a "?" and the rest of the token are all numbers
- if (tok.sval.startsWith("?")) {
- buf.append("?");
+ if (tok.sval.startsWith(""+QUESTION_MARK)) {
+ buf.append(QUESTION_MARK);
String pIndex = tok.sval.substring(1);
if (pIndex.length() > 0) {
paramOrder.add(Integer.valueOf(pIndex));
@@ -390,11 +420,11 @@ public class SQLStoreQuery
} else
buf.append(tok.sval);
break;
- case'\'':
- buf.append('\'');
+ case '\'':
+ buf.append(SINGLE_QUOTE);
if (tok.sval != null) {
buf.append(tok.sval);
- buf.append('\'');
+ buf.append(SINGLE_QUOTE);
}
break;
default:
Modified:
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Column.java
URL:
http://svn.apache.org/viewvc/openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Column.java?rev=1477430&r1=1477429&r2=1477430&view=diff
==============================================================================
---
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Column.java
(original)
+++
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Column.java
Tue Apr 30 00:41:14 2013
@@ -62,6 +62,9 @@ public class Column
private DBIdentifier _typeName = DBIdentifier.NULL;
private int _javaType = JavaTypes.OBJECT;
private int _size = 0;
+ private int _precision = -1;
+ private int _scale = -1;
+ private int _radix = 10;
private int _decimals = 0;
private String _defaultStr = null;
private Object _default = null;
@@ -376,6 +379,29 @@ public class Column
public void setDecimalDigits(int digits) {
_decimals = digits;
}
+
+ public int getPrecision() {
+ return _precision;
+ }
+
+ public void setPrecision(int p) {
+ _precision = p;
+ }
+
+ public int getScale() {
+ return _scale;
+ }
+
+ public void setScale(int s) {
+ _scale = s;
+ }
+ public int getRadix() {
+ return _radix;
+ }
+
+ public void setRadix(int r) {
+ _radix = r;
+ }
/**
* Return the default value set for the column, if any.
@@ -490,6 +516,22 @@ public class Column
public boolean isNotNullExplicit() {
return _notNull != null;
}
+
+ /**
+ * Sets nullability of this receiver by the given flag.
+ * @param flag one of the JDBC nullability flag namely
+ * <LI> {@link DatabaseMetaData#columnNullableUnknown} : not known if the
column can be set to null value
+ * <LI> {@link DatabaseMetaData#columnNullable} : the column can be set to
null value
+ * <LI> {@link DatabaseMetaData#columnNoNulls} : the column can not be set
to null value
+ */
+ public void setNullability(short flag) {
+ switch (flag) {
+ case DatabaseMetaData.columnNullableUnknown : _notNull = null;
break;
+ case DatabaseMetaData.columnNullable : _notNull = false; break;
+ case DatabaseMetaData.columnNoNulls : _notNull = true; break;
+
+ }
+ }
/**
* Whether this column is auto-assigned a value on insert.
@@ -788,6 +830,12 @@ public class Column
setSize(from.getSize());
if (getDecimalDigits() == 0)
setDecimalDigits(from.getDecimalDigits());
+ if (getScale() == 0)
+ setScale(from.getScale());
+ if (getPrecision() == 0)
+ setPrecision(from.getPrecision());
+ if (getRadix() == 10)
+ setRadix(from.getRadix());
if (getDefaultString() == null)
setDefaultString(from.getDefaultString());
if (!isNotNullExplicit() && from.isNotNullExplicit())
Modified:
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
URL:
http://svn.apache.org/viewvc/openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?rev=1477430&r1=1477429&r2=1477430&view=diff
==============================================================================
---
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
(original)
+++
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
Tue Apr 30 00:41:14 2013
@@ -61,6 +61,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import java.util.TreeMap;
import javax.sql.DataSource;
@@ -4657,6 +4658,54 @@ public class DBDictionary
protected String getGeneratedKeySequenceName(Column col) {
return toDBName(namingUtil.getGeneratedKeySequenceName(col,
maxAutoAssignNameLength));
}
+
+ // Stored Procedures
+// public void getStoredProcedures(DatabaseMetaData meta, DBIdentifier
catalog, DBIdentifier schema)
+// throws SQLException {
+// ResultSet rs = meta.getProcedures(
+// getCatalogNameForMetadata(catalog),
+// getSchemaNameForMetadata(schema),
+// null);
+// while (rs.next()) {
+// String procName = rs.getString(3);
+// ResultSet rs2 = meta.getProcedureColumns(
+// getCatalogNameForMetadata(catalog),
+// getSchemaNameForMetadata(schema),
+// procName,
+// null);
+// StoredProcedureMetaData sp = new StoredProcedureMetaData(rs2);
+//
+// }
+// }
+ protected Map<String, StoredProcedure> _procs = new TreeMap<String,
StoredProcedure>();
+
+ /**
+ * Gets the metadata of the stored procedure by the given name either from
the cached version or
+ * by enquiring the database.
+ * @param meta the database meta data
+ * @param catalog the catalog name or null
+ * @param schema the schema name or null
+ * @param procedure the procedure name
+ * @return metadata about the named procedure or null
+ * @throws SQLException when metadata query goes wrong
+ */
+ public StoredProcedure getStoredProcedure(DatabaseMetaData meta,
DBIdentifier catalog, DBIdentifier schema,
+ String procedure) throws SQLException {
+ if (_procs.containsKey(procedure)) {
+ return _procs.get(procedure);
+ }
+ ResultSet rs = meta.getProcedureColumns(
+ getCatalogNameForMetadata(catalog),
+ getSchemaNameForMetadata(schema),
+ procedure,
+ null);
+ StoredProcedure sp = null;
+ if (rs.next()) {
+ sp = new StoredProcedure(rs);
+ }
+ _procs.put(procedure, sp);
+ return sp;
+ }
///////////////////////////////
// Configurable implementation
Added:
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/StoredProcedure.java
URL:
http://svn.apache.org/viewvc/openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/StoredProcedure.java?rev=1477430&view=auto
==============================================================================
---
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/StoredProcedure.java
(added)
+++
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/StoredProcedure.java
Tue Apr 30 00:41:14 2013
@@ -0,0 +1,315 @@
+/*
+ * 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.identifier.DBIdentifier.DBIdentifierType;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.Schemas;
+/**
+ * Holds metadata about a Stored Procedure.
+ * <br>
+ * 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.
+ * <br>
+ * 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<Column> _cols = new ArrayList<Column>();
+ private List<String> _params = new ArrayList<String>();
+
+
+ private List<String> _sql = new ArrayList<String>();
+ private final boolean _fromDatabase;
+
+ private static enum Action {CREATE, DROP, CALL};
+
+ /**
+ * 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 static enum PARAM {UNKNOW, IN, INOUT, RESULT, OUT, RETURN}
+
+ public static enum SQL {NONE,MODIFY,READ, CONTAINS};
+
+ /**
+ * Create a procedure of the given name.
+ */
+ public StoredProcedure(String name) {
+ _name = DBIdentifier.newProcedure(name);
+ _fromDatabase = false;
+ }
+
+ /**
+ * <pre>
+ *
+ * 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
+ * </pre>
+ **/
+
+ 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), 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));
+ _params.add(col.getIdentifier().getName() + " " +
col.getTypeIdentifier().getName());
+ i++;
+ } while (rs.next());
+ }
+
+ public Column[] getInColumns() {
+ return getColumns((short)DatabaseMetaData.procedureColumnIn);
+ }
+
+ public Column[] getInOutColumns() {
+ return getColumns((short)DatabaseMetaData.procedureColumnInOut);
+ }
+
+ public Column[] getOutColumns() {
+ return getColumns((short)DatabaseMetaData.procedureColumnOut);
+ }
+
+ /**
+ * 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) {
+ List<Column> cols = null;
+ for (Column col : _cols) {
+ if (col.getFlag(flag)) {
+ if (cols == null) cols = new
ArrayList<Column>();
+ 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<String> 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<String> 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.
+ * @param i number of result sets to be read
+ * @param cls the owning classof the method
+ * @param method name of the static method
+ * @param paramTypes argument type of the method
+ * @return
+ */
+ 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");
+ }
+ }
+
+ public String toString() {
+ return getName();
+ }
+}
Propchange:
openjpa/sandboxes/21/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/StoredProcedure.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/AbstractProcedureList.java
URL:
http://svn.apache.org/viewvc/openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/AbstractProcedureList.java?rev=1477430&r1=1477429&r2=1477430&view=diff
==============================================================================
---
openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/AbstractProcedureList.java
(original)
+++
openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/AbstractProcedureList.java
Tue Apr 30 00:41:14 2013
@@ -22,6 +22,8 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
+import org.apache.openjpa.jdbc.sql.StoredProcedure;
+
/*
* holds the stored procedures that will be used by test cases
*/
Modified:
openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/DerbyProcedureList.java
URL:
http://svn.apache.org/viewvc/openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/DerbyProcedureList.java?rev=1477430&r1=1477429&r2=1477430&view=diff
==============================================================================
---
openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/DerbyProcedureList.java
(original)
+++
openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/DerbyProcedureList.java
Tue Apr 30 00:41:14 2013
@@ -23,6 +23,8 @@ import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
+import org.apache.openjpa.jdbc.sql.StoredProcedure;
+
/*
* holds the stored procedures that will be used by test cases
*/
@@ -30,33 +32,54 @@ public class DerbyProcedureList extends
public DerbyProcedureList() {
put(new StoredProcedure("ADD_X_TO_CHARLIE")
- .styleSQL("JAVA")
- .updateSQL(this.getClass(), "addXToCharlie", (Class<?>[])null));
+ .setLanguage("JAVA")
+ .setParameterStyle("JAVA")
+ .setSQL(StoredProcedure.SQL.MODIFY)
+ .setExternalName(this.getClass(), "addXToCharlie",
(Class<?>[])null));
+
put(new StoredProcedure("ADD_SUFFIX_TO_NAME")
- .addParameter("NAME VARCHAR(128)")
- .addParameter("SUFFIX VARCHAR(128)")
- .styleSQL("JAVA")
- .updateSQL(this.getClass(), "addSuffixToName",
String.class, String.class));
+ .addParameter("NAME", "VARCHAR(128)")
+ .addParameter("SUFFIX", "VARCHAR(128)")
+ .setLanguage("JAVA")
+ .setParameterStyle("JAVA")
+ .setExternalName(this.getClass(),
"addSuffixToName", String.class, String.class));
+
put(new StoredProcedure("GET_ALL_APPLICANTS")
- .styleSQL("JAVA")
- .readSQL(1, this.getClass(), "getAllApplicants",
ResultSet[].class));
+ .setLanguage("JAVA")
+ .setParameterStyle("JAVA")
+ .setSQL(StoredProcedure.SQL.READ)
+ .setResult(1)
+ .setExternalName(this.getClass(), "getAllApplicants",
ResultSet[].class));
+
put(new StoredProcedure("GET_TWO_APPLICANTS")
- .addParameter("NAME VARCHAR(128)")
- .addParameter("SUFFIX VARCHAR(128)")
- .styleSQL("JAVA")
- .readSQL(1, this.getClass(), "getTwoApplicants", String.class,
String.class, ResultSet[].class));
+ .addParameter("NAME", "VARCHAR(128)")
+ .addParameter("SUFFIX", "VARCHAR(128)")
+ .setLanguage("JAVA")
+ .setParameterStyle("JAVA")
+ .setResult(1)
+ .setExternalName(this.getClass(), "getTwoApplicants",
String.class, String.class, ResultSet[].class));
+
put(new StoredProcedure("GET_ALL_APPLICANTS_AND_GAMES")
- .styleSQL("JAVA")
- .readSQL(2, this.getClass(), "getAllApplicantsAndGames",
ResultSet[].class, ResultSet[].class));
+ .setLanguage("JAVA")
+ .setParameterStyle("JAVA")
+ .setResult(2)
+ .setExternalName(this.getClass(), "getAllApplicantsAndGames",
ResultSet[].class, ResultSet[].class));
+
put(new StoredProcedure("GET_TWO_APPLICANTS_AND_GAMES")
- .addParameter("NAME VARCHAR(128)")
- .addParameter("SUFFIX VARCHAR(128)")
- .styleSQL("JAVA")
- .readSQL(2, this.getClass(),
"getTwoApplicantsAndGames", String.class,String.class,
+ .addParameter("NAME", "VARCHAR(128)")
+ .addParameter("SUFFIX", "VARCHAR(128)")
+ .setLanguage("JAVA")
+ .setParameterStyle("JAVA")
+ .setResult(2)
+ .setExternalName(this.getClass(),
"getTwoApplicantsAndGames", String.class,String.class,
ResultSet[].class, ResultSet[].class));
}
-
+ /**
+ * This stored procedure accepts no input parameter and produces no return
result.
+ * It updates Applicant's whose name is 'Charlie' to 'CharlieX'
+ * @throws Exception
+ */
public static void addXToCharlie() throws Exception {
Connection conn =
DriverManager.getConnection("jdbc:default:connection");
PreparedStatement ps1 = conn.prepareStatement("update APPLICANT set
name = 'Charliex' "
@@ -66,6 +89,12 @@ public class DerbyProcedureList extends
conn.close();
}
+ /**
+ * This stored procedure accepts one input parameter and produces no
return result.
+ * It updates Applicant's whose name is <N> to <N>+<suffix> where both
+ * <N> and <suffix> are input parameters.
+ * @throws Exception
+ */
public static void addSuffixToName(String name, String suffix)
throws Exception {
Connection conn =
DriverManager.getConnection("jdbc:default:connection");
Modified:
openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/ProcedureList.java
URL:
http://svn.apache.org/viewvc/openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/ProcedureList.java?rev=1477430&r1=1477429&r2=1477430&view=diff
==============================================================================
---
openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/ProcedureList.java
(original)
+++
openjpa/sandboxes/21/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/procedure/ProcedureList.java
Tue Apr 30 00:41:14 2013
@@ -20,6 +20,8 @@ package org.apache.openjpa.persistence.j
import java.util.Collection;
+import org.apache.openjpa.jdbc.sql.StoredProcedure;
+
/**
* Provides a collection of stored procedure definitions
* to be tested.