--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.drda.DRDAResultSet\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.sql.ResultSet;\r
+import java.sql.ResultSetMetaData;\r
+import java.sql.SQLException;\r
+import java.sql.Types;\r
+import java.util.ArrayList;\r
+\r
+import org.apache.derby.iapi.jdbc.EngineResultSet;\r
+\r
+/**\r
+ DRDAResultSet holds result set information\r
+*/\r
+class DRDAResultSet\r
+{\r
+ //NOTE!\r
+ //\r
+ // Since DRDAResultSets are reused, ALL variables should be set \r
+ // to their default values in reset().\r
+\r
+ // resultSet states are NOT_OPENED and SUSPENDED\r
+ protected static final int NOT_OPENED = 1;\r
+ protected static final int SUSPENDED = 2;\r
+ public static final int QRYCLSIMP_DEFAULT = CodePoint.QRYCLSIMP_NO; \r
+ \r
+ boolean explicitlyClosed = false;\r
+\r
+ int state;\r
+ protected boolean hasdata = true;\r
+ protected int[] rsLens; // result length for each column\r
+ private int[] rsDRDATypes; // DRDA Types of the result set columns\r
+ private int[] rsPrecision; // result precision for Decimal types\r
+ private int[] rsScale; // result sale for Decimal types\r
+\r
+ protected int [] outovr_drdaType; // Output override DRDA type and length\r
+\r
+ protected int withHoldCursor; // hold cursor after commit attribute\r
+ protected int scrollType = ResultSet.TYPE_FORWARD_ONLY; // Sensitive or Insensitive scroll attribute\r
+ protected int concurType; // Concurency type\r
+ protected long rowCount; // Number of rows we have processed\r
+ private ResultSet rs; // Current ResultSet\r
+\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 int qryclsimp; // Implicit Query Close Setting\r
+ protected boolean qryrelscr; // Query relative scrolling\r
+ protected long qryrownbr; // Query row number\r
+ protected boolean qryrfrtbl; // Query refresh answer set table\r
+ protected int qryscrorn; // Query scroll orientation\r
+ protected boolean qryrowsns; // Query row sensitivity\r
+ protected boolean qryblkrst; // Query block reset\r
+ protected boolean qryrtndta; // Query returns data\r
+ protected int qryrowset; // Query row set\r
+ private int qryprctyp; // Protocol type\r
+ private boolean gotPrctyp; // save the result, for performance\r
+ protected int rtnextdta; // Return of EXTDTA option\r
+ protected int nbrrow; // number of fetch or insert rows\r
+ protected byte [] rslsetflg; // Result Set Flags\r
+\r
+ private ArrayList extDtaObjects; // Arraylist of Blobs and Clobs \r
+ // Return Values to \r
+ // send with extdta objects.\r
+ \r
+ private ArrayList rsExtPositions;\r
+\r
+ protected ConsistencyToken pkgcnstkn; // Unique consistency token for ResultSet 0\r
+\r
+ // splitQRYDTA is normally null. If it is non-null, it means that\r
+ // the last QRYDTA response which was sent for this statement was\r
+ // split according to the LMTBLKPRC protocol, and this array contains\r
+ // the bytes that didn't fit. These bytes should be the first bytes\r
+ // emitted in the next QRYDTA response to a CNTQRY request.\r
+ private byte []splitQRYDTA;\r
+\r
+ DRDAResultSet()\r
+ {\r
+ state = NOT_OPENED;\r
+ // Initialize qryclsimp to NO. Only result sets requested by\r
+ // an OPNQRY command should be implicitly closed. OPNQRY will\r
+ // set qryclsimp later in setOPNQRYOptions().\r
+ qryclsimp = CodePoint.QRYCLSIMP_NO;\r
+ }\r
+\r
+ /**\r
+ * Set result set and initialize type array.\r
+ *\r
+ * @param value\r
+ * \r
+ */\r
+\r
+ protected void setResultSet(ResultSet value) throws SQLException\r
+ {\r
+ int numCols;\r
+ rs = value;\r
+ gotPrctyp = false;\r
+ if (value != null)\r
+ {\r
+ numCols= rs.getMetaData().getColumnCount();\r
+ rsDRDATypes = new int[numCols];\r
+ }\r
+ explicitlyClosed = false;\r
+ }\r
+\r
+\r
+ /**\r
+ * set consistency token for this resultSet\r
+ *\r
+ */\r
+ protected void setPkgcnstkn(ConsistencyToken pkgcnstkn)\r
+ {\r
+ this.pkgcnstkn = pkgcnstkn;\r
+ }\r
+\r
+\r
+ /**\r
+ * \r
+ * @return the underlying java.sql.ResultSet\r
+ */\r
+ protected ResultSet getResultSet()\r
+ {\r
+ return rs;\r
+ }\r
+\r
+ public void setSplitQRYDTA(byte []data)\r
+ {\r
+ splitQRYDTA = data;\r
+ }\r
+ public byte[]getSplitQRYDTA()\r
+ {\r
+ return splitQRYDTA;\r
+ }\r
+\r
+ /** \r
+ * Set ResultSet DRDA DataTypes\r
+ * @param value drdaTypes for columns.\r
+ **/\r
+ protected void setRsDRDATypes(int [] value)\r
+ {\r
+ rsDRDATypes = value;\r
+\r
+ }\r
+\r
+ /**\r
+ *@return ResultSet DRDA DataTypes\r
+ **/\r
+\r
+ protected int[] getRsDRDATypes()\r
+ {\r
+ // use the given override if it is present\r
+ if (outovr_drdaType != null)\r
+ return outovr_drdaType;\r
+ return rsDRDATypes;\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
+ if (rsPrecision == null)\r
+ rsPrecision = new int[rsDRDATypes.length];\r
+ rsPrecision[index -1] = 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
+ if (rsPrecision == null)\r
+ return 0;\r
+ return rsPrecision[index-1];\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
+ if (rsScale == null)\r
+ rsScale = new int[rsDRDATypes.length];\r
+ rsScale[index-1] = 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
+ if (rsScale == null)\r
+ return 0;\r
+ \r
+ return rsScale[index -1];\r
+ }\r
+ \r
+ \r
+ /**\r
+ * set resultset/out parameter DRDAType\r
+ *\r
+ * @param index - starting with 1\r
+ * @param type\r
+ */\r
+ protected void setRsDRDAType(int index, int type)\r
+ {\r
+ rsDRDATypes[index -1] = type;\r
+ \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
+ if ((outovr_drdaType != null) && (outovr_drdaType[index-1] != 0)) {\r
+ // Override with requested type. 0 means use default\r
+ return outovr_drdaType[index-1];\r
+ }\r
+ return rsDRDATypes[index -1];\r
+ }\r
+ \r
+\r
+ /**\r
+ * set resultset DRDA Len\r
+ *\r
+ * @param index - starting with 1\r
+ * @param value\r
+ */\r
+ protected void setRsLen(int index, int value)\r
+ {\r
+ if (rsLens == null)\r
+ rsLens = new int[rsDRDATypes.length];\r
+ rsLens[index -1] = value;\r
+ \r
+ }\r
+ \r
+ /**\r
+ * get resultset DRDALen\r
+ * @param index - starting with 1\r
+ * @return length of column value\r
+ */\r
+ protected int getRsLen(int index)\r
+ {\r
+ return rsLens[index -1];\r
+ }\r
+ \r
+\r
+ /**\r
+ * Add extDtaObject\r
+ * @param o - object to add\r
+ */\r
+ protected void addExtDtaObject (Object o, int jdbcIndex )\r
+ {\r
+ if (extDtaObjects == null)\r
+ extDtaObjects = new java.util.ArrayList();\r
+ extDtaObjects.add (o);\r
+\r
+ if (rsExtPositions == null)\r
+ rsExtPositions = new java.util.ArrayList();\r
+ \r
+ // need to record the 0 based position so subtract 1\r
+ rsExtPositions.add (new Integer(jdbcIndex -1 ));\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Clear externalized lob objects in current result set\r
+ */\r
+ protected void clearExtDtaObjects ()\r
+ {\r
+ if (extDtaObjects != null)\r
+ extDtaObjects.clear();\r
+ if (rsExtPositions != null)\r
+ rsExtPositions.clear();\r
+ \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
+ if ((rsExtPositions == null) || \r
+ rsExtPositions.get(index) == null)\r
+ return false;\r
+ \r
+\r
+ // Column number is starting on 1\r
+ int colnum = ((Integer) rsExtPositions.get(index)).intValue() + 1;\r
+ \r
+ if (FdocaConstants.isNullable(getRsDRDAType(colnum)))\r
+ return true;\r
+ else \r
+ return false;\r
+ }\r
+ \r
+\r
+ /**\r
+ * Get the extData Objects\r
+ *\r
+ * @return ArrayList with extdta\r
+ */\r
+ protected ArrayList getExtDtaObjects()\r
+ {\r
+ return extDtaObjects;\r
+ }\r
+\r
+ /**\r
+ * Set the extData Objects\r
+ */\r
+ protected void setExtDtaObjects(ArrayList a)\r
+ {\r
+ extDtaObjects =a;\r
+ }\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 (rs != null)\r
+ rs.close();\r
+ rs = null;\r
+ outovr_drdaType = null;\r
+ rsLens = null;\r
+ rsDRDATypes = null;\r
+ rsPrecision = null;\r
+ rsScale = null;\r
+ extDtaObjects = null;\r
+ splitQRYDTA = null;\r
+ rsExtPositions = null;\r
+ }\r
+ \r
+ /**\r
+ * This method resets the state of this DRDAResultset object so that it can\r
+ * be re-used. This method should reset all variables of this class.\r
+ * \r
+ */\r
+ protected void reset() {\r
+ explicitlyClosed = false;\r
+ state = NOT_OPENED;\r
+ hasdata = true;\r
+ rsLens = null;\r
+ rsDRDATypes = null;\r
+ rsPrecision = null;\r
+ rsScale = null;\r
+ \r
+ outovr_drdaType = null;\r
+ \r
+ withHoldCursor = 0; \r
+ scrollType = ResultSet.TYPE_FORWARD_ONLY;\r
+ concurType = 0;\r
+ rowCount = 0;\r
+ rs = null;\r
+ \r
+ blksize = 0;\r
+ maxblkext = 0; \r
+ outovropt = 0;\r
+ qryclsimp = CodePoint.QRYCLSIMP_NO; \r
+ qryrelscr = false;\r
+ qryrownbr = 0;\r
+ qryrfrtbl = false; \r
+ qryscrorn = 0;\r
+ qryrowsns = false; \r
+ qryblkrst = false;\r
+ qryrtndta = false; \r
+ qryrowset = 0;\r
+ qryprctyp = 0;\r
+ gotPrctyp = false; \r
+ rtnextdta = 0; \r
+ nbrrow = 0;\r
+ rslsetflg = null; \r
+\r
+ extDtaObjects = null;\r
+ rsExtPositions = null;\r
+ pkgcnstkn = null;\r
+ splitQRYDTA = null; \r
+ }\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
+ explicitlyClosed = true;\r
+ }\r
+\r
+ /* \r
+ * @return whether CLSQRY has been called on the\r
+ * current result set.\r
+ */\r
+ protected boolean wasExplicitlyClosed()\r
+ {\r
+ return explicitlyClosed;\r
+ }\r
+\r
+\r
+ /****\r
+ * Check to see if the result set for this statement\r
+ * has at least one column that is BLOB/CLOB.\r
+ * @return True if the result has at least one blob/clob\r
+ * column; false otherwise.\r
+ ****/\r
+ \r
+ protected boolean hasLobColumns() throws SQLException\r
+ {\r
+ ResultSetMetaData rsmd = rs.getMetaData();\r
+ int ncols = rsmd.getColumnCount();\r
+ for (int i = 1; i <= ncols; i++)\r
+ {\r
+ int type = rsmd.getColumnType(i);\r
+ if (type == Types.BLOB || type == Types.CLOB)\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Get the cursor name for the ResultSet\r
+ */\r
+ public String getResultSetCursorName() throws SQLException\r
+ {\r
+\r
+ if (rs != null)\r
+ return rs.getCursorName();\r
+ else \r
+ return null;\r
+ }\r
+\r
+ protected int getQryprctyp()\r
+ throws SQLException\r
+ {\r
+ if (!gotPrctyp && qryprctyp == CodePoint.LMTBLKPRC)\r
+ {\r
+ gotPrctyp = true;\r
+ if (rs == null || ((EngineResultSet)rs).isForUpdate() ||\r
+ /* for now we are not supporting LOB under LMTBLKPRC. drda spec only\r
+ * disallows LOB under LMTBLKPRC if OUTOVR is also for ANY CNTQRY reply.\r
+ * To support LOB, QRYDTA protocols for LOB will need to be changed.\r
+ */\r
+ hasLobColumns())\r
+ {\r
+ qryprctyp = CodePoint.FIXROWPRC;\r
+ }\r
+ }\r
+ return qryprctyp;\r
+ }\r
+\r
+ protected void setQryprctyp(int qryprctyp)\r
+ {\r
+ this.qryprctyp = qryprctyp;\r
+ }\r
+\r
+ /**\r
+ * is ResultSet closed\r
+ * @return whether the resultSet is closed\r
+ */\r
+ protected boolean isClosed()\r
+ {\r
+ return (state == NOT_OPENED);\r
+ }\r
+\r
+ /**\r
+ * Set state to SUSPENDED (result set is opened)\r
+ */\r
+ protected void suspend()\r
+ {\r
+ state = SUSPENDED;\r
+ }\r
+\r
+\r
+ protected String toDebugString(String indent)\r
+ {\r
+ String s = indent + "***** DRDASResultSet toDebugString ******\n";\r
+ s += indent + "State:" + getStateString(state)+ "\n";\r
+ s += indent + "pkgcnstkn: {" + pkgcnstkn + "}\n"; \r
+ s += indent + "cursor Name: ";\r
+ String cursorName = null;\r
+ try {\r
+ if (rs != null)\r
+ cursorName = rs.getCursorName();\r
+ }\r
+ catch (SQLException se )\r
+ {\r
+ cursorName = "invalid rs";\r
+ }\r
+ s += indent + cursorName + "\n";\r
+ \r
+ return s;\r
+ }\r
+\r
+\r
+ private String getStateString( int i )\r
+ {\r
+ switch (i)\r
+ {\r
+ case NOT_OPENED:\r
+ return "NOT_OPENED";\r
+ case SUSPENDED:\r
+ return "SUSPENDED";\r
+ default:\r
+ return "UNKNOWN_STATE";\r
+ }\r
+\r
+ }\r
+ \r
+ /**\r
+ * Sets the OPNQRYOptions. For more information on the meaning of these\r
+ * values consult the DRDA Technical Standard document. \r
+ * \r
+ * @param blksize Query block Size\r
+ * @param qryblkctl Use to set the query protocol type\r
+ * @param maxblkext Maximum number of extra blocks\r
+ * @param outovropt Output override option\r
+ * @param qryrowset Query row set\r
+ * @param qryclsimpl Implicit query close setting\r
+ */\r
+ protected void setOPNQRYOptions(int blksize, int qryblkctl,\r
+ int maxblkext, int outovropt,int qryrowset,int qryclsimpl)\r
+ {\r
+ this.blksize = blksize;\r
+ setQryprctyp(qryblkctl);\r
+ this.maxblkext = maxblkext;\r
+ this.outovropt = outovropt;\r
+ this.qryrowset = qryrowset;\r
+ this.qryclsimp = (qryclsimpl == CodePoint.QRYCLSIMP_SERVER_CHOICE)\r
+ ? DRDAResultSet.QRYCLSIMP_DEFAULT : qryclsimpl;\r
+\r
+ // Assume that we are returning data until a CNTQRY command\r
+ // tells us otherwise. (DERBY-822)\r
+ qryrtndta = true;\r
+\r
+ // For scrollable result sets, we don't know the fetch\r
+ // orientation until we get a CNTQRY command. Set orientation\r
+ // and row number to make pre-fetching possible. (DERBY-822)\r
+ qryscrorn = CodePoint.QRYSCRREL;\r
+ qryrownbr = 1;\r
+ }\r
+}\r