Author: shawkins
Date: 2012-09-06 15:02:53 -0400 (Thu, 06 Sep 2012)
New Revision: 4406
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleImplementJoinStrategy.java
trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java
Log:
TEIID-2190 ensuring index use retains all equi-join predicates
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleImplementJoinStrategy.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleImplementJoinStrategy.java 2012-09-06
15:58:12 UTC (rev 4405)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleImplementJoinStrategy.java 2012-09-06
19:02:53 UTC (rev 4406)
@@ -25,8 +25,10 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.teiid.api.exception.query.QueryMetadataException;
@@ -131,44 +133,51 @@
key = NewCalculateCostUtil.getKeyUsed(leftExpressions, null, metadata,
null);
right = false;
}
- if (key != null) {
+ if (key != null &&
joinNode.getProperty(NodeConstants.Info.DEPENDENT_VALUE_SOURCE) == null) {
//redo the join predicates based upon the key alone
List<Object> keyCols = metadata.getElementIDsInKey(key);
int[] reorder = new int[keyCols.size()];
- List<Integer> toCriteria = new
ArrayList<Integer>(rightExpressions.size() - keyCols.size());
+ LinkedHashSet<Integer> toCriteria = new
LinkedHashSet<Integer>();
List<Expression> keyExpressions =
right?rightExpressions:leftExpressions;
- for (int j = 0; j < keyExpressions.size(); j++) {
- Expression ses = keyExpressions.get(j);
- if (!(ses instanceof ElementSymbol)) {
+ Map<Object, Integer> indexMap = new LinkedHashMap<Object,
Integer>();
+ for (int i = 0; i < keyExpressions.size(); i++) {
+ Expression ses = keyExpressions.get(i);
+ if (!(ses instanceof ElementSymbol)) {
continue;
}
- ElementSymbol es = (ElementSymbol)ses;
- boolean found = false;
- for (int i = 0; !found && i < keyCols.size(); i++) {
- if (es.getMetadataID().equals(keyCols.get(i))) {
- reorder[i] = j;
- found = true;
+ Integer existing = indexMap.put(((ElementSymbol)ses).getMetadataID(), i);
+ if (existing != null) {
+ toCriteria.add(existing);
+ }
+ }
+ boolean found = true;
+ for (int i = 0; i < keyCols.size(); i++) {
+ Object id = keyCols.get(i);
+ Integer index = indexMap.remove(id);
+ if (index == null) {
+ found = false;
+ break;
+ }
+ reorder[i] = index;
+ }
+ if (found) {
+ toCriteria.addAll(indexMap.values());
+ List<Criteria> joinCriteria = (List<Criteria>)
joinNode.getProperty(Info.NON_EQUI_JOIN_CRITERIA);
+ for (int index : toCriteria) {
+ Expression lses = leftExpressions.get(index);
+ Expression rses = rightExpressions.get(index);
+ CompareCriteria cc = new CompareCriteria(lses, CompareCriteria.EQ, rses);
+ if (joinCriteria == null || joinCriteria.isEmpty()) {
+ joinCriteria = new ArrayList<Criteria>();
}
- }
- if (!found) {
- toCriteria.add(j);
- }
- }
- List<Criteria> joinCriteria = (List<Criteria>)
joinNode.getProperty(Info.NON_EQUI_JOIN_CRITERIA);
- for (int index : toCriteria) {
- Expression lses = leftExpressions.get(index);
- Expression rses = rightExpressions.get(index);
- CompareCriteria cc = new CompareCriteria(lses, CompareCriteria.EQ, rses);
- if (joinCriteria == null || joinCriteria.isEmpty()) {
- joinCriteria = new ArrayList<Criteria>();
joinCriteria.add(cc);
}
- }
- joinNode.setProperty(Info.NON_EQUI_JOIN_CRITERIA, joinCriteria);
- leftExpressions = RelationalNode.projectTuple(reorder, leftExpressions);
- rightExpressions = RelationalNode.projectTuple(reorder, rightExpressions);
- joinNode.setProperty(NodeConstants.Info.LEFT_EXPRESSIONS, leftExpressions);
- joinNode.setProperty(NodeConstants.Info.RIGHT_EXPRESSIONS,
rightExpressions);
+ joinNode.setProperty(Info.NON_EQUI_JOIN_CRITERIA, joinCriteria);
+ leftExpressions = RelationalNode.projectTuple(reorder, leftExpressions);
+ rightExpressions = RelationalNode.projectTuple(reorder, rightExpressions);
+ joinNode.setProperty(NodeConstants.Info.LEFT_EXPRESSIONS,
leftExpressions);
+ joinNode.setProperty(NodeConstants.Info.RIGHT_EXPRESSIONS,
rightExpressions);
+ }
}
boolean pushedLeft = insertSort(joinNode.getFirstChild(), leftExpressions, joinNode,
metadata, capabilitiesFinder, pushLeft);
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java 2012-09-06
15:58:12 UTC (rev 4405)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java 2012-09-06
19:02:53 UTC (rev 4406)
@@ -475,9 +475,25 @@
execute("insert into x (e2, e1) values (2, 'b')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
execute("insert into x1 (e2, e1) values (3, 'b')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
execute("select x.e1 from x makenotdep, x1 makenotdep where x.e2 = x1.e2 and x.e1
= x1.e1", new List[0]); //$NON-NLS-1$
+ //ensure join is preserved
execute("select x.e1 from x left outer join x1 on x.e2 = x1.e2 and x.e1 =
x1.e1", new List[] {Arrays.asList("b")}); //$NON-NLS-1$
}
+ @Test public void testUnneededMergePredicate1() throws Exception {
+ execute("create local temporary table x (e1 string, e2 integer, e3 integer,
primary key (e1))", new List[] {Arrays.asList(0)}); //$NON-NLS-1$
+ execute("create local temporary table x1 (e1 string, e2 integer, e3
integer)", new List[] {Arrays.asList(0)}); //$NON-NLS-1$
+
+ execute("insert into x (e3, e2, e1) values (4, 2, '1')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ execute("insert into x (e3, e2, e1) values (4, 2, '2')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ execute("insert into x1 (e3, e2, e1) values (5, 2, '1')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ execute("insert into x1 (e3, e2, e1) values (5, 1, '2')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ //ensure predicates are preserved
+ execute("select x.e1 from /*+ makenotdep */ x inner join /*+ makenotdep */ x1 on
x.e1 = x1.e1 and upper(x.e1) = x1.e2", new List[] {Arrays.asList("1"),
Arrays.asList("2")}); //$NON-NLS-1$
+ execute("select x.e1 from /*+ makenotdep */ x inner join /*+ makenotdep */ x1 on
x.e1 = x1.e1 and upper(x.e1) = x1.e2 and x1.e3 = x.e3", new List[0]); //$NON-NLS-1$
+ //ensure there's no bad interaction with makedep
+ execute("select x.e1 from /*+ makedep */ x inner join x1 on x.e1 = x1.e1 and x.e2
= x1.e2", new List[] {Arrays.asList("1")}); //$NON-NLS-1$
+ }
+
private void sampleTable() throws Exception {
execute("create local temporary table x (e1 string, e2 integer, primary key (e1,
e2))", new List[] {Arrays.asList(0)}); //$NON-NLS-1$
execute("insert into x (e2, e1) values (3, 'b')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$