Author: shawkins
Date: 2012-09-26 19:15:59 -0400 (Wed, 26 Sep 2012)
New Revision: 4475
Modified:
trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
trunk/common-core/src/main/java/org/teiid/core/util/StringUtil.java
trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java
trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java
trunk/engine/src/main/java/org/teiid/query/optimizer/TriggerActionPlanner.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/CreateCursorResultSetInstruction.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/ErrorInstruction.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/ExecDynamicSqlInstruction.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/IfInstruction.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/Program.java
trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java
trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/BatchedUpdateCommand.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/Command.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/DynamicCommand.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/ProcedureContainer.java
trunk/engine/src/main/java/org/teiid/query/sql/proc/CommandStatement.java
trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateProcedureCommand.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcErrors.java
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java
trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java
trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java
trunk/engine/src/test/java/org/teiid/query/validator/TestAlterValidation.java
trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
trunk/runtime/src/main/java/org/teiid/runtime/EmbeddedServer.java
trunk/runtime/src/test/java/org/teiid/runtime/TestEmbeddedServer.java
trunk/runtime/src/test/java/org/teiid/transport/TestCommSockets.java
trunk/test-integration/common/src/test/java/org/teiid/jdbc/FakeServer.java
trunk/test-integration/common/src/test/java/org/teiid/systemmodel/TestMetadataUpdates.java
Log:
TEIID-2226 TEIID-1386 replacing the path logic for result detection and refining exception
support
Modified: trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-09-26 17:05:51 UTC
(rev 4474)
+++ trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-09-26 23:15:59 UTC
(rev 4475)
@@ -57,7 +57,9 @@
<li>TEIID-2187 the CONSTRAINT keyword is not correctly used in table DDL. It
should be replaced with a comma from scripts to be compatible with 8.2. If desired, 8.2
now supports the CONSTRAINT keyword to provide a name for each constraint.
<li>TEIID-2181 system tables no longer contain valid OIDs. That responsibility
has moved to the pg_catalog.
<li>TEIID-1386 the SQLState and errorCode reported by a TeiidSQLException will
typically be from the top level nested SQLException. If there is also a nested
TeiidException, the TeiidSQLException.teiidCode will be set to the TeiidException.getCode
value and the TeiidSQLException.errorCode will be set
- to the integer suffix of the teiidCode if possible.
+ to the integer suffix of the teiidCode if possible.
+ <li>TEIID-2226 All statements that return result sets that are executed as
command statements in a procedure are validated against the expected resultset columns of
the procedure.
+ If the statement is not intended to be returnable, WITHOUT RETURN can be added to
the end of the statement.
</ul>
<h4>from 8.0</h4>
Modified: trunk/common-core/src/main/java/org/teiid/core/util/StringUtil.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/util/StringUtil.java 2012-09-26
17:05:51 UTC (rev 4474)
+++ trunk/common-core/src/main/java/org/teiid/core/util/StringUtil.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -74,18 +74,34 @@
*/
public static final String LINE_SEPARATOR =
System.getProperty(LINE_SEPARATOR_PROPERTY_NAME, Constants.NEW_LINE);
- public static final Comparator CASE_INSENSITIVE_ORDER =
String.CASE_INSENSITIVE_ORDER;
+ public static final Comparator<String> CASE_INSENSITIVE_ORDER =
String.CASE_INSENSITIVE_ORDER;
+
+ public static final Comparator<String> NULL_SAFE_CASE_INSENSITIVE_ORDER = new
Comparator<String>() {
+ @Override
+ public int compare(String o1, String o2) {
+ if (o1 == null) {
+ if (o2 == null) {
+ return 0;
+ }
+ return -1;
+ }
+ if (o2 == null) {
+ return 1;
+ }
+ return String.CASE_INSENSITIVE_ORDER.compare(o1, o2);
+ }
+ };
- public static final Comparator CASE_SENSITIVE_ORDER = new Comparator() {
+ public static final Comparator<String> CASE_SENSITIVE_ORDER = new
Comparator<String>() {
/**
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
* @since 4.2
*/
- public int compare(Object o1, Object o2) {
+ public int compare(String o1, String o2) {
if ( o1 == o2 ) {
return 0;
}
- return ((String)o1).compareTo((String)o2);
+ return o1.compareTo(o2);
}
};
Modified: trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java 2012-09-26 17:05:51 UTC
(rev 4474)
+++ trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java 2012-09-26 23:15:59 UTC
(rev 4475)
@@ -330,7 +330,6 @@
TEIID30364,
TEIID30365,
TEIID30366,
- TEIID30367,
TEIID30371,
TEIID30372,
TEIID30373,
@@ -535,6 +534,7 @@
TEIID31118,
TEIID31119,
TEIID31120,
- TEIID31121,
+ TEIID31121,
+ TEIID31122,
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java 2012-09-26
17:05:51 UTC (rev 4474)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -36,6 +36,7 @@
import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
import org.teiid.query.processor.ProcessorPlan;
import org.teiid.query.processor.proc.*;
+import org.teiid.query.processor.proc.CreateCursorResultSetInstruction.Mode;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.lang.DynamicCommand;
import org.teiid.query.sql.lang.SPParameter;
@@ -97,7 +98,7 @@
// create plan from program and initialized environment
ProcedurePlan plan = new ProcedurePlan(programBlock);
-
+ plan.setMetadata(metadata);
plan.setOutputElements(cupc.getProjectedSymbols());
if(debug) {
@@ -231,12 +232,9 @@
ProcessorPlan commandPlan = cmdStmt.getCommand().getProcessorPlan();
if (command.getType() == Command.TYPE_DYNAMIC){
- instruction = new
ExecDynamicSqlInstruction(parentProcCommand,((DynamicCommand)command), metadata,
idGenerator, capFinder );
+ instruction = new
ExecDynamicSqlInstruction(parentProcCommand,((DynamicCommand)command), metadata,
idGenerator, capFinder, cmdStmt.isReturnable() );
}else{
- instruction = new
CreateCursorResultSetInstruction(CreateCursorResultSetInstruction.RS_NAME, commandPlan,
- command.getType() == Command.TYPE_INSERT
- || command.getType() == Command.TYPE_UPDATE
- || command.getType() == Command.TYPE_DELETE);
+ instruction = new CreateCursorResultSetInstruction(null, commandPlan,
(!command.returnsResultSet()&&!(command instanceof
StoredProcedure))?Mode.UPDATE:(cmdStmt.isReturnable()&&cmdStmt.getCommand().returnsResultSet())?Mode.HOLD:Mode.NOHOLD);
//handle stored procedure calls
if (command.getType() == Command.TYPE_STORED_PROCEDURE) {
StoredProcedure sp = (StoredProcedure)command;
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java 2012-09-26
17:05:51 UTC (rev 4474)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -22,9 +22,6 @@
package org.teiid.query.optimizer;
-import java.util.LinkedList;
-import java.util.List;
-
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.api.exception.query.QueryPlannerException;
import org.teiid.api.exception.query.QueryResolverException;
@@ -40,21 +37,17 @@
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.TempCapabilitiesFinder;
import org.teiid.query.metadata.TempMetadataAdapter;
+import org.teiid.query.metadata.TempMetadataID;
import org.teiid.query.metadata.TempMetadataStore;
import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
import org.teiid.query.optimizer.relational.RelationalPlanner;
import org.teiid.query.optimizer.xml.XMLPlanner;
import org.teiid.query.processor.ProcessorPlan;
-import org.teiid.query.processor.proc.ProcedurePlan;
import org.teiid.query.resolver.QueryResolver;
import org.teiid.query.rewriter.QueryRewriter;
import org.teiid.query.sql.lang.Command;
-import org.teiid.query.sql.lang.ProcedureContainer;
import org.teiid.query.sql.lang.Query;
-import org.teiid.query.sql.lang.SPParameter;
-import org.teiid.query.sql.lang.StoredProcedure;
import org.teiid.query.sql.proc.CreateProcedureCommand;
-import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.util.CommandContext;
@@ -111,14 +104,16 @@
switch (command.getType()) {
case Command.TYPE_UPDATE_PROCEDURE:
CreateProcedureCommand cupc = (CreateProcedureCommand)command;
- if (cupc.getUserCommand() == null) {
+ if (cupc.getUpdateType() != Command.TYPE_UNKNOWN) {
//row update procedure
result = planProcedure(command, metadata, idGenerator, capFinder, analysisRecord,
context);
} else {
- StoredProcedure c = (StoredProcedure)cupc.getUserCommand();
Object pid = cupc.getVirtualGroup().getMetadataID();
- if (c != null) {
- pid = c.getProcedureID();
+ if (pid instanceof TempMetadataID) {
+ TempMetadataID tid = (TempMetadataID)pid;
+ if (tid.getOriginalMetadataID() != null) {
+ pid = tid.getOriginalMetadataID();
+ }
}
String fullName = metadata.getFullName(pid);
fullName = "procedure cache:" + fullName; //$NON-NLS-1$
@@ -141,34 +136,6 @@
context.accessedPlanningObject(id);
}
}
- // propagate procedure parameters to the plan to allow runtime type checking
- ProcedureContainer container = (ProcedureContainer)cupc.getUserCommand();
- ProcedurePlan plan = (ProcedurePlan)result;
- if (container != null) {
- if (container instanceof StoredProcedure) {
- plan.setRequiresTransaction(container.getUpdateCount() > 0);
- StoredProcedure sp = (StoredProcedure)container;
- if (sp.returnParameters()) {
- List<ElementSymbol> outParams = new LinkedList<ElementSymbol>();
- for (SPParameter param : sp.getParameters()) {
- if (param.getParameterType() == SPParameter.RETURN_VALUE) {
- outParams.add(param.getParameterSymbol());
- }
- }
- for (SPParameter param : sp.getParameters()) {
- if (param.getParameterType() == SPParameter.INOUT ||
- param.getParameterType() == SPParameter.OUT) {
- outParams.add(param.getParameterSymbol());
- }
- }
- if (outParams.size() > 0) {
- plan.setOutParams(outParams);
- }
- }
- plan.setParams(sp.getProcedureParameters());
- }
- plan.setMetadata(metadata);
- }
break;
case Command.TYPE_BATCHED_UPDATE:
result = BATCHED_UPDATE_PLANNER.optimize(command, idGenerator, metadata, capFinder,
analysisRecord, context);
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/TriggerActionPlanner.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/TriggerActionPlanner.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/TriggerActionPlanner.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -99,7 +99,7 @@
result.setLookupMap(RelationalNode.createLookupMap(query.getProjectedSymbols()));
CreateProcedureCommand command = new CreateProcedureCommand(ta.getBlock());
command.setVirtualGroup(ta.getView());
- command.setUpdateType(userCommand.getClass().getSimpleName());
+ command.setUpdateType(userCommand.getType());
ProcedurePlan rowProcedure = (ProcedurePlan)QueryOptimizer.optimizePlan(command,
metadata, idGenerator, capFinder, analysisRecord, context);
result.setRowProcedure(rowProcedure);
return result;
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -61,6 +61,7 @@
import org.teiid.query.optimizer.relational.rules.RulePlaceAccess;
import org.teiid.query.optimizer.relational.rules.RulePushAggregates;
import org.teiid.query.processor.ProcessorPlan;
+import org.teiid.query.processor.proc.ProcedurePlan;
import org.teiid.query.processor.relational.AccessNode;
import org.teiid.query.processor.relational.RelationalPlan;
import org.teiid.query.processor.relational.JoinNode.JoinStrategyType;
@@ -581,13 +582,18 @@
if (c == null) {
c = QueryResolver.expandCommand(container, metadata, analysisRecord);
if (c != null) {
+ if (c instanceof CreateProcedureCommand) {
+ //TODO: find a better way to do this
+ ((CreateProcedureCommand)c).setProjectedSymbols(container.getProjectedSymbols());
+ }
Request.validateWithVisitor(new ValidationVisitor(), metadata, c);
metadata.addToMetadataCache(metadataId, cacheString, c.clone());
}
} else {
c = (Command)c.clone();
if (c instanceof CreateProcedureCommand) {
- ((CreateProcedureCommand)c).setUserCommand(container);
+ //TODO: find a better way to do this
+ ((CreateProcedureCommand)c).setProjectedSymbols(container.getProjectedSymbols());
}
}
if (c != null) {
@@ -1007,6 +1013,30 @@
actualMetadata = ((TempMetadataAdapter)metadata).getMetadata();
}
ProcessorPlan plan = QueryOptimizer.optimizePlan(toPlan, actualMetadata, idGenerator,
capFinder, analysisRecord, context);
+ //hack for the optimizer not knowing the containing command when forming the plan
+ if (nestedCommand instanceof StoredProcedure && plan instanceof ProcedurePlan)
{
+ StoredProcedure container = (StoredProcedure)nestedCommand;
+ ProcedurePlan pp = (ProcedurePlan)plan;
+ pp.setRequiresTransaction(container.getUpdateCount() > 0);
+ if (container.returnParameters()) {
+ List<ElementSymbol> outParams = new LinkedList<ElementSymbol>();
+ for (SPParameter param : container.getParameters()) {
+ if (param.getParameterType() == SPParameter.RETURN_VALUE) {
+ outParams.add(param.getParameterSymbol());
+ }
+ }
+ for (SPParameter param : container.getParameters()) {
+ if (param.getParameterType() == SPParameter.INOUT ||
+ param.getParameterType() == SPParameter.OUT) {
+ outParams.add(param.getParameterSymbol());
+ }
+ }
+ if (outParams.size() > 0) {
+ pp.setOutParams(outParams);
+ }
+ }
+ pp.setParams(container.getProcedureParameters());
+ }
node.setProperty(NodeConstants.Info.PROCESSOR_PLAN, plan);
}
}
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/proc/CreateCursorResultSetInstruction.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/proc/CreateCursorResultSetInstruction.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/main/java/org/teiid/query/processor/proc/CreateCursorResultSetInstruction.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -40,17 +40,21 @@
*/
public class CreateCursorResultSetInstruction extends ProgramInstruction {
- public static final String RS_NAME = "EXECSQL_INSTRUCTION"; //$NON-NLS-1$
+ public enum Mode {
+ UPDATE,
+ HOLD,
+ NOHOLD
+ }
protected String rsName;
protected ProcessorPlan plan;
- private boolean update;
+ private Mode mode;
private Map<ElementSymbol, ElementSymbol> procAssignments;
- public CreateCursorResultSetInstruction(String rsName, ProcessorPlan plan, boolean
update){
+ public CreateCursorResultSetInstruction(String rsName, ProcessorPlan plan, Mode
mode){
this.rsName = rsName;
this.plan = plan;
- this.update = update;
+ this.mode = mode;
}
public void setProcAssignments(
@@ -60,22 +64,8 @@
public void process(ProcedurePlan procEnv)
throws BlockedException, TeiidComponentException, TeiidProcessingException {
-
- if(procEnv.resultSetExists(rsName)) {
- procEnv.removeResults(rsName);
- }
-
- procEnv.executePlan(plan, rsName, procAssignments, !update);
-
- if (update) {
- boolean hasNext = procEnv.iterateCursor(rsName);
- if (hasNext) {
- procEnv.getCurrentVariableContext().setValue(ProcedurePlan.ROWCOUNT,
procEnv.getCurrentRow(rsName).get(0));
- } else {
- procEnv.getCurrentVariableContext().setValue(ProcedurePlan.ROWCOUNT, 0);
- }
- procEnv.removeResults(rsName);
- }
+
+ procEnv.executePlan(plan, rsName, procAssignments, mode);
}
/**
@@ -83,7 +73,7 @@
*/
public CreateCursorResultSetInstruction clone(){
ProcessorPlan clonedPlan = this.plan.clone();
- CreateCursorResultSetInstruction clone = new
CreateCursorResultSetInstruction(this.rsName, clonedPlan, update);
+ CreateCursorResultSetInstruction clone = new
CreateCursorResultSetInstruction(this.rsName, clonedPlan, mode);
clone.setProcAssignments(procAssignments);
return clone;
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/ErrorInstruction.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/proc/ErrorInstruction.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/main/java/org/teiid/query/processor/proc/ErrorInstruction.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -29,6 +29,7 @@
import org.teiid.core.TeiidProcessingException;
import org.teiid.jdbc.TeiidSQLException;
import org.teiid.logging.LogManager;
+import org.teiid.query.QueryPlugin;
import org.teiid.query.sql.symbol.Expression;
@@ -85,7 +86,7 @@
return;
}
if (value == null) {
- throw new TeiidProcessingException();
+ throw new TeiidProcessingException(QueryPlugin.Event.TEIID31122,
QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31122));
}
throw TeiidSQLException.create((Exception)value);
}
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/proc/ExecDynamicSqlInstruction.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/proc/ExecDynamicSqlInstruction.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/main/java/org/teiid/query/processor/proc/ExecDynamicSqlInstruction.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -52,6 +52,7 @@
import org.teiid.query.parser.QueryParser;
import org.teiid.query.processor.ProcessorPlan;
import org.teiid.query.processor.RegisterRequestParameter;
+import org.teiid.query.processor.proc.CreateCursorResultSetInstruction.Mode;
import org.teiid.query.resolver.QueryResolver;
import org.teiid.query.rewriter.QueryRewriter;
import org.teiid.query.sql.ProcedureReservedWords;
@@ -92,6 +93,7 @@
// the metadata for this plan
private QueryMetadataInterface metadata;
+ private boolean returnable;
// The parent command
CreateProcedureCommand parentProcCommand;
@@ -101,12 +103,13 @@
public ExecDynamicSqlInstruction(
CreateProcedureCommand parentProcCommand,
DynamicCommand command, QueryMetadataInterface metadata,
- IDGenerator idGenerator, CapabilitiesFinder capFinder) {
+ IDGenerator idGenerator, CapabilitiesFinder capFinder, boolean returnable) {
this.parentProcCommand = parentProcCommand;
this.dynamicCommand = command;
this.metadata = metadata;
this.capFinder = capFinder;
this.idGenerator = idGenerator;
+ this.returnable = returnable;
}
/**
@@ -185,7 +188,7 @@
.createNonRecordingRecord(), procEnv
.getContext());
- CreateCursorResultSetInstruction inst = new
CreateCursorResultSetInstruction(CreateCursorResultSetInstruction.RS_NAME, commandPlan,
dynamicCommand.getIntoGroup() != null) {
+ CreateCursorResultSetInstruction inst = new CreateCursorResultSetInstruction(null,
commandPlan, dynamicCommand.getIntoGroup() !=
null?Mode.UPDATE:returnable?Mode.HOLD:Mode.NOHOLD) {
@Override
public void process(ProcedurePlan procEnv)
throws BlockedException, TeiidComponentException,
@@ -316,8 +319,8 @@
// do a recursion check
// Add group to recursion stack
CommandContext context = procEnv.getContext();
- if (parentProcCommand.getUpdateType() != null) {
- context.pushCall(parentProcCommand.getUpdateType() + " " +
parentProcCommand.getVirtualGroup()); //$NON-NLS-1$
+ if (parentProcCommand.getUpdateType() != Command.TYPE_UNKNOWN) {
+ context.pushCall(Command.getCommandToken(parentProcCommand.getUpdateType()) + "
" + parentProcCommand.getVirtualGroup()); //$NON-NLS-1$
} else {
context.pushCall(parentProcCommand.getVirtualGroup().toString());
}
@@ -328,7 +331,7 @@
*/
public ExecDynamicSqlInstruction clone() {
ExecDynamicSqlInstruction clone = new ExecDynamicSqlInstruction(
- parentProcCommand, dynamicCommand, metadata, idGenerator, capFinder);
+ parentProcCommand, dynamicCommand, metadata, idGenerator, capFinder, returnable);
return clone;
}
@@ -341,5 +344,13 @@
props.addProperty(PROP_SQL, dynamicCommand.toString());
return props;
}
+
+ public boolean isReturnable() {
+ return returnable;
+ }
+
+ public void setReturnable(boolean returnable) {
+ this.returnable = returnable;
+ }
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/IfInstruction.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/proc/IfInstruction.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/main/java/org/teiid/query/processor/proc/IfInstruction.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -125,7 +125,14 @@
}
public String toString() {
- return "IF INSTRUCTION:"; //$NON-NLS-1$
+ StringBuffer sb = new StringBuffer("IF INSTRUCTION: "); //$NON-NLS-1$
+ sb.append(condition);
+ sb.append("\n").append(ifProgram); //$NON-NLS-1$
+ if (elseProgram!=null) {
+ sb.append("\nELSE\n"); //$NON-NLS-1$
+ sb.append(elseProgram);
+ }
+ return sb.toString();
}
public PlanNode getDescriptionProperties() {
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -49,7 +49,7 @@
private String label;
public LoopInstruction(Program loopProgram, String rsName, ProcessorPlan plan, String
label) {
- super(rsName, plan, false);
+ super(rsName, plan, Mode.NOHOLD);
this.loopProgram = loopProgram;
this.label = label;
}
@@ -105,7 +105,7 @@
public boolean testCondition(ProcedurePlan procEnv) throws TeiidComponentException,
TeiidProcessingException {
if(!procEnv.resultSetExists(rsName)) {
- procEnv.executePlan(plan, rsName, null, false);
+ procEnv.executePlan(plan, rsName, null, Mode.NOHOLD);
}
return procEnv.iterateCursor(rsName);
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -28,12 +28,12 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
+import java.util.TreeMap;
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.api.exception.query.QueryValidatorException;
@@ -52,6 +52,7 @@
import org.teiid.core.types.ArrayImpl;
import org.teiid.core.types.DataTypeManager;
import org.teiid.core.util.Assertion;
+import org.teiid.core.util.StringUtil;
import org.teiid.dqp.internal.process.DataTierTupleSource;
import org.teiid.dqp.service.TransactionContext;
import org.teiid.dqp.service.TransactionService;
@@ -70,6 +71,7 @@
import org.teiid.query.processor.ProcessorPlan;
import org.teiid.query.processor.QueryProcessor;
import org.teiid.query.processor.RegisterRequestParameter;
+import org.teiid.query.processor.proc.CreateCursorResultSetInstruction.Mode;
import org.teiid.query.processor.relational.SubqueryAwareEvaluator;
import org.teiid.query.resolver.command.UpdateProcedureResolver;
import org.teiid.query.sql.ProcedureReservedWords;
@@ -93,6 +95,13 @@
TupleBuffer resultsBuffer;
}
+ static ElementSymbol ROWCOUNT =
+ new
ElementSymbol(ProcedureReservedWords.VARIABLES+"."+ProcedureReservedWords.ROWCOUNT);
//$NON-NLS-1$
+
+ static {
+ ROWCOUNT.setType(DataTypeManager.DefaultDataClasses.INTEGER);
+ }
+
private Program originalProgram;
// State initialized by processor
@@ -113,18 +122,11 @@
private List<ElementSymbol> outParams;
private QueryMetadataInterface metadata;
- private Map<String, CursorState> cursorStates = new HashMap<String,
CursorState>();
+ private Map<String, CursorState> cursorStates = new TreeMap<String,
CursorState>(StringUtil.NULL_SAFE_CASE_INSENSITIVE_ORDER);
- static ElementSymbol ROWCOUNT =
- new
ElementSymbol(ProcedureReservedWords.VARIABLES+"."+ProcedureReservedWords.ROWCOUNT);
//$NON-NLS-1$
-
- static {
- ROWCOUNT.setType(DataTypeManager.DefaultDataClasses.INTEGER);
- }
-
private VariableContext currentVarContext;
- private TupleSource lastTupleSource;
+ private CursorState last;
private List outputElements;
@@ -202,11 +204,10 @@
evaluatedParams = false;
cursorStates.clear();
createVariableContext();
- lastTupleSource = null;
+ last = null;
done = false;
currentState = null;
-
finalTupleSource = null;
beginBatch = 1;
batchRows = null;
@@ -377,20 +378,16 @@
LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Executing
instruction", inst); //$NON-NLS-1$
inst.process(this);
}
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (TeiidComponentException e) {
+ throw e;
} catch (Exception e) {
- if (e instanceof BlockedException) {
- throw (BlockedException)e;
- }
+ //processing or teiidsqlexception
while (program.getExceptionGroup() == null) {
this.pop(false);
if (this.programs.empty()) {
//reached the top without a handler, so throw
- if (e instanceof RuntimeException) {
- throw (RuntimeException)e;
- }
- if (e instanceof TeiidComponentException) {
- throw (TeiidComponentException)e;
- }
if (e instanceof TeiidProcessingException) {
throw (TeiidProcessingException)e;
}
@@ -398,7 +395,6 @@
}
program = peek();
}
- //assign variables
if (program.getExceptionProgram() == null) {
this.pop(true);
continue;
@@ -419,10 +415,10 @@
program.incrementProgramCounter();
}
- if(lastTupleSource == null){
+ if(last == null){
return CollectionTupleSource.createNullTupleSource();
}
- return lastTupleSource;
+ return last.ts;
}
private ElementSymbol exceptionSymbol(GroupSymbol gs, int pos) {
@@ -543,11 +539,16 @@
return this.currentVarContext;
}
- public void executePlan(ProcessorPlan command, String rsName, Map<ElementSymbol,
ElementSymbol> procAssignments, boolean keepRs)
+ public void executePlan(ProcessorPlan command, String rsName, Map<ElementSymbol,
ElementSymbol> procAssignments, CreateCursorResultSetInstruction.Mode mode)
throws TeiidComponentException, TeiidProcessingException {
- CursorState state = this.cursorStates.get(rsName.toUpperCase());
+ CursorState state = this.cursorStates.get(rsName);
if (state == null) {
+ if (this.currentState != null &&
this.currentState.processor.getProcessorPlan() != command) {
+ //sanity check for non-deterministic paths
+ removeState(this.currentState);
+ this.currentState = null;
+ }
if (this.currentState == null) {
//this may not be the first time the plan is being run
command.reset();
@@ -557,16 +558,17 @@
state = new CursorState();
state.processor = new QueryProcessor(command, subContext, this.bufferMgr,
this.dataMgr);
state.ts = new BatchIterator(state.processor);
- if (procAssignments != null &&
state.processor.getOutputElements().size() - procAssignments.size() > 0) {
+ if (mode == Mode.HOLD && procAssignments != null &&
state.processor.getOutputElements().size() - procAssignments.size() > 0) {
state.resultsBuffer =
bufferMgr.createTupleBuffer(state.processor.getOutputElements().subList(0,
state.processor.getOutputElements().size() - procAssignments.size()),
getContext().getConnectionId(), TupleSourceType.PROCESSOR);
- } else if (this.blockContext != null) {
+ } else if ((this.blockContext != null ||
this.programs.peek().isTrappingExceptions()) && (mode == Mode.HOLD || rsName !=
null)) {
state.resultsBuffer =
bufferMgr.createTupleBuffer(state.processor.getOutputElements(),
getContext().getConnectionId(), TupleSourceType.PROCESSOR);
}
this.currentState = state;
}
- //force execution to the first batch
+ //force execution to the first batch to ensure that the plan is executed in the
context of the procedure
this.currentState.ts.hasNext();
if (procAssignments != null) {
+ //proc assignments force us to scroll through the entire results and save as we
go
while (this.currentState.ts.hasNext()) {
if (this.currentState.currentRow != null &&
this.currentState.resultsBuffer != null) {
this.currentState.resultsBuffer.addTuple(this.currentState.currentRow.subList(0,
this.currentState.resultsBuffer.getSchema().size()));
@@ -583,28 +585,49 @@
int index =
this.currentState.processor.getOutputElements().indexOf(entry.getKey());
getCurrentVariableContext().setValue(entry.getValue(),
DataTypeManager.transformValue(this.currentState.currentRow.get(index),
entry.getValue().getType()));
}
- //no resultset
- if (this.currentState.resultsBuffer == null) {
- this.currentState.processor.closeProcessing();
- this.currentState = null;
- return;
- }
- this.currentState.resultsBuffer.close();
- this.currentState.ts =
this.currentState.resultsBuffer.createIndexedTupleSource();
- } else if (this.blockContext != null) {
- //process fully in a block transaction
+ } else if (this.currentState.resultsBuffer != null) {
+ //result should be saved, typically to respect txn semantics
while (this.currentState.ts.hasNext()) {
List<?> tuple = this.currentState.ts.nextTuple();
this.currentState.resultsBuffer.addTuple(tuple);
+ }
+ } else if (mode == Mode.UPDATE) {
+ List<?> t = this.currentState.ts.nextTuple();
+ if (this.currentState.ts.hasNext()) {
+ throw new AssertionError("Invalid update count result - more than 1 row
returned"); //$NON-NLS-1$
+ }
+ removeState(this.currentState);
+ this.currentState = null;
+ int rowCount = 0;
+ if (t != null) {
+ rowCount = (Integer)t.get(0);
+ }
+ getCurrentVariableContext().setValue(ProcedurePlan.ROWCOUNT, rowCount);
+ return;
+ }
+ if (rsName == null && mode == Mode.NOHOLD) {
+ //unnamed without hold
+ //process fully, but don't save
+ //TODO: could set the rowcount in this case
+ while (this.currentState.ts.hasNext()) {
+ this.currentState.ts.nextTuple();
}
+ this.currentState = null;
+ return;
+ }
+ if (this.currentState.resultsBuffer != null) {
+ //close the results buffer and use a buffer backed tuplesource
this.currentState.resultsBuffer.close();
- this.currentState.ts =
this.currentState.resultsBuffer.createIndexedTupleSource();
- }
- this.cursorStates.put(rsName.toUpperCase(), this.currentState);
+ this.currentState.ts =
this.currentState.resultsBuffer.createIndexedTupleSource(true);
+ }
+ CursorState old = this.cursorStates.put(rsName, this.currentState);
+ if (old != null) {
+ removeState(old);
+ }
//keep a reference to the tuple source
//it may be the last one
- if (keepRs) {
- this.lastTupleSource = this.currentState.ts;
+ if (mode == Mode.HOLD) {
+ this.last = this.currentState;
}
this.currentState = null;
}
@@ -647,6 +670,7 @@
public void push(Program program) throws XATransactionException {
program.reset(this.getContext().getConnectionId());
+ program.setTrappingExceptions(program.getExceptionGroup() != null ||
(!this.programs.isEmpty() && this.programs.peek().isTrappingExceptions()));
TempTableStore tts = getTempTableStore();
getContext().setTempTableStore(program.getTempTableStore());
program.getTempTableStore().setParentTempTableStore(tts);
@@ -680,15 +704,13 @@
}
public List<?> getCurrentRow(String rsName) throws TeiidComponentException {
- return getCursorState(rsName.toUpperCase()).currentRow;
+ return getCursorState(rsName).currentRow;
}
public boolean iterateCursor(String rsName)
throws TeiidComponentException, TeiidProcessingException {
- String rsKey = rsName.toUpperCase();
-
- CursorState state = getCursorState(rsKey);
+ CursorState state = getCursorState(rsName);
state.currentRow = state.ts.nextTuple();
return (state.currentRow != null);
@@ -703,15 +725,21 @@
}
public void removeResults(String rsName) {
- String rsKey = rsName.toUpperCase();
- CursorState state = this.cursorStates.remove(rsKey);
- if (state != null) {
+ CursorState state = this.cursorStates.remove(rsName);
+ removeState(state);
+ }
+
+ private void removeState(CursorState state) {
+ if (state != null) {
state.processor.closeProcessing();
if (state.resultsBuffer != null) {
state.resultsBuffer.remove();
}
}
- }
+ if (state == last) {
+ last = null;
+ }
+ }
/**
* Get the schema from the tuple source that
@@ -721,20 +749,14 @@
* @throws QueryProcessorException if the list of elements is null
*/
public List getSchema(String rsName) throws TeiidComponentException {
-
- // get the tuple source
- String rsKey = rsName.toUpperCase();
-
- CursorState cursorState = getCursorState(rsKey);
+ CursorState cursorState = getCursorState(rsName);
// get the schema from the tuple source
List schema = cursorState.processor.getOutputElements();
return schema;
}
public boolean resultSetExists(String rsName) {
- String rsKey = rsName.toUpperCase();
- boolean exists = this.cursorStates.containsKey(rsKey);
- return exists;
+ return this.cursorStates.containsKey(rsName);
}
public CommandContext getContext() {
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/Program.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/Program.java 2012-09-26
17:05:51 UTC (rev 4474)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/Program.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -46,6 +46,7 @@
private boolean startedTxn;
private String exceptionGroup;
private Program exceptionProgram;
+ private boolean trappingExceptions = false;
/**
* Constructor for Program.
@@ -117,6 +118,7 @@
counter = 0;
this.tempTables = new TempTableStore(sessionId, TransactionMode.ISOLATE_WRITES);
this.startedTxn = false;
+ this.trappingExceptions = false;
}
int getProgramCounter(){
@@ -283,5 +285,13 @@
public Program getExceptionProgram() {
return exceptionProgram;
}
+
+ public boolean isTrappingExceptions() {
+ return trappingExceptions;
+ }
+
+ public void setTrappingExceptions(boolean trappingExceptions) {
+ this.trappingExceptions = trappingExceptions;
+ }
}
Modified:
trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -24,6 +24,7 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import org.teiid.api.exception.query.QueryMetadataException;
@@ -270,7 +271,6 @@
} else if (currentCommand instanceof CreateProcedureCommand) {
CreateProcedureCommand cupc = (CreateProcedureCommand)currentCommand;
cupc.setVirtualGroup(container);
-
if (type == Command.TYPE_STORED_PROCEDURE) {
StoredProcedureInfo info =
metadata.getStoredProcedureInfoForProcedure(container.getName());
// Create temporary metadata that defines a group based on either the stored
proc
@@ -281,15 +281,22 @@
List<ElementSymbol> tempElements = new
ArrayList<ElementSymbol>(info.getParameters().size());
boolean[] updatable = new boolean[info.getParameters().size()];
int i = 0;
+ List<ElementSymbol> rsColumns = Collections.emptyList();
for (SPParameter param : info.getParameters()) {
if(param.getParameterType() != ParameterInfo.RESULT_SET) {
ElementSymbol symbol = param.getParameterSymbol();
tempElements.add(symbol);
updatable[i++] = param.getParameterType() != ParameterInfo.IN;
+ } else {
+ rsColumns = param.getResultSetColumns();
}
}
-
ProcedureContainerResolver.addScalarGroup(procName, childMetadata,
externalGroups, tempElements, updatable);
+ cupc.setResultSetColumns(rsColumns);
+ //the relational planner will override this with the appropriate value
+ cupc.setProjectedSymbols(rsColumns);
+ } else {
+ cupc.setUpdateType(type);
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java 2012-09-26
17:05:51 UTC (rev 4474)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -59,7 +59,6 @@
import org.teiid.query.sql.lang.SubqueryContainer;
import org.teiid.query.sql.lang.UnaryFromClause;
import org.teiid.query.sql.navigator.DeepPostOrderNavigator;
-import org.teiid.query.sql.proc.CreateProcedureCommand;
import org.teiid.query.sql.symbol.AliasSymbol;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
@@ -103,14 +102,6 @@
if (command == null) {
return null;
}
- if (command instanceof CreateProcedureCommand) {
- CreateProcedureCommand cupCommand = (CreateProcedureCommand)command;
- cupCommand.setUserCommand(proc);
- //if the subcommand is virtual stored procedure, it must have the same
- //projected symbol as its parent.
- cupCommand.setProjectedSymbols(proc.getProjectedSymbols());
- cupCommand.setResultSetColumns(proc.getResultSetColumns());
- }
resolveCommand(command, proc.getGroup(), proc.getType(),
metadata.getDesignTimeMetadata());
return command;
}
Modified:
trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -22,7 +22,6 @@
package org.teiid.query.resolver.command;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
@@ -67,11 +66,6 @@
*/
public class UpdateProcedureResolver implements CommandResolver {
- public static class StatementNode {
- CommandStatement cs;
- List<StatementNode> children;
- }
-
public static final List<ElementSymbol> exceptionGroup;
static {
ElementSymbol es1 = new ElementSymbol("STATE"); //$NON-NLS-1$
@@ -95,7 +89,11 @@
if (command instanceof TriggerAction) {
TriggerAction ta = (TriggerAction)command;
- resolveBlock(new CreateProcedureCommand(), ta.getBlock(),
ta.getExternalGroupContexts(), metadata, null);
+ CreateProcedureCommand cmd = new CreateProcedureCommand(ta.getBlock());
+ cmd.setVirtualGroup(ta.getView());
+ //TODO: this is not generally correct - we should update the api to set the
appropriate type
+ cmd.setUpdateType(Command.TYPE_INSERT);
+ resolveBlock(cmd, ta.getBlock(), ta.getExternalGroupContexts(), metadata);
return;
}
@@ -112,41 +110,11 @@
symbols.add(updateCount);
ProcedureContainerResolver.addScalarGroup(ProcedureReservedWords.VARIABLES,
metadata.getMetadataStore(), externalGroups, symbols);
- StatementNode sn = new StatementNode();
- resolveBlock(procCommand, procCommand.getBlock(), externalGroups, metadata, sn);
-
- //validate the possible returned resultsets
- if (procCommand.getResultSetColumns() == null ||
!procCommand.getResultSetColumns().isEmpty()) {
- setReturnable(procCommand, sn);
- }
+ resolveBlock(procCommand, procCommand.getBlock(), externalGroups, metadata);
}
- private void setReturnable(CreateProcedureCommand procCommand, StatementNode sn) {
- if (sn.cs != null) {
- sn.cs.setReturnable(true);
- //this logic is for designer, which want's to populate a resultset from the proc
text
- if (procCommand.getResultSetColumns() == null) {
- List<? extends Expression> symbols =
sn.cs.getCommand().getProjectedSymbols();
- if (sn.cs.getCommand() instanceof StoredProcedure) {
- StoredProcedure sp = (StoredProcedure)sn.cs.getCommand();
- if (sp.isCallableStatement()) {
- symbols = sp.getResultSetColumns();
- }
- }
- procCommand.setResultSetColumns(symbols);
- //TODO: what about out parameters
- procCommand.setProjectedSymbols(symbols);
- }
- }
- if (sn.children != null) {
- for (StatementNode child : sn.children) {
- setReturnable(procCommand, child);
- }
- }
- }
-
public void resolveBlock(CreateProcedureCommand command, Block block, GroupContext
externalGroups,
- TempMetadataAdapter metadata,
org.teiid.query.resolver.command.UpdateProcedureResolver.StatementNode sn)
+ TempMetadataAdapter metadata)
throws QueryResolverException, QueryMetadataException, TeiidComponentException {
LogManager.logTrace(org.teiid.logging.LogConstants.CTX_QUERY_RESOLVER, new
Object[]{"Resolving block", block}); //$NON-NLS-1$
@@ -159,7 +127,7 @@
GroupSymbol variables =
ProcedureContainerResolver.addScalarGroup(ProcedureReservedWords.VARIABLES, store,
externalGroups, new LinkedList<Expression>());
for (Statement statement : block.getStatements()) {
- resolveStatement(command, statement, externalGroups, variables, metadata,
sn);
+ resolveStatement(command, statement, externalGroups, variables, metadata);
}
if (block.getExceptionGroup() != null) {
@@ -175,13 +143,13 @@
if (block.getExceptionStatements() != null) {
ProcedureContainerResolver.addScalarGroup(block.getExceptionGroup(), store,
externalGroups, exceptionGroup, false);
for (Statement statement : block.getExceptionStatements()) {
- resolveStatement(command, statement, externalGroups, variables,
metadata, sn);
+ resolveStatement(command, statement, externalGroups, variables,
metadata);
}
}
}
}
- private void resolveStatement(CreateProcedureCommand command, Statement statement,
GroupContext externalGroups, GroupSymbol variables, TempMetadataAdapter metadata,
StatementNode sn)
+ private void resolveStatement(CreateProcedureCommand command, Statement statement,
GroupContext externalGroups, GroupSymbol variables, TempMetadataAdapter metadata)
throws QueryResolverException, QueryMetadataException, TeiidComponentException {
LogManager.logTrace(org.teiid.logging.LogConstants.CTX_QUERY_RESOLVER, new
Object[]{"Resolving statement", statement}); //$NON-NLS-1$
@@ -193,9 +161,9 @@
resolveEmbeddedCommand(metadata, externalGroups,
container.getCommand());
}
ResolverVisitor.resolveLanguageObject(ifCrit, null, externalGroups,
metadata);
- resolveBlock(command, ifStmt.getIfBlock(), externalGroups, metadata,
pushChild(sn));
+ resolveBlock(command, ifStmt.getIfBlock(), externalGroups, metadata);
if(ifStmt.hasElseBlock()) {
- resolveBlock(command, ifStmt.getElseBlock(), externalGroups,
metadata, pushChild(sn));
+ resolveBlock(command, ifStmt.getElseBlock(), externalGroups,
metadata);
}
break;
case Statement.TYPE_COMMAND:
@@ -234,15 +202,19 @@
DynamicCommand dynCommand = (DynamicCommand)subCommand;
if(dynCommand.getIntoGroup() == null
- && !dynCommand.isAsClauseSet() &&
!command.getProjectedSymbols().isEmpty()) {
- dynCommand.setAsColumns(command.getProjectedSymbols());
+ && !dynCommand.isAsClauseSet()) {
+ if ((command.getResultSetColumns() != null &&
command.getResultSetColumns().isEmpty()) || !cmdStmt.isReturnable()) {
+ //we're not interested in the resultset
+ dynCommand.setAsColumns(Collections.EMPTY_LIST);
+ } else {
+ //should match the procedure
+ dynCommand.setAsColumns(command.getResultSetColumns());
+ }
}
}
-
- //this could be the last select statement, set the projected symbol
- //on the virtual procedure command
- if (subCommand.returnsResultSet() && sn != null) {
- clearReturnableStatement(sn, cmdStmt);
+
+ if (command.getResultSetColumns() == null &&
cmdStmt.isReturnable() && subCommand.returnsResultSet() &&
!subCommand.getResultSetColumns().isEmpty()) {
+ command.setResultSetColumns(subCommand.getResultSetColumns());
}
break;
@@ -283,9 +255,6 @@
exprStmt.setExpression(ResolverUtil.convertExpression(exprStmt.getExpression(),
varTypeName, metadata));
if (statement.getType() == Statement.TYPE_ERROR) {
ResolverVisitor.checkException(exprStmt.getExpression());
- if (!((RaiseStatement)statement).isWarning()) {
- clearReturnableStatement(sn, null);
- }
}
}
break;
@@ -296,7 +265,7 @@
resolveEmbeddedCommand(metadata, externalGroups,
container.getCommand());
}
ResolverVisitor.resolveLanguageObject(whileCrit, null, externalGroups,
metadata);
- resolveBlock(command, whileStmt.getBlock(), externalGroups, metadata,
pushChild(sn));
+ resolveBlock(command, whileStmt.getBlock(), externalGroups, metadata);
break;
case Statement.TYPE_LOOP:
LoopStatement loopStmt = (LoopStatement) statement;
@@ -314,24 +283,14 @@
ProcedureContainerResolver.addScalarGroup(groupName, store,
externalGroups, symbols, false);
- resolveBlock(command, loopStmt.getBlock(), externalGroups, metadata,
pushChild(sn));
+ resolveBlock(command, loopStmt.getBlock(), externalGroups, metadata);
break;
case Statement.TYPE_COMPOUND:
- resolveBlock(command, (Block)statement, externalGroups, metadata, sn);
+ resolveBlock(command, (Block)statement, externalGroups, metadata);
break;
}
}
- private void clearReturnableStatement(StatementNode sn,
- CommandStatement cmdStmt) {
- updateDynamicAs(sn);
-
- sn.cs = cmdStmt;
- if (sn.children != null) {
- sn.children.clear();
- }
- }
-
private void isValidGroup(TempMetadataAdapter metadata, String groupName)
throws QueryResolverException {
if (metadata.getMetadataStore().getTempGroupID(groupName) != null) {
@@ -344,32 +303,6 @@
}
}
- private void updateDynamicAs(StatementNode sn) {
- if (sn.cs != null && sn.cs.getCommand().getType() == Command.TYPE_DYNAMIC) {
- DynamicCommand dynamicCommand = (DynamicCommand)sn.cs.getCommand();
- if (!dynamicCommand.isAsClauseSet()) {
- dynamicCommand.setAsColumns(Collections.EMPTY_LIST);
- }
- }
- if (sn.children != null) {
- for (StatementNode child : sn.children) {
- updateDynamicAs(child);
- }
- }
- }
-
- private StatementNode pushChild(StatementNode sn) {
- if (sn != null) {
- if (sn.children == null) {
- sn.children = new ArrayList<StatementNode>();
- }
- StatementNode child = new StatementNode();
- sn.children.add(child);
- sn = child;
- }
- return sn;
- }
-
private boolean isAssignable(TempMetadataAdapter metadata, SPParameter param)
throws TeiidComponentException, QueryMetadataException {
if (!(param.getExpression() instanceof ElementSymbol)) {
Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2012-09-26
17:05:51 UTC (rev 4474)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -232,15 +232,13 @@
return command;
}
- private Command rewriteUpdateProcedure(CreateProcedureCommand command)
- throws TeiidComponentException, TeiidProcessingException{
+ private Command rewriteUpdateProcedure(CreateProcedureCommand command) throws
TeiidComponentException {
Block block = rewriteBlock(command.getBlock());
command.setBlock(block);
return command;
}
- private Block rewriteBlock(Block block)
- throws TeiidComponentException, TeiidProcessingException{
+ private Block rewriteBlock(Block block) throws TeiidComponentException {
List<Statement> statements = block.getStatements();
List<Statement> newStmts = rewriteStatements(statements);
block.setStatements(newStmts);
@@ -250,15 +248,23 @@
return block;
}
- private List<Statement> rewriteStatements(List<Statement> statements)
- throws TeiidComponentException, TeiidProcessingException {
+ private List<Statement> rewriteStatements(List<Statement> statements) throws
TeiidComponentException {
Iterator<Statement> stmtIter = statements.iterator();
List<Statement> newStmts = new ArrayList<Statement>(statements.size());
// plan each statement in the block
while(stmtIter.hasNext()) {
Statement stmnt = stmtIter.next();
- rewriteStatement(stmnt, newStmts);
+ try {
+ rewriteStatement(stmnt, newStmts);
+ } catch (TeiidProcessingException e) {
+ /*
+ * defer the processing of the exception until runtime as there may be an exception
handler
+ */
+ RaiseStatement raise = new RaiseStatement(new Constant(e));
+ newStmts.add(raise);
+ break;
+ }
}
return newStmts;
}
@@ -343,9 +349,7 @@
crit = rewriteCriteria(crit);
whileStatement.setCondition(crit);
- if(crit.equals(TRUE_CRITERIA)) {
- throw new QueryValidatorException(QueryPlugin.Event.TEIID30367,
QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30367));
- } else if(crit.equals(FALSE_CRITERIA) || crit.equals(UNKNOWN_CRITERIA))
{
+ if(crit.equals(FALSE_CRITERIA) || crit.equals(UNKNOWN_CRITERIA)) {
return;
}
whileStatement.setBlock(rewriteBlock(whileStatement.getBlock()));
@@ -354,6 +358,9 @@
return;
}
break;
+ case Statement.TYPE_COMPOUND:
+ statement = rewriteBlock((Block) statement);
+ break;
}
newStmts.add(statement);
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/BatchedUpdateCommand.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/lang/BatchedUpdateCommand.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/main/java/org/teiid/query/sql/lang/BatchedUpdateCommand.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -102,30 +102,15 @@
public String toString() {
StringBuffer val = new StringBuffer("BatchedUpdate{"); //$NON-NLS-1$
if (commands != null && commands.size() > 0) {
- val.append(getCommandToken(commands.get(0)));
+ val.append(getCommandToken(commands.get(0).getType()));
for (int i = 1; i < commands.size(); i++) {
- val.append(',').append(getCommandToken(commands.get(i)));
+
val.append(',').append(getCommandToken(commands.get(i).getType()));
}
}
val.append('}');
return val.toString();
}
- private char getCommandToken(Command command) {
- int commandType = command.getType();
- if (commandType == Command.TYPE_INSERT) {
- return 'I';
- } else if (commandType == Command.TYPE_UPDATE) {
- return 'U';
- } else if (commandType == Command.TYPE_DELETE) {
- return 'D';
- } else if (commandType == Command.TYPE_QUERY) {
- // SELECT INTO command
- return 'S';
- }
- return '?';
- }
-
public void setVariableContexts(List<VariableContext> variableContexts) {
this.variableContexts = variableContexts;
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/Command.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/Command.java 2012-09-26 17:05:51
UTC (rev 4474)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/Command.java 2012-09-26 23:15:59
UTC (rev 4475)
@@ -75,11 +75,6 @@
public static final int TYPE_DELETE = 4;
/**
- * Represents any SQL statement, wrapped as a string
- */
- public static final int TYPE_SQL = 5;
-
- /**
* Represents a stored procedure command
*/
public static final int TYPE_STORED_PROCEDURE = 6;
@@ -349,4 +344,46 @@
public boolean returnsResultSet() {
return false;
}
+
+ /**
+ * @return null if unknown, empty if results are not returned, or the resultset
columns
+ */
+ public List<? extends Expression> getResultSetColumns() {
+ if (returnsResultSet()) {
+ return getProjectedSymbols();
+ }
+ return Collections.emptyList();
+ }
+
+ //TODO: replace with enum
+ public static String getCommandToken(int commandType) {
+ switch (commandType) {
+ case Command.TYPE_INSERT:
+ return "I"; //$NON-NLS-1$
+ case Command.TYPE_UPDATE:
+ return "U"; //$NON-NLS-1$
+ case Command.TYPE_DELETE:
+ return "D"; //$NON-NLS-1$
+ case Command.TYPE_DROP:
+ return "DT"; //$NON-NLS-1$
+ case Command.TYPE_ALTER_PROC:
+ return "AP"; //$NON-NLS-1$
+ case Command.TYPE_ALTER_TRIGGER:
+ return "AT"; //$NON-NLS-1$
+ case Command.TYPE_ALTER_VIEW:
+ return "AV"; //$NON-NLS-1$
+ case Command.TYPE_CREATE:
+ return "CT"; //$NON-NLS-1$
+ case Command.TYPE_DYNAMIC:
+ return "Dy"; //$NON-NLS-1$
+ case Command.TYPE_QUERY:
+ return "S"; //$NON-NLS-1$
+ case Command.TYPE_STORED_PROCEDURE:
+ return "Sp"; //$NON-NLS-1$
+ case Command.TYPE_UPDATE_PROCEDURE:
+ return "Up"; //$NON-NLS-1$
+ }
+ return "?"; //$NON-NLS-1$
+ }
+
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/DynamicCommand.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/DynamicCommand.java 2012-09-26
17:05:51 UTC (rev 4474)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/DynamicCommand.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -260,5 +260,14 @@
public boolean returnsResultSet() {
return intoGroup == null;
}
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<? extends Expression> getResultSetColumns() {
+ if (returnsResultSet()) {
+ return asColumns;
+ }
+ return Collections.emptyList();
+ }
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/ProcedureContainer.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/ProcedureContainer.java 2012-09-26
17:05:51 UTC (rev 4474)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/ProcedureContainer.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -22,8 +22,6 @@
package org.teiid.query.sql.lang;
-import java.util.List;
-
import org.teiid.query.validator.UpdateValidator.UpdateInfo;
@@ -66,9 +64,5 @@
public void setUpdateInfo(UpdateInfo updateInfo) {
this.updateInfo = updateInfo;
}
-
- public List getResultSetColumns() {
- return getProjectedSymbols();
- }
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/proc/CommandStatement.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/proc/CommandStatement.java 2012-09-26
17:05:51 UTC (rev 4474)
+++ trunk/engine/src/main/java/org/teiid/query/sql/proc/CommandStatement.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -37,7 +37,7 @@
// the command this statement represents
Command command;
- private boolean returnable;
+ private boolean returnable = true;
/**
* Constructor for CommandStatement.
Modified: trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateProcedureCommand.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateProcedureCommand.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateProcedureCommand.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -46,15 +46,12 @@
// top level block for the procedure
private Block block;
- // the command the user submitted against the virtual group being updated
- private Command userCommand;
-
private List projectedSymbols;
- private List resultSetColumns;
+ private List<? extends Expression> resultSetColumns;
private GroupSymbol virtualGroup;
- private String updateType;
+ private int updateType = Command.TYPE_UNKNOWN;
/**
* Constructor for CreateUpdateProcedureCommand.
@@ -96,22 +93,6 @@
this.block = block;
}
- /**
- * Set the user's command to which this obj which is the subcommand
- * @param command The user's command
- */
- public void setUserCommand(Command command) {
- this.userCommand = command;
- }
-
- /**
- * Get the user's command to which this obj which is the subcommand
- * @return The user's command
- */
- public Command getUserCommand() {
- return this.userCommand;
- }
-
// =========================================================================
// P R O C E S S I N G M E T H O D S
// =========================================================================
@@ -207,11 +188,11 @@
return Collections.EMPTY_LIST;
}
- public List getResultSetColumns() {
+ public List<? extends Expression> getResultSetColumns() {
return resultSetColumns;
}
- public void setResultSetColumns(List resultSetColumns) {
+ public void setResultSetColumns(List<? extends Expression> resultSetColumns) {
this.resultSetColumns = resultSetColumns;
}
@@ -237,11 +218,12 @@
this.virtualGroup = virtualGroup;
}
- public void setUpdateType(String updateType) {
- this.updateType = updateType;
+ public void setUpdateType(int type) {
+ this.resultSetColumns = Collections.emptyList();
+ this.updateType = type;
}
- public String getUpdateType() {
+ public int getUpdateType() {
return updateType;
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -47,7 +47,6 @@
import org.teiid.query.sql.lang.TextTable.TextColumn;
import org.teiid.query.sql.lang.XMLTable.XMLColumn;
import org.teiid.query.sql.proc.*;
-import org.teiid.query.sql.proc.BranchingStatement.BranchingMode;
import org.teiid.query.sql.proc.Statement.Labeled;
import org.teiid.query.sql.symbol.*;
import org.teiid.query.sql.symbol.AggregateSymbol.Type;
@@ -1418,6 +1417,12 @@
public void visit( CommandStatement obj ) {
visitNode(obj.getCommand());
+ if (!obj.isReturnable()) {
+ append(SPACE);
+ append(WITHOUT);
+ append(SPACE);
+ append(RETURN);
+ }
append(";"); //$NON-NLS-1$
}
Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2012-09-26
17:05:51 UTC (rev 4474)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -408,11 +408,14 @@
public void visit(CreateProcedureCommand obj) {
//check that the procedure does not contain references to itself
- if (obj.getUpdateType() == null) {
+ if (obj.getUpdateType() == Command.TYPE_UNKNOWN) {
if (GroupCollectorVisitor.getGroups(obj,true).contains(obj.getVirtualGroup()))
{
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.Procedure_has_group_self_reference"),obj);
//$NON-NLS-1$
}
- this.createProc = obj;
+ if (obj.getResultSetColumns() != null) {
+ //some unit tests bypass setting the columns
+ this.createProc = obj;
+ }
}
}
@@ -1471,20 +1474,20 @@
@Override
public void visit(CommandStatement obj) {
- if (obj.isReturnable() && this.createProc != null) {
- List<? extends Expression> symbols = obj.getCommand().getProjectedSymbols();
- if (obj.getCommand() instanceof StoredProcedure) {
- StoredProcedure sp = (StoredProcedure)obj.getCommand();
- if (sp.isCallableStatement()) {
- symbols = sp.getResultSetColumns();
- }
- }
- try {
- QueryResolver.validateProjectedSymbols(createProc.getVirtualGroup(),
createProc.getResultSetColumns(), symbols);
- } catch (QueryValidatorException e) {
- handleValidationError(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31121,
createProc.getVirtualGroup(), obj, e.getMessage()), obj);
- }
+ if (this.createProc == null || this.createProc.getResultSetColumns().isEmpty() ||
!obj.isReturnable() || !obj.getCommand().returnsResultSet()) {
+ return;
}
+ List<? extends Expression> symbols = obj.getCommand().getResultSetColumns();
+ if (symbols == null && obj.getCommand() instanceof DynamicCommand) {
+ DynamicCommand cmd = (DynamicCommand)obj.getCommand();
+ cmd.setAsColumns(this.createProc.getResultSetColumns());
+ return;
+ }
+ try {
+ QueryResolver.validateProjectedSymbols(createProc.getVirtualGroup(),
createProc.getResultSetColumns(), symbols);
+ } catch (QueryValidatorException e) {
+ handleValidationError(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31121,
createProc.getVirtualGroup(), obj, e.getMessage()), obj);
+ }
}
@Override
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2012-09-26 17:05:51
UTC (rev 4474)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2012-09-26 23:15:59
UTC (rev 4475)
@@ -906,7 +906,7 @@
/*
name=raise statement
description=Raises an error or warning with the given message.
-example={code:sql}RAISE SQLEXCEPTION '00A' 'something went wrong'{code}
+example={code:sql}RAISE SQLEXCEPTION 'something went wrong'{code}
*/
RaiseStatement raiseStatement(ParseInfo info) :
{
@@ -1187,7 +1187,7 @@
{
variableID = new ElementSymbol(var);
}
- [[<COLON>]<EQ>
+ [<EQ>
value = assignStatementOperand(info)
]
@@ -1205,28 +1205,31 @@
/*
name=assignment statement
description=Assigns a variable a value in a procedure.
-example={code:sql}x := 'b'{code}
+example={code:sql}x = 'b'{code}
*/
Statement assignStatement(ParseInfo info) :
{
LanguageObject value = null;
String var = null;
ElementSymbol elementID = null;
+ boolean returnable=true;
}
{
var = id()
{
elementID = new ElementSymbol(var);
}
- [<COLON>]<EQ>
+ <EQ>
(value = assignStatementOperand(info) |
- value = storedProcedure(info, 2) {
+ (value = storedProcedure(info, 2) [(<WITH>|<WITHOUT> {returnable =
false;}) <RETURN>]) {
StoredProcedure storedProcedure = (StoredProcedure)value;
SPParameter parameter = new SPParameter(1, SPParameter.RETURN_VALUE,
"return"); //$NON-NLS-1$
parameter.setExpression(elementID);
storedProcedure.setParameter(parameter);
- storedProcedure.setCalledWithReturn(true);
- return new CommandStatement(storedProcedure);
+ storedProcedure.setCalledWithReturn(true);
+ CommandStatement cs = new CommandStatement(storedProcedure);
+ cs.setReturnable(returnable);
+ return cs;
}
)
@@ -1265,7 +1268,7 @@
/*
name=data statement
-description=A procedure statement that executes a SQL statement. An update statement can
have its update count accessed via the ROWS_UPDATED variable.
+description=A procedure statement that executes a SQL statement. An update statement can
have its update count accessed via the ROWCOUNT variable.
*/
CommandStatement sqlStatement(ParseInfo info) :
{
@@ -1273,14 +1276,17 @@
String var = null;
ElementSymbol elementID = null;
StoredProcedure storedProcedure = null;
+ boolean returnable = true;
}
{
(LOOKAHEAD(2) cmd = userCommand(info) |
cmd = dynamicCommand(info)
- )
+ ) [(<WITH>|<WITHOUT> {returnable = false;}) <RETURN>]
{
- return new CommandStatement(cmd);
+ CommandStatement cs = new CommandStatement(cmd);
+ cs.setReturnable(returnable);
+ return cs;
}
}
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2012-09-26 17:05:51
UTC (rev 4474)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2012-09-26 23:15:59
UTC (rev 4475)
@@ -752,8 +752,6 @@
XMLQuery.resolvingError=Failed to resolve the query ''{0}''
TEIID30085=Invalid order by at {0}
-TEIID30367=Infinite loop detected, procedure will not be executed.
-
TEIID30244=The batch contained an unrecognized command: {0}
TEIID30272=Error getting modelID
TEIID30213=Cannot find namespace URI for namespace {0} of element {1}
@@ -1032,7 +1030,8 @@
TEIID31115=Function based index {1} expression {0} is not deterministic.
TEIID31116=Function based index {1} expression {0} could not be resolved: {2}
TEIID31120=An exception may only be chained to another exception. {0} is not valid.
-TEIID31121=The expected result set of the procedure {0} does not match the result set
from returnable statement {1} - {2}
+TEIID31121=The expected result set of the procedure {0} does not match the result set
from returnable statement {1} use WITHOUT RETURN to indicate the statement should not be
returned - {2}
+TEIID31122=Null exception reference.
SQLParser.proc_type_conflict=Result type {1} conflicts with return type {2} for procedure
{0}
SQLParser.param_out=Procedure {0} RESULT param {1} must be of type OUT.
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -122,7 +122,7 @@
helpProcess(plan, context, dm, null);
fail();
} catch (QueryProcessingException e) {
- assertEquals("TEIID30168 Couldn't execute the dynamic SQL command
\"EXECUTE IMMEDIATE 'delete from gx where gx.x = new.x'\" with the SQL
statement \"'delete from gx where gx.x = new.x'\" due to: TEIID30347
There is a recursive invocation of group 'Insert gx'. Please correct the
SQL.", e.getMessage());
+ assertEquals("TEIID30168 Couldn't execute the dynamic SQL command
\"EXECUTE IMMEDIATE 'delete from gx where gx.x = new.x'\" with the SQL
statement \"'delete from gx where gx.x = new.x'\" due to: TEIID30347
There is a recursive invocation of group 'I gx'. Please correct the SQL.",
e.getMessage());
}
}
Modified: trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcErrors.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcErrors.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcErrors.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -74,7 +74,20 @@
assertEquals("abc", tse.getSQLState());
assertEquals(1, tse.getErrorCode());
}
+ }
+
+ @Test public void testExceptionGroup() throws Exception {
+ String ddl =
+ "create virtual procedure vproc () returns string as begin select 1/0;
exception e \"return\" = e.state || ' ' || e.errorcode || ' ' ||
e.teiidcode || ' ' || cast(e.exception as string) || ' ' || cast(e.chain
as string); end;";
+ TransformationMetadata tm = TestProcedureResolving.createMetadata(ddl);
+
+ String sql = "call vproc()"; //$NON-NLS-1$
+
+ ProcessorPlan plan = getProcedurePlan(sql, tm);
+
+ HardcodedDataManager dataManager = new HardcodedDataManager(tm);
+ helpTestProcess(plan, new List[] {Arrays.asList("50000 30328 TEIID30328
org.teiid.jdbc.TeiidSQLException: TEIID30328 Unable to evaluate (1 / 0): TEIID30384 Error
while evaluating function / org.teiid.api.exception.query.ExpressionEvaluationException:
TEIID30328 Unable to evaluate (1 / 0): TEIID30384 Error while evaluating function
/")}, dataManager, tm);
}
@Test public void testExceptionHandling() throws Exception {
@@ -99,5 +112,39 @@
assertEquals("caught", tse.getMessage());
assertEquals("hello world", tse.getCause().getMessage());
}
+
+ /**
+ * ensures that a processing error is trappable
+ */
+ @Test public void testExceptionHandlingWithResultSet() throws Exception {
+ String ddl =
+ "create virtual procedure proc2 (x integer) as begin atomic select 1; begin
select 1/x; end exception e end;";
+ TransformationMetadata tm = TestProcedureResolving.createMetadata(ddl);
+
+ String sql = "call proc2(0)"; //$NON-NLS-1$
+
+ ProcessorPlan plan = getProcedurePlan(sql, tm);
+
+ HardcodedDataManager dataManager = new HardcodedDataManager(tm);
+
+ helpTestProcess(plan, new List[] {Arrays.asList(1)}, dataManager, tm);
+ }
+
+ /**
+ * ensures that the whole result is formed so that the error does not escape the
handler
+ */
+ @Test public void testExceptionHandlingWithResultSet1() throws Exception {
+ String ddl =
+ "create virtual procedure proc2 (x integer) as begin create local temporary
table t (i integer); insert into t (i) values (1); declare integer y = 0; while (y <
16) begin insert into t (i) select 1 from t; y = y+1; end insert into t (i) values (0);
select cast(1/i as string) from t; exception e end;";
+ TransformationMetadata tm = TestProcedureResolving.createMetadata(ddl);
+
+ String sql = "call proc2(0)"; //$NON-NLS-1$
+
+ ProcessorPlan plan = getProcedurePlan(sql, tm);
+
+ HardcodedDataManager dataManager = new HardcodedDataManager(tm);
+
+ helpTestProcess(plan, new List[0], dataManager, tm);
+ }
}
Modified:
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -930,7 +930,6 @@
helpTestProcess(plan, null, dataMgr, metadata);
fail("exception expected");
} catch (QueryProcessingException e) {
- assertTrue(e.getCause() instanceof QueryValidatorException);
}
}
@@ -2056,7 +2055,7 @@
}
@Test public void testNestedBlock() throws Exception {
- String ddl = "create virtual procedure proc (z STRING) returns table (x string,
y string) as begin declare string x = z; select x; begin select x, x; end end;";
+ String ddl = "create virtual procedure proc (z STRING) returns table (x string,
y string) as begin declare string x = z; select x without return; begin select x, x; end
end;";
TransformationMetadata tm = TestProcedureResolving.createMetadata(ddl);
String sql = "call proc('a')"; //$NON-NLS-1$
Modified: trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java 2012-09-26
17:05:51 UTC (rev 4474)
+++ trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -38,7 +38,6 @@
import org.junit.Ignore;
import org.junit.Test;
import org.teiid.api.exception.query.QueryMetadataException;
-import org.teiid.api.exception.query.QueryValidatorException;
import org.teiid.client.metadata.ParameterInfo;
import org.teiid.common.buffer.BufferManagerFactory;
import org.teiid.core.TeiidComponentException;
@@ -1107,26 +1106,6 @@
helpTestRewriteCriteria("(pm1.g1.e1 = 1 and pm1.g1.e2 = 2) and (pm1.g1.e3 =
1 and pm1.g1.e4 = 2.0e0)", "(pm1.g1.e1 = '1') AND (pm1.g1.e2 = 2) AND
(pm1.g1.e3 = TRUE) AND (pm1.g1.e4 = 2.0e0)"); //$NON-NLS-1$ //$NON-NLS-2$
}
- @Test public void testRewriteWhile() throws Exception {
-
- String procedure = "FOR EACH ROW\n"; //$NON-NLS-1$
- procedure = procedure + "BEGIN\n"; //$NON-NLS-1$
- procedure = procedure + "while (1 = 1)\n"; //$NON-NLS-1$
- procedure = procedure + "BEGIN\n"; //$NON-NLS-1$
- procedure = procedure + "Select vm1.g1.e1 from vm1.g1;\n";
//$NON-NLS-1$
- procedure = procedure + "END\n"; //$NON-NLS-1$
- procedure = procedure + "END\n"; //$NON-NLS-1$
-
- String userQuery = "Insert into vm1.g1 (e1, e2) values ('String',
1)"; //$NON-NLS-1$
-
- try {
- getRewritenProcedure(procedure, userQuery, Table.TriggerEvent.INSERT);
- fail("exception expected"); //$NON-NLS-1$
- } catch (QueryValidatorException e) {
- assertEquals("TEIID30367 Infinite loop detected, procedure will not be
executed.", e.getMessage()); //$NON-NLS-1$
- }
- }
-
@Test public void testRewriteWhile1() throws Exception {
String procedure = "FOR EACH ROW\n"; //$NON-NLS-1$
@@ -1196,6 +1175,17 @@
String expected = "CREATE VIRTUAL PROCEDURE\nBEGIN\nBEGIN ATOMIC\nSELECT e1
FROM pm1.g1;\nEND\nEND"; //$NON-NLS-1$
helpTestRewriteCommand(procedure1, expected);
+ }
+
+ @Test public void testExceptionHandling() {
+ String procedure1 = "CREATE virtual PROCEDURE begin "; //$NON-NLS-1$
+ procedure1 += "select 1/0;\n"; //$NON-NLS-1$
+ procedure1 += "exception e\n"; //$NON-NLS-1$
+ procedure1 += "end\n"; //$NON-NLS-1$
+
+ String expected = "CREATE VIRTUAL PROCEDURE\nBEGIN\nRAISE
'org.teiid.api.exception.query.ExpressionEvaluationException: TEIID30328 Unable to
evaluate (1 / 0): TEIID30384 Error while evaluating function /';\nEXCEPTION
e\nEND"; //$NON-NLS-1$
+
+ helpTestRewriteCommand(procedure1, expected);
}
@Test public void testRewriteDeclare() {
Modified:
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -1381,6 +1381,20 @@
helpTest(cmdStmt, "SELECT x FROM g;"); //$NON-NLS-1$
}
+ @Test public void testCommandStatement1a() {
+ Query q1 = new Query();
+ Select select = new Select();
+ select.addSymbol(new ElementSymbol("x")); //$NON-NLS-1$
+ q1.setSelect(select);
+ From from = new From();
+ from.addGroup(new GroupSymbol("g")); //$NON-NLS-1$
+ q1.setFrom(from);
+
+ CommandStatement cmdStmt = new CommandStatement(q1);
+ cmdStmt.setReturnable(false);
+ helpTest(cmdStmt, "SELECT x FROM g WITHOUT RETURN;"); //$NON-NLS-1$
+ }
+
@Test public void testCommandStatement2() {
Delete d1 = new Delete();
d1.setGroup(new GroupSymbol("g")); //$NON-NLS-1$
Modified: trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -301,7 +301,7 @@
ColumnSet<Procedure> vsprs7 = createResultSet("TEIIDSP7.vsprs1",
new String[] { "StringKey" }, new String[] {
DataTypeManager.DefaultDataTypes.STRING }); //$NON-NLS-1$ //$NON-NLS-2$
ProcedureParameter vsp7p1 = createParameter("p1", ParameterInfo.IN,
DataTypeManager.DefaultDataTypes.INTEGER); //$NON-NLS-1$
- QueryNode vspqn7 = new QueryNode("CREATE VIRTUAL PROCEDURE BEGIN declare
integer x; x = exec spTest9(p1); declare integer y; exec spTest11(inkey=>x,
outkey=>y); select convert(x, string) || y; END"); //$NON-NLS-1$ //$NON-NLS-2$
+ QueryNode vspqn7 = new QueryNode("CREATE VIRTUAL PROCEDURE BEGIN declare
integer x; x = exec spTest9(p1); declare integer y; exec spTest11(inkey=>x,
outkey=>y) without return; select convert(x, string) || y; END"); //$NON-NLS-1$
//$NON-NLS-2$
Procedure vsp7 = createVirtualProcedure("TEIIDSP7", mmspTest1,
Arrays.asList(vsp7p1), vspqn7); //$NON-NLS-1$
vsp7.setResultSet(vsprs7);
Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestAlterValidation.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/validator/TestAlterValidation.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/engine/src/test/java/org/teiid/query/validator/TestAlterValidation.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -46,7 +46,7 @@
@Test public void testValidateAlterProcedure() {
TestValidator.helpValidate("alter procedure spTest8a as begin select 1; end",
new String[] {"spTest8a"}, RealMetadataFactory.exampleBQTCached());
- TestValidator.helpValidate("alter procedure MMSP1 as begin select 1; end",
new String[] {"BEGIN\nSELECT 1;\nEND"},
RealMetadataFactory.exampleBQTCached());
+ TestValidator.helpValidate("alter procedure MMSP1 as begin select 1; end",
new String[] {"SELECT 1;"}, RealMetadataFactory.exampleBQTCached());
}
}
Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java 2012-09-26
17:05:51 UTC (rev 4474)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -1469,7 +1469,7 @@
.append("BEGIN\n") //$NON-NLS-1$
.append("CREATE LOCAL TEMPORARY TABLE x (column1
string);") //$NON-NLS-1$
.append("execute string 'SELECT e1 FROM
pm1.g2' as e1 string INTO x;\n") //$NON-NLS-1$
- .append("select column1 from x;\n")
//$NON-NLS-1$
+ .append("select cast(column1 as integer) from
x;\n") //$NON-NLS-1$
.append("END\n"); //$NON-NLS-1$
QueryMetadataInterface metadata = RealMetadataFactory.example1Cached();
Modified: trunk/runtime/src/main/java/org/teiid/runtime/EmbeddedServer.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/runtime/EmbeddedServer.java 2012-09-26 17:05:51
UTC (rev 4474)
+++ trunk/runtime/src/main/java/org/teiid/runtime/EmbeddedServer.java 2012-09-26 23:15:59
UTC (rev 4475)
@@ -265,6 +265,8 @@
protected boolean detectTransactions = true;
private Boolean running;
private EmbeddedConfiguration config;
+ private SessionAwareCache<CachedResults> rs;
+ private SessionAwareCache<PreparedPlan> ppc;
public EmbeddedServer() {
@@ -321,8 +323,8 @@
startVDBRepository();
- SessionAwareCache<CachedResults> rs = new
SessionAwareCache<CachedResults>("resultset", config.getCacheFactory(),
SessionAwareCache.Type.RESULTSET, config.getMaxResultSetCacheStaleness()); //$NON-NLS-1$
- SessionAwareCache<PreparedPlan> ppc = new
SessionAwareCache<PreparedPlan>("preparedplan", config.getCacheFactory(),
SessionAwareCache.Type.PREPAREDPLAN, 0); //$NON-NLS-1$
+ rs = new SessionAwareCache<CachedResults>("resultset",
config.getCacheFactory(), SessionAwareCache.Type.RESULTSET,
config.getMaxResultSetCacheStaleness()); //$NON-NLS-1$
+ ppc = new SessionAwareCache<PreparedPlan>("preparedplan",
config.getCacheFactory(), SessionAwareCache.Type.PREPAREDPLAN, 0); //$NON-NLS-1$
rs.setTupleBufferCache(bs.getTupleBufferCache());
this.dqp.setResultsetCache(rs);
@@ -378,6 +380,8 @@
if (replicator != null) {
replicator.stop(vdb.getVDB().getAttachment(GlobalTableStore.class));
}
+ rs.clearForVDB(name, 1);
+ ppc.clearForVDB(name, 1);
}
@Override
@@ -500,6 +504,7 @@
}
public void undeployVDB(String vdbName) {
+ checkStarted();
this.repo.removeVDB(vdbName, 1);
}
Modified: trunk/runtime/src/test/java/org/teiid/runtime/TestEmbeddedServer.java
===================================================================
--- trunk/runtime/src/test/java/org/teiid/runtime/TestEmbeddedServer.java 2012-09-26
17:05:51 UTC (rev 4474)
+++ trunk/runtime/src/test/java/org/teiid/runtime/TestEmbeddedServer.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -332,7 +332,8 @@
mmd1.setSchemaSourceType("ddl");
mmd1.setSchemaText("create view v as select 1; " +
"create virtual procedure proc () options (updatecount 2) as begin select * from
v; end; " +
- "create virtual procedure proc1 () as begin atomic select * from v; end;
");
+ "create virtual procedure proc1 () as begin atomic select * from v; end; "
+
+ "create virtual procedure proc2 (x integer) as begin atomic select 1; begin
select 1/x; end exception e end;");
es.deployVDB("test", mmd1);
@@ -365,6 +366,14 @@
s.execute("set noexec on");
s.execute("select 1");
assertFalse(s.getResultSet().next());
+
+ s.execute("set autoCommitTxn off");
+ s.execute("set noexec off");
+ s.execute("call proc2(0)");
+ //verify that the block txn was committed because the exception was caught
+ assertEquals(1, tm.txnHistory.size());
+ txn = tm.txnHistory.remove(0);
+ Mockito.verify(txn).commit();
}
}
Modified: trunk/runtime/src/test/java/org/teiid/transport/TestCommSockets.java
===================================================================
--- trunk/runtime/src/test/java/org/teiid/transport/TestCommSockets.java 2012-09-26
17:05:51 UTC (rev 4474)
+++ trunk/runtime/src/test/java/org/teiid/transport/TestCommSockets.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -230,9 +230,10 @@
assertEquals(2, stats.objectsRead); // handshake response, logon,
assertEquals(1, stats.sockets);
conn.cleanUp();
+ assertEquals(1, this.service.getActiveSessionsCount());
helpEstablishConnection(false, config, p);
conn.selectServerInstance(false);
- assertEquals(2, this.service.getActiveSessions().size());
+ assertEquals(2, this.service.getActiveSessionsCount());
assertTrue(conn.isOpen(1000));
stats = listener.getStats();
assertEquals(7, stats.objectsRead); // ping (pool test), assert identity, ping
(isOpen)
Modified: trunk/test-integration/common/src/test/java/org/teiid/jdbc/FakeServer.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/jdbc/FakeServer.java 2012-09-26
17:05:51 UTC (rev 4474)
+++ trunk/test-integration/common/src/test/java/org/teiid/jdbc/FakeServer.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -201,10 +201,6 @@
return this.repo.getLiveVDB(vdbName, 1);
}
- public void undeployVDB(String vdbName) {
- this.repo.removeVDB(vdbName, 1);
- }
-
public ConnectionImpl createConnection(String embeddedURL) throws Exception {
return getDriver().connect(embeddedURL, null);
}
Modified:
trunk/test-integration/common/src/test/java/org/teiid/systemmodel/TestMetadataUpdates.java
===================================================================
---
trunk/test-integration/common/src/test/java/org/teiid/systemmodel/TestMetadataUpdates.java 2012-09-26
17:05:51 UTC (rev 4474)
+++
trunk/test-integration/common/src/test/java/org/teiid/systemmodel/TestMetadataUpdates.java 2012-09-26
23:15:59 UTC (rev 4475)
@@ -29,7 +29,9 @@
import java.sql.SQLException;
import java.sql.Statement;
+import org.junit.After;
import org.junit.AfterClass;
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
@@ -45,15 +47,29 @@
@SuppressWarnings("nls")
public class TestMetadataUpdates {
- static Connection connection;
+ Connection connection;
static final String VDB = "metadata";
+
+ private static FakeServer server;
- @BeforeClass public static void setUp() throws Exception {
- FakeServer server = new FakeServer(true);
- server.deployVDB(VDB, UnitTestUtil.getTestDataPath() + "/metadata.vdb",
new DeployVDBParameter(null, getMetadataRepo()));
- connection = server.createConnection("jdbc:teiid:" + VDB); //$NON-NLS-1$
//$NON-NLS-2$
+ @BeforeClass public static void oneTimeSetUp() throws Exception {
+ server = new FakeServer(true);
}
+
+ @AfterClass public static void oneTimeTearDown() throws Exception {
+ server.stop();
+ }
+
+ @Before public void setup() throws Exception {
+ server.undeployVDB(VDB);
+ server.deployVDB(VDB, UnitTestUtil.getTestDataPath() + "/metadata.vdb", new
DeployVDBParameter(null, getMetadataRepo()));
+ connection = server.createConnection("jdbc:teiid:" + VDB); //$NON-NLS-1$
//$NON-NLS-2$
+ }
+
+ @After public void tearDown() throws SQLException {
+ connection.close();
+ }
private static DefaultMetadataRepository getMetadataRepo() {
DefaultMetadataRepository repo = Mockito.mock(DefaultMetadataRepository.class);
@@ -92,10 +108,6 @@
return repo;
}
- @AfterClass public static void tearDown() throws SQLException {
- connection.close();
- }
-
@Test public void testViewMetadataRepositoryMerge() throws Exception {
Statement s = connection.createStatement();
ResultSet rs = s.executeQuery("select * from vw");
@@ -152,7 +164,6 @@
assertEquals(2011, rs.getInt(1));
assertFalse(s.execute("alter procedure proc as begin select '2012';
end"));
-
//the sleep is needed to ensure that the plan is invalidated
Thread.sleep(100);