Author: shawkins
Date: 2009-12-23 10:14:00 -0500 (Wed, 23 Dec 2009)
New Revision: 1699
Removed:
trunk/engine/src/main/java/com/metamatrix/query/processor/BaseProcessorPlan.java
Modified:
trunk/engine/src/main/java/com/metamatrix/query/optimizer/batch/BatchedUpdatePlanner.java
trunk/engine/src/main/java/com/metamatrix/query/processor/ProcessorPlan.java
trunk/engine/src/main/java/com/metamatrix/query/processor/batch/BatchedUpdatePlan.java
trunk/engine/src/main/java/com/metamatrix/query/processor/proc/ProcedurePlan.java
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/RelationalPlan.java
trunk/engine/src/main/java/com/metamatrix/query/processor/xml/XMLPlan.java
trunk/engine/src/main/java/com/metamatrix/query/processor/xquery/XQueryPlan.java
trunk/engine/src/main/java/com/metamatrix/query/sql/util/VariableContext.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java
trunk/engine/src/test/java/com/metamatrix/query/optimizer/batch/TestBatchedUpdatePlanner.java
trunk/engine/src/test/java/com/metamatrix/query/processor/FakeDataManager.java
trunk/engine/src/test/java/com/metamatrix/query/processor/FakeProcessorPlan.java
trunk/engine/src/test/java/com/metamatrix/query/processor/TestBaseProcessorPlan.java
trunk/engine/src/test/java/com/metamatrix/query/processor/batch/TestBatchedUpdatePlan.java
trunk/engine/src/test/java/com/metamatrix/query/unittest/FakeMetadataFactory.java
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestDataTierManager.java
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedStatement.java
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedStatementBatchedUpdate.java
Log:
TEIID-911 fix for virtual bulk updates. the variablecontext was not being used by
BatchedUpdatePlan
Modified:
trunk/engine/src/main/java/com/metamatrix/query/optimizer/batch/BatchedUpdatePlanner.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/optimizer/batch/BatchedUpdatePlanner.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/main/java/com/metamatrix/query/optimizer/batch/BatchedUpdatePlanner.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -96,6 +96,10 @@
List updateCommands = batchedUpdateCommand.getUpdateCommands();
int numCommands = updateCommands.size();
List<VariableContext> allContexts =
batchedUpdateCommand.getVariableContexts();
+ List<VariableContext> planContexts = null;
+ if (allContexts != null) {
+ planContexts = new ArrayList<VariableContext>(allContexts.size());
+ }
for (int commandIndex = 0; commandIndex < numCommands; commandIndex++) {
// Potentially the first command of a batch
Command updateCommand = (Command)updateCommands.get(commandIndex);
@@ -153,6 +157,9 @@
projectNode.addChild(batchNode);
// Add a new RelationalPlan that represents the plan for this
batch.
childPlans.add(new RelationalPlan(projectNode));
+ if (planContexts != null) {
+ planContexts.add(new VariableContext());
+ }
// Skip those commands that were added to this batch
commandIndex += batch.size() - 1;
commandWasBatched = true;
@@ -166,9 +173,12 @@
plan = QueryOptimizer.optimizePlan(cmd, metadata, idGenerator, capFinder,
analysisRecord, context);
}
childPlans.add(plan);
+ if (allContexts != null) {
+ planContexts.add(allContexts.get(commandIndex));
+ }
}
}
- return new BatchedUpdatePlan(childPlans,
batchedUpdateCommand.getUpdateCommands().size());
+ return new BatchedUpdatePlan(childPlans,
batchedUpdateCommand.getUpdateCommands().size(), planContexts);
}
/**
Deleted: trunk/engine/src/main/java/com/metamatrix/query/processor/BaseProcessorPlan.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/processor/BaseProcessorPlan.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/main/java/com/metamatrix/query/processor/BaseProcessorPlan.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -1,85 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package com.metamatrix.query.processor;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.metamatrix.api.exception.MetaMatrixException;
-import com.metamatrix.query.util.CommandContext;
-
-/**
- */
-public abstract class BaseProcessorPlan implements ProcessorPlan{
-
- private List warnings = null;
-
- private CommandContext context;
-
- /**
- * Constructor for BaseProcessorPlan.
- */
- public BaseProcessorPlan() {
- super();
- }
-
- /**
- * @see com.metamatrix.query.processor.ProcessorPlan#getAndClearWarnings()
- */
- public List getAndClearWarnings() {
- if (warnings == null) {
- return null;
- }
- List copied = warnings;
- warnings = null;
- return copied;
- }
-
- protected void addWarning(MetaMatrixException warning) {
- if (warnings == null) {
- warnings = new ArrayList(1);
- }
- warnings.add(warning);
- }
-
- /**
- * @return
- */
- public CommandContext getContext() {
- return context;
- }
-
- /**
- * @param context
- */
- public void setContext(CommandContext context) {
- this.context = context;
- }
-
- public void reset() {
- warnings = null;
- }
-
- public abstract Object clone();
-
-}
Modified: trunk/engine/src/main/java/com/metamatrix/query/processor/ProcessorPlan.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/processor/ProcessorPlan.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/main/java/com/metamatrix/query/processor/ProcessorPlan.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -22,10 +22,12 @@
package com.metamatrix.query.processor;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.metamatrix.api.exception.MetaMatrixComponentException;
+import com.metamatrix.api.exception.MetaMatrixException;
import com.metamatrix.api.exception.MetaMatrixProcessingException;
import com.metamatrix.common.buffer.*;
import com.metamatrix.query.processor.BatchCollector.BatchProducer;
@@ -44,7 +46,11 @@
* the call to {@link #close}.
* </p>
*/
-public interface ProcessorPlan extends Cloneable, Describable, BatchProducer {
+public abstract class ProcessorPlan implements Cloneable, Describable, BatchProducer {
+
+ private List warnings = null;
+
+ private CommandContext context;
/**
* Initialize the plan with some required pieces of data for making
@@ -56,7 +62,7 @@
* @param dataMgr Data manager reference
* @param bufferMgr Buffer manager reference
*/
- void initialize(CommandContext context, ProcessorDataManager dataMgr, BufferManager
bufferMgr);
+ public abstract void initialize(CommandContext context, ProcessorDataManager dataMgr,
BufferManager bufferMgr);
/**
* Get all warnings found while processing this plan. These warnings may
@@ -65,30 +71,52 @@
* the current warnings list. The warnings are in order they were detected.
* @return Current list of warnings, never null
*/
- List<Exception> getAndClearWarnings();
+ public List getAndClearWarnings() {
+ if (warnings == null) {
+ return null;
+ }
+ List copied = warnings;
+ warnings = null;
+ return copied;
+ }
+ protected void addWarning(MetaMatrixException warning) {
+ if (warnings == null) {
+ warnings = new ArrayList(1);
+ }
+ warnings.add(warning);
+ }
+
/**
* Reset a plan so that it can be processed again.
*/
- void reset();
+ public void reset() {
+ this.warnings = null;
+ }
/**
* Get list of resolved elements describing output columns for this plan.
* @return List of SingleElementSymbol
*/
- List getOutputElements();
+ public abstract List getOutputElements();
/**
* Get the processor context, which can be modified.
* @return context object
*/
- CommandContext getContext();
+ public CommandContext getContext() {
+ return context;
+ }
+ public void setContext(CommandContext context) {
+ this.context = context;
+ }
+
/**
* Open the plan for processing.
* @throws MetaMatrixComponentException
*/
- void open() throws MetaMatrixComponentException, MetaMatrixProcessingException;
+ public abstract void open() throws MetaMatrixComponentException,
MetaMatrixProcessingException;
/**
* Get a batch of results or possibly an Exception.
@@ -98,15 +126,14 @@
* @throws MetaMatrixProcessingException for business rule exception, related
* to user input or modeling
*/
- TupleBatch nextBatch() throws BlockedException, MetaMatrixComponentException,
MetaMatrixProcessingException;
+ public abstract TupleBatch nextBatch() throws BlockedException,
MetaMatrixComponentException, MetaMatrixProcessingException;
/**
* Close the plan after processing.
* @throws MetaMatrixComponentException
*/
- void close() throws MetaMatrixComponentException;
+ public abstract void close() throws MetaMatrixComponentException;
-
/**
* Return a safe clone of the ProcessorPlan. A ProcessorPlan may only be
* safely cloned in between processings. That is, it is only safe to clone
@@ -115,12 +142,12 @@
* @return safe clone of this ProcessorPlan, as long as it is not open for
* processing
*/
- Object clone();
+ public abstract ProcessorPlan clone();
/**
* Finds all nested plans and returns them.
* @return List of ProcessorPlan
* @since 4.2
*/
- Collection getChildPlans();
+ public abstract Collection getChildPlans();
}
Modified:
trunk/engine/src/main/java/com/metamatrix/query/processor/batch/BatchedUpdatePlan.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/processor/batch/BatchedUpdatePlan.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/main/java/com/metamatrix/query/processor/batch/BatchedUpdatePlan.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -34,20 +34,23 @@
import com.metamatrix.common.buffer.BlockedException;
import com.metamatrix.common.buffer.BufferManager;
import com.metamatrix.common.buffer.TupleBatch;
-import com.metamatrix.query.processor.BaseProcessorPlan;
import com.metamatrix.query.processor.DescribableUtil;
import com.metamatrix.query.processor.ProcessorDataManager;
import com.metamatrix.query.processor.ProcessorPlan;
import com.metamatrix.query.sql.lang.Command;
+import com.metamatrix.query.sql.util.VariableContext;
import com.metamatrix.query.util.CommandContext;
/**
* Plan for execution for a batched update command. The plan executes the child plans of
the
* individual commands in order.
+ *
+ * If variableContexts are provided, then this is a bulk update where all plans are the
same object.
+ *
* @since 4.2
*/
-public class BatchedUpdatePlan extends BaseProcessorPlan {
+public class BatchedUpdatePlan extends ProcessorPlan {
/** Array that holds the child update plans */
private ProcessorPlan[] updatePlans;
@@ -60,6 +63,8 @@
/** The position of the command for which the update count is being retrieved */
private int commandIndex = 0;
+ private List<VariableContext> contexts; //only set for bulk updates
+
/**
*
* @param childPlans the child update plans for this batch
@@ -67,22 +72,29 @@
* commands have been batched together.
* @since 4.2
*/
- public BatchedUpdatePlan(List childPlans, int commandsInBatch) {
+ public BatchedUpdatePlan(List childPlans, int commandsInBatch,
List<VariableContext> contexts) {
this.updatePlans = (ProcessorPlan[])childPlans.toArray(new
ProcessorPlan[childPlans.size()]);
this.planOpened = new boolean[updatePlans.length];
this.updateCounts = new List[commandsInBatch];
+ this.contexts = contexts;
}
/**
* @see java.lang.Object#clone()
* @since 4.2
*/
- public Object clone() {
- List clonedPlans = new ArrayList(updatePlans.length);
- for (int i = 0; i < updatePlans.length; i++) {
- clonedPlans.add(updatePlans[i].clone());
+ public BatchedUpdatePlan clone() {
+ List<ProcessorPlan> clonedPlans = new
ArrayList<ProcessorPlan>(updatePlans.length);
+
+ clonedPlans.add((ProcessorPlan)updatePlans[0].clone());
+ for (int i = 1; i <updatePlans.length; i++) {
+ if (contexts == null) {
+ clonedPlans.add((ProcessorPlan)updatePlans[1].clone());
+ } else {
+ clonedPlans.add(clonedPlans.get(0));
+ }
}
- return new BatchedUpdatePlan(clonedPlans, updateCounts.length);
+ return new BatchedUpdatePlan(clonedPlans, updateCounts.length, contexts);
}
/**
@@ -90,8 +102,11 @@
* @since 4.2
*/
public void initialize(CommandContext context, ProcessorDataManager dataMgr,
BufferManager bufferMgr) {
+ context = (CommandContext)context.clone();
+ context.setVariableContext(new VariableContext()); //start a new root variable
context
+ this.setContext(context);
// Initialize all the child plans
- for (int i = 0; i < updatePlans.length; i++) {
+ for (int i = 0; i < getPlanCount(); i++) {
updatePlans[i].initialize(context, dataMgr, bufferMgr);
}
}
@@ -111,8 +126,7 @@
public void open() throws MetaMatrixComponentException, MetaMatrixProcessingException
{
// It's ok to open() the first plan, as it is not dependent on any prior
commands.
// See note for defect 16166 in the nextBatch() method.
- updatePlans[0].open();
- planOpened[0] = true;
+ openPlan();
}
/**
@@ -130,8 +144,7 @@
* guarantee that the commands in the previous plan are completed before
the commands in any subsequent
* plans are executed.
*/
- updatePlans[planIndex].open();
- planOpened[planIndex] = true;
+ openPlan();
}
// Execute nextBatch() on each plan in sequence
List[] currentBatch = updatePlans[planIndex].nextBatch().getAllTuples(); //
Can throw BlockedException
@@ -148,6 +161,19 @@
return batch;
}
+ private void openPlan() throws MetaMatrixComponentException,
+ MetaMatrixProcessingException {
+ if (this.contexts != null && !this.contexts.isEmpty()) {
+ CommandContext context = updatePlans[planIndex].getContext();
+ context.getVariableContext().clear();
+ VariableContext currentValues = this.contexts.get(planIndex);
+ context.getVariableContext().putAll(currentValues);
+ }
+ updatePlans[planIndex].reset();
+ updatePlans[planIndex].open();
+ planOpened[planIndex] = true;
+ }
+
/**
* @see com.metamatrix.query.processor.ProcessorPlan#close()
* @since 4.2
@@ -185,7 +211,7 @@
Map props = new HashMap();
props.put(PROP_TYPE, "Batched Update Plan"); //$NON-NLS-1$
List children = new ArrayList();
- for (int i = 0; i < updatePlans.length; i++) {
+ for (int i = 0; i < getPlanCount(); i++) {
children.add(updatePlans[i].getDescriptionProperties());
}
props.put(PROP_CHILDREN, children);
@@ -195,7 +221,7 @@
public String toString() {
StringBuffer val = new StringBuffer("BatchedUpdatePlan {\n");
//$NON-NLS-1$
- for (int i = 0; i < updatePlans.length; i++) {
+ for (int i = 0; i < getPlanCount(); i++) {
val.append(updatePlans[i])
.append("\n"); //$NON-NLS-1$
}
@@ -203,6 +229,10 @@
return val.toString();
}
+ private int getPlanCount() {
+ return (contexts != null?1:updatePlans.length);
+ }
+
/**
* Returns the child plans for this batch. Used primarily for unit tests.
* @return
Modified:
trunk/engine/src/main/java/com/metamatrix/query/processor/proc/ProcedurePlan.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/processor/proc/ProcedurePlan.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/main/java/com/metamatrix/query/processor/proc/ProcedurePlan.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -47,7 +47,6 @@
import com.metamatrix.query.execution.QueryExecPlugin;
import com.metamatrix.query.metadata.QueryMetadataInterface;
import com.metamatrix.query.metadata.SupportConstants;
-import com.metamatrix.query.processor.BaseProcessorPlan;
import com.metamatrix.query.processor.BatchIterator;
import com.metamatrix.query.processor.CollectionTupleSource;
import com.metamatrix.query.processor.DescribableUtil;
@@ -71,7 +70,7 @@
import com.metamatrix.query.util.ErrorMessageKeys;
/**
*/
-public class ProcedurePlan extends BaseProcessorPlan {
+public class ProcedurePlan extends ProcessorPlan {
public static class CursorState {
private QueryProcessor processor;
@@ -320,7 +319,7 @@
return "ProcedurePlan:\n" +
ProgramUtil.programToString(this.originalProgram); //$NON-NLS-1$
}
- public Object clone(){
+ public ProcessorPlan clone(){
ProcedurePlan plan = new ProcedurePlan((Program)originalProgram.clone());
plan.setUpdateProcedure(this.isUpdateProcedure());
plan.setOutputElements(this.getOutputElements());
Modified:
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/RelationalPlan.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/RelationalPlan.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/RelationalPlan.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -35,7 +35,6 @@
import com.metamatrix.common.buffer.BufferManager;
import com.metamatrix.common.buffer.TupleBatch;
import com.metamatrix.common.log.LogManager;
-import com.metamatrix.query.processor.BaseProcessorPlan;
import com.metamatrix.query.processor.DescribableUtil;
import com.metamatrix.query.processor.ProcessorDataManager;
import com.metamatrix.query.processor.ProcessorPlan;
@@ -44,7 +43,7 @@
/**
*/
-public class RelationalPlan extends BaseProcessorPlan {
+public class RelationalPlan extends ProcessorPlan {
// Initialize state - don't reset
private RelationalNode root;
@@ -130,7 +129,7 @@
return this.root.toString();
}
- public Object clone(){
+ public RelationalPlan clone(){
RelationalPlan plan = new RelationalPlan((RelationalNode)root.clone());
plan.setOutputElements(new ArrayList(( outputCols != null ? outputCols :
Collections.EMPTY_LIST )));
return plan;
Modified: trunk/engine/src/main/java/com/metamatrix/query/processor/xml/XMLPlan.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/processor/xml/XMLPlan.java 2009-12-22
19:36:54 UTC (rev 1698)
+++ trunk/engine/src/main/java/com/metamatrix/query/processor/xml/XMLPlan.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -73,7 +73,6 @@
import com.metamatrix.common.types.XMLType;
import com.metamatrix.core.util.Assertion;
import com.metamatrix.query.execution.QueryExecPlugin;
-import com.metamatrix.query.processor.BaseProcessorPlan;
import com.metamatrix.query.processor.DescribableUtil;
import com.metamatrix.query.processor.ProcessorDataManager;
import com.metamatrix.query.processor.ProcessorPlan;
@@ -89,7 +88,7 @@
/**
*
*/
-public class XMLPlan extends BaseProcessorPlan {
+public class XMLPlan extends ProcessorPlan {
// State passed during construction
private XMLProcessorEnvironment env;
@@ -645,7 +644,7 @@
* in other words, it's only safe to call clone() on a plan after nextTuple()
returns null,
* meaning the plan has finished processing.
*/
- public Object clone(){
+ public XMLPlan clone(){
XMLPlan xmlPlan = new XMLPlan((XMLProcessorEnvironment)this.env.clone());
return xmlPlan;
}
Modified:
trunk/engine/src/main/java/com/metamatrix/query/processor/xquery/XQueryPlan.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/processor/xquery/XQueryPlan.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/main/java/com/metamatrix/query/processor/xquery/XQueryPlan.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -40,9 +40,9 @@
import com.metamatrix.common.types.DataTypeManager;
import com.metamatrix.common.types.Streamable;
import com.metamatrix.common.types.XMLType;
-import com.metamatrix.query.processor.BaseProcessorPlan;
import com.metamatrix.query.processor.DescribableUtil;
import com.metamatrix.query.processor.ProcessorDataManager;
+import com.metamatrix.query.processor.ProcessorPlan;
import com.metamatrix.query.processor.dynamic.SqlEval;
import com.metamatrix.query.processor.xml.XMLUtil;
import com.metamatrix.query.sql.lang.XQuery;
@@ -54,7 +54,7 @@
/**
* XQuery execution Plan
*/
-public class XQueryPlan extends BaseProcessorPlan {
+public class XQueryPlan extends ProcessorPlan {
private XQuery xQuery;
private BufferManager bufferMgr;
private String xmlFormat;
@@ -76,7 +76,7 @@
/**
* @see java.lang.Object#clone()
*/
- public Object clone() {
+ public XQueryPlan clone() {
XQuery clonedQuery = (XQuery)this.xQuery.clone();
return new XQueryPlan(clonedQuery);
}
Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/util/VariableContext.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/sql/util/VariableContext.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/main/java/com/metamatrix/query/sql/util/VariableContext.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -177,4 +177,12 @@
return this.variableMap.toString();
}
+ public void clear() {
+ this.variableMap.clear();
+ }
+
+ public void putAll(VariableContext other) {
+ this.variableMap.putAll(other.variableMap);
+ }
+
}
Modified:
trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -191,11 +191,13 @@
throw new QueryValidatorException("No batch values sent for prepared batch
update"); //$NON-NLS-1$
}
boolean supportPreparedBatchUpdate = false;
+ Command command = null;
if (this.processPlan instanceof RelationalPlan) {
RelationalPlan rPlan = (RelationalPlan)this.processPlan;
if (rPlan.getRootNode() instanceof AccessNode) {
AccessNode aNode = (AccessNode)rPlan.getRootNode();
String modelName = aNode.getModelName();
+ command = aNode.getCommand();
SourceCapabilities caps = capabilitiesFinder.findCapabilities(modelName);
supportPreparedBatchUpdate =
caps.supportsCapability(SourceCapabilities.Capability.BULK_UPDATE);
}
@@ -216,11 +218,13 @@
List<Object> multiValue = multiValues.get(i);
multiValue.add(values.get(i));
}
- continue;
+ } else { //just accumulate copies of the command/plan - clones are not necessary
+ if (command == null) {
+ command = this.prepPlan.getCommand();
+ command.setProcessorPlan(this.processPlan);
+ }
+ commands.add(command);
}
- Command c = (Command)this.prepPlan.getCommand().clone();
- commands.add(c);
- c.setProcessorPlan((ProcessorPlan)this.processPlan.clone());
}
if (paramValues.size() > 1) {
Modified:
trunk/engine/src/test/java/com/metamatrix/query/optimizer/batch/TestBatchedUpdatePlanner.java
===================================================================
---
trunk/engine/src/test/java/com/metamatrix/query/optimizer/batch/TestBatchedUpdatePlanner.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/test/java/com/metamatrix/query/optimizer/batch/TestBatchedUpdatePlanner.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -67,9 +67,9 @@
super(name);
}
- public static List helpGetCommands(String[] sql, QueryMetadataInterface md) throws
QueryParserException, QueryResolverException, MetaMatrixComponentException,
QueryValidatorException {
+ public static List<Command> helpGetCommands(String[] sql,
QueryMetadataInterface md) throws QueryParserException, QueryResolverException,
MetaMatrixComponentException, QueryValidatorException {
if(DEBUG) System.out.println("\n####################################\n"
+ sql); //$NON-NLS-1$
- List commands = new ArrayList(sql.length);
+ List<Command> commands = new ArrayList<Command>(sql.length);
for (int i = 0; i < sql.length; i++) {
Command command = QueryParser.getQueryParser().parseCommand(sql[i]);
QueryResolver.resolveCommand(command, md);
Modified: trunk/engine/src/test/java/com/metamatrix/query/processor/FakeDataManager.java
===================================================================
---
trunk/engine/src/test/java/com/metamatrix/query/processor/FakeDataManager.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/test/java/com/metamatrix/query/processor/FakeDataManager.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -76,18 +76,26 @@
// Track history to verify it later
private List<String> queries = new ArrayList<String>();
+ private boolean recordingCommands = true;
- public FakeDataManager() {
- }
-
/**
* Return string form of all queries run against this FDM
- * @return List<String>
+ * @return List<String> recorded commands
*/
public List<String> getQueries() {
return this.queries;
}
+ /**
+ * Clears the list of recorded commands and returns a copy
+ * @return a copy of the recorded commands prior to clearing the list
+ */
+ public List<String> clearQueries() {
+ List<String> rc = new ArrayList<String>(this.getQueries());
+ this.queries.clear();
+ return rc;
+ }
+
public void registerTuples(Object groupID, List elements, List[] data) {
tuples.put(groupID, new Object[] { elements, data });
}
@@ -101,9 +109,10 @@
LogManager.logTrace(LOG_CONTEXT, new Object[]{"Register Request:",
command, ",processorID:", processorID, ",model name:",
modelName,",TupleSourceID nodeID:",new Integer(nodeID)}); //$NON-NLS-1$
//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-
- if (! (command instanceof BatchedUpdateCommand) ) {
- this.queries.add(command.toString());
+ if (this.recordingCommands) {
+ if (! (command instanceof BatchedUpdateCommand) ) {
+ this.queries.add(command.toString());
+ }
}
if (ReferenceCollectorVisitor.getReferences(command).size() > 0) {
@@ -122,9 +131,11 @@
if ( command.getSubCommands().get(0) instanceof Update ) {
group = ((Update)command.getSubCommands().get(0)).getGroup();
}
- for ( Iterator<Command> it = ((BatchedUpdateCommand)
command).getUpdateCommands().iterator(); it.hasNext(); ) {
- this.queries.add(it.next().toString());
- }
+ if (this.recordingCommands) {
+ for ( Iterator<Command> it = ((BatchedUpdateCommand)
command).getUpdateCommands().iterator(); it.hasNext(); ) {
+ this.queries.add(it.next().toString());
+ }
+ }
}
Object groupID = group.getMetadataID();
@@ -350,8 +361,31 @@
}
@Override
- public void clearCodeTables() {
-
- }
+ public void clearCodeTables() {/* does nothing */}
+ /**
+ * Are commands/queries that are registered with the data manager being
+ * recorded?
+ * <p>
+ * Recorded commands can be retrieved by {@link #getQueries()}
+ *
+ * @return whether or not commands should be recorded
+ */
+ public boolean isRecordingCommands() {
+ return recordingCommands;
+ }
+
+ /**
+ * Indicate whether or not commands/queries registered with the data
+ * manager are to be recorded in {@link #queries}.
+ * <p>
+ * Recorded commands can be retrieved by {@link #getQueries()}
+ *
+ * @param shouldRecord should commands be recorded?
+ */
+ public void setRecordingCommands(boolean shouldRecord) {
+ this.recordingCommands = shouldRecord;
+ }
+
+
}
\ No newline at end of file
Modified:
trunk/engine/src/test/java/com/metamatrix/query/processor/FakeProcessorPlan.java
===================================================================
---
trunk/engine/src/test/java/com/metamatrix/query/processor/FakeProcessorPlan.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/test/java/com/metamatrix/query/processor/FakeProcessorPlan.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -30,7 +30,7 @@
/**
*/
-public class FakeProcessorPlan extends BaseProcessorPlan {
+public class FakeProcessorPlan extends ProcessorPlan {
private List outputElements;
private List batches;
@@ -51,7 +51,7 @@
/**
* @see java.lang.Object#clone()
*/
- public Object clone() {
+ public FakeProcessorPlan clone() {
throw new UnsupportedOperationException();
}
Modified:
trunk/engine/src/test/java/com/metamatrix/query/processor/TestBaseProcessorPlan.java
===================================================================
---
trunk/engine/src/test/java/com/metamatrix/query/processor/TestBaseProcessorPlan.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/test/java/com/metamatrix/query/processor/TestBaseProcessorPlan.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -35,7 +35,6 @@
import com.metamatrix.common.buffer.BlockedException;
import com.metamatrix.common.buffer.BufferManager;
import com.metamatrix.common.buffer.TupleBatch;
-import com.metamatrix.common.buffer.TupleSource;
import com.metamatrix.query.util.CommandContext;
public class TestBaseProcessorPlan extends TestCase {
@@ -55,15 +54,13 @@
assertNull("Did not clear warnings from plan",
plan.getAndClearWarnings()); //$NON-NLS-1$
}
-
-
- private static class FakeProcessorPlan extends BaseProcessorPlan {
+ private static class FakeProcessorPlan extends ProcessorPlan {
/**
* @see java.lang.Object#clone()
*/
- public Object clone() {
+ public FakeProcessorPlan clone() {
return null;
}
@@ -74,12 +71,6 @@
}
/**
- * @see
com.metamatrix.query.processor.ProcessorPlan#connectTupleSource(com.metamatrix.common.buffer.TupleSource,
int)
- */
- public void connectTupleSource(TupleSource source, int dataRequestID) {
- }
-
- /**
* @see com.metamatrix.query.processor.ProcessorPlan#getOutputElements()
*/
public List getOutputElements() {
@@ -108,14 +99,6 @@
public void open() throws MetaMatrixComponentException {
}
- /* (non-Javadoc)
- * @see com.metamatrix.query.processor.ProcessorPlan#getUpdateCount()
- */
- public int getUpdateCount() {
- // TODO Auto-generated method stub
- return 0;
- }
-
public Map getDescriptionProperties() {
return new HashMap();
}
Modified:
trunk/engine/src/test/java/com/metamatrix/query/processor/batch/TestBatchedUpdatePlan.java
===================================================================
---
trunk/engine/src/test/java/com/metamatrix/query/processor/batch/TestBatchedUpdatePlan.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/test/java/com/metamatrix/query/processor/batch/TestBatchedUpdatePlan.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -36,8 +36,8 @@
import com.metamatrix.common.buffer.BufferManager;
import com.metamatrix.common.buffer.TupleBatch;
import com.metamatrix.common.buffer.TupleSource;
-import com.metamatrix.query.processor.BaseProcessorPlan;
import com.metamatrix.query.processor.ProcessorDataManager;
+import com.metamatrix.query.processor.ProcessorPlan;
import com.metamatrix.query.util.CommandContext;
@@ -58,7 +58,7 @@
totalCommands += commandsPerPlan[i];
plans.add(new FakeProcessorPlan(commandsPerPlan[i]));
}
- BatchedUpdatePlan plan = new BatchedUpdatePlan(plans, totalCommands);
+ BatchedUpdatePlan plan = new BatchedUpdatePlan(plans, totalCommands, null);
TupleBatch batch = plan.nextBatch();
assertEquals(totalCommands, batch.getRowCount());
for (int i = 1; i <= totalCommands; i++) {
@@ -71,7 +71,7 @@
for (int i = 0; i < plans.length; i++) {
plans[i] = new FakeProcessorPlan(1);
}
- BatchedUpdatePlan plan = new BatchedUpdatePlan(Arrays.asList(plans),
plans.length);
+ BatchedUpdatePlan plan = new BatchedUpdatePlan(Arrays.asList(plans),
plans.length, null);
plan.open();
// First plan may or may not be opened, but all subsequent plans should not be
opened.
for (int i = 1; i < plans.length; i++) {
@@ -91,14 +91,14 @@
helpTestNextBatch(new int[] {1, 1, 1, 1});
}
- private class FakeProcessorPlan extends BaseProcessorPlan {
+ private class FakeProcessorPlan extends ProcessorPlan {
private int counts = 0;
private boolean opened = false;
private int updateConnectorCount = 1;
private FakeProcessorPlan(int commands) {
counts = commands;
}
- public Object clone() {return null;}
+ public FakeProcessorPlan clone() {return null;}
public void close() throws MetaMatrixComponentException {}
public void connectTupleSource(TupleSource source, int dataRequestID) {}
public List getOutputElements() {return null;}
Modified:
trunk/engine/src/test/java/com/metamatrix/query/unittest/FakeMetadataFactory.java
===================================================================
---
trunk/engine/src/test/java/com/metamatrix/query/unittest/FakeMetadataFactory.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/test/java/com/metamatrix/query/unittest/FakeMetadataFactory.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -887,8 +887,10 @@
QueryNode vspqn41 = new QueryNode("vsp41", "CREATE VIRTUAL
PROCEDURE BEGIN SELECT e1 FROM pm1.g1 where e2=15; END"); //$NON-NLS-1$
//$NON-NLS-2$
FakeMetadataObject vsp41 = createVirtualProcedure("pm1.vsp41", pm1,
Arrays.asList(new FakeMetadataObject[] { vspp1 }), vspqn41); //$NON-NLS-1$
- vm1g1.putProperty(FakeMetadataObject.Props.INSERT_PROCEDURE, "CREATE
PROCEDURE BEGIN ROWS_UPDATED = INSERT INTO pm1.g1(e2) values(INPUT.e2); END");
//$NON-NLS-1$
- vm1g1.putProperty(FakeMetadataObject.Props.UPDATE_PROCEDURE, "CREATE
PROCEDURE BEGIN ROWS_UPDATED = UPDATE pm1.g1 SET e2 = INPUT.e2; END"); //$NON-NLS-1$
+ vm1g1.putProperty(FakeMetadataObject.Props.INSERT_PROCEDURE, "CREATE
PROCEDURE BEGIN ROWS_UPDATED = INSERT INTO pm1.g1(e1, e2, e3, e4) values(INPUT.e1,
INPUT.e2, INPUT.e3, INPUT.e4); END"); //$NON-NLS-1$
+ vm1g1.putProperty(FakeMetadataObject.Props.UPDATE_PROCEDURE, "CREATE
PROCEDURE BEGIN ROWS_UPDATED = UPDATE pm1.g1 SET e1 = INPUT.e1, e2 = INPUT.e2, e3 =
INPUT.e3, e4=INPUT.e4 WHERE TRANSLATE CRITERIA; END"); //$NON-NLS-1$
+ vm1g1.putProperty(FakeMetadataObject.Props.DELETE_PROCEDURE, "CREATE
PROCEDURE BEGIN ROWS_UPDATED = DELETE FROM pm1.g1 WHERE TRANSLATE CRITERIA; END");
//$NON-NLS-1$
+
vm1g37.putProperty(FakeMetadataObject.Props.INSERT_PROCEDURE, "CREATE
PROCEDURE BEGIN ROWS_UPDATED = INSERT INTO pm4.g1(e1, e2, e3, e4) values(INPUT.e1,
INPUT.e2, INPUT.e3, INPUT.e4); END"); //$NON-NLS-1$
vm1g37.putProperty(FakeMetadataObject.Props.DELETE_PROCEDURE, "CREATE
PROCEDURE BEGIN ROWS_UPDATED = DELETE FROM pm4.g1 where translate criteria; END");
//$NON-NLS-1$
QueryNode vspqn37 = new QueryNode("vsp37", "CREATE VIRTUAL
PROCEDURE BEGIN DECLARE integer x; VARIABLES.x=5; INSERT INTO vm1.g1(e2)
values(VARIABLES.x); END"); //$NON-NLS-1$ //$NON-NLS-2$
Modified:
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestDataTierManager.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestDataTierManager.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestDataTierManager.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -29,10 +29,10 @@
import java.util.Map;
import java.util.Properties;
-import org.teiid.connector.metadata.runtime.MetadataStore;
-
import junit.framework.TestCase;
+import org.teiid.connector.metadata.runtime.MetadataStore;
+
import com.metamatrix.api.exception.ComponentNotFoundException;
import com.metamatrix.api.exception.MetaMatrixComponentException;
import com.metamatrix.api.exception.MetaMatrixException;
@@ -316,11 +316,9 @@
}
}
- private static class FakeProcessorPlan implements ProcessorPlan {
- public Object clone() {return this;}
+ private static class FakeProcessorPlan extends ProcessorPlan {
+ public FakeProcessorPlan clone() {return this;}
public void close() throws MetaMatrixComponentException {}
- public List getAndClearWarnings() {return null;}
- public CommandContext getContext() {return null;}
public List getOutputElements() {return Collections.EMPTY_LIST;}
public void initialize(CommandContext context,ProcessorDataManager
dataMgr,BufferManager bufferMgr) {}
public TupleBatch nextBatch() throws
BlockedException,MetaMatrixComponentException {
Modified:
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedStatement.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedStatement.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedStatement.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -124,9 +124,22 @@
//make sure the plan is only created once
assertEquals("should reuse the plan", exHitCount,
prepPlanCache.hitCount); //$NON-NLS-1$
+ // If we are using FakeDataManager, stop command recording to prevent
+ // duplicate commands
+ boolean dmir = false;
+ if (dataManager instanceof FakeDataManager && ((FakeDataManager)
dataManager).isRecordingCommands()) {
+ dmir = true;
+ ((FakeDataManager) dataManager).setRecordingCommands(false);
+ }
// Run query again
TestProcessor.doProcess(plan.processPlan, dataManager, expected, plan.context);
+ // If we are using FakeDataManager and we stopped it from recording,
+ // start it back up again
+ if (dmir == true) {
+ ((FakeDataManager) dataManager).setRecordingCommands(true);
+ }
+
//get the plan again with a new connection
assertNotNull(TestPreparedStatement.helpGetProcessorPlan(preparedSql, values,
capFinder, metadata, prepPlanCache, 7, callableStatement, false));
Modified:
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedStatementBatchedUpdate.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedStatementBatchedUpdate.java 2009-12-22
19:36:54 UTC (rev 1698)
+++
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedStatementBatchedUpdate.java 2009-12-23
15:14:00 UTC (rev 1699)
@@ -48,19 +48,53 @@
*/
public class TestPreparedStatementBatchedUpdate {
+ @Test public void testBatchedUpdatePushdown() throws Exception {
+ // Create query
+ String preparedSql = "UPDATE pm1.g1 SET pm1.g1.e1=?, pm1.g1.e3=? WHERE
pm1.g1.e2=?"; //$NON-NLS-1$
+
+ // Create a testable prepared plan cache
+ TestablePreparedPlanCache prepPlanCache = new TestablePreparedPlanCache();
+
+ // Construct data manager with data
+ HardcodedDataManager dataManager = new HardcodedDataManager();
+ dataManager.addData("UPDATE pm1.g1 SET e1 = ?, e3 = ? WHERE pm1.g1.e2 = ?",
new List[] {Arrays.asList(4)}); //$NON-NLS-1$
+ // Source capabilities must support batched updates
+ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+ BasicSourceCapabilities caps = new BasicSourceCapabilities();
+ caps.setCapabilitySupport(Capability.BULK_UPDATE, true);
+ capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
+
+ // batch with two commands
+ ArrayList<ArrayList<Object>> values = new
ArrayList<ArrayList<Object>>(2);
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { "a",
Boolean.FALSE, new Integer(0) }))); //$NON-NLS-1$
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { null,
Boolean.FALSE, new Integer(1) })));
+
+ List<?>[] expected = new List[] {
+ Arrays.asList(4)
+ };
+
+ // Create the plan and process the query
+ TestPreparedStatement.helpTestProcessing(preparedSql, values, expected, dataManager,
capFinder, FakeMetadataFactory.example1Cached(), prepPlanCache, false, false, false);
+ Update update = (Update)dataManager.getCommandHistory().iterator().next();
+
assertTrue(((Constant)update.getChangeList().getClauses().get(0).getValue()).isMultiValued());
+ }
+
/**
* Test prepared statements that use batched updates using the same prepared
- * command with varying number of commands in the batch.
+ * command with same number of commands in the batch.
* <p>
- * The test verifies that no errors occur when planning the same batched
- * command SQL with varying number of batched command parameter value sets.
- * For example, if the first executeBatch() call were to occur with three
- * batched commands a repeated call with only two batched commands should
- * not result in an error.
+ * The test verifies that no errors occur when planning and executing the
+ * same batched command SQL with the same number of batched command parameter
+ * value sets. For example, if the first executeBatch() call were to occur
+ * with two batched commands a repeated call with two batched commands
+ * should not result in an error during planning or execution and the value
+ * used in the second batched command should be used instead of any values
+ * from the first batched command.
* <p>
- * The test also verifies that a cached version of the PreparedStatement plan
- * is used on each subsequent execution of the same SQL command even though
- * the number of batched commands may vary.
+ * The test also verifies that the correct SQL is pushed to the data manager
+ * to verify that the parameter substitution occurred and is correct and the
+ * correct number of statements made it to the data manager for the respective
+ * batch command.
* <p>
* The batched command "UPDATE pm1.g1 SET pm1.g1.e1=?, pm1.g1.e3=? WHERE
pm1.g1.e2=?"
* will appear as:
@@ -69,51 +103,169 @@
* UPDATE pm1.g1 SET pm1.g1.e1=null, pm1.g1.e3=false WHERE pm1.g1.e2=1
* <p>
* UPDATE pm1.g1 SET pm1.g1.e1='a', pm1.g1.e3=false WHERE pm1.g1.e2=0
- * <p>
- * UPDATE pm1.g1 SET pm1.g1.e1='a', pm1.g1.e3=false WHERE pm1.g1.e2=0
- * UPDATE pm1.g1 SET pm1.g1.e1=null, pm1.g1.e3=false WHERE pm1.g1.e2=1
- * UPDATE pm1.g1 SET pm1.g1.e1='c', pm1.g1.e3=true WHERE pm1.g1.e2=4
* UPDATE pm1.g1 SET pm1.g1.e1='b', pm1.g1.e3=true WHERE pm1.g1.e2=5
* <p>
- * The result should be that only one command is in the plan cache and
- * no plan creation or validation errors will occur.
+ * The result should be that one command is in the plan cache and
+ * no plan creation, validation, or execution errors will occur and
+ * a predetermined set of queries were executed in the data manager.
*
* @throws Exception
*/
- @Test public void testPlanCache_VarNumCmds() throws Exception {
+ @Test public void testUpdateSameNumCmds() throws Exception {
// Create query
String preparedSql = "UPDATE pm1.g1 SET pm1.g1.e1=?, pm1.g1.e3=? WHERE
pm1.g1.e2=?"; //$NON-NLS-1$
+ // Create a testable prepared plan cache
+ TestablePreparedPlanCache prepPlanCache = new TestablePreparedPlanCache();
+
+ // Construct data manager with data
+ FakeDataManager dataManager = new FakeDataManager();
+ TestProcessor.sampleData1(dataManager);
+
+ // Source capabilities must support batched updates
+ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+ BasicSourceCapabilities caps = new BasicSourceCapabilities();
+ caps.setCapabilitySupport(Capability.BATCHED_UPDATES, true);
+ capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
- // Create PrepareedPlanCache
- PreparedPlanCache prepPlanCache = new PreparedPlanCache();
+ // Something to hold our final query list
+ List<String> finalQueryList = new ArrayList<String>(13);
+
+ // Create expected results
+ // first command should result in 2 rows affected
+ // second command should result in 2 rows affected
+ List<?>[] expected = new List[] {
+ Arrays.asList(new Object[] { new Integer(2) }),
+ Arrays.asList(new Object[] { new Integer(2) })
+ };
+
+ // batch with two commands
+ List<List<Object>> values = new ArrayList<List<Object>>(2);
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { "a",
Boolean.FALSE, new Integer(0) }))); //$NON-NLS-1$
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { null,
Boolean.FALSE, new Integer(1) })));
+
+ // Add our expected queries to the final query list
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'a', e3 = FALSE
WHERE pm1.g1.e2 = 0")); //$NON-NLS-1$
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = null, e3 = FALSE WHERE
pm1.g1.e2 = 1")); //$NON-NLS-1$
+
+ // Create the plan and process the query
+ TestPreparedStatement.helpTestProcessing(preparedSql, values, expected, dataManager,
capFinder, FakeMetadataFactory.example1Cached(), prepPlanCache, false, false, false);
+
+ // Repeat with different number of commands in batch
+ // Create expected results
+ // first command should result in 2 rows affected
+ expected = new List[] {
+ Arrays.asList(new Object[] { new Integer(2) }),
+ Arrays.asList(new Object[] { new Integer(0) })
+ };
+
+ // batch with two commands
+ values = new ArrayList<List<Object>>(1);
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { "a",
Boolean.FALSE, new Integer(0) }))); //$NON-NLS-1$
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { "b",
Boolean.TRUE, new Integer(5) }))); //$NON-NLS-1$
+
+ // Add our expected queries to the final query list
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'a', e3 = FALSE
WHERE pm1.g1.e2 = 0")); //$NON-NLS-1$
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'b', e3 = TRUE
WHERE pm1.g1.e2 = 5")); //$NON-NLS-1$
+
+ // Use the cached plan and process the query
+ TestPreparedStatement.helpTestProcessing(preparedSql, values, expected, dataManager,
capFinder, FakeMetadataFactory.example1Cached(), prepPlanCache, false, false, true);
+
+ // Verify all the queries that were run
+ assertEquals("Unexpected queries executed -", finalQueryList,
dataManager.getQueries()); //$NON-NLS-1$
+ }
+
+ /**
+ * Test prepared statements that use batched updates using the same prepared
+ * command with same number of commands in the batch. Update is performed
+ * against a view model instead of a source model.
+ * <p>
+ * The test verifies that no errors occur when planning and executing the
+ * same batched command SQL with the same number of batched command parameter
+ * value sets. For example, if the first executeBatch() call were to occur
+ * with two batched commands a repeated call with two batched commands
+ * should not result in an error during planning or execution and the value
+ * used in the second batched command should be used instead of any values
+ * from the first batched command.
+ * <p>
+ * The test also verifies that the correct SQL is pushed to the data manager
+ * to verify that the parameter substitution occurred and is correct and the
+ * correct number of statements made it to the data manager for the respective
+ * batch command.
+ * <p>
+ * The batched command "UPDATE vm1.g1 SET vm1.g1.e2=? WHERE vm1.g1.e1=?"
+ * will appear as:
+ * <p>
+ * UPDATE pm1.g1 SET e2=0 WHERE pm1.g1.e1='a'
+ * UPDATE pm1.g1 SET e2=1 WHERE pm1.g1.e1='b'
+ * <p>
+ * UPDATE pm1.g1 SET e2=2 WHERE pm1.g1.e1='c'
+ * UPDATE pm1.g1 SET e2=3 WHERE pm1.g1.e1='d'
+ * <p>
+ * The result should be that one command is in the plan cache and
+ * no plan creation, validation, or execution errors will occur and
+ * a predetermined set of queries were executed in the data manager.
+ *
+ * @throws Exception
+ */
+ @Test public void testUpdateSameNumCmds_Virtual() throws Exception {
+ // Create query
+ String preparedSql = "UPDATE vm1.g1 SET vm1.g1.e2=? WHERE vm1.g1.e1=?";
//$NON-NLS-1$
+ // Create a testable prepared plan cache
+ TestablePreparedPlanCache prepPlanCache = new TestablePreparedPlanCache();
+ // Construct data manager with data
+ FakeDataManager dataManager = new FakeDataManager();
+ TestProcessor.sampleData1(dataManager);
+
+ // Source capabilities must support batched updates
+ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+ BasicSourceCapabilities caps = new BasicSourceCapabilities();
+ caps.setCapabilitySupport(Capability.BATCHED_UPDATES, true);
+ capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
+
+ // Something to hold our final query list
+ List<String> finalQueryList = new ArrayList<String>();
+
+ // Create expected results
+ List<?>[] expected = new List[] {
+ Arrays.asList(3),
+ Arrays.asList(1)
+ };
+
// batch with two commands
ArrayList<ArrayList<Object>> values = new
ArrayList<ArrayList<Object>>(2);
- values.add( new ArrayList<Object>( Arrays.asList( new Object[] { "a",
Boolean.FALSE, new Integer(0) } ) ) ); //$NON-NLS-1$
- values.add( new ArrayList<Object>( Arrays.asList( new Object[] { null,
Boolean.FALSE, new Integer(1) } ) ) );
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { new Integer(0),
"a" }))); //$NON-NLS-1$
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { new Integer(1),
"b" }))); //$NON-NLS-1$
- //Create plan
- TestPreparedStatement.helpGetProcessorPlan(preparedSql, values, prepPlanCache);
+ // Add our expected queries to the final query list
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e2 = 0 WHERE pm1.g1.e1 =
'a'")); //$NON-NLS-1$
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e2 = 1 WHERE pm1.g1.e1 =
'b'")); //$NON-NLS-1$
+
+ // Create the plan and process the query
+ TestPreparedStatement.helpTestProcessing(preparedSql, values, expected, dataManager,
capFinder, FakeMetadataFactory.example1Cached(), prepPlanCache, false, false, false);
- // batch with one command
+ // Repeat
+ expected = new List[] {
+ Arrays.asList(1),
+ Arrays.asList(0)
+ };
+
+ // batch with two commands
values = new ArrayList<ArrayList<Object>>(1);
- values.add( new ArrayList<Object>( Arrays.asList( new Object[] { "a",
Boolean.FALSE, new Integer(0) } ) ) ); //$NON-NLS-1$
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { new Integer(2),
"c" }))); //$NON-NLS-1$
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { new Integer(3),
"d" }))); //$NON-NLS-1$
- //Create plan
- TestPreparedStatement.helpGetProcessorPlan(preparedSql, values, prepPlanCache);
+ // Add our expected queries to the final query list
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e2 = 2 WHERE pm1.g1.e1 =
'c'")); //$NON-NLS-1$
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e2 = 3 WHERE pm1.g1.e1 =
'd'")); //$NON-NLS-1$
+
+ // Use the cached plan and process the query
+ TestPreparedStatement.helpTestProcessing(preparedSql, values, expected, dataManager,
capFinder, FakeMetadataFactory.example1Cached(), prepPlanCache, false, false, true);
- // batch with four commands
- values = new ArrayList<ArrayList<Object>>(4);
- values.add( new ArrayList<Object>( Arrays.asList( new Object[] { "a",
Boolean.FALSE, new Integer(0) } ) ) ); //$NON-NLS-1$
- values.add( new ArrayList<Object>( Arrays.asList( new Object[] { null,
Boolean.FALSE, new Integer(1) } ) ) );
- values.add( new ArrayList<Object>( Arrays.asList( new Object[] { "c",
Boolean.TRUE, new Integer(4) } ) ) ); //$NON-NLS-1$
- values.add( new ArrayList<Object>( Arrays.asList( new Object[] { "b",
Boolean.TRUE, new Integer(5) } ) ) ); //$NON-NLS-1$
-
- //Create plan
- TestPreparedStatement.helpGetProcessorPlan(preparedSql, values, prepPlanCache);
- assertEquals("PreparedPlanCache size is invalid - ", 1,
prepPlanCache.getSpaceUsed() ); //$NON-NLS-1$
+ // Verify all the queries that were run
+ assertEquals("Unexpected queries executed -", finalQueryList,
dataManager.getQueries()); //$NON-NLS-1$
}
-
+
/**
* Test prepared statements that use batched updates using the same prepared
* command with varying number of commands in the batch.
@@ -124,14 +276,10 @@
* with two batched commands a repeated call with only one batched command
* should not result in an error during planning or execution.
* <p>
- * The test also verifies that a cached version of the PreparedStatement plan
- * is used on each subsequent execution of the same SQL command even though
- * the number of batched commands may vary.
- * <p>
* The test also verifies that the correct SQL is pushed to the data manager
* to verify that the parameter substitution occurred and is correct and the
* correct number of statements made it to the data manager for the respective
- * batch.
+ * batch command.
* <p>
* The batched command "UPDATE pm1.g1 SET pm1.g1.e1=?, pm1.g1.e3=? WHERE
pm1.g1.e2=?"
* will appear as:
@@ -146,16 +294,15 @@
* UPDATE pm1.g1 SET pm1.g1.e1='c', pm1.g1.e3=true WHERE pm1.g1.e2=4
* UPDATE pm1.g1 SET pm1.g1.e1='b', pm1.g1.e3=true WHERE pm1.g1.e2=5
* <p>
- * The result should be that only one command is in the plan cache and
+ * The result should be that three commands are in the plan cache and
* no plan creation, validation, or execution errors will occur and
* a predetermined set of queries were executed in the data manager.
*
* @throws Exception
*/
- @Test public void testProcessor_VarNumCmds() throws Exception {
+ @Test public void testUpdateVarNumCmds() throws Exception {
// Create query
String preparedSql = "UPDATE pm1.g1 SET pm1.g1.e1=?, pm1.g1.e3=? WHERE
pm1.g1.e2=?"; //$NON-NLS-1$
- int executionsPerTest = 2;
// Create a testable prepared plan cache
TestablePreparedPlanCache prepPlanCache = new TestablePreparedPlanCache();
@@ -186,10 +333,8 @@
values.add(new ArrayList<Object>(Arrays.asList(new Object[] { null,
Boolean.FALSE, new Integer(1) })));
// Add our expected queries to the final query list
- for ( int i = 0; i < executionsPerTest; i++ ) {
- finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'a', e3 = FALSE
WHERE pm1.g1.e2 = 0")); //$NON-NLS-1$
- finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = null, e3 = FALSE WHERE
pm1.g1.e2 = 1")); //$NON-NLS-1$
- }
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'a', e3 = FALSE
WHERE pm1.g1.e2 = 0")); //$NON-NLS-1$
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = null, e3 = FALSE WHERE
pm1.g1.e2 = 1")); //$NON-NLS-1$
// Create the plan and process the query
TestPreparedStatement.helpTestProcessing(preparedSql, values, expected, dataManager,
capFinder, FakeMetadataFactory.example1Cached(), prepPlanCache, false, false, false);
@@ -206,9 +351,7 @@
values.add(new ArrayList<Object>(Arrays.asList(new Object[] { "a",
Boolean.FALSE, new Integer(0) }))); //$NON-NLS-1$
// Add our expected queries to the final query list
- for (int i = 0; i < executionsPerTest; i++) {
- finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'a', e3 = FALSE
WHERE pm1.g1.e2 = 0")); //$NON-NLS-1$
- }
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'a', e3 = FALSE
WHERE pm1.g1.e2 = 0")); //$NON-NLS-1$
// Use the cached plan and process the query
TestPreparedStatement.helpTestProcessing(preparedSql, values, expected, dataManager,
capFinder, FakeMetadataFactory.example1Cached(), prepPlanCache, false, false, true);
@@ -234,12 +377,10 @@
values.add(new ArrayList<Object>(Arrays.asList(new Object[] { "b",
Boolean.TRUE, new Integer(5)} ))); //$NON-NLS-1$
// Add our expected queries to the final query list
- for (int i = 0; i < executionsPerTest; i++) {
- finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'a', e3 = FALSE
WHERE pm1.g1.e2 = 0")); //$NON-NLS-1$
- finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = null, e3 = FALSE WHERE
pm1.g1.e2 = 1")); //$NON-NLS-1$
- finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'c', e3 = TRUE
WHERE pm1.g1.e2 = 4")); //$NON-NLS-1$
- finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'b', e3 = TRUE
WHERE pm1.g1.e2 = 5")); //$NON-NLS-1$
- }
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'a', e3 = FALSE
WHERE pm1.g1.e2 = 0")); //$NON-NLS-1$
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = null, e3 = FALSE WHERE
pm1.g1.e2 = 1")); //$NON-NLS-1$
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'c', e3 = TRUE WHERE
pm1.g1.e2 = 4")); //$NON-NLS-1$
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'b', e3 = TRUE WHERE
pm1.g1.e2 = 5")); //$NON-NLS-1$
TestPreparedStatement.helpTestProcessing(preparedSql, values, expected, dataManager,
capFinder, FakeMetadataFactory.example1Cached(), prepPlanCache, false, false, true);
@@ -247,35 +388,118 @@
assertEquals("Unexpected queries executed -", finalQueryList,
dataManager.getQueries()); //$NON-NLS-1$
}
- @Test public void testBatchedUpdatePushdown() throws Exception {
+ /**
+ * Test prepared statements that use batched updates using the same prepared
+ * command with varying number of commands in the batch. Update is
+ * performed against a view model instead of a source model.
+ * <p>
+ * The test verifies that no errors occur when planning and executing the
+ * same batched command SQL with varying number of batched command parameter
+ * value sets. For example, if the first executeBatch() call were to occur
+ * with two batched commands a repeated call with only one batched command
+ * should not result in an error during planning or execution.
+ * <p>
+ * The test also verifies that the correct SQL is pushed to the data manager
+ * to verify that the parameter substitution occurred and is correct and the
+ * correct number of statements made it to the data manager for the respective
+ * batch command.
+ * <p>
+ * The batched command "UPDATE vm1.g1 SET vm1.g1.e1=?, vm1.g1.e3=? WHERE
vm1.g1.e2=?"
+ * will appear as:
+ * <p>
+ * UPDATE pm1.g1 SET e1='a', e3=false WHERE pm1.g1.e2=0
+ * UPDATE pm1.g1 SET e1='b', e3=true WHERE pm1.g1.e2=1
+ * <p>
+ * UPDATE pm1.g1 SET e1='c', e3=false WHERE pm1.g1.e2=1
+ * <p>
+ * UPDATE pm1.g1 SET e1='d', e3=false WHERE pm1.g1.e2=1
+ * UPDATE pm1.g1 SET e1='e', e3=false WHERE pm1.g1.e2=0
+ * UPDATE pm1.g1 SET e1='f', e3=true WHERE pm1.g1.e2=2
+ * UPDATE pm1.g1 SET e1='g', e3=true WHERE pm1.g1.e2=3
+ * <p>
+ * The result should be that three commands are in the plan cache and
+ * no plan creation, validation, or execution errors will occur and
+ * a predetermined set of queries were executed in the data manager.
+ *
+ * @throws Exception
+ */
+ @Test public void testUpdateVarNumCmds_Virtual() throws Exception {
// Create query
- String preparedSql = "UPDATE pm1.g1 SET pm1.g1.e1=?, pm1.g1.e3=? WHERE
pm1.g1.e2=?"; //$NON-NLS-1$
-
+ String preparedSql = "UPDATE vm1.g1 SET vm1.g1.e1=?, vm1.g1.e3=? WHERE
vm1.g1.e2=?"; //$NON-NLS-1$
// Create a testable prepared plan cache
TestablePreparedPlanCache prepPlanCache = new TestablePreparedPlanCache();
// Construct data manager with data
- HardcodedDataManager dataManager = new HardcodedDataManager();
- dataManager.addData("UPDATE pm1.g1 SET e1 = ?, e3 = ? WHERE pm1.g1.e2 = ?",
new List[] {Arrays.asList(4)}); //$NON-NLS-1$
+ FakeDataManager dataManager = new FakeDataManager();
+ TestProcessor.sampleData1(dataManager);
+
// Source capabilities must support batched updates
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
- caps.setCapabilitySupport(Capability.BULK_UPDATE, true);
+ caps.setCapabilitySupport(Capability.BATCHED_UPDATES, true);
capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
+ // Something to hold our final query list
+ List<String> finalQueryList = new ArrayList<String>(13);
+
+ // Create expected results
+ List<?>[] expected = new List[] {
+ Arrays.asList(2),
+ Arrays.asList(2)
+ };
+
// batch with two commands
ArrayList<ArrayList<Object>> values = new
ArrayList<ArrayList<Object>>(2);
values.add(new ArrayList<Object>(Arrays.asList(new Object[] { "a",
Boolean.FALSE, new Integer(0) }))); //$NON-NLS-1$
- values.add(new ArrayList<Object>(Arrays.asList(new Object[] { null,
Boolean.FALSE, new Integer(1) })));
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { "b",
Boolean.TRUE, new Integer(1) }))); //$NON-NLS-1$
- List<?>[] expected = new List[] {
- Arrays.asList(4)
- };
+ // Add our expected queries to the final query list
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'a', e3 = FALSE
WHERE pm1.g1.e2 = 0")); //$NON-NLS-1$
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'b', e3 = TRUE
WHERE pm1.g1.e2 = 1")); //$NON-NLS-1$
// Create the plan and process the query
TestPreparedStatement.helpTestProcessing(preparedSql, values, expected, dataManager,
capFinder, FakeMetadataFactory.example1Cached(), prepPlanCache, false, false, false);
- Update update = (Update)dataManager.getCommandHistory().iterator().next();
-
assertTrue(((Constant)update.getChangeList().getClauses().get(0).getValue()).isMultiValued());
+
+ // Repeat with different number of commands in batch
+ expected = new List[] {
+ Arrays.asList(new Object[] { new Integer(2) })
+ };
+
+ // batch with one command
+ values = new ArrayList<ArrayList<Object>>(1);
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { "c",
Boolean.FALSE, new Integer(1) }))); //$NON-NLS-1$
+
+ // Add our expected queries to the final query list
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'c', e3 = FALSE
WHERE pm1.g1.e2 = 1")); //$NON-NLS-1$
+
+ // Use the cached plan and process the query
+ TestPreparedStatement.helpTestProcessing(preparedSql, values, expected, dataManager,
capFinder, FakeMetadataFactory.example1Cached(), prepPlanCache, false, false, true);
+
+ // Repeat with different number of commands in batch
+ expected = new List[] {
+ Arrays.asList(2),
+ Arrays.asList(2),
+ Arrays.asList(1),
+ Arrays.asList(1)
+ };
+
+ // batch with four commands
+ values = new ArrayList<ArrayList<Object>>(4);
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { "d",
Boolean.FALSE, new Integer(1)} ))); //$NON-NLS-1$
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { "e",
Boolean.FALSE, new Integer(0)} ))); //$NON-NLS-1$
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { "f",
Boolean.TRUE, new Integer(2)} ))); //$NON-NLS-1$
+ values.add(new ArrayList<Object>(Arrays.asList(new Object[] { "g",
Boolean.TRUE, new Integer(3)} ))); //$NON-NLS-1$
+
+ // Add our expected queries to the final query list
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'd', e3 = FALSE
WHERE pm1.g1.e2 = 1")); //$NON-NLS-1$
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'e', e3 = FALSE
WHERE pm1.g1.e2 = 0")); //$NON-NLS-1$
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'f', e3 = TRUE WHERE
pm1.g1.e2 = 2")); //$NON-NLS-1$
+ finalQueryList.add(new String("UPDATE pm1.g1 SET e1 = 'g', e3 = TRUE WHERE
pm1.g1.e2 = 3")); //$NON-NLS-1$
+
+ TestPreparedStatement.helpTestProcessing(preparedSql, values, expected, dataManager,
capFinder, FakeMetadataFactory.example1Cached(), prepPlanCache, false, false, true);
+
+ // Verify all the queries that were run
+ assertEquals("Unexpected queries executed -", finalQueryList,
dataManager.getQueries()); //$NON-NLS-1$
}
-
+
}