teiid SVN: r3344 - in branches/7.4.x/engine/src: main/java/org/teiid/query/processor/xml and 1 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-07-27 17:13:25 -0400 (Wed, 27 Jul 2011)
New Revision: 3344
Modified:
branches/7.4.x/engine/src/main/java/org/teiid/query/processor/QueryProcessor.java
branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/ExecSqlInstruction.java
branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/PlanExecutor.java
branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/RelationalPlanExecutor.java
branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/XMLPlan.java
branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/XMLProcessorEnvironment.java
branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/FakePlanExecutor.java
branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/TestProcessorEnvironment.java
Log:
TEIID-993 adding the ability to start sibling mapping class queries in parallel.
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/processor/QueryProcessor.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/processor/QueryProcessor.java 2011-07-27 17:52:49 UTC (rev 3343)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/processor/QueryProcessor.java 2011-07-27 21:13:25 UTC (rev 3344)
@@ -169,7 +169,7 @@
return result;
}
- private void init() throws TeiidComponentException, TeiidProcessingException {
+ public void init() throws TeiidComponentException, TeiidProcessingException {
// initialize if necessary
if(!initialized) {
reserved = this.bufferMgr.reserveBuffers(this.bufferMgr.getSchemaSize(this.getOutputElements()), BufferReserveMode.FORCE);
@@ -184,7 +184,6 @@
}
}
-
/**
* Close processing and clean everything up. Should only be called by the same thread that called process.
*/
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/ExecSqlInstruction.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/ExecSqlInstruction.java 2011-07-27 17:52:49 UTC (rev 3343)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/ExecSqlInstruction.java 2011-07-27 21:13:25 UTC (rev 3344)
@@ -49,14 +49,10 @@
throws BlockedException, TeiidComponentException, TeiidProcessingException{
LogManager.logTrace(org.teiid.logging.LogConstants.CTX_XML_PLAN, new Object[]{"SQL: Result set DOESN'T exist:",resultSetName}); //$NON-NLS-1$
- PlanExecutor executor = context.getResultExecutor(resultSetName);
- if (executor == null) {
- executor = env.createResultExecutor(resultSetName, info);
- context.setResultExecutor(resultSetName, executor);
- }
+ PlanExecutor executor = getPlanExecutor(env, context);
// this execute can throw the blocked exception
- executor.execute(context.getReferenceValues());
+ executor.execute(context.getReferenceValues(), false);
// now that we done executing the plan; remove the plan from context
context.removeResultExecutor(resultSetName);
@@ -68,6 +64,16 @@
env.incrementCurrentProgramCounter();
return context;
}
+
+ public PlanExecutor getPlanExecutor(XMLProcessorEnvironment env,
+ XMLContext context) throws TeiidComponentException {
+ PlanExecutor executor = context.getResultExecutor(resultSetName);
+ if (executor == null) {
+ executor = env.createResultExecutor(resultSetName, info);
+ context.setResultExecutor(resultSetName, executor);
+ }
+ return executor;
+ }
public String toString() {
return "SQL " + resultSetName; //$NON-NLS-1$
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/PlanExecutor.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/PlanExecutor.java 2011-07-27 17:52:49 UTC (rev 3343)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/PlanExecutor.java 2011-07-27 21:13:25 UTC (rev 3344)
@@ -39,8 +39,9 @@
/**
* Execute the plan
* @param referenceValues - values for any external references
+ * @param openOnly
*/
- public void execute(Map referenceValues) throws TeiidComponentException, BlockedException, TeiidProcessingException;
+ public void execute(Map referenceValues, boolean openOnly) throws TeiidComponentException, BlockedException, TeiidProcessingException;
/**
* Get the ElementSymbol list which represents the schema of the result set
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/RelationalPlanExecutor.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/RelationalPlanExecutor.java 2011-07-27 17:52:49 UTC (rev 3343)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/RelationalPlanExecutor.java 2011-07-27 21:13:25 UTC (rev 3344)
@@ -87,15 +87,20 @@
/**
* @throws TeiidProcessingException
- * @see org.teiid.query.processor.xml.PlanExecutor#execute(java.util.Map)
+ * @see org.teiid.query.processor.xml.PlanExecutor#execute(java.util.Map, boolean)
*/
- public void execute(Map referenceValues) throws TeiidComponentException, BlockedException, TeiidProcessingException {
+ public void execute(Map referenceValues, boolean openOnly) throws TeiidComponentException, BlockedException, TeiidProcessingException {
if (this.tupleSource == null) {
setReferenceValues(referenceValues);
this.tupleSource = new BatchIterator(internalProcessor);
+ if (openOnly) {
+ internalProcessor.init();
+ }
}
- //force execution
- this.tupleSource.hasNext();
+ if (!openOnly) {
+ //force execution
+ this.tupleSource.hasNext();
+ }
}
void setReferenceValues(Map<ElementSymbol, Object> referencesValues) {
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/XMLPlan.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/XMLPlan.java 2011-07-27 17:52:49 UTC (rev 3343)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/XMLPlan.java 2011-07-27 21:13:25 UTC (rev 3344)
@@ -155,7 +155,7 @@
while(true){
// do the xml processing.
- ProcessorInstruction inst = env.getCurrentInstruction();
+ ProcessorInstruction inst = env.getCurrentInstruction(this.context);
while (inst != null){
LogManager.logTrace(LogConstants.CTX_XML_PLAN, "Executing instruction", inst); //$NON-NLS-1$
this.context = inst.process(this.env, this.context);
@@ -186,7 +186,7 @@
TupleBatch batch = new TupleBatch(nextBatchCount++, Arrays.asList(Arrays.asList(xml)));
return batch;
}
- inst = env.getCurrentInstruction();
+ inst = env.getCurrentInstruction(this.context);
}
TupleBatch batch = new TupleBatch(nextBatchCount++, Collections.EMPTY_LIST);
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/XMLProcessorEnvironment.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/XMLProcessorEnvironment.java 2011-07-27 17:52:49 UTC (rev 3343)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/processor/xml/XMLProcessorEnvironment.java 2011-07-27 21:13:25 UTC (rev 3344)
@@ -26,10 +26,12 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
+import java.util.List;
import java.util.Set;
import org.teiid.common.buffer.BufferManager;
import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
import org.teiid.logging.LogManager;
import org.teiid.logging.MessageLevel;
import org.teiid.query.mapping.xml.ResultSetInfo;
@@ -84,6 +86,7 @@
private static class ProgramState {
private Program program;
private int programCounter = 0;
+ private int lookaheadCounter;
private int recursionCount = NOT_RECURSIVE;
private static final int NOT_RECURSIVE = 0;
@@ -156,7 +159,7 @@
this.programStack.addFirst(programState);
}
- public ProcessorInstruction getCurrentInstruction() {
+ public ProcessorInstruction getCurrentInstruction(XMLContext context) throws TeiidComponentException, TeiidProcessingException {
ProgramState programState = this.programStack.getFirst();
//Case 5266: account for an empty program on to the stack;
@@ -171,6 +174,23 @@
return null;
}
+ //start all siblings
+ List<ProcessorInstruction> instrs = programState.program.getProcessorInstructions();
+ if (programState.programCounter >= programState.lookaheadCounter && instrs.size() > programState.programCounter + 1) {
+ for (programState.lookaheadCounter = programState.programCounter; programState.lookaheadCounter < instrs.size(); programState.lookaheadCounter++) {
+ ProcessorInstruction pi = instrs.get(programState.lookaheadCounter);
+ if (pi instanceof ExecStagingTableInstruction) {
+ //need to load staging tables prior to source queries
+ break;
+ }
+ if (pi instanceof ExecSqlInstruction) {
+ ExecSqlInstruction esi = (ExecSqlInstruction)pi;
+ PlanExecutor pe = esi.getPlanExecutor(this, context);
+ pe.execute(context.getReferenceValues(), true);
+ }
+ }
+ }
+
return programState.program.getInstructionAt(programState.programCounter);
}
@@ -251,8 +271,6 @@
ProgramState initialProgramState = this.programStack.getLast();
ProgramState newState = new ProgramState();
newState.program = initialProgramState.program;
- newState.programCounter = 0;
- newState.recursionCount = ProgramState.NOT_RECURSIVE;
clone.programStack.addFirst(newState);
// XML results form and format
Modified: branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/FakePlanExecutor.java
===================================================================
--- branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/FakePlanExecutor.java 2011-07-27 17:52:49 UTC (rev 3343)
+++ branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/FakePlanExecutor.java 2011-07-27 21:13:25 UTC (rev 3344)
@@ -56,7 +56,7 @@
return this.currentRow;
}
- public void execute(Map values) throws TeiidComponentException, BlockedException {
+ public void execute(Map values, boolean openOnly) throws TeiidComponentException, BlockedException {
tupleSource.openSource();
}
Modified: branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/TestProcessorEnvironment.java
===================================================================
--- branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/TestProcessorEnvironment.java 2011-07-27 17:52:49 UTC (rev 3343)
+++ branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/TestProcessorEnvironment.java 2011-07-27 21:13:25 UTC (rev 3344)
@@ -119,31 +119,31 @@
env.pushProgram(p1, true); //simulate recursion
assertEquals(p1, env.getCurrentProgram());
- assertEquals(i1, env.getCurrentInstruction());
+ assertEquals(i1, env.getCurrentInstruction(null));
assertEquals(p1, env.getCurrentProgram());
i1.process(env, context);
assertEquals(p1, env.getCurrentProgram());
- assertEquals(i2, env.getCurrentInstruction());
+ assertEquals(i2, env.getCurrentInstruction(null));
assertEquals(p1, env.getCurrentProgram());
i2.process(env, context);
assertEquals(p2, env.getCurrentProgram());
- assertEquals(i3, env.getCurrentInstruction());
+ assertEquals(i3, env.getCurrentInstruction(null));
assertEquals(p2, env.getCurrentProgram());
i3.process(env, context);
assertEquals(p2, env.getCurrentProgram());
- assertEquals(i4, env.getCurrentInstruction());
+ assertEquals(i4, env.getCurrentInstruction(null));
assertEquals(p2, env.getCurrentProgram());
i4.process(env, context);
assertEquals(p1, env.getCurrentProgram());
- assertEquals(i1, env.getCurrentInstruction());
+ assertEquals(i1, env.getCurrentInstruction(null));
assertEquals(p1, env.getCurrentProgram());
i1.process(env, context);
assertEquals(p1, env.getCurrentProgram());
- assertEquals(i2, env.getCurrentInstruction());
+ assertEquals(i2, env.getCurrentInstruction(null));
assertEquals(p1, env.getCurrentProgram());
i2.process(env, context);
assertEquals(p1, env.getCurrentProgram());
- assertEquals(null, env.getCurrentInstruction());
+ assertEquals(null, env.getCurrentInstruction(null));
assertEquals(p1, env.getCurrentProgram());
}
@@ -173,31 +173,31 @@
env.pushProgram(p2);
assertEquals(p2, env.getCurrentProgram());
- assertEquals(i3, env.getCurrentInstruction());
+ assertEquals(i3, env.getCurrentInstruction(null));
assertEquals(p2, env.getCurrentProgram());
i3.process(env, context);
assertEquals(p2, env.getCurrentProgram());
- assertEquals(i4, env.getCurrentInstruction());
+ assertEquals(i4, env.getCurrentInstruction(null));
assertEquals(p2, env.getCurrentProgram());
i4.process(env, context);
assertEquals(p1, env.getCurrentProgram());
- assertEquals(i1, env.getCurrentInstruction());
+ assertEquals(i1, env.getCurrentInstruction(null));
assertEquals(p1, env.getCurrentProgram());
i1.process(env, context);
assertEquals(p1, env.getCurrentProgram());
- assertEquals(i2, env.getCurrentInstruction());
+ assertEquals(i2, env.getCurrentInstruction(null));
assertEquals(p1, env.getCurrentProgram());
i2.process(env, context);
assertEquals(p1, env.getCurrentProgram());
- assertEquals(i1, env.getCurrentInstruction());
+ assertEquals(i1, env.getCurrentInstruction(null));
assertEquals(p1, env.getCurrentProgram());
i1.process(env, context);
assertEquals(p1, env.getCurrentProgram());
- assertEquals(i2, env.getCurrentInstruction());
+ assertEquals(i2, env.getCurrentInstruction(null));
assertEquals(p1, env.getCurrentProgram());
i2.process(env, context);
assertEquals(p1, env.getCurrentProgram());
- assertEquals(null, env.getCurrentInstruction());
+ assertEquals(null, env.getCurrentInstruction(null));
assertEquals(p1, env.getCurrentProgram());
}
13 years, 5 months
teiid SVN: r3343 - branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-07-27 13:52:49 -0400 (Wed, 27 Jul 2011)
New Revision: 3343
Modified:
branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/XMLStagaingQueryPlanner.java
Log:
TEIID-1683 completing the merge of old case changes
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/XMLStagaingQueryPlanner.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/XMLStagaingQueryPlanner.java 2011-07-27 17:49:14 UTC (rev 3342)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/XMLStagaingQueryPlanner.java 2011-07-27 17:52:49 UTC (rev 3343)
@@ -104,7 +104,7 @@
ResultSetInfo rsInfo = sourceNode.getResultSetInfo();
// If this node has been eligible for raising, it will be eligible for staging.
- if (!rsInfo.isCriteriaRaised()) {
+ if (rsInfo.hasInputSet() && !rsInfo.isCriteriaRaised()) {
return false;
}
13 years, 5 months
teiid SVN: r3342 - branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-07-27 13:49:14 -0400 (Wed, 27 Jul 2011)
New Revision: 3342
Modified:
branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/SourceNodePlannerVisitor.java
Log:
TEIID-1683 completing the merge of old case changes
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/SourceNodePlannerVisitor.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/SourceNodePlannerVisitor.java 2011-07-27 17:32:38 UTC (rev 3341)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/SourceNodePlannerVisitor.java 2011-07-27 17:49:14 UTC (rev 3342)
@@ -127,7 +127,7 @@
// going through the raising the criteria.
// if the original query is not a select.. we are out of luck. we can expand on this later
// versions. make sure bindings are only to parent.
- if (parent == null || !canRaiseInputset(command, bindings) || !areBindingsOnlyToNode(modifiedNode, parent)) {
+ if (!rsInfo.hasInputSet() || !canRaiseInputset(command, bindings) || !areBindingsOnlyToNode(modifiedNode, parent)) {
return;
}
@@ -153,6 +153,10 @@
}
}
+ if (inputSetCriteria == null) {
+ return;
+ }
+
// Keep the criteria which is not reference based.
transformationQuery.setCriteria(nonInputsetCriteria);
13 years, 5 months
teiid SVN: r3341 - in branches/7.1.1.CP3/engine/src/main/java/org/teiid/query: tempdata and 1 other directory.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2011-07-27 13:32:38 -0400 (Wed, 27 Jul 2011)
New Revision: 3341
Modified:
branches/7.1.1.CP3/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
branches/7.1.1.CP3/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java
Log:
TEIID-1657: making view name available to the mattable request such that it can be proactively loaded at other nodes in the cluster
Modified: branches/7.1.1.CP3/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
===================================================================
--- branches/7.1.1.CP3/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2011-07-27 17:32:30 UTC (rev 3340)
+++ branches/7.1.1.CP3/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2011-07-27 17:32:38 UTC (rev 3341)
@@ -1004,6 +1004,7 @@
id = store.addTempGroup(matTableName, ResolverUtil.resolveElementsInGroup(table, metadata), false, true);
id.setQueryNode(metadata.getVirtualPlan(table.getMetadataID()));
id.setCardinality(metadata.getCardinality(table.getMetadataID()));
+ id.setOriginalMetadataID(table.getMetadataID());
Object pk = metadata.getPrimaryKey(table.getMetadataID());
if (pk != null) {
Modified: branches/7.1.1.CP3/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java
===================================================================
--- branches/7.1.1.CP3/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java 2011-07-27 17:32:30 UTC (rev 3340)
+++ branches/7.1.1.CP3/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java 2011-07-27 17:32:38 UTC (rev 3341)
@@ -420,8 +420,13 @@
if (!group.isTempGroupSymbol()) {
return null;
}
+ String viewName = null;
final String tableName = group.getNonCorrelationName().toUpperCase();
boolean remapColumns = !tableName.equalsIgnoreCase(group.getName());
+ TempMetadataID groupID = (TempMetadataID)group.getMetadataID();
+ if (groupID.getOriginalMetadataID() != null) {
+ viewName = context.getMetadata().getFullName(groupID.getOriginalMetadataID());
+ }
TempTable table = null;
if (group.isGlobalTable()) {
final TempTableStore globalStore = context.getGlobalTableStore();
@@ -445,9 +450,9 @@
if (load) {
if (!info.isValid()) {
//blocking load
- loadGlobalTable(context, group, tableName, null, globalStore, info, loadTime, true);
+ loadGlobalTable(context, group, tableName, viewName, globalStore, info, loadTime, true);
} else {
- loadAsynch(context, group, tableName, null, globalStore, info, loadTime);
+ loadAsynch(context, group, tableName, viewName, globalStore, info, loadTime);
}
}
table = globalStore.getOrCreateTempTable(tableName, query, bufferManager, false);
@@ -611,8 +616,8 @@
matTableEntry.lastUpdate = System.currentTimeMillis();
MatTableEntry entry = refreshJob.put(key, matTableEntry, null);
if (entry == null) {
- // in the case of refreshjob, cacheCreate are not being notified correctly due to nature of how Teiid uses the cache
- // so, in order to get a cacheModified event insert again.
+ // Due to nature how the JBoss Cache being used as flat keys with nodes, node creation event is
+ // hard to capture, this is way to insert and later do update to capture the node modification.
refreshJob.put(key, matTableEntry, null);
}
}
13 years, 5 months
teiid SVN: r3340 - in branches/7.4.x/engine/src: main/java/org/teiid/query/optimizer/xml and 2 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-07-27 13:32:30 -0400 (Wed, 27 Jul 2011)
New Revision: 3340
Added:
branches/7.4.x/engine/src/test/resources/TestXMLPlanningEnhancements-testThreeWayOrWithNestedSiblings.xml
Modified:
branches/7.4.x/engine/src/main/java/org/teiid/query/mapping/xml/ResultSetInfo.java
branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/CriteriaPlanner.java
branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/SourceNodePlannerVisitor.java
branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/XMLQueryPlanner.java
branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/TestXMLPlanningEnhancements.java
branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/TestXMLProcessor.java
Log:
TEIID-1683 fix for xml criteria planning with or across nested siblings
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/mapping/xml/ResultSetInfo.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/mapping/xml/ResultSetInfo.java 2011-07-27 14:43:28 UTC (rev 3339)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/mapping/xml/ResultSetInfo.java 2011-07-27 17:32:30 UTC (rev 3340)
@@ -66,6 +66,8 @@
//joined source node state
private int mappingClassNumber = 0;
private ElementSymbol mappingClassSymbol;
+ private boolean inputSet;
+ private boolean isCritNullDependent;
public ResultSetInfo(String resultName) {
this(resultName, false);
@@ -176,4 +178,20 @@
public boolean isStagedResult() {
return this.stagedResult;
}
+
+ public boolean hasInputSet() {
+ return inputSet;
+ }
+
+ public void setInputSet(boolean inputSet) {
+ this.inputSet = inputSet;
+ }
+
+ public void setCritNullDependent(boolean isCritNullDependent) {
+ this.isCritNullDependent = isCritNullDependent;
+ }
+
+ public boolean isCritNullDependent(){
+ return this.isCritNullDependent;
+ }
}
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/CriteriaPlanner.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/CriteriaPlanner.java 2011-07-27 14:43:28 UTC (rev 3339)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/CriteriaPlanner.java 2011-07-27 17:32:30 UTC (rev 3340)
@@ -37,6 +37,7 @@
import org.teiid.query.mapping.xml.MappingSourceNode;
import org.teiid.query.mapping.xml.ResultSetInfo;
import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.optimizer.relational.rules.JoinUtil;
import org.teiid.query.sql.lang.CompareCriteria;
import org.teiid.query.sql.lang.Criteria;
import org.teiid.query.sql.symbol.Constant;
@@ -44,6 +45,7 @@
import org.teiid.query.sql.symbol.Function;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.visitor.ElementCollectorVisitor;
+import org.teiid.query.sql.visitor.GroupsUsedByElementsVisitor;
public class CriteriaPlanner {
@@ -106,9 +108,15 @@
//TODO: this can be replaced with method on the source node?
MappingSourceNode criteriaRs = findRootResultSetNode(context, sourceNodes, criteria);
+ Collection<GroupSymbol> groups = GroupsUsedByElementsVisitor.getGroups(conjunct);
+ boolean userCritNullDependent = JoinUtil.isNullDependent(planEnv.getGlobalMetadata(), groups, conjunct);
+ ResultSetInfo rs = criteriaRs.getResultSetInfo();
+ if(userCritNullDependent){
+ rs.setCritNullDependent(true);
+ }
+
Criteria convertedCrit = XMLNodeMappingVisitor.convertCriteria(conjunct, planEnv.mappingDoc, planEnv.getGlobalMetadata());
- ResultSetInfo rs = criteriaRs.getResultSetInfo();
rs.setCriteria(Criteria.combineCriteria(rs.getCriteria(), convertedCrit));
rs.addToCriteriaResultSets(sourceNodes);
}
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/SourceNodePlannerVisitor.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/SourceNodePlannerVisitor.java 2011-07-27 14:43:28 UTC (rev 3339)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/SourceNodePlannerVisitor.java 2011-07-27 17:32:30 UTC (rev 3340)
@@ -122,6 +122,7 @@
MappingSourceNode parent = sourceNode.getParentSourceNode();
Collection<ElementSymbol> bindings = QueryUtil.getBindingElements(modifiedNode);
+ rsInfo.setInputSet(!bindings.isEmpty());
// root source nodes do not have any inputset criteria on them; so there is no use in
// going through the raising the criteria.
// if the original query is not a select.. we are out of luck. we can expand on this later
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/XMLQueryPlanner.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/XMLQueryPlanner.java 2011-07-27 14:43:28 UTC (rev 3339)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/xml/XMLQueryPlanner.java 2011-07-27 17:32:30 UTC (rev 3340)
@@ -300,9 +300,7 @@
Query currentQuery = contextQuery;
- for (Iterator i = resultSets.iterator(); i.hasNext();) {
- MappingSourceNode rsNode = (MappingSourceNode)i.next();
-
+ for (MappingSourceNode rsNode : resultSets) {
ResultSetInfo childRsInfo = rsNode.getResultSetInfo();
QueryNode planNode = QueryUtil.getQueryNode(childRsInfo.getResultSetName(), planEnv.getGlobalMetadata());
@@ -313,35 +311,19 @@
updateSymbolMap(symbolMap, childRsInfo.getResultSetName(), inlineViewName, planEnv.getGlobalMetadata());
// check if the criteria has been raised, if it is then we can update this as a join.
- if (childRsInfo.isCriteriaRaised()) {
+ if (!rsInfo.isCritNullDependent() && childRsInfo.hasInputSet() && childRsInfo.isCriteriaRaised()) {
Query transformationQuery = (Query) command;
SubqueryFromClause sfc = (SubqueryFromClause)transformationQuery.getFrom().getClauses().get(0);
Criteria joinCriteria = ((Query)childRsInfo.getCommand()).getCriteria();
- if (joinCriteria == null) {
- joinCriteria = QueryRewriter.TRUE_CRITERIA;
- }
-
joinCriteria = (Criteria)joinCriteria.clone();
//update the from clause
FromClause clause = currentQuery.getFrom().getClauses().remove(0);
- JoinPredicate join = null;
+ JoinPredicate join = new JoinPredicate(clause, sfc, JoinType.JOIN_LEFT_OUTER, Criteria.separateCriteriaByAnd(joinCriteria));
- if (clause instanceof JoinPredicate) {
- join = (JoinPredicate)clause;
-
- FromClause right = join.getRightClause();
-
- JoinPredicate newRight = new JoinPredicate(right, sfc, JoinType.JOIN_LEFT_OUTER, Criteria.separateCriteriaByAnd(joinCriteria));
-
- join.setRightClause(newRight);
- } else {
- join = new JoinPredicate(clause, sfc, JoinType.JOIN_LEFT_OUTER, Criteria.separateCriteriaByAnd(joinCriteria));
- }
-
currentQuery.getFrom().addClause(join);
currentQuery.getSelect().setDistinct(true);
Modified: branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/TestXMLPlanningEnhancements.java
===================================================================
--- branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/TestXMLPlanningEnhancements.java 2011-07-27 14:43:28 UTC (rev 3339)
+++ branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/TestXMLPlanningEnhancements.java 2011-07-27 17:32:30 UTC (rev 3340)
@@ -154,6 +154,15 @@
return doc;
}
+ @Test public void testThreeWayOrWithNestedSiblings() throws Exception {
+ QueryMetadataInterface metadata = TestXMLProcessor.exampleMetadataNestedWithSibling();
+ FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNestedWithSibling(metadata);
+ String resultFile = "TestXMLPlanningEnhancements-testThreeWayOrWithNestedSiblings.xml"; //$NON-NLS-1$
+ String expectedDoc = TestXMLProcessor.readFile(resultFile);
+
+ TestXMLProcessor.helpTestProcess("select * from xmltest.doc9c where itemid='003' or supplierid = '600' or orderid = '1'", expectedDoc, metadata, dataMgr); //$NON-NLS-1$
+ }
+
@Test public void testBaseballPlayersDocDefect19541() throws Exception {
QueryMetadataInterface metadata = RealMetadataFactory.exampleCase3225();
Modified: branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/TestXMLProcessor.java
===================================================================
--- branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/TestXMLProcessor.java 2011-07-27 14:43:28 UTC (rev 3339)
+++ branches/7.4.x/engine/src/test/java/org/teiid/query/processor/xml/TestXMLProcessor.java 2011-07-27 17:32:30 UTC (rev 3340)
@@ -606,7 +606,7 @@
return RealMetadataFactory.createTransformationMetadata(metadataStore, "example1");
}
- public QueryMetadataInterface exampleMetadataNestedWithSibling() {
+ public static QueryMetadataInterface exampleMetadataNestedWithSibling() {
MetadataStore metadataStore = new MetadataStore();
// Create models
@@ -1231,7 +1231,7 @@
}
/** nested with sibling*/
- private MappingDocument createXMLPlanNested2c() {
+ private static MappingDocument createXMLPlanNested2c() {
MappingDocument doc = new MappingDocument(true);
MappingElement root = doc.addChildElement(new MappingElement("Catalogs")); //$NON-NLS-1$
@@ -2256,7 +2256,7 @@
return dataMgr;
}
- private FakeDataManager exampleDataManagerNestedWithSibling(QueryMetadataInterface metadata) {
+ static FakeDataManager exampleDataManagerNestedWithSibling(QueryMetadataInterface metadata) {
FakeDataManager dataMgr = new FakeDataManager();
try {
Added: branches/7.4.x/engine/src/test/resources/TestXMLPlanningEnhancements-testThreeWayOrWithNestedSiblings.xml
===================================================================
--- branches/7.4.x/engine/src/test/resources/TestXMLPlanningEnhancements-testThreeWayOrWithNestedSiblings.xml (rev 0)
+++ branches/7.4.x/engine/src/test/resources/TestXMLPlanningEnhancements-testThreeWayOrWithNestedSiblings.xml 2011-07-27 17:32:30 UTC (rev 3340)
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Catalogs>
+ <Catalog>
+ <Items>
+ <Item ItemID="001">
+ <Name>Lamp</Name>
+ <Quantity>5</Quantity>
+ <Suppliers>
+ <Supplier SupplierID="51">
+ <Name>Chucky</Name>
+ <Zip>11111</Zip>
+ </Supplier>
+ <Supplier SupplierID="52">
+ <Name>Biff's Stuff</Name>
+ <Zip>22222</Zip>
+ </Supplier>
+ <Supplier SupplierID="53">
+ <Name>AAAA</Name>
+ <Zip>33333</Zip>
+ </Supplier>
+ <Supplier SupplierID="56">
+ <Name>Microsoft</Name>
+ <Zip>66666</Zip>
+ </Supplier>
+ </Suppliers>
+ <Orders>
+ <Order OrderID="1">
+ <Name>KMart</Name>
+ <Zip>12345</Zip>
+ </Order>
+ <Order OrderID="2">
+ <Name>Sun</Name>
+ <Zip>94040</Zip>
+ </Order>
+ <Order OrderID="3">
+ <Name>Cisco</Name>
+ <Zip>94041</Zip>
+ </Order>
+ <Order OrderID="4">
+ <Name>Doc</Name>
+ <Zip>94042</Zip>
+ </Order>
+ </Orders>
+ </Item>
+ <Item ItemID="003">
+ <Name>Goat</Name>
+ <Quantity>4</Quantity>
+ <Suppliers>
+ <Supplier SupplierID="56">
+ <Name>Microsoft</Name>
+ <Zip>66666</Zip>
+ </Supplier>
+ </Suppliers>
+ <Orders>
+ <Order OrderID="7">
+ <Name>Inktomi</Name>
+ <Zip>94044</Zip>
+ </Order>
+ </Orders>
+ </Item>
+ </Items>
+ </Catalog>
+</Catalogs>
\ No newline at end of file
Property changes on: branches/7.4.x/engine/src/test/resources/TestXMLPlanningEnhancements-testThreeWayOrWithNestedSiblings.xml
___________________________________________________________________
Added: svn:mime-type
+ text/plain
13 years, 5 months
teiid SVN: r3339 - in trunk: connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/derby and 23 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-07-27 10:43:28 -0400 (Wed, 27 Jul 2011)
New Revision: 3339
Added:
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/BaseDB2ExecutionFactory.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/RankingFunction.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/WindowFunctionProjectNode.java
trunk/engine/src/test/java/org/teiid/query/processor/TestWindowFunctions.java
Modified:
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/DB2ExecutionFactory.java
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/derby/DerbyExecutionFactory.java
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/sqlserver/SQLServerExecutionFactory.java
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/teiid/TeiidExecutionFactory.java
trunk/engine/src/main/java/org/teiid/common/buffer/STree.java
trunk/engine/src/main/java/org/teiid/common/buffer/TupleBuffer.java
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/MetaDataProcessor.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/AggregateFunction.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/ArrayAgg.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/ConstantFunction.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushLimit.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java
trunk/engine/src/main/java/org/teiid/query/processor/BatchCollector.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/ProjectNode.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/SortUtility.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/SortingFilter.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java
trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java
trunk/engine/src/main/java/org/teiid/query/sql/symbol/TextLine.java
trunk/engine/src/main/java/org/teiid/query/sql/symbol/WindowFunction.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.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/dqp/internal/process/TestDQPCore.java
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestMetaDataProcessor.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestSortOptimization.java
trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
trunk/engine/src/test/java/org/teiid/query/processor/TestAggregateProcessing.java
trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestGroupingNode.java
trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
Log:
TEIID-1667 finishing initial implementation forward merge of TEIID-1688 TEIID-1682 TEIID-1681
Added: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/BaseDB2ExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/BaseDB2ExecutionFactory.java (rev 0)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/BaseDB2ExecutionFactory.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -0,0 +1,176 @@
+/*
+ * 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 org.teiid.translator.jdbc.db2;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.teiid.language.DerivedColumn;
+import org.teiid.language.Expression;
+import org.teiid.language.Function;
+import org.teiid.language.Join;
+import org.teiid.language.LanguageFactory;
+import org.teiid.language.LanguageObject;
+import org.teiid.language.Limit;
+import org.teiid.language.Literal;
+import org.teiid.language.Comparison.Operator;
+import org.teiid.language.Join.JoinType;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.SourceSystemFunctions;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.TypeFacility;
+import org.teiid.translator.jdbc.AliasModifier;
+import org.teiid.translator.jdbc.ConvertModifier;
+import org.teiid.translator.jdbc.FunctionModifier;
+import org.teiid.translator.jdbc.JDBCExecutionFactory;
+import org.teiid.translator.jdbc.LocateFunctionModifier;
+import org.teiid.translator.jdbc.ModFunctionModifier;
+
+public class BaseDB2ExecutionFactory extends JDBCExecutionFactory {
+
+ private final class NullHandlingFormatModifier extends
+ ConvertModifier.FormatModifier {
+ private NullHandlingFormatModifier(String alias) {
+ super(alias);
+ }
+
+ @Override
+ public List<?> translate(Function function) {
+ Expression arg = function.getParameters().get(0);
+ if (arg instanceof Literal && ((Literal)arg).getValue() == null) {
+ ((Literal)function.getParameters().get(1)).setValue(this.alias);
+ return null;
+ }
+ return super.translate(function);
+ }
+ }
+
+ @Override
+ public void start() throws TranslatorException {
+ super.start();
+ registerFunctionModifier(SourceSystemFunctions.CHAR, new AliasModifier("chr")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.DAYOFMONTH, new AliasModifier("day")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.IFNULL, new AliasModifier("coalesce")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.LOCATE, new LocateFunctionModifier(getLanguageFactory()));
+ registerFunctionModifier(SourceSystemFunctions.SUBSTRING, new SubstringFunctionModifier());
+
+ registerFunctionModifier(SourceSystemFunctions.MOD, new ModFunctionModifier("MOD", getLanguageFactory())); //$NON-NLS-1$
+
+ //add in type conversion
+ ConvertModifier convertModifier = new ConvertModifier();
+ convertModifier.addTypeMapping("real", FunctionModifier.FLOAT); //$NON-NLS-1$
+ convertModifier.addTypeMapping("numeric(31,0)", FunctionModifier.BIGINTEGER); //$NON-NLS-1$
+ convertModifier.addTypeMapping("numeric(31,12)", FunctionModifier.BIGDECIMAL); //$NON-NLS-1$
+ convertModifier.addTypeMapping("char(1)", FunctionModifier.CHAR); //$NON-NLS-1$
+ convertModifier.addTypeMapping("blob", FunctionModifier.BLOB, FunctionModifier.OBJECT); //$NON-NLS-1$
+ convertModifier.addTypeMapping("clob", FunctionModifier.CLOB, FunctionModifier.XML); //$NON-NLS-1$
+ convertModifier.addConvert(FunctionModifier.TIME, FunctionModifier.TIMESTAMP, new FunctionModifier() {
+ @Override
+ public List<?> translate(Function function) {
+ return Arrays.asList("timestamp('1970-01-01', ", function.getParameters().get(0), ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ });
+ convertModifier.addConvert(FunctionModifier.DATE, FunctionModifier.TIMESTAMP, new FunctionModifier() {
+ @Override
+ public List<?> translate(Function function) {
+ return Arrays.asList("timestamp(",function.getParameters().get(0), ", '00:00:00')"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ });
+ //the next convert is not strictly necessary for db2, but it also works for derby
+ convertModifier.addConvert(FunctionModifier.STRING, FunctionModifier.FLOAT, new FunctionModifier() {
+ @Override
+ public List<?> translate(Function function) {
+ return Arrays.asList("cast(double(", function.getParameters().get(0), ") as real)"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ });
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("char"), FunctionModifier.STRING); //$NON-NLS-1$
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("smallint"), FunctionModifier.BYTE, FunctionModifier.SHORT); //$NON-NLS-1$
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("integer"), FunctionModifier.INTEGER); //$NON-NLS-1$
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("bigint"), FunctionModifier.LONG); //$NON-NLS-1$
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("double"), FunctionModifier.DOUBLE); //$NON-NLS-1$
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("date"), FunctionModifier.DATE); //$NON-NLS-1$
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("time"), FunctionModifier.TIME); //$NON-NLS-1$
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("timestamp"), FunctionModifier.TIMESTAMP); //$NON-NLS-1$
+ convertModifier.addNumericBooleanConversions();
+ registerFunctionModifier(SourceSystemFunctions.CONVERT, convertModifier);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<?> translateLimit(Limit limit, ExecutionContext context) {
+ return Arrays.asList("FETCH FIRST ", limit.getRowLimit(), " ROWS ONLY"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ @Override
+ public List<?> translate(LanguageObject obj, ExecutionContext context) {
+ //DB2 doesn't support cross join
+ convertCrossJoinToInner(obj, getLanguageFactory());
+ //DB2 needs projected nulls wrapped in casts
+ if (obj instanceof DerivedColumn) {
+ DerivedColumn selectSymbol = (DerivedColumn)obj;
+ if (selectSymbol.getExpression() instanceof Literal) {
+ Literal literal = (Literal)selectSymbol.getExpression();
+ if (literal.getValue() == null) {
+ String type = TypeFacility.RUNTIME_NAMES.INTEGER;
+ if (literal.getType() != TypeFacility.RUNTIME_TYPES.NULL) {
+ type = TypeFacility.getDataTypeName(literal.getType());
+ }
+ selectSymbol.setExpression(ConvertModifier.createConvertFunction(getLanguageFactory(), literal, type));
+ }
+ }
+ }
+ return super.translate(obj, context);
+ }
+
+ public static void convertCrossJoinToInner(LanguageObject obj, LanguageFactory lf) {
+ if (obj instanceof Join) {
+ Join join = (Join)obj;
+ if (join.getJoinType() == JoinType.CROSS_JOIN) {
+ Literal one = lf.createLiteral(1, TypeFacility.RUNTIME_TYPES.INTEGER);
+ join.setCondition(lf.createCompareCriteria(Operator.EQ, one, one));
+ join.setJoinType(JoinType.INNER_JOIN);
+ }
+ }
+ }
+
+ @Override
+ public NullOrder getDefaultNullOrder() {
+ return NullOrder.HIGH;
+ }
+
+ @Override
+ public boolean supportsInlineViews() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsExcept() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsIntersect() {
+ return true;
+ }
+
+}
Property changes on: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/BaseDB2ExecutionFactory.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/DB2ExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/DB2ExecutionFactory.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/DB2ExecutionFactory.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -23,142 +23,18 @@
package org.teiid.translator.jdbc.db2;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
-import org.teiid.language.DerivedColumn;
-import org.teiid.language.Expression;
-import org.teiid.language.Function;
-import org.teiid.language.Join;
-import org.teiid.language.LanguageFactory;
-import org.teiid.language.LanguageObject;
-import org.teiid.language.Limit;
-import org.teiid.language.Literal;
-import org.teiid.language.Comparison.Operator;
-import org.teiid.language.Join.JoinType;
-import org.teiid.translator.ExecutionContext;
-import org.teiid.translator.SourceSystemFunctions;
import org.teiid.translator.Translator;
-import org.teiid.translator.TranslatorException;
-import org.teiid.translator.TypeFacility;
-import org.teiid.translator.jdbc.AliasModifier;
-import org.teiid.translator.jdbc.ConvertModifier;
-import org.teiid.translator.jdbc.FunctionModifier;
-import org.teiid.translator.jdbc.JDBCExecutionFactory;
-import org.teiid.translator.jdbc.LocateFunctionModifier;
-import org.teiid.translator.jdbc.ModFunctionModifier;
@Translator(name="db2", description="A translator for IBM DB2 Database")
-public class DB2ExecutionFactory extends JDBCExecutionFactory {
-
- private final class NullHandlingFormatModifier extends
- ConvertModifier.FormatModifier {
- private NullHandlingFormatModifier(String alias) {
- super(alias);
- }
-
- @Override
- public List<?> translate(Function function) {
- Expression arg = function.getParameters().get(0);
- if (arg instanceof Literal && ((Literal)arg).getValue() == null) {
- ((Literal)function.getParameters().get(1)).setValue(this.alias);
- return null;
- }
- return super.translate(function);
- }
- }
-
- @Override
- public void start() throws TranslatorException {
- super.start();
- registerFunctionModifier(SourceSystemFunctions.CHAR, new AliasModifier("chr")); //$NON-NLS-1$
- registerFunctionModifier(SourceSystemFunctions.DAYOFMONTH, new AliasModifier("day")); //$NON-NLS-1$
- registerFunctionModifier(SourceSystemFunctions.IFNULL, new AliasModifier("coalesce")); //$NON-NLS-1$
- registerFunctionModifier(SourceSystemFunctions.LOCATE, new LocateFunctionModifier(getLanguageFactory()));
- registerFunctionModifier(SourceSystemFunctions.SUBSTRING, new SubstringFunctionModifier());
-
- registerFunctionModifier(SourceSystemFunctions.MOD, new ModFunctionModifier("MOD", getLanguageFactory())); //$NON-NLS-1$
-
- //add in type conversion
- ConvertModifier convertModifier = new ConvertModifier();
- convertModifier.addTypeMapping("real", FunctionModifier.FLOAT); //$NON-NLS-1$
- convertModifier.addTypeMapping("numeric(31,0)", FunctionModifier.BIGINTEGER); //$NON-NLS-1$
- convertModifier.addTypeMapping("numeric(31,12)", FunctionModifier.BIGDECIMAL); //$NON-NLS-1$
- convertModifier.addTypeMapping("char(1)", FunctionModifier.CHAR); //$NON-NLS-1$
- convertModifier.addTypeMapping("blob", FunctionModifier.BLOB, FunctionModifier.OBJECT); //$NON-NLS-1$
- convertModifier.addTypeMapping("clob", FunctionModifier.CLOB, FunctionModifier.XML); //$NON-NLS-1$
- convertModifier.addConvert(FunctionModifier.TIME, FunctionModifier.TIMESTAMP, new FunctionModifier() {
- @Override
- public List<?> translate(Function function) {
- return Arrays.asList("timestamp('1970-01-01', ", function.getParameters().get(0), ")"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- });
- convertModifier.addConvert(FunctionModifier.DATE, FunctionModifier.TIMESTAMP, new FunctionModifier() {
- @Override
- public List<?> translate(Function function) {
- return Arrays.asList("timestamp(",function.getParameters().get(0), ", '00:00:00')"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- });
- //the next convert is not strictly necessary for db2, but it also works for derby
- convertModifier.addConvert(FunctionModifier.STRING, FunctionModifier.FLOAT, new FunctionModifier() {
- @Override
- public List<?> translate(Function function) {
- return Arrays.asList("cast(double(", function.getParameters().get(0), ") as real)"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- });
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("char"), FunctionModifier.STRING); //$NON-NLS-1$
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("smallint"), FunctionModifier.BYTE, FunctionModifier.SHORT); //$NON-NLS-1$
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("integer"), FunctionModifier.INTEGER); //$NON-NLS-1$
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("bigint"), FunctionModifier.LONG); //$NON-NLS-1$
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("double"), FunctionModifier.DOUBLE); //$NON-NLS-1$
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("date"), FunctionModifier.DATE); //$NON-NLS-1$
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("time"), FunctionModifier.TIME); //$NON-NLS-1$
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("timestamp"), FunctionModifier.TIMESTAMP); //$NON-NLS-1$
- convertModifier.addNumericBooleanConversions();
- registerFunctionModifier(SourceSystemFunctions.CONVERT, convertModifier);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public List<?> translateLimit(Limit limit, ExecutionContext context) {
- return Arrays.asList("FETCH FIRST ", limit.getRowLimit(), " ROWS ONLY"); //$NON-NLS-1$ //$NON-NLS-2$
- }
+public class DB2ExecutionFactory extends BaseDB2ExecutionFactory {
- @Override
- public List<?> translate(LanguageObject obj, ExecutionContext context) {
- //DB2 doesn't support cross join
- convertCrossJoinToInner(obj, getLanguageFactory());
- //DB2 needs projected nulls wrapped in casts
- if (obj instanceof DerivedColumn) {
- DerivedColumn selectSymbol = (DerivedColumn)obj;
- if (selectSymbol.getExpression() instanceof Literal) {
- Literal literal = (Literal)selectSymbol.getExpression();
- if (literal.getValue() == null) {
- String type = TypeFacility.RUNTIME_NAMES.INTEGER;
- if (literal.getType() != TypeFacility.RUNTIME_TYPES.NULL) {
- type = TypeFacility.getDataTypeName(literal.getType());
- }
- selectSymbol.setExpression(ConvertModifier.createConvertFunction(getLanguageFactory(), literal, type));
- }
- }
- }
- return super.translate(obj, context);
- }
-
- public static void convertCrossJoinToInner(LanguageObject obj, LanguageFactory lf) {
- if (obj instanceof Join) {
- Join join = (Join)obj;
- if (join.getJoinType() == JoinType.CROSS_JOIN) {
- Literal one = lf.createLiteral(1, TypeFacility.RUNTIME_TYPES.INTEGER);
- join.setCondition(lf.createCompareCriteria(Operator.EQ, one, one));
- join.setJoinType(JoinType.INNER_JOIN);
- }
- }
- }
+ public static final String EIGHT_0 = "8.0"; //$NON-NLS-1$
+ public static final String NINE_1 = "9.1"; //$NON-NLS-1$
- @Override
- public NullOrder getDefaultNullOrder() {
- return NullOrder.HIGH;
+ public DB2ExecutionFactory() {
+ setDatabaseVersion(EIGHT_0);
}
@Override
@@ -228,39 +104,30 @@
supportedFunctions.add("COALESCE"); //$NON-NLS-1$
return supportedFunctions;
}
-
+
@Override
- public boolean supportsInlineViews() {
- return true;
- }
-
- @Override
public boolean supportsFunctionsInGroupBy() {
return true;
}
@Override
- public boolean supportsRowLimit() {
+ public boolean supportsAggregatesEnhancedNumeric() {
return true;
}
-
+
@Override
- public boolean supportsExcept() {
+ public boolean supportsCommonTableExpressions() {
return true;
}
-
- @Override
- public boolean supportsIntersect() {
- return true;
- }
@Override
- public boolean supportsAggregatesEnhancedNumeric() {
+ public boolean supportsRowLimit() {
return true;
}
@Override
- public boolean supportsCommonTableExpressions() {
- return true;
- }
+ public boolean supportsElementaryOlapOperations() {
+ return getDatabaseVersion().compareTo(NINE_1) >= 0;
+ }
+
}
Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/derby/DerbyExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/derby/DerbyExecutionFactory.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/derby/DerbyExecutionFactory.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -29,14 +29,14 @@
import org.teiid.translator.Translator;
import org.teiid.translator.TranslatorException;
import org.teiid.translator.jdbc.EscapeSyntaxModifier;
-import org.teiid.translator.jdbc.db2.DB2ExecutionFactory;
+import org.teiid.translator.jdbc.db2.BaseDB2ExecutionFactory;
import org.teiid.translator.jdbc.oracle.LeftOrRightFunctionModifier;
/**
* @since 4.3
*/
@Translator(name="derby", description="A translator for Apache Derby Database")
-public class DerbyExecutionFactory extends DB2ExecutionFactory {
+public class DerbyExecutionFactory extends BaseDB2ExecutionFactory {
public static final String TEN_1 = "10.1"; //$NON-NLS-1$
public static final String TEN_2 = "10.2"; //$NON-NLS-1$
@@ -181,8 +181,4 @@
return this.getDatabaseVersion().compareTo(TEN_5) >= 0;
}
- @Override
- public boolean supportsFunctionsInGroupBy() {
- return false;
- }
}
Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -532,4 +532,9 @@
return true;
}
+ @Override
+ public boolean supportsElementaryOlapOperations() {
+ return true;
+ }
+
}
Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/sqlserver/SQLServerExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/sqlserver/SQLServerExecutionFactory.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/sqlserver/SQLServerExecutionFactory.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -226,5 +226,10 @@
protected boolean supportsCrossJoin() {
return true;
}
+
+ @Override
+ public boolean supportsElementaryOlapOperations() {
+ return true;
+ }
}
Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/teiid/TeiidExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/teiid/TeiidExecutionFactory.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/teiid/TeiidExecutionFactory.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -42,6 +42,7 @@
public static final String SEVEN_2 = "7.2"; //$NON-NLS-1$
public static final String SEVEN_3 = "7.3"; //$NON-NLS-1$
public static final String SEVEN_4 = "7.4"; //$NON-NLS-1$
+ public static final String SEVEN_5 = "7.5"; //$NON-NLS-1$
public TeiidExecutionFactory() {
setDatabaseVersion(SEVEN_0);
@@ -201,4 +202,19 @@
public boolean supportsCommonTableExpressions() {
return getDatabaseVersion().compareTo(SEVEN_2) >= 0;
}
+
+ @Override
+ public boolean supportsAdvancedOlapOperations() {
+ return getDatabaseVersion().compareTo(SEVEN_5) >= 0;
+ }
+
+ @Override
+ public boolean supportsElementaryOlapOperations() {
+ return getDatabaseVersion().compareTo(SEVEN_5) >= 0;
+ }
+
+ @Override
+ public boolean supportsArrayAgg() {
+ return getDatabaseVersion().compareTo(SEVEN_5) >= 0;
+ }
}
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/STree.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/STree.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/STree.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -169,6 +169,10 @@
return null;
}
+ public List find(List n) throws TeiidComponentException {
+ return find(n, new LinkedList<SearchResult>());
+ }
+
public List insert(List tuple, InsertMode mode, int sizeHint) throws TeiidComponentException {
LinkedList<SearchResult> places = new LinkedList<SearchResult>();
List match = null;
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/TupleBuffer.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/TupleBuffer.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/TupleBuffer.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -48,13 +48,13 @@
* @return
* @since 4.2
*/
- public static String[] getTypeNames(List expressions) {
+ public static String[] getTypeNames(List<? extends Expression> expressions) {
if (expressions == null) {
return null;
}
String[] types = new String[expressions.size()];
- for (ListIterator i = expressions.listIterator(); i.hasNext();) {
- Expression expr = (Expression)i.next();
+ for (ListIterator<? extends Expression> i = expressions.listIterator(); i.hasNext();) {
+ Expression expr = i.next();
types[i.previousIndex()] = DataTypeManager.getDataTypeName(expr.getType());
}
return types;
@@ -63,7 +63,7 @@
//construction state
private BatchManager manager;
private String tupleSourceID;
- private List<?> schema;
+ private List<? extends Expression> schema;
private String[] types;
private int batchSize;
@@ -80,7 +80,7 @@
private String uuid;
private FileStore lobStore;
- public TupleBuffer(BatchManager manager, String id, List<?> schema, int[] lobIndexes, int batchSize) {
+ public TupleBuffer(BatchManager manager, String id, List<? extends Expression> schema, int[] lobIndexes, int batchSize) {
this.manager = manager;
this.tupleSourceID = id;
this.schema = schema;
@@ -276,7 +276,7 @@
this.isFinal = isFinal;
}
- public List<?> getSchema() {
+ public List<? extends Expression> getSchema() {
return schema;
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -192,24 +192,17 @@
symbol = ((AliasSymbol)symbol).getSymbol();
}
- org.teiid.language.Expression iExp = null;
- if(symbol instanceof ElementSymbol) {
- iExp = translate((ElementSymbol)symbol);
- } else if(symbol instanceof AggregateSymbol) {
- iExp = translate((AggregateSymbol)symbol);
- } else if(symbol instanceof ExpressionSymbol) {
- iExp = translate(((ExpressionSymbol)symbol).getExpression());
- }
+ org.teiid.language.Expression iExp = translate(symbol);
DerivedColumn selectSymbol = new DerivedColumn(alias, iExp);
translatedSymbols.add(selectSymbol);
}
List<TableReference> items = null;
if (query.getFrom() != null) {
- List clauses = query.getFrom().getClauses();
+ List<FromClause> clauses = query.getFrom().getClauses();
items = new ArrayList<TableReference>(clauses.size());
- for (Iterator i = clauses.iterator(); i.hasNext();) {
- items.add(translate((FromClause)i.next()));
+ for (Iterator<FromClause> i = clauses.iterator(); i.hasNext();) {
+ items.add(translate(i.next()));
}
}
Select q = new Select(translatedSymbols, query
@@ -485,8 +478,12 @@
return translate((ScalarSubquery)expr);
} else if (expr instanceof SearchedCaseExpression) {
return translate((SearchedCaseExpression)expr);
- } else if (expr instanceof SingleElementSymbol) {
- return translate((SingleElementSymbol)expr);
+ } else if (expr instanceof ElementSymbol) {
+ return translate((ElementSymbol)expr);
+ } else if (expr instanceof AggregateSymbol) {
+ return translate((AggregateSymbol)expr);
+ } else if (expr instanceof ExpressionSymbol) {
+ return translate((ExpressionSymbol)expr);
} else if (expr instanceof Criteria) {
return translate((Criteria)expr);
} else if (expr instanceof WindowFunction) {
@@ -563,18 +560,6 @@
return new org.teiid.language.ScalarSubquery(translate(ss.getCommand()));
}
- org.teiid.language.Expression translate(SingleElementSymbol symbol) {
- if (symbol == null) return null;
- if (symbol instanceof ElementSymbol) {
- return translate((ElementSymbol)symbol);
- } else if (symbol instanceof AggregateSymbol) {
- return translate((AggregateSymbol)symbol);
- } else if (symbol instanceof ExpressionSymbol) {
- return translate((ExpressionSymbol)symbol);
- }
- throw new AssertionError();
- }
-
org.teiid.language.Expression translate(AliasSymbol symbol) {
return translate(symbol.getSymbol());
}
@@ -604,7 +589,6 @@
return translate(symbol.getExpression());
}
-
/* Insert */
org.teiid.language.Insert translate(Insert insert) {
List<ElementSymbol> elements = insert.getVariables();
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/MetaDataProcessor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/MetaDataProcessor.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/MetaDataProcessor.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -58,6 +58,7 @@
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.symbol.Reference;
import org.teiid.query.sql.symbol.SingleElementSymbol;
+import org.teiid.query.sql.symbol.WindowFunction;
import org.teiid.query.sql.symbol.AggregateSymbol.Type;
import org.teiid.query.sql.visitor.ReferenceCollectorVisitor;
import org.teiid.query.tempdata.TempTableStore;
@@ -231,6 +232,8 @@
return createElementMetadata(label, (ElementSymbol) symbol);
} else if(symbol instanceof AggregateSymbol) {
return createAggregateMetadata(label, (AggregateSymbol) symbol);
+ } else if (symbol instanceof WindowFunction) {
+ return createAggregateMetadata(label, ((WindowFunction) symbol).getFunction());
}
return createTypedMetadata(label, symbol);
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -209,7 +209,7 @@
update = true;
GroupingNode groupNode = new GroupingNode(getID());
AggregateSymbol sumCount = new AggregateSymbol("SumCount", NonReserved.SUM, false, (Expression)accessNode.getElements().get(0)); //$NON-NLS-1$
- List<Expression> outputElements = new ArrayList<Expression>(1);
+ List<SingleElementSymbol> outputElements = new ArrayList<SingleElementSymbol>(1);
outputElements.add(sumCount);
groupNode.setElements(outputElements);
groupNode.addChild(unionNode);
@@ -218,8 +218,8 @@
Expression intSum = ResolverUtil.getConversion(sumCount, DataTypeManager.getDataTypeName(sumCount.getType()), DataTypeManager.DefaultDataTypes.INTEGER, false, metadata.getFunctionLibrary());
- Expression rowCount = new ExpressionSymbol("RowCount", intSum); //$NON-NLS-1$
- outputElements = new ArrayList<Expression>(1);
+ ExpressionSymbol rowCount = new ExpressionSymbol("RowCount", intSum); //$NON-NLS-1$
+ outputElements = new ArrayList<SingleElementSymbol>(1);
outputElements.add(rowCount);
projectNode.setElements(outputElements);
projectNode.setSelectSymbols(outputElements);
Modified: trunk/engine/src/main/java/org/teiid/query/function/aggregate/AggregateFunction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/aggregate/AggregateFunction.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/AggregateFunction.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -39,10 +39,15 @@
public abstract class AggregateFunction {
private int expressionIndex = -1;
+ private int conditionIndex = -1;
public void setExpressionIndex(int expressionIndex) {
this.expressionIndex = expressionIndex;
}
+
+ public void setConditionIndex(int conditionIndex) {
+ this.conditionIndex = conditionIndex;
+ }
/**
* Called to initialize the function. In the future this may expand
@@ -58,18 +63,21 @@
public abstract void reset();
public void addInput(List<?> tuple) throws TeiidComponentException, TeiidProcessingException {
+ if (conditionIndex != -1 && !Boolean.TRUE.equals(tuple.get(conditionIndex))) {
+ return;
+ }
if (expressionIndex == -1) {
addInputDirect(null, tuple);
return;
}
Object input = tuple.get(expressionIndex);
- if (!filter(input)) {
+ if (input != null || respectsNull()) {
addInputDirect(input, tuple);
}
}
- boolean filter(Object value) {
- return value == null;
+ public boolean respectsNull() {
+ return false;
}
/**
Modified: trunk/engine/src/main/java/org/teiid/query/function/aggregate/ArrayAgg.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/aggregate/ArrayAgg.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/ArrayAgg.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -62,10 +62,10 @@
public void reset() {
this.result = null;
}
+
+ @Override
+ public boolean respectsNull() {
+ return true;
+ }
- @Override
- boolean filter(Object value) {
- // handle the null values too.
- return false;
- }
}
Modified: trunk/engine/src/main/java/org/teiid/query/function/aggregate/ConstantFunction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/aggregate/ConstantFunction.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/ConstantFunction.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -40,8 +40,8 @@
}
@Override
- boolean filter(Object input) {
- return false;
+ public boolean respectsNull() {
+ return true;
}
/**
Added: trunk/engine/src/main/java/org/teiid/query/function/aggregate/RankingFunction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/aggregate/RankingFunction.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/RankingFunction.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -0,0 +1,74 @@
+/*
+ * 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 org.teiid.query.function.aggregate;
+
+import java.util.List;
+
+import org.teiid.api.exception.query.ExpressionEvaluationException;
+import org.teiid.api.exception.query.FunctionExecutionException;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.query.processor.relational.GroupingNode;
+import org.teiid.query.sql.symbol.AggregateSymbol.Type;
+
+/**
+ * computes rank/dense_rank
+ */
+public class RankingFunction extends AggregateFunction {
+
+ private int count = 0;
+ private int result = 0;
+ private int[] orderIndexes;
+ private Type type;
+ private List<?> previousTuple;
+
+ public RankingFunction(Type function, int[] orderIndexes) {
+ this.type = function;
+ this.orderIndexes = orderIndexes;
+ }
+
+ @Override
+ public void reset() {
+ count = 0;
+ result = 0;
+ }
+
+ @Override
+ public void addInputDirect(Object input, List<?> tuple)
+ throws FunctionExecutionException, ExpressionEvaluationException,
+ TeiidComponentException {
+ if (previousTuple == null || !GroupingNode.sameGroup(orderIndexes, tuple, previousTuple)) {
+ count++;
+ result = count;
+ } else if (type == Type.RANK) {
+ count++;
+ }
+ previousTuple = tuple;
+ }
+
+ @Override
+ public Object getResult() throws FunctionExecutionException,
+ ExpressionEvaluationException, TeiidComponentException {
+ return result;
+ }
+
+}
Property changes on: trunk/engine/src/main/java/org/teiid/query/function/aggregate/RankingFunction.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -26,6 +26,7 @@
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.api.exception.query.QueryPlannerException;
@@ -45,6 +46,8 @@
import org.teiid.query.optimizer.relational.plantree.NodeConstants.Info;
import org.teiid.query.optimizer.relational.rules.CapabilitiesUtil;
import org.teiid.query.optimizer.relational.rules.FrameUtil;
+import org.teiid.query.optimizer.relational.rules.RuleAssignOutputElements;
+import org.teiid.query.optimizer.relational.rules.RuleChooseJoinStrategy;
import org.teiid.query.processor.ProcessorPlan;
import org.teiid.query.processor.relational.AccessNode;
import org.teiid.query.processor.relational.ArrayTableNode;
@@ -69,6 +72,7 @@
import org.teiid.query.processor.relational.SortNode;
import org.teiid.query.processor.relational.TextTableNode;
import org.teiid.query.processor.relational.UnionAllNode;
+import org.teiid.query.processor.relational.WindowFunctionProjectNode;
import org.teiid.query.processor.relational.XMLTableNode;
import org.teiid.query.processor.relational.JoinNode.JoinStrategyType;
import org.teiid.query.processor.relational.MergeJoinStrategy.SortOption;
@@ -80,6 +84,7 @@
import org.teiid.query.sql.lang.Insert;
import org.teiid.query.sql.lang.JoinType;
import org.teiid.query.sql.lang.OrderBy;
+import org.teiid.query.sql.lang.OrderByItem;
import org.teiid.query.sql.lang.Query;
import org.teiid.query.sql.lang.QueryCommand;
import org.teiid.query.sql.lang.StoredProcedure;
@@ -90,7 +95,10 @@
import org.teiid.query.sql.lang.XMLTable.XMLColumn;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.ExpressionSymbol;
import org.teiid.query.sql.symbol.GroupSymbol;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
+import org.teiid.query.sql.symbol.WindowFunction;
import org.teiid.query.sql.util.SymbolMap;
import org.teiid.query.sql.visitor.EvaluatableVisitor;
import org.teiid.query.sql.visitor.GroupCollectorVisitor;
@@ -213,11 +221,25 @@
}
} else {
- List symbols = (List) node.getProperty(NodeConstants.Info.PROJECT_COLS);
+ List<SingleElementSymbol> symbols = (List) node.getProperty(NodeConstants.Info.PROJECT_COLS);
ProjectNode pnode = new ProjectNode(getID());
pnode.setSelectSymbols(symbols);
processNode = pnode;
+
+ if (node.hasBooleanProperty(Info.HAS_WINDOW_FUNCTIONS)) {
+ WindowFunctionProjectNode wfpn = new WindowFunctionProjectNode(getID());
+ Set<WindowFunction> windowFunctions = RuleAssignOutputElements.getWindowFunctions(symbols);
+ //TODO: check for selecting all window functions
+ List<SingleElementSymbol> outputElements = new ArrayList<SingleElementSymbol>(windowFunctions);
+ //collect the other projected expressions
+ for (SingleElementSymbol singleElementSymbol : (List<SingleElementSymbol>)node.getFirstChild().getProperty(Info.OUTPUT_COLS)) {
+ outputElements.add(singleElementSymbol);
+ }
+ wfpn.setElements(outputElements);
+ wfpn.init();
+ pnode.addChild(wfpn);
+ }
}
break;
@@ -374,9 +396,32 @@
break;
case NodeConstants.Types.GROUP:
GroupingNode gnode = new GroupingNode(getID());
- gnode.setGroupingElements( (List<Expression>) node.getProperty(NodeConstants.Info.GROUP_COLS) );
- gnode.setOutputMapping((SymbolMap)node.getProperty(NodeConstants.Info.SYMBOL_MAP));
+ SymbolMap groupingMap = (SymbolMap)node.getProperty(NodeConstants.Info.SYMBOL_MAP);
+ gnode.setOutputMapping(groupingMap);
gnode.setRemoveDuplicates(node.hasBooleanProperty(NodeConstants.Info.IS_DUP_REMOVAL));
+ List<Expression> gCols = (List) node.getProperty(NodeConstants.Info.GROUP_COLS);
+ orderBy = (OrderBy) node.getProperty(Info.SORT_ORDER);
+ if (orderBy == null) {
+ if (gCols != null) {
+ orderBy = new OrderBy(RuleChooseJoinStrategy.createExpressionSymbols(gCols));
+ }
+ } else {
+ for (int i = 0; i < gCols.size(); i++) {
+ if (i < orderBy.getOrderByItems().size()) {
+ OrderByItem orderByItem = orderBy.getOrderByItems().get(i);
+ Expression ex = SymbolMap.getExpression(orderByItem.getSymbol());
+ if (ex instanceof ElementSymbol) {
+ ex = groupingMap.getMappedExpression((ElementSymbol) ex);
+ orderByItem.setSymbol(new ExpressionSymbol("expr", ex)); //$NON-NLS-1$
+ }
+ } else {
+ orderBy.addVariable(new ExpressionSymbol("expr", gCols.get(i)), OrderBy.ASC); //$NON-NLS-1$
+ }
+ }
+ }
+ if (orderBy != null) {
+ gnode.setOrderBy(orderBy.getOrderByItems());
+ }
processNode = gnode;
break;
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -285,7 +285,10 @@
}
if (!singleMapping) {
//add back the anon group
- groups.add(((SymbolMap)node.getProperty(Info.SYMBOL_MAP)).asMap().keySet().iterator().next().getGroupSymbol());
+ SymbolMap property = (SymbolMap)node.getProperty(Info.SYMBOL_MAP);
+ if (!property.asMap().isEmpty()) {
+ groups.add(property.asMap().keySet().iterator().next().getGroupSymbol());
+ }
}
} else if (type == NodeConstants.Types.SOURCE || type == NodeConstants.Types.ACCESS) {
convertAccessPatterns(symbolMap, node);
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -29,6 +29,7 @@
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.teiid.api.exception.query.QueryMetadataException;
@@ -59,7 +60,9 @@
import org.teiid.query.sql.symbol.ExpressionSymbol;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.symbol.SingleElementSymbol;
+import org.teiid.query.sql.symbol.WindowFunction;
import org.teiid.query.sql.util.SymbolMap;
+import org.teiid.query.sql.visitor.AggregateSymbolCollectorVisitor;
import org.teiid.query.sql.visitor.ElementCollectorVisitor;
import org.teiid.query.sql.visitor.GroupsUsedByElementsVisitor;
import org.teiid.query.util.CommandContext;
@@ -210,6 +213,12 @@
root.addGroups(GroupsUsedByElementsVisitor.getGroups(projectCols));
root.addGroups(GroupsUsedByElementsVisitor.getGroups(root.getCorrelatedReferenceElements()));
}
+ if (root.hasBooleanProperty(Info.HAS_WINDOW_FUNCTIONS)) {
+ Set<WindowFunction> windowFunctions = getWindowFunctions(projectCols);
+ if (windowFunctions.isEmpty()) {
+ root.setProperty(Info.HAS_WINDOW_FUNCTIONS, false);
+ }
+ }
}
List<SingleElementSymbol> requiredInput = collectRequiredInputSymbols(root);
@@ -220,7 +229,9 @@
NodeEditor.removeChildNode(root.getParent(), root);
SymbolMap symbolMap = (SymbolMap) old.getProperty(NodeConstants.Info.SYMBOL_MAP);
- FrameUtil.convertFrame(next.getParent(), symbolMap.asMap().keySet().iterator().next().getGroupSymbol(), null, symbolMap.asMap(), metadata);
+ if (!symbolMap.asMap().isEmpty()) {
+ FrameUtil.convertFrame(next.getParent(), symbolMap.asMap().keySet().iterator().next().getGroupSymbol(), null, symbolMap.asMap(), metadata);
+ }
PlanNode parent = next.getParent();
while (parent.getParent() != null && parent.getParent().getType() != NodeConstants.Types.SOURCE) {
parent = parent.getParent();
@@ -258,6 +269,15 @@
}
}
+ public static Set<WindowFunction> getWindowFunctions(
+ List<SingleElementSymbol> projectCols) {
+ LinkedHashSet<WindowFunction> windowFunctions = new LinkedHashSet<WindowFunction>();
+ for (SingleElementSymbol singleElementSymbol : projectCols) {
+ AggregateSymbolCollectorVisitor.getAggregates(singleElementSymbol, null, null, null, windowFunctions, null);
+ }
+ return windowFunctions;
+ }
+
private List<SingleElementSymbol> filterElements(Collection<? extends SingleElementSymbol> requiredInput, Set<GroupSymbol> filterGroups) {
List<SingleElementSymbol> filteredElements = new ArrayList<SingleElementSymbol>();
for (SingleElementSymbol element : requiredInput) {
@@ -504,16 +524,18 @@
ElementCollectorVisitor.getElements(expression, requiredSymbols);
}
}
- boolean hasAggregate = false;
SymbolMap symbolMap = (SymbolMap) node.getProperty(NodeConstants.Info.SYMBOL_MAP);
+ Set<ElementSymbol> usedAggregates = new HashSet<ElementSymbol>();
// Take credit for creating any aggregates that are needed above
for (SingleElementSymbol outputSymbol : outputCols) {
+ if (!(outputSymbol instanceof ElementSymbol)) {
+ continue;
+ }
createdSymbols.add(outputSymbol);
Expression ex = symbolMap.getMappedExpression((ElementSymbol) outputSymbol);
if(ex instanceof AggregateSymbol) {
AggregateSymbol agg = (AggregateSymbol)ex;
- hasAggregate = true;
Expression aggExpr = agg.getExpression();
if(aggExpr != null) {
ElementCollectorVisitor.getElements(aggExpr, requiredSymbols);
@@ -526,9 +548,16 @@
if(condition != null) {
ElementCollectorVisitor.getElements(condition, requiredSymbols);
}
+ usedAggregates.add((ElementSymbol) outputSymbol);
}
}
- if (requiredSymbols.isEmpty() && !hasAggregate) {
+ //update the aggs in the symbolmap
+ for (Map.Entry<ElementSymbol, Expression> entry : new ArrayList<Map.Entry<ElementSymbol, Expression>>(symbolMap.asMap().entrySet())) {
+ if (entry.getValue() instanceof AggregateSymbol && !usedAggregates.contains(entry.getKey())) {
+ symbolMap.asUpdatableMap().remove(entry.getKey());
+ }
+ }
+ if (requiredSymbols.isEmpty() && usedAggregates.isEmpty()) {
node.setProperty(Info.IS_OPTIONAL, true);
}
break;
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -89,7 +89,8 @@
} else {
root = checkForProjectOptimization(node, root, metadata, capFinder, record);
}
- List<SingleElementSymbol> orderColumns = ((OrderBy)node.getProperty(NodeConstants.Info.SORT_ORDER)).getSortKeys();
+ OrderBy orderBy = (OrderBy)node.getProperty(NodeConstants.Info.SORT_ORDER);
+ List<SingleElementSymbol> orderColumns = orderBy.getSortKeys();
List<Expression> sortExpressions = new ArrayList<Expression>(orderColumns.size());
PlanNode possibleSort = NodeEditor.findNodePreOrder(node, NodeConstants.Types.GROUP, NodeConstants.Types.SOURCE | NodeConstants.Types.ACCESS);
if (possibleSort != null) {
@@ -118,6 +119,7 @@
NodeEditor.removeChildNode(node.getParent(), node);
node = nextNode;
}
+ possibleSort.setProperty(Info.SORT_ORDER, orderBy);
}
break;
}
@@ -132,8 +134,33 @@
if (!node.hasCollectionProperty(NodeConstants.Info.GROUP_COLS)) {
break;
}
- if (mergeSortWithDupRemovalAcrossSource(node)) {
+ SymbolMap map = (SymbolMap)node.getProperty(Info.SYMBOL_MAP);
+ boolean cardinalityDependent = false;
+ boolean canOptimize = true;
+ for (Expression ex : map.asMap().values()) {
+ if (ex instanceof AggregateSymbol) {
+ AggregateSymbol agg = (AggregateSymbol)ex;
+ if (agg.isCardinalityDependent()) {
+ cardinalityDependent = true;
+ break;
+ }
+ } else if (!(ex instanceof ElementSymbol)) {
+ //there is an expression in the grouping columns
+ canOptimize = false;
+ break;
+ }
+ }
+ if (canOptimize && mergeSortWithDupRemovalAcrossSource(node)) {
node.setProperty(NodeConstants.Info.IS_DUP_REMOVAL, true);
+ if (cardinalityDependent) {
+ PlanNode source = NodeEditor.findNodePreOrder(node, NodeConstants.Types.SOURCE);
+ List<SingleElementSymbol> sourceOutput = (List<SingleElementSymbol>)source.getProperty(Info.OUTPUT_COLS);
+ PlanNode child = node.getFirstChild();
+ while (child != source) {
+ child.setProperty(Info.OUTPUT_COLS, sourceOutput);
+ child = child.getFirstChild();
+ }
+ }
}
//TODO: check the join interesting order
parentBlocking = true;
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushLimit.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushLimit.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushLimit.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -51,6 +51,7 @@
import org.teiid.query.sql.symbol.Constant;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.Function;
+import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.symbol.SearchedCaseExpression;
import org.teiid.query.sql.visitor.EvaluatableVisitor;
import org.teiid.query.util.CommandContext;
@@ -168,6 +169,13 @@
}
case NodeConstants.Types.SOURCE:
{
+ GroupSymbol virtualGroup = child.getGroups().iterator().next();
+ if (virtualGroup.isProcedure()) {
+ return false;
+ }
+ if (FrameUtil.isProcedure(child.getFirstChild())) {
+ return false;
+ }
return true;
}
default:
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -44,6 +44,7 @@
import org.teiid.query.optimizer.relational.plantree.NodeEditor;
import org.teiid.query.optimizer.relational.plantree.NodeFactory;
import org.teiid.query.optimizer.relational.plantree.PlanNode;
+import org.teiid.query.optimizer.relational.plantree.NodeConstants.Info;
import org.teiid.query.sql.lang.CompareCriteria;
import org.teiid.query.sql.lang.Criteria;
import org.teiid.query.sql.lang.JoinType;
@@ -133,6 +134,12 @@
if (FrameUtil.isProcedure(parentNode)) {
return null;
}
+
+ PlanNode orderBy = NodeEditor.findParent(parentNode, NodeConstants.Types.SORT, NodeConstants.Types.SOURCE);
+ if (orderBy != null && orderBy.hasBooleanProperty(Info.UNRELATED_SORT) && !canRaiseOverSort(accessNode, metadata, capFinder, orderBy, record, false)) {
+ //this project node logically has the responsibility of creating the sort keys
+ return null;
+ }
return performRaise(rootNode, accessNode, parentNode);
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/BatchCollector.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/BatchCollector.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/processor/BatchCollector.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -78,7 +78,7 @@
}
@Override
- public List<?> nextTuple() throws TeiidComponentException,
+ public List<Object> nextTuple() throws TeiidComponentException,
TeiidProcessingException {
while (true) {
if(sourceBatch == null) {
@@ -104,7 +104,7 @@
}
@SuppressWarnings("unused")
- protected List updateTuple(List tuple) throws ExpressionEvaluationException, BlockedException, TeiidComponentException {
+ protected List<?> updateTuple(List<?> tuple) throws ExpressionEvaluationException, BlockedException, TeiidComponentException {
return tuple;
}
@@ -150,7 +150,9 @@
// Check for termination condition
if(batch.getTerminationFlag()) {
done = true;
- buffer.close();
+ if (!this.sourceNode.hasFinalBuffer()) {
+ buffer.close();
+ }
break;
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -26,7 +26,6 @@
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
@@ -41,6 +40,7 @@
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
import org.teiid.language.SQLConstants.NonReserved;
+import org.teiid.language.SortSpecification.NullOrdering;
import org.teiid.query.eval.Evaluator;
import org.teiid.query.function.aggregate.AggregateFunction;
import org.teiid.query.function.aggregate.ArrayAgg;
@@ -55,12 +55,14 @@
import org.teiid.query.function.aggregate.XMLAgg;
import org.teiid.query.processor.BatchCollector;
import org.teiid.query.processor.ProcessorDataManager;
+import org.teiid.query.processor.BatchCollector.BatchProducer;
import org.teiid.query.processor.relational.SortUtility.Mode;
import org.teiid.query.sql.lang.OrderBy;
import org.teiid.query.sql.lang.OrderByItem;
import org.teiid.query.sql.symbol.AggregateSymbol;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.sql.symbol.TextLine;
import org.teiid.query.sql.symbol.AggregateSymbol.Type;
import org.teiid.query.sql.util.SymbolMap;
@@ -69,9 +71,34 @@
public class GroupingNode extends RelationalNode {
- // Grouping columns set by the planner
- private List<Expression> sortElements;
- private List<Boolean> sortTypes;
+ static class ProjectingTupleSource extends
+ BatchCollector.BatchProducerTupleSource {
+
+ private Evaluator eval;
+ private List<Expression> collectedExpressions;
+
+ ProjectingTupleSource(BatchProducer sourceNode, Evaluator eval, List<Expression> expressions) {
+ super(sourceNode);
+ this.eval = eval;
+ this.collectedExpressions = expressions;
+ }
+
+ @Override
+ protected List<Object> updateTuple(List<?> tuple) throws ExpressionEvaluationException, BlockedException, TeiidComponentException {
+ int columns = collectedExpressions.size();
+ List<Object> exprTuple = new ArrayList<Object>(columns);
+ for(int col = 0; col<columns; col++) {
+ // The following call may throw BlockedException, but all state to this point
+ // is saved in class variables so we can start over on building this tuple
+ Object value = eval.evaluate(collectedExpressions.get(col), tuple);
+ exprTuple.add(value);
+ }
+ return exprTuple;
+ }
+ }
+
+ // Grouping columns set by the planner
+ private List<OrderByItem> orderBy;
private boolean removeDuplicates;
private SymbolMap outputMapping;
@@ -79,6 +106,7 @@
private int phase = COLLECTION;
private Map elementMap; // Map of incoming symbol to index in source elements
private List<Expression> collectedExpressions; // Collected Expressions
+ private int distinctCols = -1;
// Sort phase
private SortUtility sortUtility;
@@ -87,14 +115,14 @@
// Group phase
private AggregateFunction[] functions;
- private int[] conditions;
- private List lastRow;
- private List currentGroupTuple;
+ private List<?> lastRow;
+ private List<?> currentGroupTuple;
private Evaluator eval;
private static final int COLLECTION = 1;
private static final int SORT = 2;
private static final int GROUP = 3;
+ private int[] indexes;
public GroupingNode(int nodeID) {
super(nodeID);
@@ -122,19 +150,9 @@
this.removeDuplicates = removeDuplicates;
}
- /**
- * Called by the planner to initialize the grouping node. Set the list of grouping
- * expressions - these may be either elements or expressions and the list itself may
- * be null to indicate an implied grouping on all columns
- * @param groupingElements
- * @since 4.2
- */
- public void setGroupingElements(List<Expression> groupingElements) {
- this.sortElements = groupingElements;
- if(groupingElements != null) {
- sortTypes = Collections.nCopies(groupingElements.size(), Boolean.valueOf(OrderBy.ASC));
- }
- }
+ public void setOrderBy(List<OrderByItem> orderBy) {
+ this.orderBy = orderBy;
+ }
public void setOutputMapping(SymbolMap outputMapping) {
this.outputMapping = outputMapping;
@@ -150,20 +168,28 @@
}
// Incoming elements and lookup map for evaluating expressions
- List sourceElements = this.getChildren()[0].getElements();
+ List<SingleElementSymbol> sourceElements = this.getChildren()[0].getElements();
this.elementMap = createLookupMap(sourceElements);
// List should contain all grouping columns / expressions as we need those for sorting
- if(this.sortElements != null) {
- this.collectedExpressions = new ArrayList<Expression>(this.sortElements.size() + getElements().size());
- this.collectedExpressions.addAll(sortElements);
+ if(this.orderBy != null) {
+ this.collectedExpressions = new ArrayList<Expression>(this.orderBy.size() + getElements().size());
+ for (OrderByItem item : this.orderBy) {
+ Expression ex = SymbolMap.getExpression(item.getSymbol());
+ this.collectedExpressions.add(ex);
+ }
+ if (removeDuplicates) {
+ for (SingleElementSymbol ses : sourceElements) {
+ collectExpression(SymbolMap.getExpression(ses));
+ }
+ distinctCols = collectedExpressions.size();
+ }
} else {
this.collectedExpressions = new ArrayList<Expression>(getElements().size());
}
// Construct aggregate function state accumulators
functions = new AggregateFunction[getElements().size()];
- conditions = new int[getElements().size()];
for(int i=0; i<getElements().size(); i++) {
Expression symbol = (Expression) getElements().get(i);
if (this.outputMapping != null) {
@@ -171,12 +197,8 @@
}
Class<?> outputType = symbol.getType();
Class<?> inputType = symbol.getType();
- conditions[i] = -1;
if(symbol instanceof AggregateSymbol) {
AggregateSymbol aggSymbol = (AggregateSymbol) symbol;
- if (aggSymbol.getCondition() != null) {
- conditions[i] = collectExpression(aggSymbol.getCondition());
- }
if(aggSymbol.getExpression() == null) {
functions[i] = new Count();
} else {
@@ -244,6 +266,9 @@
}
functions[i].setExpressionIndex(index);
}
+ if (aggSymbol.getCondition() != null) {
+ functions[i].setConditionIndex(collectExpression(aggSymbol.getCondition()));
+ }
} else {
functions[i] = new ConstantFunction();
functions[i].setExpressionIndex(this.collectedExpressions.indexOf(symbol));
@@ -288,42 +313,39 @@
}
public TupleSource getCollectionTupleSource() {
-
final RelationalNode sourceNode = this.getChildren()[0];
-
- return new BatchCollector.BatchProducerTupleSource(sourceNode) {
-
- @Override
- protected List updateTuple(List tuple) throws ExpressionEvaluationException, BlockedException, TeiidComponentException {
- int columns = collectedExpressions.size();
- List<Object> exprTuple = new ArrayList<Object>(columns);
- for(int col = 0; col<columns; col++) {
- // The following call may throw BlockedException, but all state to this point
- // is saved in class variables so we can start over on building this tuple
- Object value = eval.evaluate(collectedExpressions.get(col), tuple);
- exprTuple.add(value);
- }
- return exprTuple;
- }
- };
-
+ return new ProjectingTupleSource(sourceNode, eval, collectedExpressions);
}
private void collectionPhase() {
eval = new Evaluator(elementMap, getDataManager(), getContext());
- if(this.sortElements == null) {
+ if(this.orderBy == null) {
// No need to sort
this.groupTupleSource = getCollectionTupleSource();
this.phase = GROUP;
} else {
- //create a temporary positional schema
- List<ElementSymbol> schema = new ArrayList<ElementSymbol>();
- for (int i = 0; i < collectedExpressions.size(); i++) {
- schema.add(new ElementSymbol(String.valueOf(i)));
+ List<NullOrdering> nullOrdering = new ArrayList<NullOrdering>(orderBy.size());
+ List<Boolean> sortTypes = new ArrayList<Boolean>(orderBy.size());
+ int size = orderBy.size();
+ if (this.removeDuplicates) {
+ //sort on all inputs
+ size = distinctCols;
}
- this.sortUtility = new SortUtility(getCollectionTupleSource(), schema.subList(0, sortElements.size()),
- sortTypes, removeDuplicates?Mode.DUP_REMOVE_SORT:Mode.SORT, getBufferManager(),
- getConnectionID(), schema);
+ int[] sortIndexes = new int[size];
+ for (int i = 0; i < size; i++) {
+ if (i < this.orderBy.size()) {
+ OrderByItem item = this.orderBy.get(i);
+ nullOrdering.add(item.getNullOrdering());
+ sortTypes.add(item.isAscending());
+ } else {
+ nullOrdering.add(null);
+ sortTypes.add(OrderBy.ASC);
+ }
+ sortIndexes[i] = i;
+ }
+ this.indexes = Arrays.copyOf(sortIndexes, orderBy.size());
+ this.sortUtility = new SortUtility(getCollectionTupleSource(), removeDuplicates?Mode.DUP_REMOVE_SORT:Mode.SORT, getBufferManager(),
+ getConnectionID(), collectedExpressions, sortTypes, nullOrdering, sortIndexes);
this.phase = SORT;
}
}
@@ -349,7 +371,7 @@
// First row we've seen
lastRow = currentGroupTuple;
- } else if(! sameGroup(currentGroupTuple, lastRow)) {
+ } else if(! sameGroup(indexes, currentGroupTuple, lastRow)) {
// Close old group
List<Object> row = new ArrayList<Object>(functions.length);
for(int i=0; i<functions.length; i++) {
@@ -371,7 +393,7 @@
updateAggregates(currentGroupTuple);
currentGroupTuple = null;
}
- if(lastRow != null || sortElements == null) {
+ if(lastRow != null || orderBy == null) {
// Close last group
List<Object> row = new ArrayList<Object>(functions.length);
for(int i=0; i<functions.length; i++) {
@@ -385,17 +407,14 @@
return pullBatch();
}
- private boolean sameGroup(List newTuple, List oldTuple) {
- // Check for no grouping columns
- if(sortElements == null) {
- return true;
- }
+ public static boolean sameGroup(int[] indexes, List<?> newTuple, List<?> oldTuple) {
+ if (indexes == null) {
+ return true;
+ }
+ for(int i=indexes.length-1; i>=0; i--) {
+ Object oldValue = oldTuple.get(indexes[i]);
+ Object newValue = newTuple.get(indexes[i]);
- // Walk backwards through sort cols as the last columns are most likely to be different
- for(int i=sortElements.size()-1; i>=0; i--) {
- Object oldValue = oldTuple.get(i);
- Object newValue = newTuple.get(i);
-
if(oldValue == null) {
if(newValue != null) {
return false;
@@ -417,9 +436,6 @@
throws TeiidComponentException, TeiidProcessingException {
for(int i=0; i<functions.length; i++) {
- if (conditions[i] != -1 && !Boolean.TRUE.equals(tuple.get(conditions[i]))) {
- continue;
- }
functions[i].addInput(tuple);
}
}
@@ -433,7 +449,7 @@
protected void getNodeString(StringBuffer str) {
super.getNodeString(str);
- str.append(sortElements);
+ str.append(orderBy);
if (outputMapping != null) {
str.append(outputMapping);
}
@@ -442,10 +458,9 @@
public Object clone(){
GroupingNode clonedNode = new GroupingNode(super.getID());
super.copy(this, clonedNode);
- clonedNode.sortElements = sortElements;
- clonedNode.sortTypes = sortTypes;
clonedNode.removeDuplicates = removeDuplicates;
clonedNode.outputMapping = outputMapping;
+ clonedNode.orderBy = orderBy;
return clonedNode;
}
@@ -453,15 +468,14 @@
// Default implementation - should be overridden
PlanNode props = super.getDescriptionProperties();
- if(sortElements != null) {
- int elements = sortElements.size();
+ if(orderBy != null) {
+ int elements = orderBy.size();
List<String> groupCols = new ArrayList<String>(elements);
for(int i=0; i<elements; i++) {
- groupCols.add(this.sortElements.get(i).toString());
+ groupCols.add(this.orderBy.get(i).toString());
}
props.addProperty(PROP_GROUP_COLS, groupCols);
}
-
props.addProperty(PROP_SORT_MODE, String.valueOf(this.removeDuplicates));
return props;
Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/ProjectNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/ProjectNode.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/ProjectNode.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -22,7 +22,7 @@
package org.teiid.query.processor.relational;
-import static org.teiid.query.analysis.AnalysisRecord.PROP_SELECT_COLS;
+import static org.teiid.query.analysis.AnalysisRecord.*;
import java.util.ArrayList;
import java.util.Arrays;
@@ -37,26 +37,24 @@
import org.teiid.common.buffer.TupleBatch;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
-import org.teiid.core.util.Assertion;
-import org.teiid.query.QueryPlugin;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.processor.ProcessorDataManager;
-import org.teiid.query.sql.symbol.AggregateSymbol;
import org.teiid.query.sql.symbol.AliasSymbol;
-import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
-import org.teiid.query.sql.symbol.ExpressionSymbol;
-import org.teiid.query.sql.symbol.SelectSymbol;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
+import org.teiid.query.sql.util.SymbolMap;
import org.teiid.query.util.CommandContext;
public class ProjectNode extends SubqueryAwareRelationalNode {
- private List selectSymbols;
+ private List<? extends SingleElementSymbol> selectSymbols;
// Derived element lookup map
private Map elementMap;
private boolean needsProject = true;
+ private List<Expression> expressions;
+ private int[] projectionIndexes;
// Saved state when blocked on evaluating a row - must be reset
private TupleBatch currentBatch;
@@ -81,11 +79,11 @@
* return List of select symbols
* @return List of select symbols
*/
- public List getSelectSymbols() {
+ public List<? extends SingleElementSymbol> getSelectSymbols() {
return this.selectSymbols;
}
- public void setSelectSymbols(List symbols) {
+ public void setSelectSymbols(List<? extends SingleElementSymbol> symbols) {
this.selectSymbols = symbols;
}
@@ -95,56 +93,51 @@
super.initialize(context, bufferManager, dataMgr);
// Do this lazily as the node may be reset and re-used and this info doesn't change
- if(elementMap == null) {
- //in the case of select with no from, there is no child node
- //simply return at this point
- if(this.getChildren()[0] == null){
- elementMap = new HashMap();
- return;
- }
+ if(elementMap != null) {
+ return;
+ }
+ this.projectionIndexes = new int[this.selectSymbols.size()];
+ Arrays.fill(this.projectionIndexes, -1);
+
+ this.expressions = new ArrayList<Expression>(this.selectSymbols.size());
+ for (SingleElementSymbol ses : this.selectSymbols) {
+ this.expressions.add(SymbolMap.getExpression(ses));
+ }
+ //in the case of select with no from, there is no child node
+ //simply return at this point
+ if(this.getChildren()[0] == null){
+ elementMap = new HashMap();
+ return;
+ }
- // Create element lookup map for evaluating project expressions
- List childElements = this.getChildren()[0].getElements();
- this.elementMap = createLookupMap(childElements);
+ // Create element lookup map for evaluating project expressions
+ List childElements = this.getChildren()[0].getElements();
+ this.elementMap = createLookupMap(childElements);
- // Check whether project needed at all - this occurs if:
- // 1. outputMap == null (see previous block)
- // 2. project elements are either elements or aggregate symbols (no processing required)
- // 3. order of input values == order of output values
- if(childElements.size() > 0) {
- // Start by assuming project is not needed
- needsProject = false;
-
- if(childElements.size() != getElements().size()) {
- needsProject = true;
- } else {
- for(int i=0; i<selectSymbols.size(); i++) {
- SelectSymbol symbol = (SelectSymbol) selectSymbols.get(i);
-
- if(symbol instanceof AliasSymbol) {
- Integer index = (Integer) elementMap.get(symbol);
- if(index != null && index.intValue() == i) {
- continue;
- }
- symbol = ((AliasSymbol)symbol).getSymbol();
- }
-
- if(symbol instanceof ElementSymbol || symbol instanceof AggregateSymbol) {
- Integer index = (Integer) elementMap.get(symbol);
- if(index == null || index.intValue() != i) {
- // input / output element order is not the same
- needsProject = true;
- break;
- }
-
- } else {
- // project element is either a constant or a function
- needsProject = true;
- break;
- }
- }
+ // Check whether project needed at all - this occurs if:
+ // 1. outputMap == null (see previous block)
+ // 2. project elements are either elements or aggregate symbols (no processing required)
+ // 3. order of input values == order of output values
+ needsProject = childElements.size() != getElements().size();
+ for(int i=0; i<selectSymbols.size(); i++) {
+ SingleElementSymbol symbol = selectSymbols.get(i);
+
+ if(symbol instanceof AliasSymbol) {
+ Integer index = (Integer) elementMap.get(symbol);
+ if(index != null && index.intValue() == i) {
+ projectionIndexes[i] = index;
+ continue;
}
+ symbol = ((AliasSymbol)symbol).getSymbol();
}
+
+ Integer index = (Integer) elementMap.get(symbol);
+ if(index == null || index.intValue() != i) {
+ // input / output element order is not the same
+ needsProject = true;
+ } else {
+ projectionIndexes[i] = index;
+ }
}
}
@@ -171,14 +164,14 @@
}
while (currentRow <= currentBatch.getEndRow() && !isBatchFull()) {
- List tuple = currentBatch.getTuple(currentRow);
+ List<?> tuple = currentBatch.getTuple(currentRow);
- List projectedTuple = new ArrayList(selectSymbols.size());
+ List<Object> projectedTuple = new ArrayList<Object>(selectSymbols.size());
// Walk through symbols
- for(int i=0; i<selectSymbols.size(); i++) {
- SelectSymbol symbol = (SelectSymbol) selectSymbols.get(i);
- updateTuple(symbol, tuple, projectedTuple);
+ for(int i=0; i<expressions.size(); i++) {
+ Expression symbol = expressions.get(i);
+ updateTuple(symbol, i, tuple, projectedTuple);
}
// Add to batch
@@ -196,28 +189,14 @@
return pullBatch();
}
- private void updateTuple(SelectSymbol symbol, List values, List tuple)
+ private void updateTuple(Expression symbol, int projectionIndex, List<?> values, List<Object> tuple)
throws BlockedException, TeiidComponentException, ExpressionEvaluationException {
- if (symbol instanceof AliasSymbol) {
- // First check AliasSymbol itself
- Integer index = (Integer) elementMap.get(symbol);
- if(index != null) {
- tuple.add(values.get(index.intValue()));
- return;
- }
- // Didn't find it, so try aliased symbol below
- symbol = ((AliasSymbol)symbol).getSymbol();
- }
-
- Integer index = (Integer) elementMap.get(symbol);
- if(index != null) {
- tuple.add(values.get(index.intValue()));
- } else if(symbol instanceof ExpressionSymbol) {
- Expression expression = ((ExpressionSymbol)symbol).getExpression();
- tuple.add(getEvaluator(this.elementMap).evaluate(expression, values));
- } else {
- Assertion.failed(QueryPlugin.Util.getString("ERR.015.006.0034", symbol.getClass().getName())); //$NON-NLS-1$
+ int index = this.projectionIndexes[projectionIndex];
+ if(index != -1) {
+ tuple.add(values.get(index));
+ } else {
+ tuple.add(getEvaluator(this.elementMap).evaluate(symbol, values));
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/SortUtility.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/SortUtility.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/SortUtility.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -109,19 +109,12 @@
private Collection<List<?>> workingTuples;
public SortUtility(TupleSource sourceID, List<OrderByItem> items, Mode mode, BufferManager bufferMgr,
- String groupName, List schema) {
- this.source = sourceID;
- this.mode = mode;
- this.bufferManager = bufferMgr;
- this.groupName = groupName;
- this.schema = schema;
- this.schemaSize = bufferManager.getSchemaSize(this.schema);
- int distinctIndex = items != null? items.size() - 1:0;
+ String groupName, List<? extends Expression> schema) {
List<Expression> sortElements = null;
List<Boolean> sortTypes = null;
List<NullOrdering> nullOrderings = null;
if (items == null) {
- sortElements = (List<Expression>) this.schema;
+ sortElements = (List<Expression>) schema;
sortTypes = Collections.nCopies(sortElements.size(), OrderBy.ASC);
} else {
sortElements = new ArrayList(items.size());
@@ -148,7 +141,29 @@
cols[iter.previousIndex()] = schema.indexOf(elem);
Assertion.assertTrue(cols[iter.previousIndex()] != -1);
}
+ init(sourceID, mode, bufferMgr, groupName, schema, sortTypes,
+ nullOrderings, cols);
+ }
+
+ public SortUtility(TupleSource sourceID, Mode mode, BufferManager bufferMgr,
+ String groupName, List<? extends Expression> schema,
+ List<Boolean> sortTypes, List<NullOrdering> nullOrderings,
+ int[] cols) {
+ init(sourceID, mode, bufferMgr, groupName, schema, sortTypes, nullOrderings, cols);
+ }
+
+ private void init(TupleSource sourceID, Mode mode, BufferManager bufferMgr,
+ String groupName, List<? extends Expression> schema,
+ List<Boolean> sortTypes, List<NullOrdering> nullOrderings,
+ int[] cols) {
+ this.source = sourceID;
+ this.mode = mode;
+ this.bufferManager = bufferMgr;
+ this.groupName = groupName;
+ this.schema = schema;
+ this.schemaSize = bufferManager.getSchemaSize(this.schema);
this.comparator = new ListNestedSortComparator(cols, sortTypes);
+ int distinctIndex = cols.length - 1;
this.comparator.setDistinctIndex(distinctIndex);
this.comparator.setNullOrdering(nullOrderings);
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/SortingFilter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/SortingFilter.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/SortingFilter.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -158,4 +158,9 @@
// Return
return this.proxy.getResult();
}
+
+ @Override
+ public boolean respectsNull() {
+ return this.proxy.respectsNull();
+ }
}
Added: trunk/engine/src/main/java/org/teiid/query/processor/relational/WindowFunctionProjectNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/WindowFunctionProjectNode.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/WindowFunctionProjectNode.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -0,0 +1,497 @@
+/*
+ * 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 org.teiid.query.processor.relational;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.teiid.api.exception.query.ExpressionEvaluationException;
+import org.teiid.api.exception.query.FunctionExecutionException;
+import org.teiid.common.buffer.BlockedException;
+import org.teiid.common.buffer.BufferManager;
+import org.teiid.common.buffer.IndexedTupleSource;
+import org.teiid.common.buffer.STree;
+import org.teiid.common.buffer.TupleBatch;
+import org.teiid.common.buffer.TupleBuffer;
+import org.teiid.common.buffer.TupleSource;
+import org.teiid.common.buffer.BufferManager.TupleSourceType;
+import org.teiid.common.buffer.STree.InsertMode;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.language.SortSpecification.NullOrdering;
+import org.teiid.query.eval.Evaluator;
+import org.teiid.query.function.aggregate.AggregateFunction;
+import org.teiid.query.function.aggregate.ArrayAgg;
+import org.teiid.query.function.aggregate.Avg;
+import org.teiid.query.function.aggregate.Count;
+import org.teiid.query.function.aggregate.Max;
+import org.teiid.query.function.aggregate.Min;
+import org.teiid.query.function.aggregate.RankingFunction;
+import org.teiid.query.function.aggregate.StatsFunction;
+import org.teiid.query.function.aggregate.Sum;
+import org.teiid.query.function.aggregate.TextAgg;
+import org.teiid.query.function.aggregate.XMLAgg;
+import org.teiid.query.processor.ProcessorDataManager;
+import org.teiid.query.processor.relational.GroupingNode.ProjectingTupleSource;
+import org.teiid.query.processor.relational.SortUtility.Mode;
+import org.teiid.query.sql.lang.OrderBy;
+import org.teiid.query.sql.lang.OrderByItem;
+import org.teiid.query.sql.symbol.AggregateSymbol;
+import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.TextLine;
+import org.teiid.query.sql.symbol.WindowFunction;
+import org.teiid.query.sql.symbol.WindowSpecification;
+import org.teiid.query.sql.symbol.AggregateSymbol.Type;
+import org.teiid.query.sql.util.SymbolMap;
+import org.teiid.query.util.CommandContext;
+
+
+public class WindowFunctionProjectNode extends SubqueryAwareRelationalNode {
+
+ private enum Phase {
+ COLLECT,
+ PROCESS,
+ OUTPUT
+ }
+
+ private static class WindowFunctionInfo {
+ WindowFunction function;
+ int expressionIndex = -1;
+ int conditionIndex = -1;
+ int outputIndex;
+ }
+
+ private static class WindowSpecificationInfo {
+ List<Integer> groupIndexes = new ArrayList<Integer>();
+ List<Integer> sortIndexes = new ArrayList<Integer>();
+ List<NullOrdering> nullOrderings = new ArrayList<NullOrdering>();
+ List<Boolean> orderType = new ArrayList<Boolean>();
+ List<WindowFunctionInfo> functions = new ArrayList<WindowFunctionInfo>();
+ }
+
+ private LinkedHashMap<WindowSpecification, WindowSpecificationInfo> windows = new LinkedHashMap<WindowSpecification, WindowSpecificationInfo>();
+ private LinkedHashMap<Expression, Integer> expressionIndexes;
+ private LinkedHashMap<Integer, Integer> passThrough = new LinkedHashMap<Integer, Integer>();
+
+ private Map elementMap;
+
+ //processing state
+ private Phase phase = Phase.COLLECT;
+ private TupleBuffer tb;
+ private TupleSource inputTs;
+ private STree[] partitionMapping;
+ private STree[] valueMapping;
+ private IndexedTupleSource outputTs;
+
+ public WindowFunctionProjectNode(int nodeId) {
+ super(nodeId);
+ }
+
+ protected WindowFunctionProjectNode() {
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ this.tb = null;
+ this.inputTs = null;
+ this.phase = Phase.COLLECT;
+ this.partitionMapping = null;
+ this.valueMapping = null;
+ this.outputTs = null;
+ }
+
+ @Override
+ public void closeDirect() {
+ if (tb != null) {
+ tb.remove();
+ tb = null;
+ }
+ if (partitionMapping != null) {
+ for (STree tree : partitionMapping) {
+ if (tree != null) {
+ tree.remove();
+ }
+ }
+ partitionMapping = null;
+ }
+ if (valueMapping != null) {
+ for (STree tree : valueMapping) {
+ tree.remove();
+ }
+ valueMapping = null;
+ }
+ }
+
+ public Object clone(){
+ WindowFunctionProjectNode clonedNode = new WindowFunctionProjectNode();
+ this.copy(this, clonedNode);
+ clonedNode.windows = windows;
+ clonedNode.expressionIndexes = expressionIndexes;
+ clonedNode.passThrough = passThrough;
+ return clonedNode;
+ }
+
+ /**
+ * This state can be determined prior to initialize and is the same for all nodes,
+ * so it is moved into it's own init routine
+ */
+ public void init() {
+ expressionIndexes = new LinkedHashMap<Expression, Integer>();
+ for (int i = 0; i < getElements().size(); i++) {
+ Expression ex = SymbolMap.getExpression((Expression) getElements().get(i));
+ if (ex instanceof WindowFunction) {
+ WindowFunction wf = (WindowFunction)ex;
+ WindowSpecification ws = wf.getWindowSpecification();
+ WindowSpecificationInfo wsi = windows.get(ws);
+ if (wsi == null) {
+ wsi = new WindowSpecificationInfo();
+ windows.put(wf.getWindowSpecification(), wsi);
+ if (ws.getPartition() != null) {
+ for (Expression ex1 : ws.getPartition()) {
+ Integer index = getIndex(ex1);
+ wsi.groupIndexes.add(index);
+ wsi.orderType.add(OrderBy.ASC);
+ wsi.nullOrderings.add(null);
+ }
+ }
+ if (ws.getOrderBy() != null) {
+ for (OrderByItem item : ws.getOrderBy().getOrderByItems()) {
+ Expression ex1 = SymbolMap.getExpression(item.getSymbol());
+ Integer index = getIndex(ex1);
+ wsi.sortIndexes.add(index);
+ wsi.orderType.add(item.isAscending());
+ wsi.nullOrderings.add(item.getNullOrdering());
+ }
+ }
+ }
+ WindowFunctionInfo wfi = new WindowFunctionInfo();
+ wfi.function = wf;
+ ex = wf.getFunction().getExpression();
+ if (ex != null) {
+ wfi.expressionIndex = getIndex(ex);
+ }
+ if (wf.getFunction().getCondition() != null) {
+ ex = wf.getFunction().getCondition();
+ wfi.conditionIndex = getIndex(ex);
+ }
+ wfi.outputIndex = i;
+ wsi.functions.add(wfi);
+ } else {
+ int index = getIndex(ex);
+ passThrough.put(i, index);
+ }
+ }
+ }
+
+ @Override
+ protected TupleBatch nextBatchDirect() throws BlockedException,
+ TeiidComponentException, TeiidProcessingException {
+
+ if (phase == Phase.COLLECT) {
+ saveInput();
+ phase = Phase.PROCESS;
+ partitionMapping = new STree[this.windows.size()];
+ valueMapping = new STree[this.windows.size()];
+ }
+
+ if (phase == Phase.PROCESS) {
+ buildResults();
+ phase = Phase.OUTPUT;
+ }
+
+ if (phase == Phase.OUTPUT) {
+ if (outputTs == null) {
+ outputTs = tb.createIndexedTupleSource(true);
+ }
+ while (outputTs.hasNext()) {
+ List<?> tuple = outputTs.nextTuple();
+ int rowId = (Integer)tuple.get(tuple.size() - 1);
+ int size = getElements().size();
+ ArrayList<Object> outputRow = new ArrayList<Object>(size);
+ for (int i = 0; i < size; i++) {
+ outputRow.add(null);
+ }
+ for (Map.Entry<Integer, Integer> entry : passThrough.entrySet()) {
+ outputRow.set(entry.getKey(), tuple.get(entry.getValue()));
+ }
+ List<Map.Entry<WindowSpecification, WindowSpecificationInfo>> specs = new ArrayList<Map.Entry<WindowSpecification,WindowSpecificationInfo>>(windows.entrySet());
+ for (int specIndex = 0; specIndex < specs.size(); specIndex++) {
+ Map.Entry<WindowSpecification, WindowSpecificationInfo> entry = specs.get(specIndex);
+ List<?> idRow = Arrays.asList(rowId);
+ if (partitionMapping[specIndex] != null) {
+ idRow = partitionMapping[specIndex].find(idRow);
+ idRow = idRow.subList(1, 2);
+ }
+ List<?> valueRow = valueMapping[specIndex].find(idRow);
+ List<WindowFunctionInfo> functions = entry.getValue().functions;
+ for (int i = 0; i < functions.size(); i++) {
+ WindowFunctionInfo wfi = functions.get(i);
+ outputRow.set(wfi.outputIndex, valueRow.get(i+1));
+ }
+ }
+ this.addBatchRow(outputRow);
+ if (this.isBatchFull()) {
+ return pullBatch();
+ }
+ }
+ terminateBatches();
+ }
+ return this.pullBatch();
+ }
+
+ /**
+ * Build the results by maintaining indexes that either map
+ * rowid->values
+ * or
+ * rowid->partitionid and partitionid->values
+ *
+ * TODO use the size hint for tree balancing
+ */
+ private void buildResults() throws TeiidComponentException,
+ TeiidProcessingException, FunctionExecutionException,
+ ExpressionEvaluationException {
+ List<Map.Entry<WindowSpecification, WindowSpecificationInfo>> specs = new ArrayList<Map.Entry<WindowSpecification,WindowSpecificationInfo>>(windows.entrySet());
+ for (int specIndex = 0; specIndex < specs.size(); specIndex++) {
+ Map.Entry<WindowSpecification, WindowSpecificationInfo> entry = specs.get(specIndex);
+ WindowSpecificationInfo info = entry.getValue();
+ IndexedTupleSource specificationTs = tb.createIndexedTupleSource();
+ int[] groupingIndexes = null;
+ int[] orderIndexes = null;
+
+ //if there is partitioning or ordering, then sort
+ if (!info.orderType.isEmpty()) {
+ int[] sortKeys = new int[info.orderType.size()];
+ int i = 0;
+ if (!info.groupIndexes.isEmpty()) {
+ for (Integer sortIndex : info.groupIndexes) {
+ sortKeys[i++] = sortIndex;
+ }
+ groupingIndexes = Arrays.copyOf(sortKeys, info.groupIndexes.size());
+ ElementSymbol key = new ElementSymbol("rowid"); //$NON-NLS-1$
+ key.setType(DataTypeManager.DefaultDataClasses.INTEGER);
+ ElementSymbol value = new ElementSymbol("partitionid"); //$NON-NLS-1$
+ key.setType(DataTypeManager.DefaultDataClasses.INTEGER);
+ List<ElementSymbol> elements = Arrays.asList(key, value);
+ partitionMapping[specIndex] = this.getBufferManager().createSTree(elements, this.getConnectionID(), 1);
+ }
+ if (!info.sortIndexes.isEmpty()) {
+ for (Integer sortIndex : info.sortIndexes) {
+ sortKeys[i++] = sortIndex;
+ }
+ orderIndexes = Arrays.copyOfRange(sortKeys, info.groupIndexes.size(), info.groupIndexes.size() + info.sortIndexes.size());
+ }
+ SortUtility su = new SortUtility(specificationTs, Mode.SORT, this.getBufferManager(), this.getConnectionID(), tb.getSchema(), info.orderType, info.nullOrderings, sortKeys);
+ TupleBuffer sorted = su.sort();
+ specificationTs = sorted.createIndexedTupleSource(true);
+ }
+ List<AggregateFunction> aggs = initializeAccumulators(info, specIndex, orderIndexes);
+
+ int partitionId = 0;
+ List<?> lastRow = null;
+ while (specificationTs.hasNext()) {
+ List<?> tuple = specificationTs.nextTuple();
+ boolean sameGroup = true;
+ if (lastRow != null) {
+ sameGroup = GroupingNode.sameGroup(groupingIndexes, tuple, lastRow);
+ if (!sameGroup || orderIndexes != null) {
+ saveValues(specIndex, orderIndexes, aggs, partitionId, lastRow, sameGroup);
+ }
+ }
+ if (orderIndexes == null) {
+ if (!sameGroup) {
+ partitionId++;
+ }
+ List<Object> partitionTuple = Arrays.asList(tuple.get(tuple.size() - 1), partitionId);
+ partitionMapping[specIndex].insert(partitionTuple, InsertMode.NEW, -1);
+ }
+ for (AggregateFunction function : aggs) {
+ function.addInput(tuple);
+ }
+ lastRow = tuple;
+ }
+ if(lastRow != null) {
+ saveValues(specIndex, orderIndexes, aggs, partitionId, lastRow, true);
+ }
+ }
+ }
+
+ private void saveValues(int specIndex, int[] orderIndexes,
+ List<AggregateFunction> aggs, int partitionId, List<?> tuple,
+ boolean sameGroup) throws FunctionExecutionException,
+ ExpressionEvaluationException, TeiidComponentException,
+ TeiidProcessingException {
+ List<Object> row = new ArrayList<Object>(aggs.size() + 1);
+ if (orderIndexes == null) {
+ row.add(partitionId);
+ } else {
+ //use the rowid
+ row.add(tuple.get(tuple.size() - 1));
+ }
+ for (AggregateFunction function : aggs) {
+ row.add(function.getResult());
+ if (!sameGroup) {
+ function.reset();
+ }
+ }
+ valueMapping[specIndex].insert(row, orderIndexes != null?InsertMode.NEW:InsertMode.ORDERED, -1);
+ }
+
+ private List<AggregateFunction> initializeAccumulators(WindowSpecificationInfo info, int specIndex,
+ int[] orderIndexes) {
+ List<AggregateFunction> aggs = new ArrayList<AggregateFunction>();
+ //initialize the function accumulators
+ List<ElementSymbol> elements = new ArrayList<ElementSymbol>(info.functions.size() + 1);
+ ElementSymbol key = new ElementSymbol("id"); //$NON-NLS-1$
+ key.setType(DataTypeManager.DefaultDataClasses.INTEGER);
+ elements.add(key);
+
+ CommandContext context = this.getContext();
+ for (WindowFunctionInfo wfi : info.functions) {
+ AggregateSymbol aggSymbol = wfi.function.getFunction();
+ Class<?> outputType = aggSymbol.getType();
+ ElementSymbol value = new ElementSymbol("val"); //$NON-NLS-1$
+ value.setType(outputType);
+ elements.add(value);
+ Class<?> inputType = aggSymbol.getType();
+ if (aggSymbol.getExpression() != null) {
+ inputType = aggSymbol.getExpression().getType();
+ }
+ Type function = aggSymbol.getAggregateFunction();
+ AggregateFunction af = null;
+ switch (function) {
+ case RANK:
+ case DENSE_RANK:
+ af = new RankingFunction(function, orderIndexes);
+ break;
+ case ROW_NUMBER: //same as count(*)
+ case COUNT:
+ af = new Count();
+ break;
+ case SUM:
+ af = new Sum();
+ break;
+ case AVG:
+ af = new Avg();
+ break;
+ case MIN:
+ af = new Min();
+ break;
+ case MAX:
+ af = new Max();
+ break;
+ case XMLAGG:
+ af = new XMLAgg(context);
+ break;
+ case ARRAY_AGG:
+ af = new ArrayAgg(context);
+ break;
+ case TEXTAGG:
+ af = new TextAgg(context, (TextLine)aggSymbol.getExpression());
+ break;
+ default:
+ af = new StatsFunction(function);
+ }
+
+ af.setExpressionIndex(wfi.expressionIndex);
+ af.setConditionIndex(wfi.conditionIndex);
+ af.initialize(outputType, inputType);
+ aggs.add(af);
+ }
+
+ valueMapping[specIndex] = this.getBufferManager().createSTree(elements, this.getConnectionID(), 1);
+
+ return aggs;
+ }
+
+ /**
+ * Save the input generating any necessary expressions and adding a row id
+ * @param collectedExpressions
+ * @return
+ * @throws TeiidComponentException
+ * @throws TeiidProcessingException
+ */
+ private void saveInput()
+ throws TeiidComponentException, TeiidProcessingException {
+ if (inputTs == null) {
+ List<Expression> collectedExpressions = new ArrayList<Expression>(expressionIndexes.keySet());
+ Evaluator eval = new Evaluator(elementMap, getDataManager(), getContext());
+ final RelationalNode sourceNode = this.getChildren()[0];
+ inputTs = new ProjectingTupleSource(sourceNode, eval, collectedExpressions) {
+ int index = 0;
+ @Override
+ public List<Object> nextTuple() throws TeiidComponentException,
+ TeiidProcessingException {
+ List<Object> tuple = super.nextTuple();
+ if (tuple != null) {
+ tuple.add(index++);
+ }
+ return tuple;
+ }
+ };
+ List<ElementSymbol> schema = new ArrayList<ElementSymbol>(collectedExpressions.size() + 1);
+ int index = 0;
+ for (Expression ex : collectedExpressions) {
+ ElementSymbol es = new ElementSymbol(String.valueOf(index++));
+ es.setType(ex.getType());
+ schema.add(es);
+ }
+ //add in the row id
+ ElementSymbol es = new ElementSymbol(String.valueOf(index++));
+ es.setType(DataTypeManager.DefaultDataClasses.INTEGER);
+ schema.add(es);
+ tb = this.getBufferManager().createTupleBuffer(schema, this.getConnectionID(), TupleSourceType.PROCESSOR);
+ }
+
+ List<?> tuple = null;
+ while ((tuple = inputTs.nextTuple()) != null) {
+ tb.addTuple(tuple);
+ }
+ tb.close();
+ inputTs.closeSource();
+ inputTs = null;
+ }
+
+ private Integer getIndex(Expression ex) {
+ Integer index = expressionIndexes.get(ex);
+ if (index == null) {
+ index = expressionIndexes.size();
+ expressionIndexes.put(ex, index);
+ }
+ return index;
+ }
+
+ @Override
+ public void initialize(CommandContext context, BufferManager bufferManager,
+ ProcessorDataManager dataMgr) {
+ super.initialize(context, bufferManager, dataMgr);
+ List sourceElements = this.getChildren()[0].getElements();
+ this.elementMap = createLookupMap(sourceElements);
+ }
+
+}
Property changes on: trunk/engine/src/main/java/org/teiid/query/processor/relational/WindowFunctionProjectNode.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -266,9 +266,6 @@
public void processRow(NodeInfo row) {
this.item = row;
rowCount++;
- if (rowCount % 100 == 0) {
- System.out.println(System.currentTimeMillis() + " " + rowCount);
- }
try {
this.buffer.addTuple(processRow());
} catch (TeiidException e) {
Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -163,25 +163,30 @@
* @return Type of the symbol
*/
public Class<?> getType() {
- if(this.aggregate == Type.COUNT) {
+ switch (this.aggregate) {
+ case COUNT:
return COUNT_TYPE;
- } else if(this.aggregate == Type.SUM ) {
+ case SUM:
Class<?> expressionType = this.getExpression().getType();
return SUM_TYPES.get(expressionType);
- } else if (this.aggregate == Type.AVG) {
- Class<?> expressionType = this.getExpression().getType();
+ case AVG:
+ expressionType = this.getExpression().getType();
return AVG_TYPES.get(expressionType);
- } else if (isBoolean()) {
+ case ARRAY_AGG:
+ return DataTypeManager.DefaultDataClasses.OBJECT;
+ case TEXTAGG:
+ return DataTypeManager.DefaultDataClasses.BLOB;
+ case RANK:
+ case ROW_NUMBER:
+ case DENSE_RANK:
+ return DataTypeManager.DefaultDataClasses.INTEGER;
+ }
+ if (isBoolean()) {
return DataTypeManager.DefaultDataClasses.BOOLEAN;
} else if (isEnhancedNumeric()) {
return DataTypeManager.DefaultDataClasses.DOUBLE;
- } else if (this.aggregate == Type.ARRAY_AGG) {
- return DataTypeManager.DefaultDataClasses.OBJECT;
- } else if (this.aggregate == Type.RANK || this.aggregate == Type.ROW_NUMBER || this.aggregate == Type.DENSE_RANK){
- return DataTypeManager.DefaultDataClasses.INTEGER;
- } else {
- return this.getExpression().getType();
}
+ return this.getExpression().getType();
}
public boolean isBoolean() {
Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/TextLine.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/TextLine.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/TextLine.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -88,7 +88,7 @@
@Override
public Class<?> getType() {
- return DataTypeManager.DefaultDataClasses.BLOB;
+ return DataTypeManager.DefaultDataClasses.STRING;
}
@Override
Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/WindowFunction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/WindowFunction.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/WindowFunction.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -27,15 +27,19 @@
import org.teiid.query.sql.LanguageVisitor;
import org.teiid.query.sql.visitor.SQLStringVisitor;
-public class WindowFunction implements Expression {
+public class WindowFunction extends SingleElementSymbol {
private AggregateSymbol function;
private WindowSpecification windowSpecification;
- public WindowFunction() {
-
+ public WindowFunction(String name) {
+ super(name);
}
+ protected WindowFunction(String name, String canonical) {
+ super(name, canonical);
+ }
+
public AggregateSymbol getFunction() {
return function;
}
@@ -88,7 +92,7 @@
@Override
public WindowFunction clone() {
- WindowFunction clone = new WindowFunction();
+ WindowFunction clone = new WindowFunction(this.getName(), this.getCanonical());
clone.setFunction((AggregateSymbol) this.function.clone());
clone.setWindowSpecification(this.windowSpecification.clone());
return clone;
Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -391,14 +391,26 @@
}
final ExpressionMappingVisitor visitor = new ExpressionMappingVisitor(exprMap);
visitor.elementSymbolsOnly = true;
+ boolean preOrder = true;
+ boolean useReverseMapping = true;
for (Map.Entry<? extends Expression, ? extends Expression> entry : exprMap.entrySet()) {
if (!(entry.getKey() instanceof ElementSymbol)) {
visitor.elementSymbolsOnly = false;
break;
}
}
- boolean useReverseMapping = !Collections.disjoint(GroupsUsedByElementsVisitor.getGroups(exprMap.keySet()),
- GroupsUsedByElementsVisitor.getGroups(exprMap.values()));
+ if (!visitor.elementSymbolsOnly) {
+ for (Map.Entry<? extends Expression, ? extends Expression> entry : exprMap.entrySet()) {
+ if (!(entry.getValue() instanceof ElementSymbol)) {
+ useReverseMapping = !Collections.disjoint(GroupsUsedByElementsVisitor.getGroups(exprMap.keySet()),
+ GroupsUsedByElementsVisitor.getGroups(exprMap.values()));
+ break;
+ }
+ }
+ } else {
+ preOrder = false;
+ useReverseMapping = false;
+ }
if (useReverseMapping) {
final Set<Expression> reverseSet = new HashSet<Expression>(exprMap.values());
@@ -412,7 +424,7 @@
};
obj.acceptVisitor(pon);
} else {
- PreOrPostOrderNavigator.doVisit(obj, visitor, PreOrPostOrderNavigator.PRE_ORDER, false);
+ PreOrPostOrderNavigator.doVisit(obj, visitor, preOrder, false);
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -756,7 +756,13 @@
Criteria having = query.getHaving();
validateNoAggsInClause(groupBy);
validateNoAggsInClause(query.getCriteria());
- validateNoAggsInClause(query.getFrom());
+ if (query.getFrom() == null) {
+ validateNoAggsInClause(select);
+ validateNoAggsInClause(query.getOrderBy());
+ } else {
+ validateNoAggsInClause(query.getFrom());
+ }
+
Set<Expression> groupSymbols = null;
boolean hasAgg = false;
if (groupBy != null) {
@@ -1212,10 +1218,20 @@
case DENSE_RANK:
case ROW_NUMBER:
if (windowFunction.getWindowSpecification().getOrderBy() == null) {
- handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.analytical_requires_order_by", windowFunction), windowFunction); //$NON-NLS-1$
+ handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.ranking_requires_order_by", windowFunction), windowFunction); //$NON-NLS-1$
}
+ break;
+ case TEXTAGG:
+ case ARRAY_AGG:
+ if (windowFunction.getWindowSpecification().getOrderBy() != null) {
+ handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.window_order_by", windowFunction), windowFunction); //$NON-NLS-1$
+ }
+ break;
}
validateNoSubqueriesOrOuterReferences(windowFunction);
+ if (windowFunction.getFunction().getOrderBy() != null || windowFunction.getFunction().isDistinct()) {
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0042", new Object[] {windowFunction.getFunction(), windowFunction}), windowFunction); //$NON-NLS-1$
+ }
}
@Override
@@ -1256,9 +1272,6 @@
handleValidationError(QueryPlugin.Util.getString("AggregateValidationVisitor.invalid_distinct", new Object[] {aggregateFunction, obj}), obj); //$NON-NLS-1$
}
}
- if (obj.isWindowed() && obj.getOrderBy() != null) {
- handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0042", new Object[] {aggregateFunction, obj}), obj); //$NON-NLS-1$
- }
if (obj.getAggregateFunction() != Type.TEXTAGG) {
return;
}
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2011-07-27 14:43:28 UTC (rev 3339)
@@ -1869,17 +1869,11 @@
)
{
SingleElementSymbol es = null;
- if(expression instanceof ElementSymbol) {
- es = (ElementSymbol) expression;
+ if(!(expression instanceof SingleElementSymbol)) {
+ String functionName = generateFunctionName(info, null);
+ es = new ExpressionSymbol(functionName, expression);
} else {
- String func = null;
- if(expression instanceof AggregateSymbol) {
- es = (AggregateSymbol)expression;
- func = ((AggregateSymbol)expression).getAggregateFunction().name();
- } else {
- String functionName = generateFunctionName(info, null);
- es = new ExpressionSymbol(functionName, expression);
- }
+ es = (SingleElementSymbol)expression;
}
if(alias != null) {
alias = validateAlias(alias);
@@ -3455,7 +3449,10 @@
[orderBy = orderby(info)]
<RPAREN>
{
- WindowFunction result = new WindowFunction();
+ String aggName = "win_" + ((AggregateSymbol)agg).getName();
+ String name = generateFunctionName(info, aggName);
+
+ WindowFunction result = new WindowFunction(aggName);
WindowSpecification ws = new WindowSpecification();
result.setFunction((AggregateSymbol)agg);
ws.setPartition(partitionList);
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2011-07-27 14:43:28 UTC (rev 3339)
@@ -207,7 +207,7 @@
ERR.015.012.0037 = {0} cannot be used outside of aggregate functions since they are not present in a GROUP BY clause.
ERR.015.012.0039 = Nested aggregate expressions are not allowed: {0}
ERR.015.012.0041 = The aggregate function {0} cannot be used with non-numeric expressions: {1}
-ERR.015.012.0042 = The aggregate function {0} cannot use its own order by clause when windowed: {1}
+ERR.015.012.0042 = A windowed aggregate function {0} cannot use its own order by clause or be distinct: {1}
AggregateValidationVisitor.non_comparable = The aggregate function {0} cannot be used with non-comparable expressions: {1}
AggregateValidationVisitor.non_xml = The XMLAGG aggregate function {0} requires an expression of type XML: {1}
AggregateValidationVisitor.non_boolean=The boolean aggregate functions ANY, SOME, EVERY require a boolean expression.
@@ -259,7 +259,7 @@
SQLParser.Unknown_join_type=Unknown join type: {0}
-SQLParser.Aggregate_only_top_level=Aggregate functions are only allowed HAVING/SELECT/ORDER BY clauses. Window functions are only allowed in the SELECT/ORDER BY clauses: {0}
+SQLParser.Aggregate_only_top_level=Aggregate functions are only allowed HAVING/SELECT/ORDER BY clauses. Window functions are only allowed in the SELECT/ORDER BY clauses: {0}. Both require a FROM clause to be present.
SQLParser.window_only_top_level=Window functions are not allowed in the HAVING clause: {0}
SQLParser.Unknown_agg_func=Unknown aggregate function: {0}
SQLParser.Invalid_func=Invalid function name: [{0}]
@@ -680,7 +680,8 @@
SimpleQueryResolver.procedure_cache_not_used=Procedure caching will not be used for {0} due to the use of OPTION NOCACHE.
ValidationVisitor.groupby_subquery=Expressions used in a GROUP BY clause cannot be constant and must not contain subqueries: "{0}".
ValidationVisitor.filter_subquery=Expressions used in a FILTER clause or a window function must not contain subqueries nor outer references: "{0}".
-ValidationVisitor.analytical_requires_order_by=The window analytical functions RANK, DENSE_RANK, and ROW_NUMBER require the use of an ORDER BY clause in the window specification: {0}.
+ValidationVisitor.ranking_requires_order_by=The window ranking functions RANK, DENSE_RANK, and ROW_NUMBER require the use of an ORDER BY clause in the window specification: {0}.
+ValidationVisitor.window_order_by=The window specification for TEXTAGG and ARRAY_AGG cannot use an ORDER BY clause: {0}.
ValidationVisitor.Procedure_has_group_self_reference=Procedure cannot have a Group reference to itself.
ExpressionEvaluator.Expected_props_for_payload_function=Unable to evaluate {0}: expected Properties for command payload but got object of type {1}
ValidationVisitor.The_rowlimit_function_cannot_be_used_in_a_non-XML_command=The ''rowlimit'' and ''rowlimitexception'' functions cannot be used in a non-XML command
Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestDQPCore.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestDQPCore.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestDQPCore.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -363,6 +363,27 @@
assertEquals(1, agds.getExecuteCount().get());
}
+ @Test public void testUsingFinalBuffer() throws Exception {
+ String sql = "select intkey from bqt1.smalla union select 1";
+ ((BufferManagerImpl)core.getBufferManager()).setProcessorBatchSize(2);
+ agds.sleep = 500;
+ RequestMessage reqMsg = exampleRequestMessage(sql);
+ Future<ResultsMessage> message = core.executeRequest(reqMsg.getExecutionId(), reqMsg);
+ ResultsMessage rm = message.get(500000, TimeUnit.MILLISECONDS);
+ assertNull(rm.getException());
+ assertEquals(1, rm.getResults().length);
+
+ message = core.processCursorRequest(reqMsg.getExecutionId(), 3, 2);
+ rm = message.get(500000, TimeUnit.MILLISECONDS);
+ assertNull(rm.getException());
+ assertEquals(1, rm.getResults().length);
+
+ message = core.processCursorRequest(reqMsg.getExecutionId(), 3, 2);
+ rm = message.get(500000, TimeUnit.MILLISECONDS);
+ assertNull(rm.getException());
+ assertEquals(0, rm.getResults().length);
+ }
+
@Test public void testPreparedPlanInvalidation() throws Exception {
String sql = "insert into #temp select * FROM vqt.SmallB"; //$NON-NLS-1$
String userName = "1"; //$NON-NLS-1$
Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestMetaDataProcessor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestMetaDataProcessor.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestMetaDataProcessor.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -155,7 +155,17 @@
helpCheckNumericAttributes(response, 2, 22, 20, 0);
helpCheckNumericAttributes(response, 3, 22, 20, 0);
}
-
+
+ @Test public void testWindowFunction() throws Exception {
+ QueryMetadataInterface metadata = TestMetaDataProcessor.examplePrivatePhysicalModel();
+ String sql = "SELECT min(e1) over () FROM pm1.g2"; //$NON-NLS-1$
+
+ MetadataResult response = helpTestQuery(metadata, sql, TestMetaDataProcessor.examplePrivatePhysicalModelVDB());
+ helpCheckNumericAttributes(response, 0, 21, 19, 4);
+ assertEquals("e1", response.getColumnMetadata()[0].get(ResultsMetadataConstants.ELEMENT_NAME)); //$NON-NLS-1$
+ assertEquals("win_min", response.getColumnMetadata()[0].get(ResultsMetadataConstants.ELEMENT_LABEL)); //$NON-NLS-1$
+ }
+
@Test public void testMetadataGenerationForAllTypes() throws Exception {
Set<String> dataTypes = DataTypeManager.getAllDataTypeNames();
for (String type : dataTypes) {
@@ -246,7 +256,7 @@
Table pm1g2 = RealMetadataFactory.createPhysicalGroup("g2", pm1); //$NON-NLS-1$
// Create physical elements
- List<Column> pm1g1e = RealMetadataFactory.createElements(pm1g1,
+ RealMetadataFactory.createElements(pm1g1,
new String[] { "e1"}, //$NON-NLS-1$
new String[] { DataTypeManager.DefaultDataTypes.SHORT});
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestSortOptimization.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestSortOptimization.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestSortOptimization.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -146,6 +146,39 @@
checkNodeTypes(plan, new int[] {0}, new Class[] {DupRemoveSortNode.class});
}
+ /**
+ * The grouping expression inhibits combining the dup removal.
+ */
+ @Test public void testGroupDupCombination1() {
+ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+ BasicSourceCapabilities caps = new BasicSourceCapabilities();
+ capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
+
+ // Create query
+ String sql = "select max(e1), e2 || e1 from (select distinct e1, e2 from pm1.g1) x group by e2 || e1"; //$NON-NLS-1$
+
+ ProcessorPlan plan = helpPlan(sql, RealMetadataFactory.example1Cached(), null, capFinder,
+ new String[] {"SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1"}, TestOptimizer.SHOULD_SUCCEED); //$NON-NLS-1$
+
+ checkNodeTypes(plan, new int[] {
+ 1, // Access
+ 0, // DependentAccess
+ 0, // DependentSelect
+ 0, // DependentProject
+ 0, // DupRemove
+ 1, // Grouping
+ 0, // NestedLoopJoinStrategy
+ 0, // MergeJoinStrategy
+ 0, // Null
+ 0, // PlanExecution
+ 1, // Project
+ 0, // Select
+ 0, // Sort
+ 0 // UnionAll
+ });
+ checkNodeTypes(plan, new int[] {1}, new Class[] {DupRemoveSortNode.class});
+ }
+
@Test public void testSortGroupCombination() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -6849,13 +6849,13 @@
@Test public void testWindowFunction() throws Exception {
String sql = "select row_number() over (partition by x order by y) from g";
Query query = new Query();
- WindowFunction wf = new WindowFunction();
+ WindowFunction wf = new WindowFunction("expr");
wf.setFunction(new AggregateSymbol("expr", "ROW_NUMBER", false, null));
WindowSpecification ws = new WindowSpecification();
ws.setPartition(new ArrayList<Expression>(Arrays.asList(new ElementSymbol("x"))));
ws.setOrderBy(new OrderBy(Arrays.asList(new ElementSymbol("y"))));
wf.setWindowSpecification(ws);
- query.setSelect(new Select(Arrays.asList(new ExpressionSymbol("x", wf))));
+ query.setSelect(new Select(Arrays.asList(wf)));
query.setFrom(new From(Arrays.asList(new UnaryFromClause(new GroupSymbol("g")))));
helpTest(sql, "SELECT ROW_NUMBER() OVER (PARTITION BY x ORDER BY y) FROM g", query);
}
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestAggregateProcessing.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestAggregateProcessing.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestAggregateProcessing.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -400,6 +400,23 @@
helpProcess(plan, cc, dataManager, expected);
}
+ @Test public void testDupGroupCombination() throws Exception {
+ String sql = "select count(e2), e1 from (select distinct e1, e2, e3 from pm1.g1) x group by e1"; //$NON-NLS-1$
+
+ List[] expected = new List[] {
+ Arrays.asList(2, "a"),
+ };
+
+ HardcodedDataManager dataManager = new HardcodedDataManager();
+ dataManager.addData("SELECT pm1.g1.e1, pm1.g1.e2, pm1.g1.e3 FROM pm1.g1", new List[] {
+ Arrays.asList("a", 0, Boolean.TRUE),
+ Arrays.asList("a", 0, Boolean.FALSE),
+ });
+
+ ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached());
+ helpProcess(plan, dataManager, expected);
+ }
+
@Test public void testAggFilter() throws Exception {
// Create query
String sql = "SELECT e2, count(*) filter (where e3) from pm1.g1 group by e2 order by e2"; //$NON-NLS-1$
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -4485,6 +4485,30 @@
helpProcess(plan, dataManager, expected);
}
+ @Test public void testSortGroupCombination() throws Exception {
+ String sql = "select e2, max(e1) from pm1.g1 x group by e2 order by e2 desc"; //$NON-NLS-1$
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+ ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached(), TestOptimizer.getGenericFinder());
+
+ helpProcess(plan, dataManager, new List[] {
+ Arrays.asList(3, "a"),
+ Arrays.asList(2, "b"),
+ Arrays.asList(1, "c"),
+ Arrays.asList(0, "a")});
+ }
+
+ @Test public void testUnorderedLimitWithProc() throws Exception {
+ String sql = "select e1 from (exec pm1.sq1()) x limit 1";
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+ ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached(), TestOptimizer.getGenericFinder());
+
+ helpProcess(plan, dataManager, new List[] {Arrays.asList("a")});
+ }
+
@Test public void testCase3() {
// Create query
String sql = "SELECT e2, CASE e2 WHEN 1 THEN 2 ELSE null END FROM pm1.g1 WHERE e2 BETWEEN 1 AND 2"; //$NON-NLS-1$
@@ -7574,12 +7598,12 @@
String sql = "SELECT pm1.g1.e2 as y FROM pm1.g1 ORDER BY e3 || e1";
List[] expected = new List[] {
+ Arrays.asList(1),
Arrays.asList(0),
- Arrays.asList(1),
+ Arrays.asList(0),
+ Arrays.asList(2),
Arrays.asList(3),
Arrays.asList(1),
- Arrays.asList(2),
- Arrays.asList(0),
};
FakeDataManager dataManager = new FakeDataManager();
Copied: trunk/engine/src/test/java/org/teiid/query/processor/TestWindowFunctions.java (from rev 3330, trunk/engine/src/test/java/org/teiid/query/optimizer/TestWindowFunctions.java)
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestWindowFunctions.java (rev 0)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestWindowFunctions.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -0,0 +1,131 @@
+/*
+ * 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 org.teiid.query.processor;
+
+import static org.teiid.query.optimizer.TestOptimizer.*;
+import static org.teiid.query.processor.TestProcessor.*;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.teiid.query.optimizer.TestOptimizer;
+import org.teiid.query.optimizer.TestOptimizer.ComparisonMode;
+import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
+import org.teiid.query.optimizer.capabilities.DefaultCapabilitiesFinder;
+import org.teiid.query.optimizer.capabilities.SourceCapabilities.Capability;
+import org.teiid.query.unittest.RealMetadataFactory;
+
+@SuppressWarnings({"nls", "unchecked"})
+public class TestWindowFunctions {
+
+ @Test public void testViewNotRemoved() throws Exception {
+ BasicSourceCapabilities caps = getTypicalCapabilities();
+ caps.setCapabilitySupport(Capability.ELEMENTARY_OLAP, true);
+ caps.setCapabilitySupport(Capability.QUERY_FROM_INLINE_VIEWS, true);
+ ProcessorPlan plan = TestOptimizer.helpPlan("SELECT y FROM (select row_number() over (order by e1) as y from pm1.g1) as x where x.y = 10", //$NON-NLS-1$
+ RealMetadataFactory.example1Cached(), null, new DefaultCapabilitiesFinder(caps),
+ new String[] {
+ "SELECT v_0.c_0 FROM (SELECT ROW_NUMBER() OVER (ORDER BY g_0.e1) AS c_0 FROM pm1.g1 AS g_0) AS v_0 WHERE v_0.c_0 = 10"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
+
+ checkNodeTypes(plan, FULL_PUSHDOWN);
+ }
+
+ @Test public void testRanking() throws Exception {
+ String sql = "select e1, row_number() over (order by e1), rank() over (order by e1), dense_rank() over (order by e1 nulls last) from pm1.g1";
+
+ List<?>[] expected = new List[] {
+ Arrays.asList("a", 2, 2, 1),
+ Arrays.asList(null, 1, 1, 4),
+ Arrays.asList("a", 3, 2, 1),
+ Arrays.asList("c", 6, 6, 3),
+ Arrays.asList("b", 5, 5, 2),
+ Arrays.asList("a", 4, 2, 1),
+ };
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+ ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached(), TestOptimizer.getGenericFinder());
+
+ helpProcess(plan, dataManager, expected);
+ }
+
+ @Test public void testPartitionedMax() throws Exception {
+ String sql = "select e2, max(e1) over (partition by e2) as y from pm1.g1";
+
+ List<?>[] expected = new List[] {
+ Arrays.asList(0, "a"),
+ Arrays.asList(1, "c"),
+ Arrays.asList(3, "a"),
+ Arrays.asList(1, "c"),
+ Arrays.asList(2, "b"),
+ Arrays.asList(0, "a"),
+ };
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+ ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached(), TestOptimizer.getGenericFinder());
+
+ helpProcess(plan, dataManager, expected);
+ }
+
+ @Test public void testUnrelatedWindowFunctionOrderBy() throws Exception {
+ String sql = "select e2, e1 from pm1.g1 order by count(e1) over (partition by e3), e2";
+
+ List<?>[] expected = new List[] {
+ Arrays.asList(1, "c"),
+ Arrays.asList(3, "a"),
+ Arrays.asList(0, "a"),
+ Arrays.asList(0, "a"),
+ Arrays.asList(1, null),
+ Arrays.asList(2, "b"),
+ };
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+ ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached(), TestOptimizer.getGenericFinder());
+
+ helpProcess(plan, dataManager, expected);
+ }
+
+ @Test public void testWindowFunctionOrderBy() throws Exception {
+ String sql = "select e2, e1, count(e1) over (partition by e3) as c from pm1.g1 order by c, e2";
+
+ List<?>[] expected = new List[] {
+ Arrays.asList(1, "c", 2),
+ Arrays.asList(3, "a", 2),
+ Arrays.asList(0, "a", 3),
+ Arrays.asList(0, "a", 3),
+ Arrays.asList(1, null, 3),
+ Arrays.asList(2, "b", 3),
+ };
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+ ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached(), TestOptimizer.getGenericFinder());
+
+ helpProcess(plan, dataManager, expected);
+ }
+
+
+}
Property changes on: trunk/engine/src/test/java/org/teiid/query/processor/TestWindowFunctions.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/engine/src/test/java/org/teiid/query/processor/relational/TestGroupingNode.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/relational/TestGroupingNode.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/test/java/org/teiid/query/processor/relational/TestGroupingNode.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -22,7 +22,7 @@
package org.teiid.query.processor.relational;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.*;
import java.math.BigDecimal;
import java.util.ArrayList;
@@ -45,6 +45,7 @@
import org.teiid.query.processor.FakeDataManager;
import org.teiid.query.processor.FakeTupleSource;
import org.teiid.query.processor.ProcessorDataManager;
+import org.teiid.query.sql.lang.OrderBy;
import org.teiid.query.sql.symbol.AggregateSymbol;
import org.teiid.query.sql.symbol.Constant;
import org.teiid.query.sql.symbol.ElementSymbol;
@@ -153,7 +154,7 @@
List groupingElements = new ArrayList();
groupingElements.add(col1);
- node.setGroupingElements(groupingElements);
+ node.setOrderBy(new OrderBy(groupingElements).getOrderByItems());
CommandContext context = new CommandContext("pid", "test", null, null, 1); //$NON-NLS-1$ //$NON-NLS-2$
List[] expected = new List[] {
@@ -231,8 +232,6 @@
outputElements.add(new AggregateSymbol("bigAvg", "AVG", false, bigDecimal)); //$NON-NLS-1$ //$NON-NLS-2$
node.setElements(outputElements);
- // Set grouping elements to null
- node.setGroupingElements(null);
CommandContext context = new CommandContext("pid", "test", null, null, 1); //$NON-NLS-1$ //$NON-NLS-2$
List[] data = new List[] {
@@ -272,7 +271,7 @@
// Set grouping elements to null
List groupingElements = new ArrayList();
groupingElements.add(col1);
- node.setGroupingElements(groupingElements);
+ node.setOrderBy(new OrderBy(groupingElements).getOrderByItems());
CommandContext context = new CommandContext("pid", "test", null, null, 1); //$NON-NLS-1$ //$NON-NLS-2$
List[] data = new List[] {
@@ -320,7 +319,7 @@
List groupingElements = new ArrayList();
groupingElements.add(col1);
- node.setGroupingElements(groupingElements);
+ node.setOrderBy(new OrderBy(groupingElements).getOrderByItems());
CommandContext context = new CommandContext("pid", "test", null, null, 1); //$NON-NLS-1$ //$NON-NLS-2$
FakeDataManager dataMgr = new FakeDataManager();
@@ -366,7 +365,7 @@
if (groupBy) {
List groupingElements = new ArrayList();
groupingElements.add(new ElementSymbol("col1")); //$NON-NLS-1$
- node.setGroupingElements(groupingElements);
+ node.setOrderBy(new OrderBy(groupingElements).getOrderByItems());
}
CommandContext context = new CommandContext("pid", "test", null, null, 1); //$NON-NLS-1$ //$NON-NLS-2$
@@ -434,7 +433,7 @@
List groupingElements = new ArrayList();
groupingElements.add(col1);
- node.setGroupingElements(groupingElements);
+ node.setOrderBy(new OrderBy(groupingElements).getOrderByItems());
return node;
}
Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java 2011-07-27 14:34:57 UTC (rev 3338)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java 2011-07-27 14:43:28 UTC (rev 3339)
@@ -1896,7 +1896,7 @@
}
@Test public void testWindowFunctionWithNestedOrdering() {
- helpValidate("SELECT xmlagg(xmlelement(name x, e1) order by e2) over () from pm1.g1", new String[] {"XMLAGG(XMLELEMENT(NAME x, e1) ORDER BY e2)"}, RealMetadataFactory.example1Cached());
+ helpValidate("SELECT xmlagg(xmlelement(name x, e1) order by e2) over () from pm1.g1", new String[] {"XMLAGG(XMLELEMENT(NAME x, e1) ORDER BY e2) OVER ()"}, RealMetadataFactory.example1Cached());
}
@Test public void testWindowFunctionWithNestedaggAllowed() {
@@ -1907,4 +1907,8 @@
helpValidate("SELECT max(min(e1)) over (order by max(e2)) from pm1.g1 group by e1", new String[] {"MIN(e1)"}, RealMetadataFactory.example1Cached());
}
+ @Test public void testWindowFunctionWithoutFrom() {
+ helpValidate("select count(*) over () as y", new String[] {"COUNT(*) OVER ()"}, RealMetadataFactory.example1Cached());
+ }
+
}
13 years, 5 months
teiid SVN: r3338 - in branches/7.4.x/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc: derby and 1 other directory.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-07-27 10:34:57 -0400 (Wed, 27 Jul 2011)
New Revision: 3338
Added:
branches/7.4.x/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/BaseDB2ExecutionFactory.java
Modified:
branches/7.4.x/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/DB2ExecutionFactory.java
branches/7.4.x/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/derby/DerbyExecutionFactory.java
Log:
TEIID-1688 fixing derby capabilities
Added: branches/7.4.x/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/BaseDB2ExecutionFactory.java
===================================================================
--- branches/7.4.x/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/BaseDB2ExecutionFactory.java (rev 0)
+++ branches/7.4.x/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/BaseDB2ExecutionFactory.java 2011-07-27 14:34:57 UTC (rev 3338)
@@ -0,0 +1,177 @@
+/*
+ * 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 org.teiid.translator.jdbc.db2;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.teiid.language.DerivedColumn;
+import org.teiid.language.Expression;
+import org.teiid.language.Function;
+import org.teiid.language.Join;
+import org.teiid.language.LanguageFactory;
+import org.teiid.language.LanguageObject;
+import org.teiid.language.Limit;
+import org.teiid.language.Literal;
+import org.teiid.language.Comparison.Operator;
+import org.teiid.language.Join.JoinType;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.SourceSystemFunctions;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.TypeFacility;
+import org.teiid.translator.jdbc.AliasModifier;
+import org.teiid.translator.jdbc.ConvertModifier;
+import org.teiid.translator.jdbc.FunctionModifier;
+import org.teiid.translator.jdbc.JDBCExecutionFactory;
+import org.teiid.translator.jdbc.LocateFunctionModifier;
+import org.teiid.translator.jdbc.ModFunctionModifier;
+
+public class BaseDB2ExecutionFactory extends JDBCExecutionFactory {
+
+ private final class NullHandlingFormatModifier extends
+ ConvertModifier.FormatModifier {
+ private NullHandlingFormatModifier(String alias) {
+ super(alias);
+ }
+
+ @Override
+ public List<?> translate(Function function) {
+ Expression arg = function.getParameters().get(0);
+ if (arg instanceof Literal && ((Literal)arg).getValue() == null) {
+ ((Literal)function.getParameters().get(1)).setValue(this.alias);
+ return null;
+ }
+ return super.translate(function);
+ }
+ }
+
+ @Override
+ public void start() throws TranslatorException {
+ super.start();
+ registerFunctionModifier(SourceSystemFunctions.CHAR, new AliasModifier("chr")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.DAYOFMONTH, new AliasModifier("day")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.IFNULL, new AliasModifier("coalesce")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.LOCATE, new LocateFunctionModifier(getLanguageFactory()));
+ registerFunctionModifier(SourceSystemFunctions.SUBSTRING, new SubstringFunctionModifier());
+
+ registerFunctionModifier(SourceSystemFunctions.MOD, new ModFunctionModifier("MOD", getLanguageFactory())); //$NON-NLS-1$
+
+ //add in type conversion
+ ConvertModifier convertModifier = new ConvertModifier();
+ convertModifier.addTypeMapping("real", FunctionModifier.FLOAT); //$NON-NLS-1$
+ convertModifier.addTypeMapping("numeric(31,0)", FunctionModifier.BIGINTEGER); //$NON-NLS-1$
+ convertModifier.addTypeMapping("numeric(31,12)", FunctionModifier.BIGDECIMAL); //$NON-NLS-1$
+ convertModifier.addTypeMapping("char(1)", FunctionModifier.CHAR); //$NON-NLS-1$
+ convertModifier.addTypeMapping("blob", FunctionModifier.BLOB, FunctionModifier.OBJECT); //$NON-NLS-1$
+ convertModifier.addTypeMapping("clob", FunctionModifier.CLOB, FunctionModifier.XML); //$NON-NLS-1$
+ convertModifier.addConvert(FunctionModifier.TIME, FunctionModifier.TIMESTAMP, new FunctionModifier() {
+ @Override
+ public List<?> translate(Function function) {
+ return Arrays.asList("timestamp('1970-01-01', ", function.getParameters().get(0), ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ });
+ convertModifier.addConvert(FunctionModifier.DATE, FunctionModifier.TIMESTAMP, new FunctionModifier() {
+ @Override
+ public List<?> translate(Function function) {
+ return Arrays.asList("timestamp(",function.getParameters().get(0), ", '00:00:00')"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ });
+ //the next convert is not strictly necessary for db2, but it also works for derby
+ convertModifier.addConvert(FunctionModifier.STRING, FunctionModifier.FLOAT, new FunctionModifier() {
+ @Override
+ public List<?> translate(Function function) {
+ return Arrays.asList("cast(double(", function.getParameters().get(0), ") as real)"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ });
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("char"), FunctionModifier.STRING); //$NON-NLS-1$
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("smallint"), FunctionModifier.BYTE, FunctionModifier.SHORT); //$NON-NLS-1$
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("integer"), FunctionModifier.INTEGER); //$NON-NLS-1$
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("bigint"), FunctionModifier.LONG); //$NON-NLS-1$
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("double"), FunctionModifier.DOUBLE); //$NON-NLS-1$
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("date"), FunctionModifier.DATE); //$NON-NLS-1$
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("time"), FunctionModifier.TIME); //$NON-NLS-1$
+ convertModifier.addTypeConversion(new NullHandlingFormatModifier("timestamp"), FunctionModifier.TIMESTAMP); //$NON-NLS-1$
+ convertModifier.addNumericBooleanConversions();
+ registerFunctionModifier(SourceSystemFunctions.CONVERT, convertModifier);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<?> translateLimit(Limit limit, ExecutionContext context) {
+ return Arrays.asList("FETCH FIRST ", limit.getRowLimit(), " ROWS ONLY"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ @Override
+ public List<?> translate(LanguageObject obj, ExecutionContext context) {
+ //DB2 doesn't support cross join
+ convertCrossJoinToInner(obj, getLanguageFactory());
+ //DB2 needs projected nulls wrapped in casts
+ if (obj instanceof DerivedColumn) {
+ DerivedColumn selectSymbol = (DerivedColumn)obj;
+ if (selectSymbol.getExpression() instanceof Literal) {
+ Literal literal = (Literal)selectSymbol.getExpression();
+ if (literal.getValue() == null) {
+ String type = TypeFacility.RUNTIME_NAMES.INTEGER;
+ if (literal.getType() != TypeFacility.RUNTIME_TYPES.NULL) {
+ type = TypeFacility.getDataTypeName(literal.getType());
+ }
+ selectSymbol.setExpression(ConvertModifier.createConvertFunction(getLanguageFactory(), literal, type));
+ }
+ }
+ }
+ return super.translate(obj, context);
+ }
+
+ public static void convertCrossJoinToInner(LanguageObject obj, LanguageFactory lf) {
+ if (obj instanceof Join) {
+ Join join = (Join)obj;
+ if (join.getJoinType() == JoinType.CROSS_JOIN) {
+ Literal one = lf.createLiteral(1, TypeFacility.RUNTIME_TYPES.INTEGER);
+ join.setCondition(lf.createCompareCriteria(Operator.EQ, one, one));
+ join.setJoinType(JoinType.INNER_JOIN);
+ }
+ }
+ }
+
+ @Override
+ public NullOrder getDefaultNullOrder() {
+ return NullOrder.HIGH;
+ }
+
+ @Override
+ public boolean supportsInlineViews() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsExcept() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsIntersect() {
+ return true;
+ }
+
+}
Property changes on: branches/7.4.x/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/BaseDB2ExecutionFactory.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: branches/7.4.x/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/DB2ExecutionFactory.java
===================================================================
--- branches/7.4.x/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/DB2ExecutionFactory.java 2011-07-27 10:59:10 UTC (rev 3337)
+++ branches/7.4.x/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/DB2ExecutionFactory.java 2011-07-27 14:34:57 UTC (rev 3338)
@@ -23,145 +23,14 @@
package org.teiid.translator.jdbc.db2;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
-import org.teiid.language.DerivedColumn;
-import org.teiid.language.Expression;
-import org.teiid.language.Function;
-import org.teiid.language.Join;
-import org.teiid.language.LanguageFactory;
-import org.teiid.language.LanguageObject;
-import org.teiid.language.Limit;
-import org.teiid.language.Literal;
-import org.teiid.language.Comparison.Operator;
-import org.teiid.language.Join.JoinType;
-import org.teiid.translator.ExecutionContext;
-import org.teiid.translator.SourceSystemFunctions;
import org.teiid.translator.Translator;
-import org.teiid.translator.TranslatorException;
-import org.teiid.translator.TypeFacility;
-import org.teiid.translator.jdbc.AliasModifier;
-import org.teiid.translator.jdbc.ConvertModifier;
-import org.teiid.translator.jdbc.FunctionModifier;
-import org.teiid.translator.jdbc.JDBCExecutionFactory;
-import org.teiid.translator.jdbc.LocateFunctionModifier;
-import org.teiid.translator.jdbc.ModFunctionModifier;
@Translator(name="db2", description="A translator for IBM DB2 Database")
-public class DB2ExecutionFactory extends JDBCExecutionFactory {
-
- private final class NullHandlingFormatModifier extends
- ConvertModifier.FormatModifier {
- private NullHandlingFormatModifier(String alias) {
- super(alias);
- }
-
- @Override
- public List<?> translate(Function function) {
- Expression arg = function.getParameters().get(0);
- if (arg instanceof Literal && ((Literal)arg).getValue() == null) {
- ((Literal)function.getParameters().get(1)).setValue(this.alias);
- return null;
- }
- return super.translate(function);
- }
- }
-
- @Override
- public void start() throws TranslatorException {
- super.start();
- registerFunctionModifier(SourceSystemFunctions.CHAR, new AliasModifier("chr")); //$NON-NLS-1$
- registerFunctionModifier(SourceSystemFunctions.DAYOFMONTH, new AliasModifier("day")); //$NON-NLS-1$
- registerFunctionModifier(SourceSystemFunctions.IFNULL, new AliasModifier("coalesce")); //$NON-NLS-1$
- registerFunctionModifier(SourceSystemFunctions.LOCATE, new LocateFunctionModifier(getLanguageFactory()));
- registerFunctionModifier(SourceSystemFunctions.SUBSTRING, new SubstringFunctionModifier());
-
- registerFunctionModifier(SourceSystemFunctions.MOD, new ModFunctionModifier("MOD", getLanguageFactory())); //$NON-NLS-1$
-
- //add in type conversion
- ConvertModifier convertModifier = new ConvertModifier();
- convertModifier.addTypeMapping("real", FunctionModifier.FLOAT); //$NON-NLS-1$
- convertModifier.addTypeMapping("numeric(31,0)", FunctionModifier.BIGINTEGER); //$NON-NLS-1$
- convertModifier.addTypeMapping("numeric(31,12)", FunctionModifier.BIGDECIMAL); //$NON-NLS-1$
- convertModifier.addTypeMapping("char(1)", FunctionModifier.CHAR); //$NON-NLS-1$
- convertModifier.addTypeMapping("blob", FunctionModifier.BLOB, FunctionModifier.OBJECT); //$NON-NLS-1$
- convertModifier.addTypeMapping("clob", FunctionModifier.CLOB, FunctionModifier.XML); //$NON-NLS-1$
- convertModifier.addConvert(FunctionModifier.TIME, FunctionModifier.TIMESTAMP, new FunctionModifier() {
- @Override
- public List<?> translate(Function function) {
- return Arrays.asList("timestamp('1970-01-01', ", function.getParameters().get(0), ")"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- });
- convertModifier.addConvert(FunctionModifier.DATE, FunctionModifier.TIMESTAMP, new FunctionModifier() {
- @Override
- public List<?> translate(Function function) {
- return Arrays.asList("timestamp(",function.getParameters().get(0), ", '00:00:00')"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- });
- //the next convert is not strictly necessary for db2, but it also works for derby
- convertModifier.addConvert(FunctionModifier.STRING, FunctionModifier.FLOAT, new FunctionModifier() {
- @Override
- public List<?> translate(Function function) {
- return Arrays.asList("cast(double(", function.getParameters().get(0), ") as real)"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- });
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("char"), FunctionModifier.STRING); //$NON-NLS-1$
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("smallint"), FunctionModifier.BYTE, FunctionModifier.SHORT); //$NON-NLS-1$
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("integer"), FunctionModifier.INTEGER); //$NON-NLS-1$
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("bigint"), FunctionModifier.LONG); //$NON-NLS-1$
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("double"), FunctionModifier.DOUBLE); //$NON-NLS-1$
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("date"), FunctionModifier.DATE); //$NON-NLS-1$
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("time"), FunctionModifier.TIME); //$NON-NLS-1$
- convertModifier.addTypeConversion(new NullHandlingFormatModifier("timestamp"), FunctionModifier.TIMESTAMP); //$NON-NLS-1$
- convertModifier.addNumericBooleanConversions();
- registerFunctionModifier(SourceSystemFunctions.CONVERT, convertModifier);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public List<?> translateLimit(Limit limit, ExecutionContext context) {
- return Arrays.asList("FETCH FIRST ", limit.getRowLimit(), " ROWS ONLY"); //$NON-NLS-1$ //$NON-NLS-2$
- }
+public class DB2ExecutionFactory extends BaseDB2ExecutionFactory {
@Override
- public List<?> translate(LanguageObject obj, ExecutionContext context) {
- //DB2 doesn't support cross join
- convertCrossJoinToInner(obj, getLanguageFactory());
- //DB2 needs projected nulls wrapped in casts
- if (obj instanceof DerivedColumn) {
- DerivedColumn selectSymbol = (DerivedColumn)obj;
- if (selectSymbol.getExpression() instanceof Literal) {
- Literal literal = (Literal)selectSymbol.getExpression();
- if (literal.getValue() == null) {
- String type = TypeFacility.RUNTIME_NAMES.INTEGER;
- if (literal.getType() != TypeFacility.RUNTIME_TYPES.NULL) {
- type = TypeFacility.getDataTypeName(literal.getType());
- }
- selectSymbol.setExpression(ConvertModifier.createConvertFunction(getLanguageFactory(), literal, type));
- }
- }
- }
- return super.translate(obj, context);
- }
-
- public static void convertCrossJoinToInner(LanguageObject obj, LanguageFactory lf) {
- if (obj instanceof Join) {
- Join join = (Join)obj;
- if (join.getJoinType() == JoinType.CROSS_JOIN) {
- Literal one = lf.createLiteral(1, TypeFacility.RUNTIME_TYPES.INTEGER);
- join.setCondition(lf.createCompareCriteria(Operator.EQ, one, one));
- join.setJoinType(JoinType.INNER_JOIN);
- }
- }
- }
-
- @Override
- public NullOrder getDefaultNullOrder() {
- return NullOrder.HIGH;
- }
-
- @Override
public List<String> getSupportedFunctions() {
List<String> supportedFunctions = new ArrayList<String>();
supportedFunctions.addAll(super.getSupportedFunctions());
@@ -230,37 +99,23 @@
}
@Override
- public boolean supportsInlineViews() {
- return true;
- }
-
- @Override
public boolean supportsFunctionsInGroupBy() {
return true;
}
@Override
- public boolean supportsRowLimit() {
+ public boolean supportsAggregatesEnhancedNumeric() {
return true;
}
-
+
@Override
- public boolean supportsExcept() {
+ public boolean supportsCommonTableExpressions() {
return true;
}
-
- @Override
- public boolean supportsIntersect() {
- return true;
- }
@Override
- public boolean supportsAggregatesEnhancedNumeric() {
+ public boolean supportsRowLimit() {
return true;
}
- @Override
- public boolean supportsCommonTableExpressions() {
- return true;
- }
}
Modified: branches/7.4.x/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/derby/DerbyExecutionFactory.java
===================================================================
--- branches/7.4.x/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/derby/DerbyExecutionFactory.java 2011-07-27 10:59:10 UTC (rev 3337)
+++ branches/7.4.x/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/derby/DerbyExecutionFactory.java 2011-07-27 14:34:57 UTC (rev 3338)
@@ -29,14 +29,14 @@
import org.teiid.translator.Translator;
import org.teiid.translator.TranslatorException;
import org.teiid.translator.jdbc.EscapeSyntaxModifier;
-import org.teiid.translator.jdbc.db2.DB2ExecutionFactory;
+import org.teiid.translator.jdbc.db2.BaseDB2ExecutionFactory;
import org.teiid.translator.jdbc.oracle.LeftOrRightFunctionModifier;
/**
* @since 4.3
*/
@Translator(name="derby", description="A translator for Apache Derby Database")
-public class DerbyExecutionFactory extends DB2ExecutionFactory {
+public class DerbyExecutionFactory extends BaseDB2ExecutionFactory {
public static final String TEN_1 = "10.1"; //$NON-NLS-1$
public static final String TEN_2 = "10.2"; //$NON-NLS-1$
@@ -181,8 +181,4 @@
return this.getDatabaseVersion().compareTo(TEN_5) >= 0;
}
- @Override
- public boolean supportsFunctionsInGroupBy() {
- return false;
- }
}
13 years, 5 months
teiid SVN: r3337 - in branches/7.4.x/engine/src: main/java/org/teiid/query/optimizer/relational/rules and 4 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-07-27 06:59:10 -0400 (Wed, 27 Jul 2011)
New Revision: 3337
Modified:
branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java
branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java
branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java
branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/SortUtility.java
branches/7.4.x/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java
branches/7.4.x/engine/src/main/java/org/teiid/query/sql/symbol/TextLine.java
branches/7.4.x/engine/src/test/java/org/teiid/query/processor/TestAggregateProcessing.java
branches/7.4.x/engine/src/test/java/org/teiid/query/processor/relational/TestGroupingNode.java
Log:
TEIID-1682 fixing duplicate removal when merged with group by
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java 2011-07-26 20:20:59 UTC (rev 3336)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java 2011-07-27 10:59:10 UTC (rev 3337)
@@ -379,7 +379,6 @@
case NodeConstants.Types.GROUP:
GroupingNode gnode = new GroupingNode(getID());
List<SingleElementSymbol> gCols = (List) node.getProperty(NodeConstants.Info.GROUP_COLS);
- gnode.setGroupingElements( gCols );
gnode.setRemoveDuplicates(node.hasBooleanProperty(NodeConstants.Info.IS_DUP_REMOVAL));
orderBy = (OrderBy) node.getProperty(Info.SORT_ORDER);
if (orderBy == null) {
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java 2011-07-26 20:20:59 UTC (rev 3336)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java 2011-07-27 10:59:10 UTC (rev 3337)
@@ -166,8 +166,28 @@
if (!node.hasCollectionProperty(NodeConstants.Info.GROUP_COLS)) {
break;
}
+ List<SingleElementSymbol> output = (List<SingleElementSymbol>)node.getProperty(Info.OUTPUT_COLS);
+ boolean cardinalityDependent = false;
+ for (SingleElementSymbol singleElementSymbol : output) {
+ if (singleElementSymbol instanceof AggregateSymbol) {
+ AggregateSymbol agg = (AggregateSymbol)singleElementSymbol;
+ if (agg.isCardinalityDependent()) {
+ cardinalityDependent = true;
+ break;
+ }
+ }
+ }
if (mergeSortWithDupRemovalAcrossSource(node)) {
node.setProperty(NodeConstants.Info.IS_DUP_REMOVAL, true);
+ if (cardinalityDependent) {
+ PlanNode source = NodeEditor.findNodePreOrder(node, NodeConstants.Types.SOURCE);
+ List<SingleElementSymbol> sourceOutput = (List<SingleElementSymbol>)source.getProperty(Info.OUTPUT_COLS);
+ PlanNode child = node.getFirstChild();
+ while (child != source) {
+ child.setProperty(Info.OUTPUT_COLS, sourceOutput);
+ child = child.getFirstChild();
+ }
+ }
}
//TODO: check the join interesting order
parentBlocking = true;
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java 2011-07-26 20:20:59 UTC (rev 3336)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java 2011-07-27 10:59:10 UTC (rev 3337)
@@ -40,7 +40,7 @@
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
import org.teiid.language.SQLConstants.NonReserved;
-import org.teiid.query.analysis.AnalysisRecord;
+import org.teiid.language.SortSpecification.NullOrdering;
import org.teiid.query.eval.Evaluator;
import org.teiid.query.function.aggregate.AggregateFunction;
import org.teiid.query.function.aggregate.ArrayAgg;
@@ -56,6 +56,7 @@
import org.teiid.query.processor.BatchCollector;
import org.teiid.query.processor.ProcessorDataManager;
import org.teiid.query.processor.relational.SortUtility.Mode;
+import org.teiid.query.sql.lang.OrderBy;
import org.teiid.query.sql.lang.OrderByItem;
import org.teiid.query.sql.symbol.AggregateSymbol;
import org.teiid.query.sql.symbol.ElementSymbol;
@@ -63,13 +64,13 @@
import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.sql.symbol.TextLine;
import org.teiid.query.sql.symbol.AggregateSymbol.Type;
+import org.teiid.query.sql.util.SymbolMap;
import org.teiid.query.util.CommandContext;
public class GroupingNode extends RelationalNode {
// Grouping columns set by the planner
- private List sortElements;
private List<OrderByItem> orderBy;
private boolean removeDuplicates;
@@ -77,6 +78,7 @@
private int phase = COLLECTION;
private Map elementMap; // Map of incoming symbol to index in source elements
private List<Expression> collectedExpressions; // Collected Expressions
+ private int distinctCols = -1;
// Sort phase
private SortUtility sortUtility;
@@ -118,17 +120,6 @@
this.removeDuplicates = removeDuplicates;
}
- /**
- * Called by the planner to initialize the grouping node. Set the list of grouping
- * expressions - these may be either elements or expressions and the list itself may
- * be null to indicate an implied grouping on all columns
- * @param groupingElements
- * @since 4.2
- */
- public void setGroupingElements(List groupingElements) {
- this.sortElements = groupingElements;
- }
-
public void setOrderBy(List<OrderByItem> orderBy) {
this.orderBy = orderBy;
}
@@ -143,13 +134,22 @@
}
// Incoming elements and lookup map for evaluating expressions
- List sourceElements = this.getChildren()[0].getElements();
+ List<SingleElementSymbol> sourceElements = this.getChildren()[0].getElements();
this.elementMap = createLookupMap(sourceElements);
// List should contain all grouping columns / expressions as we need those for sorting
- if(this.sortElements != null) {
- this.collectedExpressions = new ArrayList<Expression>(this.sortElements.size() + getElements().size());
- this.collectedExpressions.addAll(sortElements);
+ if(this.orderBy != null) {
+ this.collectedExpressions = new ArrayList<Expression>(this.orderBy.size() + getElements().size());
+ for (OrderByItem item : this.orderBy) {
+ Expression ex = SymbolMap.getExpression(item.getSymbol());
+ this.collectedExpressions.add(ex);
+ }
+ if (removeDuplicates) {
+ for (SingleElementSymbol ses : sourceElements) {
+ collectExpression(ses);
+ }
+ }
+ distinctCols = collectedExpressions.size();
} else {
this.collectedExpressions = new ArrayList<Expression>(getElements().size());
}
@@ -299,13 +299,32 @@
}
private void collectionPhase() {
- if(this.sortElements == null) {
+ if(this.orderBy == null) {
// No need to sort
this.groupTupleSource = getCollectionTupleSource();
this.phase = GROUP;
} else {
- this.sortUtility = new SortUtility(getCollectionTupleSource(), orderBy, removeDuplicates?Mode.DUP_REMOVE_SORT:Mode.SORT, getBufferManager(),
- getConnectionID(), collectedExpressions);
+ List<NullOrdering> nullOrdering = new ArrayList<NullOrdering>(orderBy.size());
+ List<Boolean> sortTypes = new ArrayList<Boolean>(orderBy.size());
+ int size = orderBy.size();
+ if (this.removeDuplicates) {
+ //sort on all inputs
+ size = distinctCols;
+ }
+ int[] sortIndexes = new int[size];
+ for (int i = 0; i < size; i++) {
+ if (i < this.orderBy.size()) {
+ OrderByItem item = this.orderBy.get(i);
+ nullOrdering.add(item.getNullOrdering());
+ sortTypes.add(item.isAscending());
+ } else {
+ nullOrdering.add(null);
+ sortTypes.add(OrderBy.ASC);
+ }
+ sortIndexes[i] = i;
+ }
+ this.sortUtility = new SortUtility(getCollectionTupleSource(), removeDuplicates?Mode.DUP_REMOVE_SORT:Mode.SORT, getBufferManager(),
+ getConnectionID(), collectedExpressions, sortTypes, nullOrdering, sortIndexes);
this.phase = SORT;
}
}
@@ -353,7 +372,7 @@
updateAggregates(currentGroupTuple);
currentGroupTuple = null;
}
- if(lastRow != null || sortElements == null) {
+ if(lastRow != null || orderBy == null) {
// Close last group
List row = new ArrayList(functions.length);
for(int i=0; i<functions.length; i++) {
@@ -369,12 +388,12 @@
private boolean sameGroup(List newTuple, List oldTuple) {
// Check for no grouping columns
- if(sortElements == null) {
+ if(orderBy == null) {
return true;
}
// Walk backwards through sort cols as the last columns are most likely to be different
- for(int i=sortElements.size()-1; i>=0; i--) {
+ for(int i=orderBy.size()-1; i>=0; i--) {
Object oldValue = oldTuple.get(i);
Object newValue = newTuple.get(i);
@@ -412,13 +431,12 @@
protected void getNodeString(StringBuffer str) {
super.getNodeString(str);
- str.append(sortElements);
+ str.append(orderBy);
}
public Object clone(){
GroupingNode clonedNode = new GroupingNode(super.getID());
super.copy(this, clonedNode);
- clonedNode.sortElements = sortElements;
clonedNode.removeDuplicates = removeDuplicates;
clonedNode.orderBy = orderBy;
return clonedNode;
@@ -428,17 +446,14 @@
// Default implementation - should be overridden
PlanNode props = super.getDescriptionProperties();
- if(sortElements != null) {
- int elements = sortElements.size();
+ if(orderBy != null) {
+ int elements = orderBy.size();
List<String> groupCols = new ArrayList<String>(elements);
for(int i=0; i<elements; i++) {
- groupCols.add(this.sortElements.get(i).toString());
+ groupCols.add(this.orderBy.get(i).toString());
}
props.addProperty(PROP_GROUP_COLS, groupCols);
}
- if (orderBy != null) {
- props.addProperty(AnalysisRecord.PROP_SORT_COLS, orderBy.toString());
- }
props.addProperty(PROP_SORT_MODE, String.valueOf(this.removeDuplicates));
return props;
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/SortUtility.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/SortUtility.java 2011-07-26 20:20:59 UTC (rev 3336)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/SortUtility.java 2011-07-27 10:59:10 UTC (rev 3337)
@@ -45,6 +45,7 @@
import org.teiid.query.sql.lang.OrderBy;
import org.teiid.query.sql.lang.OrderByItem;
import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
/**
@@ -109,18 +110,11 @@
public SortUtility(TupleSource sourceID, List<OrderByItem> items, Mode mode, BufferManager bufferMgr,
String groupName, List schema) {
- this.source = sourceID;
- this.mode = mode;
- this.bufferManager = bufferMgr;
- this.groupName = groupName;
- this.schema = schema;
- this.schemaSize = bufferManager.getSchemaSize(this.schema);
- int distinctIndex = items != null? items.size() - 1:0;
List<Expression> sortElements = null;
List<Boolean> sortTypes = null;
List<NullOrdering> nullOrderings = null;
if (items == null) {
- sortElements = (List<Expression>) this.schema;
+ sortElements = (List<Expression>) schema;
sortTypes = Collections.nCopies(sortElements.size(), OrderBy.ASC);
} else {
sortElements = new ArrayList(items.size());
@@ -147,7 +141,29 @@
cols[iter.previousIndex()] = schema.indexOf(elem);
Assertion.assertTrue(cols[iter.previousIndex()] != -1);
}
+ init(sourceID, mode, bufferMgr, groupName, schema, sortTypes,
+ nullOrderings, cols);
+ }
+
+ public SortUtility(TupleSource sourceID, Mode mode, BufferManager bufferMgr,
+ String groupName, List<? extends Expression> schema,
+ List<Boolean> sortTypes, List<NullOrdering> nullOrderings,
+ int[] cols) {
+ init(sourceID, mode, bufferMgr, groupName, schema, sortTypes, nullOrderings, cols);
+ }
+
+ private void init(TupleSource sourceID, Mode mode, BufferManager bufferMgr,
+ String groupName, List<? extends Expression> schema,
+ List<Boolean> sortTypes, List<NullOrdering> nullOrderings,
+ int[] cols) {
+ this.source = sourceID;
+ this.mode = mode;
+ this.bufferManager = bufferMgr;
+ this.groupName = groupName;
+ this.schema = schema;
+ this.schemaSize = bufferManager.getSchemaSize(this.schema);
this.comparator = new ListNestedSortComparator(cols, sortTypes);
+ int distinctIndex = cols.length - 1;
this.comparator.setDistinctIndex(distinctIndex);
this.comparator.setNullOrdering(nullOrderings);
}
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java 2011-07-26 20:20:59 UTC (rev 3336)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java 2011-07-27 10:59:10 UTC (rev 3337)
@@ -179,6 +179,8 @@
return DataTypeManager.DefaultDataClasses.DOUBLE;
} else if (this.aggregate == Type.ARRAY_AGG) {
return DataTypeManager.DefaultDataClasses.OBJECT;
+ } else if (this.aggregate == Type.TEXTAGG) {
+ return DataTypeManager.DefaultDataClasses.BLOB;
} else {
return this.getExpression().getType();
}
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/sql/symbol/TextLine.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/sql/symbol/TextLine.java 2011-07-26 20:20:59 UTC (rev 3336)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/sql/symbol/TextLine.java 2011-07-27 10:59:10 UTC (rev 3337)
@@ -88,7 +88,7 @@
@Override
public Class<?> getType() {
- return DataTypeManager.DefaultDataClasses.BLOB;
+ return DataTypeManager.DefaultDataClasses.STRING;
}
@Override
Modified: branches/7.4.x/engine/src/test/java/org/teiid/query/processor/TestAggregateProcessing.java
===================================================================
--- branches/7.4.x/engine/src/test/java/org/teiid/query/processor/TestAggregateProcessing.java 2011-07-26 20:20:59 UTC (rev 3336)
+++ branches/7.4.x/engine/src/test/java/org/teiid/query/processor/TestAggregateProcessing.java 2011-07-27 10:59:10 UTC (rev 3337)
@@ -399,5 +399,22 @@
// Run query
helpProcess(plan, cc, dataManager, expected);
}
+
+ @Test public void testDupGroupCombination() throws Exception {
+ String sql = "select count(e2), e1 from (select distinct e1, e2, e3 from pm1.g1) x group by e1"; //$NON-NLS-1$
+ List[] expected = new List[] {
+ Arrays.asList(2, "a"),
+ };
+
+ HardcodedDataManager dataManager = new HardcodedDataManager();
+ dataManager.addData("SELECT pm1.g1.e1, pm1.g1.e2, pm1.g1.e3 FROM pm1.g1", new List[] {
+ Arrays.asList("a", 0, Boolean.TRUE),
+ Arrays.asList("a", 0, Boolean.FALSE),
+ });
+
+ ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached());
+ helpProcess(plan, dataManager, expected);
+ }
+
}
Modified: branches/7.4.x/engine/src/test/java/org/teiid/query/processor/relational/TestGroupingNode.java
===================================================================
--- branches/7.4.x/engine/src/test/java/org/teiid/query/processor/relational/TestGroupingNode.java 2011-07-26 20:20:59 UTC (rev 3336)
+++ branches/7.4.x/engine/src/test/java/org/teiid/query/processor/relational/TestGroupingNode.java 2011-07-27 10:59:10 UTC (rev 3337)
@@ -22,7 +22,7 @@
package org.teiid.query.processor.relational;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.*;
import java.math.BigDecimal;
import java.util.ArrayList;
@@ -45,6 +45,7 @@
import org.teiid.query.processor.FakeDataManager;
import org.teiid.query.processor.FakeTupleSource;
import org.teiid.query.processor.ProcessorDataManager;
+import org.teiid.query.sql.lang.OrderBy;
import org.teiid.query.sql.symbol.AggregateSymbol;
import org.teiid.query.sql.symbol.Constant;
import org.teiid.query.sql.symbol.ElementSymbol;
@@ -153,7 +154,7 @@
List groupingElements = new ArrayList();
groupingElements.add(col1);
- node.setGroupingElements(groupingElements);
+ node.setOrderBy(new OrderBy(groupingElements).getOrderByItems());
CommandContext context = new CommandContext("pid", "test", null, null, 1); //$NON-NLS-1$ //$NON-NLS-2$
List[] expected = new List[] {
@@ -231,8 +232,6 @@
outputElements.add(new AggregateSymbol("bigAvg", "AVG", false, bigDecimal)); //$NON-NLS-1$ //$NON-NLS-2$
node.setElements(outputElements);
- // Set grouping elements to null
- node.setGroupingElements(null);
CommandContext context = new CommandContext("pid", "test", null, null, 1); //$NON-NLS-1$ //$NON-NLS-2$
List[] data = new List[] {
@@ -272,7 +271,7 @@
// Set grouping elements to null
List groupingElements = new ArrayList();
groupingElements.add(col1);
- node.setGroupingElements(groupingElements);
+ node.setOrderBy(new OrderBy(groupingElements).getOrderByItems());
CommandContext context = new CommandContext("pid", "test", null, null, 1); //$NON-NLS-1$ //$NON-NLS-2$
List[] data = new List[] {
@@ -320,7 +319,7 @@
List groupingElements = new ArrayList();
groupingElements.add(col1);
- node.setGroupingElements(groupingElements);
+ node.setOrderBy(new OrderBy(groupingElements).getOrderByItems());
CommandContext context = new CommandContext("pid", "test", null, null, 1); //$NON-NLS-1$ //$NON-NLS-2$
FakeDataManager dataMgr = new FakeDataManager();
@@ -366,7 +365,7 @@
if (groupBy) {
List groupingElements = new ArrayList();
groupingElements.add(new ElementSymbol("col1")); //$NON-NLS-1$
- node.setGroupingElements(groupingElements);
+ node.setOrderBy(new OrderBy(groupingElements).getOrderByItems());
}
CommandContext context = new CommandContext("pid", "test", null, null, 1); //$NON-NLS-1$ //$NON-NLS-2$
@@ -434,7 +433,7 @@
List groupingElements = new ArrayList();
groupingElements.add(col1);
- node.setGroupingElements(groupingElements);
+ node.setOrderBy(new OrderBy(groupingElements).getOrderByItems());
return node;
}
13 years, 5 months
teiid SVN: r3336 - in branches/7.4.x/engine/src: test/java/org/teiid/dqp/internal/process and 1 other directory.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-07-26 16:20:59 -0400 (Tue, 26 Jul 2011)
New Revision: 3336
Modified:
branches/7.4.x/engine/src/main/java/org/teiid/query/processor/BatchCollector.java
branches/7.4.x/engine/src/test/java/org/teiid/dqp/internal/process/TestDQPCore.java
Log:
TEIID-1686 fix for assertion error
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/processor/BatchCollector.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/processor/BatchCollector.java 2011-07-26 20:13:42 UTC (rev 3335)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/processor/BatchCollector.java 2011-07-26 20:20:59 UTC (rev 3336)
@@ -150,7 +150,9 @@
// Check for termination condition
if(batch.getTerminationFlag()) {
done = true;
- buffer.close();
+ if (!this.sourceNode.hasFinalBuffer()) {
+ buffer.close();
+ }
break;
}
}
Modified: branches/7.4.x/engine/src/test/java/org/teiid/dqp/internal/process/TestDQPCore.java
===================================================================
--- branches/7.4.x/engine/src/test/java/org/teiid/dqp/internal/process/TestDQPCore.java 2011-07-26 20:13:42 UTC (rev 3335)
+++ branches/7.4.x/engine/src/test/java/org/teiid/dqp/internal/process/TestDQPCore.java 2011-07-26 20:20:59 UTC (rev 3336)
@@ -363,6 +363,27 @@
assertEquals(1, agds.getExecuteCount().get());
}
+ @Test public void testUsingFinalBuffer() throws Exception {
+ String sql = "select intkey from bqt1.smalla union select 1";
+ ((BufferManagerImpl)core.getBufferManager()).setProcessorBatchSize(2);
+ agds.sleep = 500;
+ RequestMessage reqMsg = exampleRequestMessage(sql);
+ Future<ResultsMessage> message = core.executeRequest(reqMsg.getExecutionId(), reqMsg);
+ ResultsMessage rm = message.get(500000, TimeUnit.MILLISECONDS);
+ assertNull(rm.getException());
+ assertEquals(1, rm.getResults().length);
+
+ message = core.processCursorRequest(reqMsg.getExecutionId(), 3, 2);
+ rm = message.get(500000, TimeUnit.MILLISECONDS);
+ assertNull(rm.getException());
+ assertEquals(1, rm.getResults().length);
+
+ message = core.processCursorRequest(reqMsg.getExecutionId(), 3, 2);
+ rm = message.get(500000, TimeUnit.MILLISECONDS);
+ assertNull(rm.getException());
+ assertEquals(0, rm.getResults().length);
+ }
+
@Test public void testPreparedPlanInvalidation() throws Exception {
String sql = "insert into #temp select * FROM vqt.SmallB"; //$NON-NLS-1$
String userName = "1"; //$NON-NLS-1$
13 years, 5 months
teiid SVN: r3335 - branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-07-26 16:13:42 -0400 (Tue, 26 Jul 2011)
New Revision: 3335
Modified:
branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java
Log:
removing invalid system out trace
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java 2011-07-25 18:19:13 UTC (rev 3334)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java 2011-07-26 20:13:42 UTC (rev 3335)
@@ -266,9 +266,6 @@
public void processRow(NodeInfo row) {
this.item = row;
rowCount++;
- if (rowCount % 100 == 0) {
- System.out.println(System.currentTimeMillis() + " " + rowCount);
- }
try {
this.buffer.addTuple(processRow());
} catch (TeiidException e) {
13 years, 5 months