Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / derby-10.3.2.1 / java / engine / org / apache / derby / impl / sql / execute / NestedLoopLeftOuterJoinResultSet.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/execute/NestedLoopLeftOuterJoinResultSet.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/execute/NestedLoopLeftOuterJoinResultSet.java
new file mode 100644 (file)
index 0000000..302e229
--- /dev/null
@@ -0,0 +1,286 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.execute.NestedLoopLeftOuterJoinResultSet\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.sql.execute;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.iapi.services.loader.GeneratedMethod;\r
+import org.apache.derby.iapi.sql.Activation;\r
+import org.apache.derby.iapi.sql.execute.ExecRow;\r
+import org.apache.derby.iapi.sql.execute.NoPutResultSet;\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+\r
+\r
+/**\r
+ * Takes 2 NoPutResultSets and a join filter and returns\r
+ * the join's rows satisfying the filter as a result set\r
+ * plus the rows from the left joined with a null row from\r
+ * the right when there is no matching row in the right\r
+ * result set.\r
+ */\r
+class NestedLoopLeftOuterJoinResultSet extends NestedLoopJoinResultSet\r
+{\r
+       protected GeneratedMethod emptyRowFun;\r
+       /* Was this originally a right outer join? */\r
+       private boolean wasRightOuterJoin;\r
+\r
+       /* Have we found a matching row from the right yet? */\r
+       private boolean matchRight = false;\r
+       private boolean returnedEmptyRight = false;\r
+       private ExecRow rightEmptyRow = null;\r
+\r
+       public int emptyRightRowsReturned = 0;\r
+\r
+       //\r
+       // ResultSet interface (leftover from NoPutResultSet)\r
+       //\r
+\r
+       /**\r
+     * Return the requested values computed\r
+     * from the next row (if any) for which\r
+     * the restriction evaluates to true.\r
+     * <p>\r
+     * restriction parameters\r
+     * are evaluated for each row.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        * @exception StandardException         ResultSetNotOpen thrown if closed\r
+        * @return the next row in the join result\r
+        */\r
+       public ExecRow  getNextRowCore() throws StandardException\r
+       {\r
+           ExecRow result = null;\r
+               boolean haveRow = false;\r
+           boolean restrict = false;\r
+           DataValueDescriptor restrictBoolean;\r
+\r
+               beginTime = getCurrentTimeMillis();\r
+               if (! isOpen)\r
+                       throw StandardException.newException(SQLState.LANG_RESULT_SET_NOT_OPEN, "next");\r
+\r
+               /* Close right and advance left if we found no match\r
+                * on right on last next().\r
+                */\r
+               if (returnedEmptyRight)\r
+               {\r
+                       /* Current scan on right is exhausted.  Need to close old scan \r
+                        * and open new scan with new "parameters".  openRight will\r
+                        * reopen the scan.\r
+                        */\r
+                       leftRow = leftResultSet.getNextRowCore();\r
+                       if (leftRow == null)\r
+                       {\r
+                               closeRight();\r
+                       }\r
+                       else\r
+                       {\r
+                               rowsSeenLeft++;\r
+                               openRight();\r
+                       }\r
+                       returnedEmptyRight = false;\r
+               }\r
+\r
+               while (leftRow != null && !haveRow)\r
+               {\r
+                       rightRow = rightResultSet.getNextRowCore();\r
+\r
+                       if (rightRow == null)\r
+                       {\r
+                               /* If we haven't found a match on the right, then\r
+                                * we join the left with a row of nulls from the\r
+                                * right.\r
+                                */\r
+                               if (! matchRight)\r
+                               {\r
+                                       haveRow = true;\r
+                                       returnedEmptyRight = true;\r
+                                       if (rightEmptyRow == null)\r
+                                       {\r
+                                               rightEmptyRow = (ExecRow) emptyRowFun.invoke(activation);\r
+                                       }\r
+\r
+                                       getMergedRow(leftRow, rightEmptyRow);\r
+                                       emptyRightRowsReturned++;\r
+                                       continue;\r
+                               }\r
+\r
+                               /* Current scan on right is exhausted.  Need to close old scan \r
+                                * and open new scan with new "parameters".  openRight()\r
+                                * will reopen the scan.\r
+                                */\r
+                               matchRight = false;\r
+                               leftRow = leftResultSet.getNextRowCore();\r
+                               if (leftRow == null)\r
+                               {\r
+                                       closeRight();\r
+                               }\r
+                               else\r
+                               {\r
+                                       rowsSeenLeft++;\r
+                                       openRight();\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               rowsSeenRight++;\r
+\r
+                               if (restriction != null)\r
+                               {\r
+                                       restrictBoolean =\r
+                                               (DataValueDescriptor) restriction.invoke(activation);\r
+\r
+                               // if the result is null, we make it false --\r
+                                       // so the row won't be returned.\r
+                                       restrict = (! restrictBoolean.isNull()) &&\r
+                                                                       restrictBoolean.getBoolean();\r
+\r
+                                       if (! restrict)\r
+                                       {\r
+                                               /* Update the run time statistics */\r
+                                               rowsFiltered++;\r
+                                               continue;\r
+                                       }\r
+                               }\r
+\r
+                               matchRight = true;\r
+\r
+                               getMergedRow(leftRow, rightRow);\r
+                               haveRow = true;\r
+                       }\r
+               }\r
+\r
+               /* Do we have a row to return? */\r
+           if (haveRow)\r
+           {\r
+                       result = mergedRow;\r
+                       setCurrentRow(mergedRow);\r
+                       rowsReturned++;\r
+           }\r
+               else\r
+               {\r
+                       clearCurrentRow();\r
+               }\r
+\r
+               nextTime += getElapsedMillis(beginTime);\r
+           return result;\r
+       }\r
+\r
+       protected void getMergedRow(ExecRow leftRow, ExecRow rightRow) \r
+                       throws StandardException\r
+       {\r
+               int colInCtr;\r
+               int colOutCtr;\r
+               int leftNumCols;\r
+               int rightNumCols;\r
+\r
+               /* Reverse left and right for return of row if this was originally\r
+                * a right outer join.  (Result columns ordered according to\r
+                * original query.)\r
+                */\r
+               if (wasRightOuterJoin)\r
+               {\r
+                       ExecRow tmp;\r
+\r
+                       tmp = leftRow;\r
+                       leftRow = rightRow;\r
+                       rightRow = tmp;\r
+                       leftNumCols = this.rightNumCols;\r
+                       rightNumCols = this.leftNumCols;\r
+               }\r
+               else\r
+               {\r
+                       leftNumCols = this.leftNumCols;\r
+                       rightNumCols = this.rightNumCols;\r
+               }\r
+\r
+               /* Merge the rows, doing just in time allocation for mergedRow.\r
+                * (By convention, left Row is to left of right Row.)\r
+                */\r
+               if (mergedRow == null)\r
+               {\r
+                       mergedRow = getExecutionFactory().getValueRow(leftNumCols + rightNumCols);\r
+               }\r
+\r
+               for (colInCtr = 1, colOutCtr = 1; colInCtr <= leftNumCols;\r
+                        colInCtr++, colOutCtr++)\r
+               {\r
+                        mergedRow.setColumn(colOutCtr, \r
+                                                                leftRow.getColumn(colInCtr));\r
+               }\r
+               for (colInCtr = 1; colInCtr <= rightNumCols; \r
+                        colInCtr++, colOutCtr++)\r
+               {\r
+                        mergedRow.setColumn(colOutCtr, \r
+                                                                rightRow.getColumn(colInCtr));\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Clear any private state that changes during scans.\r
+        * This includes things like the last row seen, etc.\r
+        * THis does not include immutable things that are\r
+        * typically set up in the constructor.\r
+        * <p>\r
+        * This method is called on open()/close() and reopen()\r
+        * <p>\r
+        * WARNING: this should be implemented in every sub\r
+        * class and it should always call super.clearScanState().\r
+        */\r
+       void clearScanState()\r
+       {\r
+               matchRight = false;\r
+               returnedEmptyRight = false;\r
+               rightEmptyRow = null;\r
+               emptyRightRowsReturned = 0;\r
+               super.clearScanState();\r
+       }\r
+\r
+\r
+    /*\r
+     * class interface\r
+     *\r
+     */\r
+    NestedLoopLeftOuterJoinResultSet(\r
+                                               NoPutResultSet leftResultSet,\r
+                                               int leftNumCols,\r
+                                               NoPutResultSet rightResultSet,\r
+                                               int rightNumCols,\r
+                                               Activation activation,\r
+                                               GeneratedMethod restriction,\r
+                                               int resultSetNumber,\r
+                                               GeneratedMethod emptyRowFun,\r
+                                               boolean wasRightOuterJoin,\r
+                                           boolean oneRowRightSide,\r
+                                           boolean notExistsRightSide,\r
+                                           double optimizerEstimatedRowCount,\r
+                                               double optimizerEstimatedCost,\r
+                                               String userSuppliedOptimizerOverrides)\r
+    {\r
+               super(leftResultSet, leftNumCols, rightResultSet, rightNumCols,\r
+                         activation, restriction, resultSetNumber, \r
+                         oneRowRightSide, notExistsRightSide,\r
+                         optimizerEstimatedRowCount, optimizerEstimatedCost, \r
+                         userSuppliedOptimizerOverrides);\r
+               this.emptyRowFun = emptyRowFun;\r
+               this.wasRightOuterJoin = wasRightOuterJoin;\r
+    }\r
+}\r