Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / drda / org / apache / derby / impl / drda / DRDAStatement.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/drda/org/apache/derby/impl/drda/DRDAStatement.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/drda/org/apache/derby/impl/drda/DRDAStatement.java
new file mode 100644 (file)
index 0000000..f757a81
--- /dev/null
@@ -0,0 +1,1834 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.drda.DRDAStatement\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.drda;\r
+\r
+import java.io.IOException;\r
+import java.io.UnsupportedEncodingException;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+import java.math.BigInteger;\r
+import java.sql.CallableStatement;\r
+import java.sql.Connection;\r
+import java.sql.ParameterMetaData;\r
+import java.sql.PreparedStatement;\r
+import java.sql.ResultSet;\r
+import java.sql.SQLException;\r
+import java.sql.Statement;\r
+import java.util.ArrayList;\r
+import java.util.Hashtable;\r
+import java.util.StringTokenizer;\r
+import java.util.Vector;\r
+import java.lang.reflect.Array;\r
+\r
+import org.apache.derby.iapi.jdbc.BrokeredConnection;\r
+import org.apache.derby.iapi.jdbc.BrokeredPreparedStatement;\r
+import org.apache.derby.iapi.jdbc.EnginePreparedStatement;\r
+import org.apache.derby.iapi.reference.JDBC30Translation;\r
+import org.apache.derby.iapi.sql.execute.ExecutionContext;\r
+import org.apache.derby.iapi.util.StringUtil;\r
+import org.apache.derby.impl.jdbc.Util;\r
+\r
+/**\r
+       DRDAStatement stores information about the statement being executed\r
+*/\r
+class DRDAStatement\r
+{\r
+\r
+       //NOTE!\r
+       //\r
+       // Since DRDAStatements are reused, ALL variables (except those noted in \r
+       // the comments for reset method) should be set to their default values \r
+       // in reset().\r
+       \r
+\r
+       protected String typDefNam;             //TYPDEFNAM for this statement\r
+       protected int byteOrder;                //deduced from typDefNam, save String comparisons\r
+       protected int ccsidSBC;                 //CCSID for single byte characters\r
+       protected int ccsidDBC;                 //CCSID for double byte characters\r
+       protected int ccsidMBC;                 //CCSID for mixed byte characters\r
+       protected String ccsidSBCEncoding;      //Java encoding for CCSIDSBC\r
+       protected String ccsidDBCEncoding;      //Java encoding for CCSIDDBC\r
+       protected String ccsidMBCEncoding;      //Java encoding for CCSIDMBC\r
+\r
+       protected Database database;            // Database this statement is created for\r
+       private   Pkgnamcsn pkgnamcsn;          // Package name/section # and  consistency token\r
+       protected ConsistencyToken pkgcnstkn;       // Consistency token for the first result set\r
+       protected String pkgid;              // package id\r
+       protected int pkgsn;            // section number\r
+       int withHoldCursor = -1;         // hold cursor after commit attribute.\r
+       protected int isolationLevel;         //JCC isolation level for Statement\r
+       protected String cursorName;\r
+       protected int scrollType = ResultSet.TYPE_FORWARD_ONLY;                 // Sensitive or Insensitive scroll attribute\r
+       protected int concurType = ResultSet.CONCUR_READ_ONLY;;                 // Concurency type\r
+       protected long rowCount;                        // Number of rows we have processed\r
+       protected byte [] rslsetflg;            // Result Set Flags\r
+       protected int maxrslcnt;                        // Maximum Result set count\r
+       protected PreparedStatement ps;     // Prepared statement\r
+       protected ParameterMetaData stmtPmeta; // param metadata\r
+       protected boolean isCall;\r
+       protected String procName;                      // callable statement's method name\r
+       private   int[] outputTypes;            // jdbc type for output parameter or NOT_OUTPUT_PARAM\r
+                                           // if not an output parameter.\r
+       private int[] outputPrecision;\r
+       private int[] outputScale;\r
+        \r
+       protected static int NOT_OUTPUT_PARAM = -100000;\r
+       protected boolean outputExpected;       // expect output from a callable statement\r
+       private Statement stmt;                         // SQL statement\r
+\r
+\r
+       private DRDAResultSet currentDrdaRs;  // Current ResultSet\r
+       private Hashtable resultSetTable;     // Hashtable with resultsets            \r
+       private ArrayList resultSetKeyList;  // ordered list of hash keys\r
+       private int numResultSets = 0;  \r
+\r
+       /** This class is used to keep track of the statement's parameters\r
+        * as they are received from the client. It uses arrays to track\r
+        * the DRDA type, the length in bytes and the externalness of each\r
+        * parameter. Arrays of int/byte are used rather than ArrayLists\r
+        * of Integer/Byte in order to re-use the same storage each time\r
+        * the statement is executed. */\r
+       private static class DrdaParamState {\r
+               // The last parameter may be streamed. \r
+               // We need to keep a record of it so we can drain it if it is not \r
+               // used.\r
+               // Only the last parameter with an EXTDTA will be streamed. \r
+               //(See DRDAConnThread.readAndSetAllExtParams()). \r
+               private EXTDTAReaderInputStream streamedParameter = null;\r
+               private int typeLstEnd_ = 0;\r
+               private byte[] typeLst_ = new byte[10];\r
+               private int[]  lenLst_ = new int[10];\r
+               private int extLstEnd_ = 0;\r
+               private int[]  extLst_ = new int[10];\r
+\r
+               private static Object growArray(Object array) {\r
+                       final int oldLen = Array.getLength(array);\r
+                       Object tmp =\r
+                               Array.newInstance(array.getClass().getComponentType(),\r
+                                                                 Math.max(oldLen,1)*2);\r
+                       System.arraycopy(array, 0, tmp, 0, oldLen);\r
+                       return tmp;\r
+               }\r
+\r
+               /**\r
+                * <code>clear</code> resets the arrays so that new parameters\r
+                * will be added at the beginning. No initialization or\r
+                * releasing of storage takes place unless the trim argument\r
+                * is true.\r
+                *\r
+                * @param trim - if true; release excess storage\r
+                */\r
+               protected void clear(boolean trim) {\r
+                       streamedParameter = null;\r
+                       typeLstEnd_ = 0;\r
+                       extLstEnd_ = 0;\r
+                       if (trim && typeLst_.length > 10) {\r
+                               typeLst_ = new byte[10];\r
+                               lenLst_ = new int[10];\r
+                               extLst_ = new int[10];\r
+                       }\r
+               }\r
+\r
+               /**\r
+                * <code>addDrdaParam</code> adds a new parameter with its\r
+                * DRDA type and byte length. The arrays are automatically\r
+                * grown if needed.\r
+                *\r
+                * @param t a <code>byte</code> value, the DRDA type of the\r
+                * parameter being added\r
+                * @param s an <code>int</code> value, the length in bytes of\r
+                * the parameter being added\r
+                */\r
+               protected void addDrdaParam(byte t, int s) {\r
+                       if (typeLstEnd_ >= typeLst_.length) {\r
+                               typeLst_ = (byte[])growArray(typeLst_);\r
+                               lenLst_ = (int[])growArray(lenLst_);\r
+                       }\r
+                       typeLst_[typeLstEnd_] = t;\r
+                       lenLst_[typeLstEnd_] = s;\r
+                       ++typeLstEnd_;\r
+               }\r
+\r
+               /**\r
+                * <code>getDrdaParamCount</code> return the number of\r
+                * parameters added so far (since last clear).\r
+                *\r
+                * @return an <code>int</code> value, the number of parameters\r
+                */\r
+               protected int  getDrdaParamCount() { return typeLstEnd_; }\r
+\r
+               /**\r
+                * <code>getDrdaType</code> returns a byte that represents the\r
+                * DRDA type of the ith parameter.\r
+                *\r
+                * @param i an <code>int</code> value, a parameter position\r
+                * (zero-based)\r
+                * @return a <code>byte</code> value, the DRDA type\r
+                */\r
+               protected byte getDrdaType(int i) { return typeLst_[i]; }\r
+\r
+               /**\r
+                * <code>getDrdaLen</code> returns the length in bytes of the\r
+                * ith parameter.\r
+                *\r
+                * @param i an <code>int</code> value, a parameter position\r
+                * (zero-based)\r
+                * @return an <code>int</code> value\r
+                */\r
+               protected int getDrdaLen(int i) { return lenLst_[i]; }\r
+\r
+               /**\r
+                * <code>addExtPos</code> marks parameter i as external. The\r
+                * array is grown as needed.\r
+                *\r
+                * @param p an <code>int</code> value, a parameter position\r
+                * (zero-based)\r
+                */\r
+               protected void addExtPos(int p) {\r
+                       if (extLstEnd_ >= extLst_.length) {\r
+                               extLst_ = (int[])growArray(extLst_);\r
+                       }\r
+                       extLst_[extLstEnd_] = p;\r
+                       ++extLstEnd_;\r
+               }\r
+\r
+               /**\r
+                * <code>getExtPosCount</code> returns the number of\r
+                * parameters marked as external so far (since last clear).\r
+                *\r
+                * @return an <code>int</code> value, the number of external\r
+                * parameters.\r
+                */\r
+               protected int getExtPosCount() { return extLstEnd_; }\r
+\r
+               /**\r
+                * <code>getExtPos</code> returns the actual parameter position\r
+                * of the ith external parameter.\r
+                *\r
+                * @param i an <code>int</code> value, index into the list of\r
+                * external parameters, zero-based\r
+                * @return an <code>int</code> value, the parameter position\r
+                * of the ith external parameter (zero-based)\r
+                */\r
+               protected int getExtPos(int i) { return extLst_[i]; }\r
+        \r
+               /**\r
+                * Read the rest of the streamed parameter if not consumed\r
+                * by the executing statement.  DERBY-3085\r
+                * @throws IOException\r
+                */\r
+               protected void drainStreamedParameter() throws IOException\r
+               {\r
+                       if (streamedParameter != null)\r
+                       {   \r
+                               // we drain the buffer 1000 bytes at a time.\r
+                               // 1000 is just a random selection that doesn't take\r
+                               // too much memory. Perhaps something else would be \r
+                               // more efficient?\r
+                               byte[] buffer = new byte[1000];\r
+                               int i;\r
+                               do {\r
+                                       i= streamedParameter.read(buffer,0,1000);\r
+                               }  while (i != -1);\r
+                       }\r
+               }\r
+            \r
+\r
+               public void setStreamedParameter(EXTDTAReaderInputStream eis) {\r
+                       streamedParameter = eis;    \r
+               }\r
+               \r
+       }\r
+       private DrdaParamState drdaParamState_ = new DrdaParamState();\r
+\r
+       // Query options  sent on EXCSQLSTT\r
+       // These the default for ResultSets created for this statement.\r
+       // These can be overriden by OPNQRY or CNTQRY,\r
+       protected int nbrrow;                   // number of fetch or insert rows\r
+       protected int qryrowset;                        // Query row set\r
+       protected int blksize;                          // Query block size\r
+       protected int maxblkext;                        // Maximum number of extra blocks\r
+       protected int outovropt;                        // Output Override option\r
+       protected boolean qryrfrtbl;            // Query refresh answer set table\r
+       private int qryprctyp = CodePoint.QRYBLKCTL_DEFAULT;   // Protocol type\r
+       \r
+       \r
+\r
+       boolean needsToSendParamData = false;\r
+       boolean explicitlyPrepared = false;    //Prepared with PRPSQLSTT (reusable) \r
+\r
+       // constructor\r
+       /**\r
+        * DRDAStatement constructor\r
+        *\r
+        * @param database\r
+        * \r
+        */\r
+       DRDAStatement (Database database) \r
+       {\r
+               this.database = database;\r
+               setTypDefValues();\r
+               this.currentDrdaRs = new DRDAResultSet();\r
+       }\r
+\r
+       /**\r
+        * set TypDef values\r
+        *\r
+        */\r
+       protected void setTypDefValues()\r
+       {\r
+               // initialize statement values to current database values\r
+               this.typDefNam = database.typDefNam;\r
+               this.byteOrder = database.byteOrder;\r
+               this.ccsidSBC = database.ccsidSBC;\r
+               this.ccsidDBC = database.ccsidDBC;\r
+               this.ccsidMBC = database.ccsidMBC;\r
+               this.ccsidSBCEncoding = database.ccsidSBCEncoding;\r
+               this.ccsidDBCEncoding = database.ccsidDBCEncoding;\r
+               this.ccsidMBCEncoding = database.ccsidMBCEncoding;\r
+       }\r
+       /**\r
+        * Set database\r
+        *\r
+        * @param database\r
+        */\r
+       protected void setDatabase(Database database)\r
+       {\r
+               this.database = database;\r
+               setTypDefValues();\r
+       }\r
+       /**\r
+        * Set statement\r
+        *\r
+        * @param conn  Connection\r
+        * @exception SQLException\r
+        */\r
+       protected void setStatement(Connection conn)\r
+               throws SQLException\r
+       {\r
+               stmt = conn.createStatement();\r
+               //beetle 3849 -  see  prepareStatement for details\r
+               if (cursorName != null)\r
+                       stmt.setCursorName(cursorName);\r
+       }\r
+       /**\r
+        * Get the statement\r
+        *\r
+        * @return statement\r
+        * @exception SQLException\r
+        */\r
+       protected Statement getStatement() \r
+               throws SQLException\r
+       {\r
+               return stmt;\r
+       }\r
+\r
+       /**Set resultSet defaults to match \r
+        * the statement defaults sent on EXCSQLSTT\r
+        * This might be overridden on OPNQRY or CNTQRY\r
+        **/\r
+\r
+       protected void setRsDefaultOptions(DRDAResultSet drs)\r
+       {\r
+               drs.nbrrow = nbrrow;\r
+               drs.qryrowset = qryrowset;\r
+               drs.blksize = blksize;\r
+               drs.maxblkext = maxblkext;\r
+               drs.outovropt = outovropt;\r
+               drs.rslsetflg = rslsetflg;\r
+               drs.scrollType = scrollType;\r
+               drs.concurType = concurType;\r
+               drs.setQryprctyp(qryprctyp);\r
+               drs.qryrowset = qryrowset;\r
+       }\r
+\r
+       /**\r
+        * Get the extData Objects\r
+        *\r
+        *  @return ArrayList with extdta\r
+        */\r
+       protected ArrayList getExtDtaObjects()\r
+       {\r
+               return currentDrdaRs.getExtDtaObjects();\r
+       }\r
+\r
+       /**\r
+        * Set the extData Objects\r
+        */\r
+       protected void  setExtDtaObjects(ArrayList a)\r
+       {\r
+               currentDrdaRs.setExtDtaObjects(a);\r
+       }\r
+\r
+       public void setSplitQRYDTA(byte []data)\r
+       {\r
+               currentDrdaRs.setSplitQRYDTA(data);\r
+       }\r
+       public byte[]getSplitQRYDTA()\r
+       {\r
+               return currentDrdaRs.getSplitQRYDTA();\r
+       }\r
+       \r
+       /**\r
+        * Add extDtaObject\r
+        * @param o - object to  add\r
+        * @param jdbcIndex - jdbc index for parameter\r
+        */\r
+       protected void  addExtDtaObject (Object o, int jdbcIndex )\r
+       {\r
+               currentDrdaRs.addExtDtaObject(o,jdbcIndex);\r
+       }\r
+\r
+       \r
+       /**\r
+        * Clear externalized lob objects in current result set\r
+        */\r
+       protected void  clearExtDtaObjects ()\r
+       {\r
+               currentDrdaRs.clearExtDtaObjects();\r
+       }\r
+\r
+       /**\r
+        *\r
+        *  get resultSetHoldability.\r
+        * \r
+        * @return the resultSet holdability for the prepared statement\r
+        *\r
+        */\r
+       protected int getResultSetHoldability() throws SQLException\r
+       {\r
+               return getResultSetHoldability(getResultSet());\r
+       }\r
+       \r
+       /**\r
+        *\r
+        *  get resultSetHoldability.\r
+        * \r
+        * @param rs ResultSet \r
+        * @return the resultSet holdability for the prepared statement\r
+        *\r
+        */\r
+       int getResultSetHoldability(ResultSet rs) throws SQLException\r
+       {\r
+               Statement rsstmt;\r
+\r
+               if (rs  != null)\r
+                       rsstmt = rs.getStatement();\r
+               else\r
+                       rsstmt = getPreparedStatement();\r
+        \r
+        return rsstmt.getResultSetHoldability();\r
+       }       \r
+\r
+       /*\r
+        * Is lob object nullable\r
+        * @param index - offset starting with 0\r
+        * @return true if object is nullable\r
+        */\r
+       protected boolean isExtDtaValueNullable(int index)\r
+       {\r
+               return currentDrdaRs.isExtDtaValueNullable(index);\r
+       }\r
+       \r
+\r
+       /**\r
+        * Set query options sent on OPNQRY and pass options down to the\r
+        * current <code>DRDAResultSet</code> object.\r
+        *\r
+        * @param blksize QRYBLKSZ (Query Block Size)\r
+        * @param qryblkctl QRYPRCTYP (Query Protocol Type)\r
+        * @param maxblkext MAXBLKEXT (Maximum Number of Extra Blocks)\r
+        * @param outovropt OUTOVROPT (Output Override Option)\r
+        * @param qryrowset QRYROWSET (Query Rowset Size)\r
+        * @param qryclsimpl QRYCLSIMP (Query Close Implicit)\r
+        * @see DRDAResultSet#setOPNQRYOptions(int, int, int, int, int, int)\r
+        */\r
+       protected void setOPNQRYOptions(int blksize, int qryblkctl,\r
+                                                                 int maxblkext, int outovropt,int qryrowset,int qryclsimpl)\r
+       {\r
+               this.blksize = blksize;\r
+               this.qryprctyp = qryblkctl;\r
+               this.maxblkext = maxblkext;\r
+               this.outovropt = outovropt;\r
+               this.qryrowset = qryrowset;\r
+               currentDrdaRs.setOPNQRYOptions( blksize, qryblkctl, maxblkext, \r
+                               outovropt, qryrowset, qryclsimpl);\r
+       }\r
+\r
+       /*\r
+        * Set query options sent on CNTQRY\r
+        */\r
+       protected void setQueryOptions(int blksize, boolean qryrelscr, \r
+                                                                       long qryrownbr,\r
+                                                                       boolean qryfrtbl,int nbrrow,int maxblkext,\r
+                                                                       int qryscrorn, boolean qryrowsns,\r
+                                                                       boolean qryblkrst,\r
+                                                                       boolean qryrtndta,int qryrowset,\r
+                                                                       int rtnextdta)\r
+       {\r
+               currentDrdaRs.blksize = blksize;\r
+               currentDrdaRs.qryrelscr = qryrelscr;\r
+               currentDrdaRs.qryrownbr = qryrownbr;\r
+               currentDrdaRs.qryrfrtbl = qryrfrtbl;\r
+               currentDrdaRs.nbrrow = nbrrow;\r
+               currentDrdaRs.maxblkext = maxblkext;\r
+               currentDrdaRs.qryscrorn = qryscrorn;\r
+               currentDrdaRs.qryrowsns = qryrowsns;\r
+               currentDrdaRs.qryblkrst = qryblkrst;\r
+               currentDrdaRs.qryrtndta = qryrtndta;\r
+               currentDrdaRs.qryrowset = qryrowset;\r
+               currentDrdaRs.rtnextdta = rtnextdta;\r
+       }\r
+\r
+\r
+\r
+       protected void setQryprctyp(int qryprctyp)\r
+       {\r
+               this.qryprctyp = qryprctyp;\r
+               currentDrdaRs.setQryprctyp(qryprctyp);\r
+       }\r
+\r
+       protected int  getQryprctyp()\r
+               throws SQLException\r
+       {\r
+               return currentDrdaRs.getQryprctyp();\r
+       }\r
+\r
+       protected void setQryrownbr(long qryrownbr)\r
+       {\r
+               currentDrdaRs.qryrownbr = qryrownbr;\r
+       }\r
+\r
+       protected long  getQryrownbr()\r
+       {\r
+               return currentDrdaRs.qryrownbr;\r
+       }\r
+\r
+\r
+       protected int  getQryrowset()\r
+       {\r
+               return currentDrdaRs.qryrowset;\r
+       }\r
+\r
+       \r
+       protected int getBlksize()\r
+       {\r
+               return currentDrdaRs.blksize;\r
+       }\r
+\r
+       protected void setQryrtndta(boolean qryrtndta)\r
+       {\r
+               currentDrdaRs.qryrtndta = qryrtndta;\r
+       }\r
+\r
+       protected boolean  getQryrtndta()\r
+       {\r
+               return currentDrdaRs.qryrtndta;\r
+       }\r
+\r
+\r
+       protected void setQryscrorn(int qryscrorn)\r
+       {\r
+               currentDrdaRs.qryscrorn = qryscrorn;\r
+       }\r
+\r
+       protected int  getQryscrorn()\r
+       {\r
+               return currentDrdaRs.qryscrorn;\r
+       }\r
+\r
+       protected void setScrollType(int scrollType)\r
+       {\r
+               currentDrdaRs.scrollType = scrollType;\r
+       }\r
+\r
+       protected int  getScrollType()\r
+       {\r
+               return currentDrdaRs.scrollType;\r
+       }\r
+\r
+       /** \r
+        * is this a scrollable cursor?\r
+        * return true if this is not a forward only cursor\r
+        */\r
+       protected boolean isScrollable()\r
+       {\r
+               return (getScrollType() != ResultSet.TYPE_FORWARD_ONLY);\r
+       }\r
+\r
+       protected void setConcurType(int scrollType)\r
+       {\r
+               currentDrdaRs.concurType = scrollType;\r
+       }\r
+\r
+       protected int  getConcurType()\r
+       {\r
+               return currentDrdaRs.concurType;\r
+       }\r
+\r
+       protected void  setOutovr_drdaType(int[] outovr_drdaType) \r
+       {\r
+          currentDrdaRs.outovr_drdaType = outovr_drdaType;\r
+       }\r
+\r
+\r
+       protected int[]         getOutovr_drdaType() \r
+       {\r
+               return currentDrdaRs.outovr_drdaType;\r
+       }\r
+       \r
+       protected boolean hasdata()\r
+       {\r
+               return currentDrdaRs.hasdata;\r
+       }\r
+       \r
+       protected void  setHasdata(boolean hasdata)\r
+       {\r
+               currentDrdaRs.hasdata = hasdata;\r
+       }\r
+\r
+       /**\r
+        * This method is used to initialize the default statement of the database\r
+        * for re-use. It is different from reset() method since default statements\r
+        * get initiliazed differently. e.g: stmt variable used in default statement\r
+        * is created only once in Database.makeConnection. \r
+        * TODO: Need to see what exactly it means to initialize the default \r
+        * statement. (DERBY-1002)\r
+        * \r
+        */\r
+       protected void initialize() \r
+       {\r
+               setTypDefValues();\r
+       }\r
+\r
+\r
+       protected PreparedStatement explicitPrepare(String sqlStmt) throws SQLException\r
+       {\r
+               explicitlyPrepared = true;\r
+               return prepare(sqlStmt);\r
+       }\r
+\r
+       protected boolean wasExplicitlyPrepared()\r
+       {\r
+               return explicitlyPrepared;\r
+       }\r
+\r
+       /**\r
+        * Create a prepared statement\r
+        *\r
+        * @param sqlStmt - SQL statement\r
+        *\r
+        * @exception SQLException\r
+        */\r
+       protected PreparedStatement prepare(String sqlStmt)   throws SQLException\r
+       {\r
+               // save current prepare iso level\r
+               int saveIsolationLevel = -1;\r
+               boolean isolationSet = false;\r
+               if (pkgnamcsn !=null && \r
+                       isolationLevel != Connection.TRANSACTION_NONE)\r
+               {\r
+                       saveIsolationLevel = database.getPrepareIsolation();\r
+                       database.setPrepareIsolation(isolationLevel);\r
+                       isolationSet = true;\r
+               }\r
+               \r
+               parsePkgidToFindHoldability();\r
+\r
+               if (isCallableSQL(sqlStmt))\r
+               {\r
+                       isCall = true;\r
+                       ps = database.getConnection().prepareCall(\r
+                               sqlStmt, scrollType, concurType, withHoldCursor);\r
+                       setupCallableStatementParams((CallableStatement)ps);\r
+               }\r
+               else\r
+               {\r
+                       ps = database.getConnection().prepareStatement(\r
+                               sqlStmt, scrollType, concurType, withHoldCursor);\r
+               }\r
+\r
+               // beetle 3849  -  Need to change the cursor name to what\r
+               // JCC thinks it will be, since there is no way in the \r
+               // protocol to communicate the actual cursor name.  JCC keeps \r
+               // a mapping from the client cursor names to the DB2 style cursor names\r
+               if (cursorName != null)//cursorName not null means we are dealing with dynamic pacakges\r
+                       ps.setCursorName(cursorName);\r
+               if (isolationSet)\r
+                       database.setPrepareIsolation(saveIsolationLevel);\r
+                               return ps;\r
+       }\r
+\r
+       /**\r
+        * Get prepared statement\r
+        *\r
+        * @return prepared statement\r
+        */\r
+       protected PreparedStatement getPreparedStatement() throws SQLException\r
+       {\r
+               return ps;\r
+       }\r
+\r
+\r
+       /**\r
+        * Executes the prepared statement and populates the resultSetTable.\r
+        * Access to the various resultSets is then possible by using\r
+        * setCurrentDrdaResultSet(String pkgnamcsn)  to set the current\r
+        * resultSet and then calling getResultSet() or the other access \r
+        * methods to get resultset data.\r
+        *\r
+        * @return true if the execution has resultSets\r
+        */\r
+       protected boolean execute() throws SQLException\r
+       {\r
+               boolean hasResultSet = ps.execute();\r
+               // DERBY-3085 - We need to make sure we drain the streamed parameter\r
+               // if not used by the server, for example if an update statement does not \r
+               // update any rows, the parameter won't be used.  Network Server will\r
+               // stream only the last parameter with an EXTDTA. This is stored when the\r
+               // parameter is set and drained now after statement execution if needed.\r
+               try {\r
+                       drdaParamState_.drainStreamedParameter();\r
+               } catch (IOException e) { \r
+                       Util.javaException(e);\r
+               }\r
+               // java.sql.Statement says any result sets that are opened\r
+               // when the statement is re-executed must be closed; this\r
+               // is handled by the call to "ps.execute()" above--but we\r
+               // also have to reset our 'numResultSets' counter, since\r
+               // all previously opened result sets are now invalid.\r
+               numResultSets = 0;\r
+\r
+               ResultSet rs = null;\r
+               boolean isCallable = (ps instanceof java.sql.CallableStatement);\r
+               if (isCallable)\r
+                       needsToSendParamData = true;\r
+\r
+               do {\r
+                       rs = ps.getResultSet();\r
+                       if (rs !=null)\r
+                       {\r
+                               //For callable statement, get holdability of statement generating the result set\r
+                               if(isCallable)\r
+                                       addResultSet(rs,getResultSetHoldability(rs));\r
+                               else\r
+                                       addResultSet(rs,withHoldCursor);\r
+                               hasResultSet = true;\r
+                       }\r
+                       // For normal selects we are done, but procedures might\r
+                       // have more resultSets\r
+               }while (isCallable && getMoreResults(JDBC30Translation.KEEP_CURRENT_RESULT));\r
+\r
+               return hasResultSet;\r
+\r
+       }\r
+       \r
+       /**\r
+        * clear out type data for parameters.\r
+        * Unfortunately we currently overload the resultSet type info\r
+        * rsDRDATypes et al with parameter info.\r
+        * RESOLVE: Need to separate this\r
+        */\r
+   protected void finishParams()\r
+       {\r
+               needsToSendParamData = false;\r
+       }\r
+\r
+       /**\r
+        * Set the pkgid sec num for this statement and the \r
+        * consistency token that will be used for the first resultSet.\r
+        * For dyamic packages The package name is encoded as follows\r
+        * SYS(S/L)(H/N)xyy \r
+        * where 'S' represents Small package and 'L' large \r
+        *                      (ignored by Derby) \r
+        * Where 'H' represents WITH HOLD, and 'N' represents NO WITH HOLD. \r
+        *                      (May be overridden by SQLATTR for WITH\r
+        *                       HOLD")\r
+        *\r
+        * Where 'www' is the package iteration (ignored by Derby)\r
+        * Where 'x' is the isolation level: 0=NC, 1=UR, 2=CS, 3=RS, 4=RR \r
+        * Where 'yy' is the package iteration 00 through FF \r
+        * Where 'zz' is unique for each platform\r
+        * Happilly, these values correspond precisely to the internal Derby\r
+        * isolation levels  in ExecutionContext.java\r
+        * x   Isolation Level                                           \r
+        * --  ---------------------\r
+        * 0   NC  (java.sql.Connection.TRANSACTION_NONE)\r
+        * 1   UR  (java.sql.Connection.TRANACTION_READ_UNCOMMITTED)\r
+        * 2   CS  (java.sql.Connection.TRANSACTION_READ_COMMITTED)\r
+        * 3   RS  (java.sql.Connection.TRANSACTION_REPEATABLE_READ)\r
+        * 4   RR  (java.sql.Connection.TRANSACTION_SERIALIZABLE)\r
+        * \r
+        * static packages have preset isolation levels \r
+        * (see getStaticPackageIsolation)\r
+        * @param pkgnamcsn  package id section number and token from the client\r
+        */\r
+       protected void setPkgnamcsn(Pkgnamcsn pkgnamcsn)\r
+       {\r
+               this.pkgnamcsn =  pkgnamcsn;\r
+               // Store the consistency string for the first ResultSet.\r
+               // this will be used to calculate consistency strings for the \r
+               // other result sets.\r
+               pkgid = pkgnamcsn.getPkgid();\r
+\r
+               if (isDynamicPkgid(pkgid))\r
+               {\r
+                       isolationLevel = Integer.parseInt(pkgid.substring(5,6));\r
+                       \r
+                       \r
+                       /*\r
+                        *   generate DB2-style cursorname\r
+                        *   example value : SQL_CURSN200C1\r
+                        *   where \r
+                        *      SQL_CUR is db2 cursor name prefix;\r
+                        *      S - Small package , L -Large package\r
+                        *      N - normal cursor, H - hold cursor \r
+                        *      200 - package id as sent by jcc \r
+                        *      C - tack-on code for cursors\r
+                        *      1 - section number sent by jcc           \r
+                        */\r
+                       \r
+                       \r
+\r
+                       // cursor name\r
+                       // trim the SYS off the pkgid so it wont' be in the cursor name\r
+                       String shortPkgid = pkgid.substring(pkgid.length() -5 , pkgid.length());\r
+                       pkgsn = pkgnamcsn.getPkgsn();\r
+                       this.cursorName = "SQL_CUR" +  shortPkgid + "C" + pkgsn ;\r
+               }\r
+               else // static package\r
+               {\r
+                       isolationLevel = getStaticPackageIsolation(pkgid);\r
+               }\r
+\r
+               this.pkgcnstkn = pkgnamcsn.getPkgcnstkn();\r
+\r
+       }\r
+\r
+\r
+       /**\r
+        * get the isolation level for a static package.\r
+        * @param pkgid - Package identifier string (e.g. SYSSTAT)\r
+        * @return isolation\r
+        */\r
+       private int getStaticPackageIsolation(String pkgid)\r
+       {\r
+               // SYSSTAT is used for metadata. and is the only static package used\r
+               // for JCC. Other static packages will need to be supported for \r
+               // CCC. Maybe a static hash table would then be in order.\r
+               if (pkgid.equals("SYSSTAT"))\r
+                       return ExecutionContext.READ_UNCOMMITTED_ISOLATION_LEVEL;\r
+               else\r
+                       return ExecutionContext.UNSPECIFIED_ISOLATION_LEVEL;\r
+       }\r
+\r
+       /**\r
+        * Get pkgnamcsn\r
+        *\r
+        * @return pkgnamcsn\r
+        */\r
+       protected Pkgnamcsn getPkgnamcsn() \r
+       {\r
+               return pkgnamcsn;\r
+\r
+       }\r
+       /**\r
+        * Get result set\r
+        *\r
+        * @return result set\r
+        */\r
+       protected ResultSet getResultSet() \r
+       {\r
+               return currentDrdaRs.getResultSet();\r
+       }\r
+\r
+       \r
+       /** \r
+        * Just get the resultset. Don't set it to current\r
+        * Assumes resultSet rsnum exists.\r
+        *\r
+        * @param rsNum resultSetNumber starting with 0\r
+        * @return  The result set in the order it was retrieved\r
+        *         \r
+        *          with getMoreResults()\r
+        **/\r
+       private  ResultSet getResultSet(int rsNum)  \r
+       {\r
+               if (rsNum == 0)\r
+                       return currentDrdaRs.getResultSet();\r
+               else\r
+               {\r
+                       ConsistencyToken key = (ConsistencyToken) resultSetKeyList.get(rsNum);\r
+                       return ((DRDAResultSet) (resultSetTable.get( key))).getResultSet();\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Set result set\r
+        *\r
+        * @param value\r
+        */\r
+       protected void setResultSet(ResultSet value) throws SQLException\r
+       {\r
+               if (currentDrdaRs.getResultSet() == null)\r
+                       numResultSets = 1;\r
+               currentDrdaRs.setResultSet(value);\r
+               setRsDefaultOptions(currentDrdaRs);\r
+       }\r
+       \r
+       /**\r
+        * Gets the current DRDA ResultSet\r
+        * \r
+        * @return DRDAResultSet\r
+        */\r
+       protected DRDAResultSet getCurrentDrdaResultSet()\r
+       {\r
+               return currentDrdaRs ;\r
+       }\r
+\r
+       /**\r
+        * Set currentDrdaResultSet \r
+        *\r
+        * @param rsNum   The result set number starting with 0\r
+        *                 \r
+        */\r
+       protected void setCurrentDrdaResultSet(int rsNum)\r
+       {\r
+               ConsistencyToken consistToken = getResultSetPkgcnstkn(rsNum);\r
+               if (currentDrdaRs.pkgcnstkn == consistToken)\r
+                       return;\r
+               currentDrdaRs = getDrdaResultSet(consistToken);\r
+\r
+       }\r
+\r
+       /**\r
+        * Set currentDrdaResultSet \r
+        *\r
+        * @param pkgnamcsn  The pkgid section number and unique resultset\r
+        *                    consistency token\r
+        *                 \r
+        */\r
+       protected void setCurrentDrdaResultSet(Pkgnamcsn pkgnamcsn)\r
+       {\r
+               pkgid = pkgnamcsn.getPkgid();\r
+               pkgsn = pkgnamcsn.getPkgsn();\r
+               ConsistencyToken consistToken = pkgnamcsn.getPkgcnstkn();\r
+               DRDAResultSet newDrdaRs = getDrdaResultSet(consistToken);\r
+               if (newDrdaRs != null)\r
+                       currentDrdaRs = newDrdaRs;\r
+       }\r
+\r
+\r
+       /*\r
+        * get DRDAResultSet by consistency token\r
+        *\r
+        */\r
+       private DRDAResultSet getDrdaResultSet(ConsistencyToken consistToken)\r
+       {\r
+               if ( resultSetTable   == null || \r
+                        (currentDrdaRs != null &&\r
+                         currentDrdaRs.pkgcnstkn == consistToken ))\r
+               {\r
+                       return currentDrdaRs;\r
+               }\r
+               else\r
+               {\r
+                       return (DRDAResultSet) (resultSetTable.get(consistToken));\r
+               }\r
+       }\r
+       \r
+       /*\r
+        * get DRDAResultSet by result set number\r
+        *\r
+        */\r
+       private DRDAResultSet getDrdaResultSet(int rsNum)\r
+       {\r
+               ConsistencyToken consistToken = getResultSetPkgcnstkn(rsNum);\r
+               return getDrdaResultSet(consistToken);\r
+       }\r
+\r
+       /** Add a new resultSet to this statement.\r
+        * Set as the current result set if  there is not an \r
+        * existing current resultset.\r
+        * @param value - ResultSet to add\r
+        * @param holdValue - Holdability of the ResultSet \r
+        * @return    Consistency token  for this resultSet\r
+        *            For a single resultSet that is the same as the statement's \r
+        *            For multiple resultSets just the consistency token is changed \r
+        */\r
+       protected ConsistencyToken addResultSet(ResultSet value, int holdValue) throws SQLException\r
+       {\r
+\r
+               DRDAResultSet newDrdaRs = null;\r
+\r
+               int rsNum = numResultSets;\r
+               ConsistencyToken newRsPkgcnstkn = calculateResultSetPkgcnstkn(rsNum);\r
+\r
+               if (rsNum == 0)\r
+                       newDrdaRs = currentDrdaRs;\r
+\r
+               else\r
+               {\r
+                       newDrdaRs = new DRDAResultSet();\r
+\r
+                       // Multiple resultSets we neeed to setup the hash table\r
+                       if (resultSetTable == null)\r
+                       {\r
+                               // If hashtable doesn't exist, create it and store resultSet 0\r
+                               // before we store our new resultSet.\r
+                               // For just a single resultSet we don't ever create the Hashtable.\r
+                               resultSetTable = new Hashtable();\r
+                               resultSetTable.put(pkgcnstkn, currentDrdaRs);\r
+                               resultSetKeyList = new ArrayList();\r
+                               resultSetKeyList.add(0, pkgcnstkn);\r
+                       }\r
+\r
+                       resultSetTable.put(newRsPkgcnstkn, newDrdaRs);\r
+                       resultSetKeyList.add(rsNum, newRsPkgcnstkn);\r
+               }\r
+\r
+               newDrdaRs.setResultSet(value);\r
+               newDrdaRs.setPkgcnstkn(newRsPkgcnstkn);\r
+               newDrdaRs.withHoldCursor = holdValue;\r
+               setRsDefaultOptions(newDrdaRs);\r
+               newDrdaRs.suspend();\r
+               numResultSets++;\r
+               return newRsPkgcnstkn;\r
+       }\r
+\r
+       /**\r
+        *\r
+        * @return      number of result sets\r
+        */\r
+       protected int getNumResultSets()\r
+       {\r
+               return numResultSets;\r
+       }\r
+       \r
+       \r
+       /**\r
+        * @param rsNum result set starting with 0\r
+        * @return  consistency token (key) for the result set   \r
+        */\r
+       protected ConsistencyToken getResultSetPkgcnstkn(int rsNum)\r
+       {\r
+               if (rsNum == 0)\r
+                       return pkgcnstkn;\r
+               else \r
+                       return (ConsistencyToken) resultSetKeyList.get(rsNum);                     \r
+       }\r
+\r
+\r
+       /** \r
+        * Set ResultSet DRDA DataTypes\r
+        * @param value drdaTypes for columns.\r
+        **/\r
+       protected void setRsDRDATypes(int [] value)\r
+       {\r
+               currentDrdaRs.setRsDRDATypes(value);\r
+       }\r
+\r
+       /**\r
+        *@return ResultSet DRDA DataTypes\r
+        **/\r
+\r
+       protected int[] getRsDRDATypes()\r
+       {\r
+               return currentDrdaRs.getRsDRDATypes();\r
+\r
+       }\r
+\r
+\r
+       /** \r
+        * Set ResultSet DRDA DataTypes Lengths\r
+        * @param value drdaTypes for columns.\r
+        **/\r
+       protected void setRsLens(int [] value)\r
+       {\r
+               currentDrdaRs.rsLens = value;\r
+\r
+       }\r
+\r
+       /**\r
+        *@return ResultSet DRDA DataTypes Lengths\r
+        **/\r
+\r
+       protected int[] getRsLens()\r
+       {\r
+               return currentDrdaRs.rsLens;\r
+       }\r
+\r
+       /**\r
+        *  Close the current resultSet\r
+        */\r
+       protected void rsClose() throws SQLException\r
+       {\r
+               if (currentDrdaRs.getResultSet() == null) \r
+                       return;\r
+\r
+               currentDrdaRs.close();\r
+               needsToSendParamData = false;           \r
+               numResultSets--;\r
+       }\r
+\r
+       /**\r
+        * Explicitly close the result set by CLSQRY\r
+        * needed to check for double close.\r
+        */\r
+       protected void CLSQRY()\r
+       {\r
+               currentDrdaRs.CLSQRY();\r
+       }\r
+\r
+       /* \r
+        * @return whether CLSQRY has been called on the\r
+        *         current result set.\r
+        */\r
+       protected boolean wasExplicitlyClosed()\r
+       {\r
+               return currentDrdaRs.wasExplicitlyClosed();\r
+       }\r
+\r
+       /**\r
+        * This method closes the JDBC objects and frees up all references held by\r
+        * this object.\r
+        * \r
+        * @throws SQLException\r
+        */\r
+       protected void close()  throws SQLException\r
+       {\r
+               if (ps != null)\r
+                       ps.close();\r
+               if (stmt != null)\r
+                       stmt.close();\r
+               currentDrdaRs.close();\r
+               resultSetTable = null;\r
+               resultSetKeyList = null;\r
+               ps = null;\r
+               stmtPmeta = null;\r
+               stmt = null;\r
+               rslsetflg = null;\r
+               procName = null;\r
+               outputTypes = null;\r
+               outputPrecision = null;\r
+               outputScale = null;\r
+               // Clear parameters and release excess storage\r
+               drdaParamState_.clear(true);\r
+       }\r
+       \r
+       /**\r
+        * This method resets the state of this DRDAStatement object so that it can\r
+        * be re-used. This method should reset all variables of this class except \r
+        * the following:\r
+     * 1. database - This variable gets initialized in the constructor and by\r
+     * call to setDatabase.\r
+     * 2. members which get initialized in setPkgnamcsn (pkgnamcsn, pkgcnstkn, \r
+     * pkgid, pkgsn, isolationLevel, cursorName). pkgnamcsn is the key used to \r
+     * find if the DRDAStatement can be re-used. Hence its value will not change \r
+     * when the object is re-used.\r
+        * \r
+        */\r
+       protected void reset() \r
+       {\r
+               setTypDefValues();\r
+               \r
+               withHoldCursor = -1;\r
+               scrollType = ResultSet.TYPE_FORWARD_ONLY;       \r
+               concurType = ResultSet.CONCUR_READ_ONLY;;\r
+               rowCount = 0;\r
+               rslsetflg = null;\r
+               maxrslcnt = 0;\r
+               ps = null;\r
+               stmtPmeta = null;\r
+               isCall = false;\r
+               procName = null;\r
+               outputTypes = null;\r
+               outputExpected = false;\r
+               stmt = null;\r
+               \r
+               currentDrdaRs.reset();\r
+               resultSetTable = null;\r
+               resultSetKeyList = null;\r
+               numResultSets = 0;\r
+               \r
+               // Clear parameters without releasing storage\r
+               drdaParamState_.clear(false);\r
+               \r
+               nbrrow = 0;\r
+               qryrowset = 0;  \r
+               blksize = 0;            \r
+               maxblkext = 0;  \r
+               outovropt = 0;  \r
+               qryrfrtbl = false;\r
+               qryprctyp = CodePoint.QRYBLKCTL_DEFAULT;\r
+\r
+               needsToSendParamData = false;\r
+               explicitlyPrepared = false;\r
+       }\r
+\r
+       /**\r
+        * is Statement closed\r
+        * @return whether the statement is closed\r
+        */\r
+       protected boolean rsIsClosed()\r
+       {\r
+               return currentDrdaRs.isClosed();\r
+       }\r
+       \r
+       /**\r
+        * Set state to SUSPENDED (result set is opened)\r
+        */\r
+       protected void rsSuspend()\r
+       {\r
+               currentDrdaRs.suspend();\r
+       }\r
+\r
+\r
+       /**\r
+        * set resultset/out parameter precision\r
+        *\r
+        * @param index - starting with 1\r
+        * @param precision\r
+        */\r
+       protected void setRsPrecision(int index, int precision)\r
+       {\r
+               currentDrdaRs.setRsPrecision(index,precision);\r
+       }\r
+\r
+       /**\r
+        * get resultset /out paramter precision\r
+        * @param index -starting with 1\r
+        * @return precision of column\r
+        */\r
+       protected int getRsPrecision(int index)\r
+       {\r
+               return currentDrdaRs.getRsPrecision(index);\r
+       }\r
+\r
+       /**\r
+        * set resultset/out parameter scale\r
+        *\r
+        * @param index - starting with 1\r
+        * @param scale\r
+        */\r
+       protected void setRsScale(int index, int scale)\r
+       {\r
+               currentDrdaRs.setRsScale(index, scale);\r
+       }\r
+\r
+       /**\r
+        * get resultset /out paramter scale\r
+        * @param index -starting with 1\r
+        * @return scale of column\r
+        */\r
+       protected int  getRsScale(int index)\r
+       {\r
+               return currentDrdaRs.getRsScale(index);\r
+       }\r
+       \r
+\r
+       /**\r
+        * set result  DRDAType\r
+        *\r
+        * @param index - starting with 1\r
+        * @param type\r
+        */\r
+       protected  void setRsDRDAType(int index, int type)\r
+       {\r
+               currentDrdaRs.setRsDRDAType(index,type);\r
+               \r
+       }\r
+\r
+       /** Clears the parameter state (type, length and ext information)\r
+        * stored in this statement, but does not release any\r
+        * storage. This reduces the cost of re-executing the statement\r
+        * since no new storage needs to be allocated. */\r
+       protected void clearDrdaParams() {\r
+               drdaParamState_.clear(false);\r
+       }\r
+\r
+       /** Get the number of external parameters in this\r
+        * statement. External means parameters that are transmitted in a\r
+        * separate DSS in the DRDA protocol.\r
+        * @return the number of external parameters\r
+        */\r
+       protected int getExtPositionCount() {\r
+               return drdaParamState_.getExtPosCount();\r
+       }\r
+\r
+       /** Get the parameter position of the i'th external parameter\r
+        * @param i - zero-based index into list of external parameters\r
+        * @return the parameter position of the i'th external parameter\r
+        */\r
+       protected int getExtPosition(int i) {\r
+               return drdaParamState_.getExtPos(i);\r
+       }\r
+\r
+       /** Mark the pos'th parameter as external\r
+        * @param pos - zero-based index into list of external parameters\r
+        */\r
+       protected void addExtPosition(int pos) {\r
+               drdaParamState_.addExtPos(pos);\r
+       }\r
+\r
+       /** Get the number of parameters, internal and external, that has\r
+        * been added to this statement.\r
+        * @return the number of parameters\r
+        */\r
+       protected int getDrdaParamCount() {\r
+               return drdaParamState_.getDrdaParamCount();\r
+       }\r
+\r
+       /** Add another parameter to this statement.\r
+        * @param t - type of the parameter\r
+        * @param l - length in bytes of the parameter\r
+        */\r
+       protected void addDrdaParam(byte t, int l) {\r
+               drdaParamState_.addDrdaParam(t, l);\r
+       }\r
+\r
+    protected void setStreamedParameter(EXTDTAReaderInputStream eis)\r
+    {\r
+        drdaParamState_.setStreamedParameter(eis);\r
+    }\r
+    \r
+       /**\r
+        * get parameter DRDAType\r
+        *\r
+        * @param index - starting with 1\r
+        * @return  DRDA Type of column\r
+        */\r
+       protected int getParamDRDAType(int index) {\r
+               return drdaParamState_.getDrdaType(index-1);\r
+       }\r
+\r
+       /**\r
+        * returns drda length of parameter as sent by client.\r
+        * @param index - starting with 1\r
+        * @return data length\r
+\r
+        */\r
+       protected int getParamLen(int index)\r
+       {\r
+               return drdaParamState_.getDrdaLen(index-1);\r
+       }\r
+\r
+\r
+       /**\r
+        *  get parameter precision or DB2 max (31)\r
+        *\r
+        *  @param index parameter index starting with 1\r
+        *\r
+        *  @return  precision\r
+        */\r
+       protected int getParamPrecision(int index) throws SQLException\r
+       {\r
+               if (ps != null && ps instanceof CallableStatement)\r
+               {\r
+                       ParameterMetaData pmeta = getParameterMetaData();\r
+\r
+                       return Math.min(pmeta.getPrecision(index),\r
+                                                       FdocaConstants.NUMERIC_MAX_PRECISION);\r
+\r
+               }\r
+               else \r
+                       return -1;\r
+       }\r
+       \r
+       /**\r
+        *  get parameter scale or DB2 max (31)\r
+        *\r
+        *  @param index parameter index starting with 1\r
+        *\r
+        *  @return  scale\r
+        */\r
+       protected int getParamScale(int index) throws SQLException\r
+       {\r
+               if (ps != null && ps instanceof CallableStatement)\r
+               {\r
+                       ParameterMetaData pmeta = getParameterMetaData();\r
+                       return Math.min(pmeta.getScale(index),FdocaConstants.NUMERIC_MAX_PRECISION);\r
+               }\r
+               else \r
+                       return -1;\r
+       }\r
+\r
+       /** \r
+        * get the number of result set columns for the current resultSet\r
+        * \r
+        * @return number of columns\r
+        */\r
+\r
+       protected int getNumRsCols()\r
+       {\r
+               int[] rsDrdaTypes = getRsDRDATypes();\r
+               if (rsDrdaTypes != null)\r
+                       return rsDrdaTypes.length;\r
+               else \r
+                       return 0;\r
+       }\r
+\r
+       /**\r
+        * get  resultset/out parameter DRDAType\r
+        *\r
+        * @param index - starting with 1\r
+        * @return  DRDA Type of column\r
+        */\r
+       protected int getRsDRDAType(int index)\r
+       {\r
+               return currentDrdaRs.getRsDRDAType(index);\r
+       }\r
+\r
+       /**\r
+        * get resultset/out parameter DRDALen\r
+        * @param index starting with 1\r
+        * \r
+        * @return length of drda data\r
+        */\r
+        \r
+       protected int getRsLen(int index)\r
+       {\r
+               return currentDrdaRs.getRsLen(index);\r
+       }\r
+\r
+       /**\r
+        * set resultset column data length\r
+        * @param index starting with 1\r
+        * @param value length\r
+        */\r
+       protected void  setRsLen(int index, int value)\r
+       {\r
+               currentDrdaRs.setRsLen(index,value);\r
+       }\r
+\r
+       /**\r
+        * @param rsNum  - result set # starting with 0 \r
+        */\r
+       public String getResultSetCursorName(int rsNum) throws SQLException\r
+       {\r
+               DRDAResultSet drdaRs = getDrdaResultSet(rsNum);\r
+               return drdaRs.getResultSetCursorName();                 \r
+\r
+       }\r
+\r
+\r
+       protected String toDebugString(String indent)\r
+       {\r
+               ResultSet rs = currentDrdaRs.getResultSet();\r
+               \r
+               String s ="";\r
+               if (ps == null) \r
+                       s += indent + ps;\r
+               else\r
+               {\r
+                       s += indent + pkgid + pkgsn ;\r
+                       s += "\t" + getSQLText();\r
+               }\r
+               return s;\r
+       }\r
+\r
+       /**  For a single result set, just echo the consistency token that the client sent us.\r
+        * For subsequent resultSets, just subtract the resultset number from\r
+        * the consistency token and that will differentiate the result sets.\r
+        * This seems to be what DB2 does\r
+        * @param rsNum  - result set # starting with 0\r
+        * \r
+        * @return  Consistency token for result set\r
+        */\r
+\r
+       protected ConsistencyToken calculateResultSetPkgcnstkn(int rsNum)\r
+       {       \r
+               ConsistencyToken consistToken = pkgcnstkn;\r
+\r
+               if (rsNum == 0 || pkgcnstkn == null)\r
+                       return consistToken;\r
+               else\r
+               {\r
+                       BigInteger consistTokenBi =\r
+                               new BigInteger(consistToken.getBytes());\r
+                       BigInteger rsNumBi = BigInteger.valueOf(rsNum);\r
+                       consistTokenBi = consistTokenBi.subtract(rsNumBi);\r
+                       consistToken = new ConsistencyToken(consistTokenBi.toByteArray());\r
+               }\r
+               return consistToken;\r
+       }\r
+\r
+       protected boolean isCallableStatement()\r
+       {\r
+               return isCall;\r
+       }\r
+\r
+       private boolean isCallableSQL(String sql)\r
+       {\r
+               java.util.StringTokenizer tokenizer = new java.util.StringTokenizer\r
+                       (sql, "\t\n\r\f=? (");\r
+                String firstToken = tokenizer.nextToken();\r
+                if (StringUtil.SQLEqualsIgnoreCase(firstToken, \r
+                                                                                       "call")) // captures CALL...and ?=CALL...\r
+                        return true;\r
+                return false;\r
+                                \r
+       }\r
+\r
+       private void setupCallableStatementParams(CallableStatement cs) throws SQLException\r
+       {\r
+               ParameterMetaData pmeta = getParameterMetaData();\r
+               int numElems = pmeta.getParameterCount();\r
+\r
+               for ( int i = 0; i < numElems; i ++)\r
+               {\r
+                       boolean outputFlag = false;\r
+                       \r
+                       int parameterMode = pmeta.getParameterMode(i + 1);\r
+                       int parameterType = pmeta.getParameterType(i + 1);\r
+                        int parameterPrecision = pmeta.getPrecision(i + 1);\r
+                        int parameterScale = pmeta.getScale(i + 1);\r
+\r
+                       switch (parameterMode) {\r
+                               case JDBC30Translation.PARAMETER_MODE_IN:\r
+                                       break;\r
+                               case JDBC30Translation.PARAMETER_MODE_OUT:\r
+                               case JDBC30Translation.PARAMETER_MODE_IN_OUT:\r
+                                       outputFlag = true;\r
+                                       break;\r
+                               case JDBC30Translation.PARAMETER_MODE_UNKNOWN:\r
+                                       // It's only unknown if array\r
+                                       String objectType = pmeta.getParameterClassName(i+1);\r
+                                       parameterType =\r
+                                               getOutputParameterTypeFromClassName(objectType);\r
+                                       if (parameterType  != NOT_OUTPUT_PARAM)\r
+                                               outputFlag = true;\r
+                       }\r
+\r
+                       if (outputFlag)\r
+                       {\r
+                               if (outputTypes == null) //not initialized yet, since previously none output\r
+                               {\r
+                                       outputTypes = new int[numElems];\r
+                                       outputPrecision = new int [numElems];\r
+                                       outputScale = new int [numElems];\r
+                                       for (int j = 0; j < numElems; j++) {\r
+                                               outputTypes[j] = NOT_OUTPUT_PARAM;  //default init value\r
+                                               outputPrecision[j] = NOT_OUTPUT_PARAM;\r
+                                               outputScale[j] = NOT_OUTPUT_PARAM;\r
+                                       }\r
+                               }\r
+                               // save the output type so we can register when we parse\r
+                               // the SQLDTA\r
+                               outputTypes[i] = parameterType;\r
+                               outputPrecision[i] = parameterPrecision;\r
+                               outputScale[i] = parameterScale;                \r
+                       }\r
+                       \r
+               }\r
+       }\r
+\r
+\r
+\r
+       /** \r
+               Given an object class  name get the paramameter type if the \r
+               parameter mode is unknown.\r
+               \r
+               Arrays except for byte arrrays are assumed to be output parameters\r
+               TINYINT output parameters are going to be broken because there\r
+               is no way to differentiate them from binary input parameters.\r
+               @param objectName Class name of object being evaluated.\r
+               indicating if this an output parameter\r
+               @return type from java.sql.Types\r
+       **/\r
+       \r
+       protected static int getOutputParameterTypeFromClassName(String\r
+                                                                                                                                       objectName)\r
+       {\r
+               \r
+               if (objectName.endsWith("[]"))\r
+               {\r
+                                       // For byte[] we are going to assume it is input.\r
+                       // For TINYINT output params you gotta use \r
+                       //  object Integer[] or use a procedure                            \r
+                                       if (objectName.equals("byte[]"))\r
+                                       {\r
+                                               return NOT_OUTPUT_PARAM;\r
+                                                       \r
+                                                       //isOutParam[offset] = false;\r
+                                                       //return java.sql.Types.VARBINARY;\r
+                                       }\r
+                                       \r
+                                       // Known arrays are output parameters\r
+                                       // otherwise we pass it's a JAVA_OBJECT\r
+                                       if (objectName.equals("java.lang.Byte[]"))\r
+                                               return java.sql.Types.TINYINT;\r
+                                       \r
+                                       if (objectName.equals("byte[][]"))\r
+                                               return java.sql.Types.VARBINARY;\r
+                                       if (objectName.equals("java.lang.String[]"))\r
+                                               return java.sql.Types.VARCHAR; \r
+                                       if (objectName.equals("int[]") || \r
+                                               objectName.equals("java.lang.Integer[]"))\r
+                                               return java.sql.Types.INTEGER;\r
+                                       else if (objectName.equals("long[]")\r
+                                                        || objectName.equals("java.lang.Long[]"))\r
+                                               return java.sql.Types.BIGINT;\r
+                                       else if (objectName.equals("java.math.BigDecimal[]"))\r
+                                               return java.sql.Types.NUMERIC;\r
+                                       else if (objectName.equals("boolean[]")  || \r
+                                                        objectName.equals("java.lang.Boolean[]"))\r
+                                               return java.sql.Types.BIT;\r
+                                       else if (objectName.equals("short[]"))\r
+                                               return java.sql.Types.SMALLINT;\r
+                                       else if (objectName.equals("float[]") ||\r
+                                                        objectName.equals("java.lang.Float[]"))\r
+                                               return java.sql.Types.REAL;\r
+                                       else if (objectName.equals("double[]") ||\r
+                                                        objectName.equals("java.lang.Double[]"))\r
+                                               return java.sql.Types.DOUBLE;\r
+                                       else if (objectName.equals("java.sql.Date[]"))\r
+                                               return java.sql.Types.DATE;\r
+                                       else if (objectName.equals("java.sql.Time[]"))\r
+                                               return java.sql.Types.TIME;\r
+                                       else if (objectName.equals("java.sql.Timestamp[]"))\r
+                                               return java.sql.Types.TIMESTAMP;\r
+               }\r
+               // Not one of the ones we know. This must be a JAVA_OBJECT\r
+               return NOT_OUTPUT_PARAM;\r
+               //isOutParam[offset] = false;                           \r
+               //return java.sql.Types.JAVA_OBJECT;\r
+\r
+       }\r
+       \r
+       \r
+       public void registerAllOutParams() throws SQLException\r
+       {\r
+               if (isCall && (outputTypes != null))\r
+                       for (int i = 1; i <= outputTypes.length; i ++)\r
+                               registerOutParam(i);\r
+               \r
+       }\r
+       \r
+       public void registerOutParam(int paramNum) throws SQLException\r
+       {\r
+               CallableStatement cs;\r
+               if (isOutputParam(paramNum))\r
+               {\r
+                       cs = (CallableStatement) ps;\r
+                       cs.registerOutParameter(paramNum, getOutputParamType(paramNum));\r
+               }\r
+       }\r
+\r
+       protected boolean hasOutputParams()\r
+       {\r
+               return (outputTypes != null);\r
+       }\r
+\r
+       /**\r
+        * is  parameter an ouput parameter\r
+        * @param paramNum parameter number starting with 1.\r
+        * return true if this is an output parameter.\r
+        */\r
+       boolean isOutputParam(int paramNum)\r
+       {\r
+               if (outputTypes != null)\r
+                       return (outputTypes[paramNum - 1] != NOT_OUTPUT_PARAM);\r
+               return false;\r
+               \r
+       }\r
+       /** \r
+        * get type for output parameter. \r
+        *\r
+        * @param paramNum - parameter number starting with 1\r
+        * @return jdbcType or NOT_OUTPUT_PARAM if this is not an output parameter\r
+        */\r
+       int getOutputParamType(int paramNum)\r
+       {\r
+               if (outputTypes != null)\r
+                       return (outputTypes[ paramNum - 1 ]);\r
+               return NOT_OUTPUT_PARAM;\r
+       }\r
+\r
+        /** \r
+         * get scale for output parameter. \r
+         *\r
+         * @param paramNum - parameter number starting with 1\r
+         * @return scale or NOT_OUTPUT_PARAM if this is not an output parameter\r
+         */\r
+        int getOutputParamScale(int paramNum){\r
+            if (outputScale != null)\r
+                return (outputScale[paramNum -1]);\r
+            return NOT_OUTPUT_PARAM;\r
+        }\r
+\r
+        /** \r
+         * get precision  for output parameter. \r
+         *\r
+         * @param paramNum - parameter number starting with 1\r
+         * @return precision or NOT_OUTPUT_PARAM if this is not an output parameter\r
+         */\r
+        int getOutputParamPrecision(int paramNum){\r
+            if (outputPrecision != null)\r
+                return (outputPrecision[paramNum -1]);\r
+            return NOT_OUTPUT_PARAM;\r
+        }\r
+        \r
+       private boolean isDynamicPkgid(String pkgid)\r
+       {\r
+               char size = pkgid.charAt(3);\r
+               \r
+               //  separate attribute used for holdability in 5.1.60\r
+               // this is just for checking that it is a dynamic package\r
+               char holdability = pkgid.charAt(4);                                                         \r
+               return (pkgid.substring(0,3).equals("SYS") && (size == 'S' ||\r
+                                                                                                          size == 'L')\r
+                               && (holdability == 'H' || holdability == 'N'));\r
+               \r
+       }\r
+\r
+   \r
+       private  void parsePkgidToFindHoldability()\r
+       {\r
+               if (withHoldCursor != -1)\r
+                       return;\r
+        \r
+               //First, check if holdability was passed as a SQL attribute "WITH HOLD" for this prepare. If yes, then withHoldCursor\r
+               //should not get overwritten by holdability from package name and that is why the check for -1\r
+               if (isDynamicPkgid(pkgid))\r
+               {       \r
+                       if(pkgid.charAt(4) == 'N')\r
+                               withHoldCursor = JDBC30Translation.CLOSE_CURSORS_AT_COMMIT;\r
+                       else  \r
+                               withHoldCursor = JDBC30Translation.HOLD_CURSORS_OVER_COMMIT;\r
+               }\r
+               else \r
+               {            \r
+                       withHoldCursor = JDBC30Translation.HOLD_CURSORS_OVER_COMMIT;\r
+               \r
+               }\r
+       }\r
+\r
+       /** \r
+        * Retrieve the ParameterMetaData for the prepared statement. \r
+        * @return ParameterMetaData for the prepared statement. \r
+        * Note: there is no separate BrokeredParameterSetMetaData.\r
+        */\r
+       protected ParameterMetaData getParameterMetaData() throws SQLException\r
+       {\r
+               if (stmtPmeta != null)\r
+                       return stmtPmeta;\r
+\r
+               stmtPmeta = ps.getParameterMetaData();\r
+        \r
+        return stmtPmeta;\r
+       }\r
+       \r
+       /**\r
+        * get more results using reflection.\r
+        * @param current - flag to pass to Statement.getMoreResults(current)\r
+        * @return true if there are more results.\r
+        * @throws SQLException\r
+        * @see java.sql.Statement#getMoreResults\r
+        *\r
+        */\r
+       private boolean getMoreResults(int current) throws SQLException\r
+       {       \r
+        return getPreparedStatement().getMoreResults(current);\r
+       }\r
+\r
+       /**\r
+        * Use reflection to retrieve SQL Text for EmbedPreparedStatement  \r
+        * or BrokeredPreparedStatement.\r
+        * @return SQL text\r
+        */\r
+       private String getSQLText() \r
+       {\r
+          String retVal = null;\r
+               Class[] emptyPARAM = {};\r
+               Object[] args = null;\r
+               try {\r
+                       Method sh = getPreparedStatement().getClass().getMethod("getSQLText",emptyPARAM);\r
+                       retVal = (String) sh.invoke(getPreparedStatement(),args);\r
+               }\r
+               catch (Exception e)\r
+               {\r
+                       //  do nothing we will just return a null string\r
+               }\r
+               return retVal;\r
+\r
+       }\r
+\r
+       /** helper method to handle exceptions generated by methods invoked \r
+        * through  reflection.\r
+        * @param e - exception thrown\r
+        * @throws SQLException - actual exception that occurred\r
+        */\r
+       private void handleReflectionException(Exception e) throws SQLException\r
+       {\r
+               if  (e instanceof InvocationTargetException) \r
+               {\r
+                       Throwable t = ((InvocationTargetException) e).getTargetException();\r
+                       \r
+                       if (t  instanceof SQLException)\r
+                       {\r
+                               throw (SQLException) t;\r
+                       }\r
+                       else\r
+                       {\r
+                               t.printStackTrace();\r
+                               throw Util.javaException(t);\r
+                       }\r
+               }\r
+               else\r
+                       // invoke can throw IllegalAccessException or \r
+                       // IllegalArgumentException, but these should not \r
+                       // occur from this code. Just in case we will throw it\r
+                       throw Util.javaException(e);\r
+               \r
+       }\r
+       \r
+       /**\r
+        * Method to decide whether the ResultSet should be closed\r
+        * implicitly based on the QRYCLSIMP value sent from the\r
+        * client. Only forward-only result sets should be implicitly\r
+        * closed. Some clients do not expect result sets to be closed\r
+        * implicitly if the protocol is LMTBLKPRC.\r
+        *\r
+        * @param lmtblkprcOK <code>true</code> if the client expects\r
+        * QRYCLSIMP to be respected for the LMTBLKPRC protocol\r
+        * @return implicit close boolean\r
+        * @exception SQLException\r
+        */\r
+       boolean isRSCloseImplicit(boolean lmtblkprcOK) throws SQLException {\r
+               return\r
+                       (currentDrdaRs.qryclsimp == CodePoint.QRYCLSIMP_YES) &&\r
+                       !isScrollable() &&\r
+                       (lmtblkprcOK ||\r
+                        (currentDrdaRs.getQryprctyp() != CodePoint.LMTBLKPRC));\r
+       }\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r