Author: shawkins
Date: 2010-07-28 11:20:07 -0400 (Wed, 28 Jul 2010)
New Revision: 2383
Modified:
trunk/common-core/src/main/java/org/teiid/core/types/XMLType.java
trunk/engine/src/main/java/org/teiid/common/buffer/TupleBrowser.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java
trunk/engine/src/main/java/org/teiid/query/tempdata/IndexCondition.java
trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java
trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java
Log:
TEIID-1167 cleaning up index condition logic
Modified: trunk/common-core/src/main/java/org/teiid/core/types/XMLType.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/types/XMLType.java 2010-07-28 04:40:32
UTC (rev 2382)
+++ trunk/common-core/src/main/java/org/teiid/core/types/XMLType.java 2010-07-28 15:20:07
UTC (rev 2383)
@@ -127,6 +127,11 @@
} catch (OptionalDataException e) {
this.encoding = Streamable.ENCODING;
}
+ try {
+ this.type = (Type)in.readObject();
+ } catch (OptionalDataException e) {
+ this.type = Type.UNKNOWN;
+ }
}
@Override
@@ -136,6 +141,7 @@
this.encoding = getEncoding(this);
}
out.writeObject(this.encoding);
+ out.writeObject(this.type);
}
/**
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/TupleBrowser.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/TupleBrowser.java 2010-07-28
04:40:32 UTC (rev 2382)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/TupleBrowser.java 2010-07-28
15:20:07 UTC (rev 2383)
@@ -31,15 +31,12 @@
/**
* Implements intelligent browsing over a {@link STree}
- *
- * TODO: when using other values we can be more efficient
- * with paging.
*/
public class TupleBrowser {
private final STree tree;
- private List<List<?>> otherValues;
+ private List<List<Object>> valueSet;
private SPage page;
private int index;
@@ -50,13 +47,30 @@
private TupleBatch values;
private boolean updated;
private boolean direction;
- private boolean range;
+
+ /**
+ * Construct a value based browser
+ * @param sTree
+ * @param valueSet
+ * @param direction
+ */
+ public TupleBrowser(STree sTree, List<List<Object>> valueSet, boolean
direction) {
+ this.tree = sTree;
+ this.direction = direction;
+ this.valueSet = valueSet;
+ }
- public TupleBrowser(STree sTree, List<?> lowerBound, List<?> upperBound,
List<List<?>> otherValues, boolean range, boolean direction) throws
TeiidComponentException {
+ /**
+ * Construct a range based browser
+ * @param sTree
+ * @param lowerBound
+ * @param upperBound
+ * @param direction
+ * @throws TeiidComponentException
+ */
+ public TupleBrowser(STree sTree, List<Object> lowerBound, List<Object>
upperBound, boolean direction) throws TeiidComponentException {
this.tree = sTree;
this.direction = direction;
- this.otherValues = otherValues;
- this.range = range;
if (lowerBound != null) {
setPage(lowerBound);
@@ -81,16 +95,11 @@
if (!direction) {
values = upper.values;
}
- } else if (range) {
- //this is a range query
- //TODO: this could also be signaled with an all null key
+ } else {
bound = tree.header[0];
while (bound.next != null) {
bound = bound.next;
}
- } else {
- bound = page;
- boundIndex = index;
}
if (!direction) {
@@ -107,32 +116,65 @@
}
}
- private void setPage(List<?> lowerBound) throws TeiidComponentException {
- if (values != null) {
- int possibleIndex = Collections.binarySearch(values.getTuples(), lowerBound,
tree.comparator);
- if (possibleIndex != -1 && possibleIndex != -values.getTuples().size() -1) {
- index = possibleIndex;
- if (possibleIndex < 0) {
- index = -index -1;
- }
- return;
- }
- }
- resetState();
+ private boolean setPage(List<?> lowerBound) throws TeiidComponentException {
LinkedList<SearchResult> places = new LinkedList<SearchResult>();
this.tree.find(lowerBound, places);
SearchResult sr = places.getLast();
page = sr.page;
index = sr.index;
+ boolean result = true;
if (index < 0) {
+ result = false;
index = -index - 1;
}
values = sr.values;
+ return result;
}
+ /**
+ * Returns the next tuple or null if there are no more results.
+ * @return
+ * @throws TeiidComponentException
+ */
public List<?> next() throws TeiidComponentException {
for (;;) {
+ //first check for value iteration
+ if (valueSet != null) {
+ if (valueSet.isEmpty()) {
+ resetState();
+ return null;
+ }
+ List<?> newValue = direction?valueSet.remove(0):valueSet.remove(valueSet.size()
-1);
+ if (values != null) {
+ int possibleIndex = Collections.binarySearch(values.getTuples(), newValue,
tree.comparator);
+ if (possibleIndex >= 0) {
+ //value exists in the current page
+ index = possibleIndex;
+ return values.getTuples().get(possibleIndex);
+ }
+ //check for end/terminal conditions
+ if (direction && possibleIndex == -values.getTuples().size() -1) {
+ if (page.next == null) {
+ resetState();
+ return null;
+ }
+ } else if (!direction && possibleIndex == -1) {
+ if (page.prev == null) {
+ resetState();
+ return null;
+ }
+ } else {
+ //the value simply doesn't exist
+ continue;
+ }
+ }
+ resetState();
+ if (!setPage(newValue)) {
+ continue;
+ }
+ return values.getTuples().get(index);
+ }
if (page == null) {
return null;
}
@@ -149,19 +191,6 @@
if (page == bound && index == boundIndex) {
resetState();
page = null; //terminate
- } else if (otherValues != null && !range) {
- if (!otherValues.isEmpty()) {
- List newBound =
direction?otherValues.remove(0):otherValues.remove(otherValues.size() -1);
- setPage(newBound);
- } else {
- otherValues = null;
- if (page != bound) {
- resetState();
- }
- page = bound;
- index = boundIndex;
- values = bound.values;
- }
} else {
index+=getOffset();
}
@@ -185,6 +214,9 @@
}
private int getOffset() {
+ if (valueSet != null) {
+ return 0;
+ }
return direction?1:-1;
}
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 2010-07-28
04:40:32 UTC (rev 2382)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java 2010-07-28
15:20:07 UTC (rev 2383)
@@ -191,13 +191,9 @@
pinode.setIntoElements(allIntoElements);
pinode.setModelName(modelName);
processNode = pinode;
- if (!metadata.isTemporaryTable(groupID)) {
- SourceCapabilities caps =
capFinder.findCapabilities(modelName);
-
pinode.setDoBatching(caps.supportsCapability(Capability.BATCHED_UPDATES));
-
pinode.setDoBulkInsert(caps.supportsCapability(Capability.BULK_UPDATE));
- } else {
- pinode.setDoBulkInsert(true);
- }
+ SourceCapabilities caps =
capFinder.findCapabilities(modelName);
+
pinode.setDoBatching(caps.supportsCapability(Capability.BATCHED_UPDATES));
+
pinode.setDoBulkInsert(caps.supportsCapability(Capability.BULK_UPDATE));
}
} catch(QueryMetadataException e) {
throw new TeiidComponentException(e);
Modified: trunk/engine/src/main/java/org/teiid/query/tempdata/IndexCondition.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/IndexCondition.java 2010-07-28
04:40:32 UTC (rev 2382)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/IndexCondition.java 2010-07-28
15:20:07 UTC (rev 2383)
@@ -35,13 +35,16 @@
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
+/**
+ * Accumulates information from criteria about a specific index column.
+ */
class IndexCondition {
static IndexCondition[] getIndexConditions(Criteria condition, List<ElementSymbol>
keyColumns) {
List<Criteria> crits = Criteria.separateCriteriaByAnd(condition);
IndexCondition[] conditions = new IndexCondition[keyColumns.size()];
for (int i = 0; i < conditions.length; i++) {
- if (i > 0 && (conditions[i - 1].range || conditions[i -1].upper != null))
{
+ if (i > 0 && conditions[i - 1].valueSet.size() != 1) {
break; //don't yet support any other types of composite key lookups
}
conditions[i] = new IndexCondition();
@@ -122,27 +125,25 @@
Constant lower = null;
Constant upper = null;
- boolean range = true;
- TreeSet<Constant> otherValues = new TreeSet<Constant>();
+ TreeSet<Constant> valueSet = new TreeSet<Constant>();
void addCondition(Constant value, int comparisionMode) {
switch (comparisionMode) {
case CompareCriteria.EQ:
- otherValues.clear();
- lower = value;
+ valueSet.clear();
+ valueSet.add(value);
+ lower = null;
upper = null;
- range = false;
break;
case CompareCriteria.GE:
case CompareCriteria.GT:
- if (lower == null) {
- range = true;
+ if (valueSet.isEmpty()) {
lower = value;
}
break;
case CompareCriteria.LE:
case CompareCriteria.LT:
- if (upper == null && range) {
+ if (valueSet.isEmpty()) {
upper = value;
}
break;
@@ -150,21 +151,12 @@
}
void addSet(TreeSet<Constant> values) {
- if (!range && lower != null) {
+ if (!valueSet.isEmpty()) {
return;
}
- Iterator<Constant> iter = values.iterator();
- Constant lowest = iter.next();
- iter.remove();
- lower = lowest;
- range = false;
- iter = values.descendingIterator();
- if (iter.hasNext()) {
- Constant highest = iter.next();
- upper = highest;
- iter.remove();
- }
- otherValues.addAll(values);
+ lower = null;
+ upper = null;
+ valueSet.addAll(values);
}
}
\ No newline at end of file
Modified: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java 2010-07-28 04:40:32
UTC (rev 2382)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java 2010-07-28 15:20:07
UTC (rev 2383)
@@ -300,18 +300,18 @@
}
private TupleBrowser createTupleBrower(Criteria condition, boolean direction) throws
TeiidComponentException {
- List lower = null;
- List upper = null;
- List<List<?>> otherValues = null;
- boolean range = true;
+ List<Object> lower = null;
+ List<Object> upper = null;
+ List<List<Object>> values = null;
if (condition != null && rowId == null) {
IndexCondition[] indexConditions = IndexCondition.getIndexConditions(condition,
columns.subList(0, tree.getKeyLength()));
if (indexConditions.length > 1 && indexConditions[indexConditions.length -
1] != null) {
- lower = new ArrayList(indexConditions.length);
+ List<Object> value = new ArrayList<Object>(indexConditions.length);
for (IndexCondition indexCondition : indexConditions) {
- lower.add(indexCondition.lower.getValue());
+ value.add(indexCondition.valueSet.iterator().next().getValue());
}
- range = false;
+ values = new ArrayList<List<Object>>(1);
+ values.add(value);
//TODO: support other composite key lookups
} else {
if (indexConditions[0].lower != null) {
@@ -320,14 +320,18 @@
if (indexConditions[0].upper != null) {
upper = Arrays.asList(indexConditions[0].upper.getValue());
}
- otherValues = new ArrayList<List<?>>();
- for (Constant constant : indexConditions[0].otherValues) {
- otherValues.add(Arrays.asList(constant.getValue()));
+ if (!indexConditions[0].valueSet.isEmpty()) {
+ values = new ArrayList<List<Object>>();
+ for (Constant constant : indexConditions[0].valueSet) {
+ values.add(Arrays.asList(constant.getValue()));
+ }
}
- range = indexConditions[0].range;
}
}
- return new TupleBrowser(this.tree, lower, upper, otherValues, range, direction);
+ if (values != null) {
+ return new TupleBrowser(this.tree, values, direction);
+ }
+ return new TupleBrowser(this.tree, lower, upper, direction);
}
public int getRowCount() {
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java 2010-07-28
04:40:32 UTC (rev 2382)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java 2010-07-28
15:20:07 UTC (rev 2383)
@@ -185,7 +185,25 @@
execute("insert into x (e2, e1) values (1, 'c')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
execute("insert into x (e2, e1) values (0, 'd')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
execute("insert into x (e2, e1) values (-1, 'e')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
- execute("select * from x where e1 in ('a', 'c',
'e')", new List[] {Arrays.asList("a", 3),
Arrays.asList("c", 1), Arrays.asList("e", -1)}); //$NON-NLS-1$
+ execute("select * from x where e1 in ('a', 'c', 'e',
'f', 'g')", new List[] {Arrays.asList("a", 3),
Arrays.asList("c", 1), Arrays.asList("e", -1)}); //$NON-NLS-1$
}
+ @Test public void testInWithIndexUpdate() throws Exception {
+ execute("create local temporary table x (e1 string, e2 integer, primary key
(e1))", new List[] {Arrays.asList(0)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (3, 'a')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (2, 'b')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (1, 'c')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (0, 'd')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (-1, 'e')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ execute("update x set e2 = 5 where e1 in ('a', 'c')", new
List[] {Arrays.asList(2)}); //$NON-NLS-1$
+ }
+
+ @Test public void testCompositeKeyCompareEquals() 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, 'a')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (2, 'b')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (1, 'c')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ execute("select * from x where e1 = 'b' and e2 = 2", new List[]
{Arrays.asList("b", 2)}); //$NON-NLS-1$
+ }
+
}