[NO ISSUE][COMP] Avoid variable reference sharing

- user model changes: no
- storage format changes: no
- interface changes: no

Details:
- IntroduceSecondaryIndexInsertDeleteRule should
  not share variable reference expressions

Change-Id: I1d8d25cf2ea78016b7f090398656f6dac718e573
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/10724
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Dmitry Lychagin <dmitry.lychagin@couchbase.com>
Reviewed-by: Glenn Galvizo <ggalvizo@uci.edu>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
index bf87fc0..c3859be 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
@@ -686,9 +686,7 @@
         int sourceIndicatorForBaseRecord = workingElement.getSourceIndicator();
         LogicalVariable sourceVarForBaseRecord = hasMetaPart
                 ? ((sourceIndicatorForBaseRecord == Index.RECORD_INDICATOR) ? recordVar : metaVar) : recordVar;
-        VariableReferenceExpression baseRecordVarRef = new VariableReferenceExpression(sourceVarForBaseRecord);
-        baseRecordVarRef.setSourceLocation(sourceLoc);
-        UnnestBranchCreator branchCreator = new UnnestBranchCreator(baseRecordVarRef, unnestSourceOp);
+        UnnestBranchCreator branchCreator = new UnnestBranchCreator(sourceVarForBaseRecord, unnestSourceOp);
 
         int initialKeyPositionQueueSize = keyPositionQueue.size();
         Set<LogicalVariable> secondaryKeyVars = new HashSet<>();
@@ -739,7 +737,7 @@
                 for (int j = 1; j < workingElement.getProjectList().size(); j++) {
                     LogicalVariable newVar = context.newVar();
                     AbstractFunctionCallExpression newVarRef =
-                            getFieldAccessFunction(new MutableObject<>(branchCreator.lastRecordVarRef), -1,
+                            getFieldAccessFunction(new MutableObject<>(branchCreator.createLastRecordVarRef()), -1,
                                     workingElement.getProjectList().get(j));
 
                     AssignOperator newAssignOp = new AssignOperator(newVar, new MutableObject<>(newVarRef));
@@ -988,12 +986,12 @@
      */
     private class UnnestBranchCreator implements ArrayIndexUtil.TypeTrackerCommandExecutor {
         private final List<LogicalVariable> lastFieldVars;
-        private VariableReferenceExpression lastRecordVarRef;
+        private LogicalVariable lastRecordVar;
         private ILogicalOperator currentTop, currentBottom;
         private boolean isFirstWalk = true;
 
-        public UnnestBranchCreator(VariableReferenceExpression recordVarRef, ILogicalOperator sourceOperator) {
-            this.lastRecordVarRef = recordVarRef;
+        public UnnestBranchCreator(LogicalVariable recordVar, ILogicalOperator sourceOperator) {
+            this.lastRecordVar = recordVar;
             this.currentTop = sourceOperator;
             this.lastFieldVars = new ArrayList<>();
         }
@@ -1006,6 +1004,12 @@
             isFirstWalk = false;
         }
 
+        public VariableReferenceExpression createLastRecordVarRef() {
+            VariableReferenceExpression varRef = new VariableReferenceExpression(lastRecordVar);
+            varRef.setSourceLocation(sourceLoc);
+            return varRef;
+        }
+
         @SafeVarargs
         public final void applyProjectDistinct(List<Mutable<ILogicalExpression>>... auxiliaryExpressions)
                 throws AlgebricksException {
@@ -1061,9 +1065,9 @@
             if (isFirstUnnestInStep) {
                 // This is the first UNNEST step. Get the field we want to UNNEST from our record.
                 accessToUnnestVar = (startingStepRecordType != null)
-                        ? getFieldAccessFunction(new MutableObject<>(lastRecordVarRef),
+                        ? getFieldAccessFunction(new MutableObject<>(createLastRecordVarRef()),
                                 startingStepRecordType.getFieldIndex(fieldName.get(0)), fieldName)
-                        : getFieldAccessFunction(new MutableObject<>(lastRecordVarRef), -1, fieldName);
+                        : getFieldAccessFunction(new MutableObject<>(createLastRecordVarRef()), -1, fieldName);
             } else {
                 // This is the second+ UNNEST step. Refer back to the previously unnested variable.
                 accessToUnnestVar = new VariableReferenceExpression(this.lastFieldVars.get(0));
@@ -1086,8 +1090,7 @@
 
             if (isLastUnnestInIntermediateStep) {
                 // This is the last UNNEST before the next array step. Update our record variable.
-                this.lastRecordVarRef = new VariableReferenceExpression(unnestVar);
-                this.lastRecordVarRef.setSourceLocation(sourceLoc);
+                this.lastRecordVar = unnestVar;
                 this.lastFieldVars.clear();
             }
         }
@@ -1102,9 +1105,9 @@
 
             // Create the function to access our final field.
             AbstractFunctionCallExpression accessToFinalVar = (startingStepRecordType != null)
-                    ? getFieldAccessFunction(new MutableObject<>(lastRecordVarRef),
+                    ? getFieldAccessFunction(new MutableObject<>(createLastRecordVarRef()),
                             startingStepRecordType.getFieldIndex(fieldName.get(0)), fieldName)
-                    : getFieldAccessFunction(new MutableObject<>(lastRecordVarRef), -1, fieldName);
+                    : getFieldAccessFunction(new MutableObject<>(createLastRecordVarRef()), -1, fieldName);
 
             LogicalVariable finalVar = context.newVar();
             this.lastFieldVars.add(finalVar);