Author: shawkins
Date: 2010-07-23 17:44:19 -0400 (Fri, 23 Jul 2010)
New Revision: 2371
Added:
trunk/engine/src/main/java/org/teiid/common/buffer/SPage.java
trunk/engine/src/main/java/org/teiid/common/buffer/STree.java
trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java
trunk/engine/src/test/java/org/teiid/common/buffer/impl/TestSTree.java
Removed:
trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStoreImpl.java
trunk/engine/src/test/java/org/teiid/internal/
trunk/runtime/src/test/java/com/metamatrix/dqp/
Modified:
trunk/api/src/main/java/org/teiid/language/SQLConstants.java
trunk/build/kits/jboss-container/teiid-releasenotes.html
trunk/engine/src/main/java/org/teiid/common/buffer/BufferManager.java
trunk/engine/src/main/java/org/teiid/common/buffer/TupleBatch.java
trunk/engine/src/main/java/org/teiid/common/buffer/TupleBuffer.java
trunk/engine/src/main/java/org/teiid/common/buffer/impl/BufferManagerImpl.java
trunk/engine/src/main/java/org/teiid/common/buffer/impl/MemoryStorageManager.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/CodeTableCache.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanJoins.java
trunk/engine/src/main/java/org/teiid/query/processor/CollectionTupleSource.java
trunk/engine/src/main/java/org/teiid/query/processor/batch/BatchedUpdatePlan.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/PlanExecutionNode.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/ProjectIntoNode.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/UnionAllNode.java
trunk/engine/src/main/java/org/teiid/query/processor/xml/XMLPlan.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/TempTableResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/Create.java
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.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/TestCodeTableCache.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptionalJoins.java
trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestProjectIntoNode.java
trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java
trunk/engine/src/test/java/org/teiid/query/sql/util/TestElementSymbolOptimizer.java
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java
Log:
TEIID-1167 initial support for temp tables with primary keys. We're using a
simplified tree structure as the index with everything hooked (or forced) into the
existing buffer support. search optimizations and other concerns have not been hooked up
yet.
Modified: trunk/api/src/main/java/org/teiid/language/SQLConstants.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/SQLConstants.java 2010-07-23 20:47:35 UTC
(rev 2370)
+++ trunk/api/src/main/java/org/teiid/language/SQLConstants.java 2010-07-23 21:44:19 UTC
(rev 2371)
@@ -96,6 +96,8 @@
public static final String NULLS = "NULLS"; //$NON-NLS-1$
public static final String FIRST = "FIRST"; //$NON-NLS-1$
public static final String LAST = "LAST"; //$NON-NLS-1$
+
+ public static final String KEY = "KEY"; //$NON-NLS-1$
}
public interface Reserved {
Modified: trunk/build/kits/jboss-container/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-container/teiid-releasenotes.html 2010-07-23 20:47:35 UTC (rev
2370)
+++ trunk/build/kits/jboss-container/teiid-releasenotes.html 2010-07-23 21:44:19 UTC (rev
2371)
@@ -120,6 +120,7 @@
The following components have been updated:
<h4>From 7.0</h4>
<ul>
+ <li>Direct integration of JBossCache jars were removed.
<li>Netty was upgraded to 3.2.0
<li>JDOM was removed.
</ul>
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/BufferManager.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/BufferManager.java 2010-07-23
20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/BufferManager.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -114,4 +114,6 @@
*/
int getSchemaSize(List elements);
+ STree createSTree(final List elements, String groupName, TupleSourceType
tupleSourceType, int keyLength);
+
}
Added: trunk/engine/src/main/java/org/teiid/common/buffer/SPage.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/SPage.java
(rev 0)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/SPage.java 2010-07-23 21:44:19 UTC
(rev 2371)
@@ -0,0 +1,143 @@
+/*
+ * 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.common.buffer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.teiid.common.buffer.BatchManager.ManagedBatch;
+import org.teiid.core.TeiidComponentException;
+
+/**
+ * A linked list Page entry in the tree
+ */
+@SuppressWarnings("unchecked")
+class SPage {
+
+ static final int MIN_PERSISTENT_SIZE = 16;
+
+ static class SearchResult {
+ int index;
+ SPage page;
+ List values;
+ public SearchResult(int index, SPage page, List values) {
+ this.index = index;
+ this.page = page;
+ this.values = values;
+ }
+ }
+
+ private static AtomicInteger counter = new AtomicInteger();
+
+ STree stree;
+
+ protected SPage next;
+ protected ManagedBatch managedBatch;
+ protected List values;
+ protected ArrayList<SPage> children;
+
+ SPage(STree stree, boolean leaf) {
+ this.stree = stree;
+ this.values = new ArrayList<SPage>(stree.pageSize);
+ if (!leaf) {
+ children = new ArrayList<SPage>(stree.pageSize/4);
+ }
+ }
+
+ static SearchResult search(SPage page, List k, SearchResult parent, List parentKey)
throws TeiidComponentException {
+ SPage previous = null;
+ List previousValues = null;
+ for (;;) {
+ List values = page.getValues();
+ int index = Collections.binarySearch(values, k, page.stree.comparator);
+ int actual = - index - 1;
+ if (previous != null) {
+ if (actual == 0) {
+ if (values.isEmpty()) {
+ page.remove();
+ previous.next = page.next;
+ }
+ return new SearchResult(-previousValues.size() - 1, previous, previousValues);
+ }
+ if (parentKey != null) {
+ if (page.stree.comparator.compare(parentKey, values.get(0)) >= 0) {
+ //TODO: the entries after this point may also need moved forward
+ //TODO: this should be done as part of insert
+ parent.page.children.set(Math.max(0, -parent.index - 2), page);
+ } else {
+ //parentKey < page.keys.get(0)
+ //TODO: this circumvents the normal probabilistic process, but
+ //ensures there is an index entry.
+ page.stree.insert(page.stree.extractKey((List) values.get(0)), parent, page);
+ parent.index--;
+ }
+ }
+ }
+ if (actual != values.size() || page.next == null) {
+ return new SearchResult(index, page, values);
+ }
+ previous = page;
+ previousValues = values;
+ page = page.next;
+ }
+ }
+
+ protected void setValues(List values) throws TeiidComponentException {
+ if (managedBatch != null) {
+ managedBatch.remove();
+ }
+ if (values.size() < MIN_PERSISTENT_SIZE) {
+ this.values = values;
+ return;
+ }
+ this.values = null;
+ TupleBatch batch = TupleBatch.directBatch(counter.getAndIncrement(), values);
+ if (children != null) {
+ batch.setDataTypes(stree.keytypes);
+ } else {
+ batch.setDataTypes(stree.types);
+ }
+ managedBatch = stree.manager.createManagedBatch(batch);
+ }
+
+ protected void remove() {
+ if (managedBatch != null) {
+ managedBatch.remove();
+ managedBatch = null;
+ }
+ }
+
+ protected List getValues() throws TeiidComponentException {
+ if (values != null) {
+ return values;
+ }
+ if (managedBatch == null) {
+ return Collections.emptyList();
+ }
+ TupleBatch batch = managedBatch.getBatch(true, stree.types);
+ return batch.getTuples();
+ }
+
+}
Property changes on: trunk/engine/src/main/java/org/teiid/common/buffer/SPage.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/engine/src/main/java/org/teiid/common/buffer/STree.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/STree.java
(rev 0)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/STree.java 2010-07-23 21:44:19 UTC
(rev 2371)
@@ -0,0 +1,343 @@
+/*
+ * 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.common.buffer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.teiid.common.buffer.SPage.SearchResult;
+import org.teiid.core.TeiidComponentException;
+
+@SuppressWarnings("unchecked")
+
+/**
+ * Self balancing search tree using skip list like logic
+ * This has similar performance similar to a B+/-Tree
+ *
+ * TODO: reserve additional memory for delete/update operations
+ * TODO: double link to support desc key access
+ */
+public class STree {
+
+ private static final Random seedGenerator = new Random();
+
+ private int randomSeed;
+ private SPage[] header = new SPage[] {new SPage(this, true)};
+ protected BatchManager manager;
+ protected Comparator comparator;
+ protected int pageSize;
+ protected int keyLength;
+ protected String[] types;
+ protected String[] keytypes;
+
+ private AtomicInteger rowCount = new AtomicInteger();
+
+ public STree(BatchManager recman,
+ final Comparator comparator,
+ int pageSize,
+ int keyLength,
+ String[] types) {
+ randomSeed = seedGenerator.nextInt() | 0x00000100; // ensure nonzero
+ this.manager = recman;
+ this.comparator = comparator;
+ this.pageSize = Math.max(pageSize, SPage.MIN_PERSISTENT_SIZE);
+ this.keyLength = keyLength;
+ this.types = types;
+ this.keytypes = Arrays.copyOf(types, keyLength);
+ }
+
+ /**
+ * Determine a new random level using an XOR rng.
+ *
+ * This uses the simplest of the generators described in George
+ * Marsaglia's "Xorshift RNGs" paper. This is not a high-quality
+ * generator but is acceptable here.
+ *
+ * See also the JSR-166 working group ConcurrentSkipListMap implementation.
+ *
+ * @return
+ */
+ private int randomLevel() {
+ int x = randomSeed;
+ x ^= x << 13;
+ x ^= x >>> 17;
+ randomSeed = x ^= x << 5;
+ int level = 0;
+ int shift = 8;
+ while ((x & 0xff) == 0xff) {
+ ++level;
+ x >>>= shift;
+ }
+ return level;
+ }
+
+ /**
+ * Search each level to find the pointer to the next level
+ * @param n
+ * @param places
+ * @return
+ * @throws IOException
+ * @throws TeiidComponentException
+ */
+ private List find(List n, List<SearchResult> places) throws
TeiidComponentException {
+ SPage x = null;
+ List parentKey = null;
+ SearchResult parent = null;
+ for (int i = header.length - 1; i >= 0; i--) {
+ if (x == null) {
+ x = header[i];
+ }
+ SearchResult s = SPage.search(x, n, parent, parentKey);
+ if (places != null) {
+ places.add(s);
+ }
+ if ((s.index == -1 && s.page == header[i]) || s.values.isEmpty()) {
+ x = null;
+ continue; //start at the beginning of the next level
+ }
+ x = s.page;
+ int index = s.index;
+ boolean matched = true;
+ if (index < 0) {
+ matched = false;
+ index = Math.max(0, -index - 2);
+ }
+ if (i == 0) {
+ if (!matched) {
+ return null;
+ }
+ return (List) s.values.get(index);
+ }
+ parentKey = (List) s.values.get(index);
+ parent = s;
+ x = x.children.get(index);
+ }
+ return null;
+ }
+
+ public List find(List k) throws TeiidComponentException {
+ return find(k, null);
+ }
+
+ public List insert(List tuple, boolean replace) throws TeiidComponentException {
+ LinkedList<SearchResult> places = new LinkedList<SearchResult>();
+ List match = find(tuple, places);
+ if (match != null) {
+ if (!replace) {
+ return match;
+ }
+ SearchResult last = places.getLast();
+ SPage page = last.page;
+ last.values.set(last.index, tuple);
+ page.setValues(last.values);
+ return match;
+ }
+ List key = extractKey(tuple);
+ int level = randomLevel();
+ assert header.length == places.size();
+ if (level >= header.length) {
+ header = Arrays.copyOf(header, level + 1);
+ }
+ rowCount.addAndGet(1);
+ SPage page = null;
+ for (int i = 0; i <= level; i++) {
+ if (places.isEmpty()) {
+ SPage newHead = new SPage(this, false);
+ ArrayList newValues = new ArrayList();
+ newValues.add(key);
+ newHead.setValues(newValues);
+ newHead.children.add(page);
+ header[i] = newHead;
+ page = newHead;
+ } else {
+ SearchResult result = places.removeLast();
+ Object value = (i == 0 ? tuple : page);
+ page = insert(key, result, value);
+ }
+ }
+ return null;
+ }
+
+ List extractKey(List tuple) {
+ return tuple.subList(0, keyLength);
+ }
+
+ SPage insert(List k, SearchResult result, Object value) throws TeiidComponentException
{
+ SPage page = result.page;
+ int index = -result.index - 1;
+ if (result.values.size() == pageSize) {
+ boolean leaf = !(value instanceof SPage);
+ SPage nextPage = new SPage(this, leaf);
+ ArrayList nextValues = new ArrayList(result.values.subList(pageSize/2, pageSize));
+ result.values.subList(pageSize/2, pageSize).clear();
+ if (!leaf) {
+ nextPage.children.addAll(page.children.subList(pageSize/2, pageSize));
+ page.children.subList(pageSize/2, pageSize).clear();
+ }
+ nextPage.next = page.next;
+ page.next = nextPage;
+ boolean inNext = false;
+ if (index <= pageSize/2) {
+ setValue(index, k, value, result.values, page);
+ } else {
+ inNext = true;
+ setValue(index - pageSize/2, k, value, nextValues, nextPage);
+ }
+ nextPage.setValues(nextValues);
+ page.setValues(result.values);
+ if (inNext) {
+ page = nextPage;
+ }
+ } else {
+ setValue(index, k, value, result.values, page);
+ page.setValues(result.values);
+ }
+ return page;
+ }
+
+ static void setValue(int index, List key, Object value, List values, SPage page) {
+ if (value instanceof SPage) {
+ values.add(index, key);
+ page.children.add(index, (SPage) value);
+ } else {
+ values.add(index, value);
+ }
+ }
+
+ public List remove(List key) throws TeiidComponentException {
+ LinkedList<SearchResult> places = new LinkedList<SearchResult>();
+ List tuple = find(key, places);
+ if (tuple == null) {
+ return null;
+ }
+ rowCount.addAndGet(-1);
+ for (int i = header.length -1; i >=0; i--) {
+ SearchResult searchResult = places.remove();
+ if (searchResult.index < 0) {
+ continue;
+ }
+ boolean cleanup = false;
+ searchResult.values.remove(searchResult.index);
+ int size = searchResult.values.size();
+ if (size == 0) {
+ if (header[i] == searchResult.page && (i != 0 || header[i].next != null)) {
+ header[i].remove();
+ header[i] = header[i].next;
+ if (header[i] == null) {
+ //remove the layer
+ header = Arrays.copyOf(header, header.length - 1);
+ }
+ } else if (i == 0 && header.length > 1) {
+ cleanup = true;
+ }
+ } else if (searchResult.page.next != null && size < pageSize/4) {
+ List nextValues = searchResult.page.next.getValues();
+ SPage next = searchResult.page.next;
+ if (nextValues.size() + size < pageSize/2) {
+ searchResult.page.next = next.next;
+ searchResult.values.addAll(nextValues);
+ nextValues.clear();
+ next.remove();
+ //any references to toMerge are now invalid
+ //setting back to the header will self heal
+ //TODO: this can take advantage of a previous link
+ next.next = header[i];
+ }
+ }
+ searchResult.page.setValues(searchResult.values);
+ if (cleanup) {
+ find(key, null); //trigger cleanup
+ }
+ }
+ return tuple;
+ }
+
+ public void remove() {
+ truncate();
+ this.manager.remove();
+ }
+
+ public int getRowCount() {
+ return this.rowCount.get();
+ }
+
+ public TupleBrowser browse(List lowerBound, List upperBound, boolean direction) {
+ return new TupleBrowser();
+ }
+
+ public int truncate() {
+ int oldSize = rowCount.getAndSet(0);
+ for (int i = 0; i < header.length; i++) {
+ SPage page = header[i];
+ while (page != null) {
+ page.remove();
+ page = page.next;
+ }
+ }
+ header = new SPage[] {new SPage(this, true)};
+ return oldSize;
+ }
+
+ //TODO: support update/delete from the browser
+ public class TupleBrowser {
+
+ SPage page = header[0];
+ int index;
+ List values;
+
+ public boolean matchedLower() {
+ return false;
+ }
+
+ public boolean matchedUpper() {
+ return false;
+ }
+
+ public List next() throws TeiidComponentException {
+ for (;;) {
+ if (values == null) {
+ values = page.getValues();
+ }
+ if (index < values.size()) {
+ return (List) values.get(index++);
+ }
+ index = 0;
+ page = page.next;
+ if (page == null) {
+ return null;
+ }
+ }
+ }
+ }
+
+ public int getKeyLength() {
+ return keyLength;
+ }
+
+}
\ No newline at end of file
Property changes on: trunk/engine/src/main/java/org/teiid/common/buffer/STree.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/TupleBatch.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/TupleBatch.java 2010-07-23 20:47:35
UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/TupleBatch.java 2010-07-23 21:44:19
UTC (rev 2371)
@@ -26,6 +26,8 @@
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.teiid.client.BatchSerializer;
@@ -45,7 +47,7 @@
private static final long serialVersionUID = 6304443387337336957L;
private int rowOffset;
- private List[] tuples;
+ private List<List> tuples;
// Optional state
private boolean terminationFlag = false;
@@ -61,6 +63,13 @@
public TupleBatch() {
}
+ public static TupleBatch directBatch(int rowOffset, List<List> tuples) {
+ TupleBatch result = new TupleBatch();
+ result.rowOffset = rowOffset;
+ result.tuples = tuples;
+ return result;
+ }
+
/**
* Constructor
* @param beginRow indicates the row of the tuple source which is the
@@ -70,7 +79,7 @@
*/
public TupleBatch(int beginRow, List[] tuples) {
this.rowOffset = beginRow;
- this.tuples = tuples;
+ this.tuples = Arrays.asList(tuples);
}
/**
@@ -82,7 +91,7 @@
*/
public TupleBatch(int beginRow, List listOfTupleLists) {
this.rowOffset = beginRow;
- this.tuples = (List[]) listOfTupleLists.toArray(new
List[listOfTupleLists.size()]);
+ this.tuples = new ArrayList(listOfTupleLists);
}
/**
@@ -100,7 +109,7 @@
* @return the last row contained in this tuple batch
*/
public int getEndRow() {
- return rowOffset + tuples.length - 1;
+ return rowOffset + tuples.size() - 1;
}
/**
@@ -108,7 +117,7 @@
* @return the number of rows contained in this tuple batch
*/
public int getRowCount() {
- return tuples.length;
+ return tuples.size();
}
/**
@@ -116,15 +125,19 @@
* @return the tuple at the given index
*/
public List getTuple(int rowIndex) {
- return tuples[rowIndex-rowOffset];
+ return tuples.get(rowIndex-rowOffset);
}
+ public List<List> getTuples() {
+ return tuples;
+ }
+
/**
* Get all tuples
* @return All tuples
*/
public List[] getAllTuples() {
- return tuples;
+ return tuples.toArray(new List[tuples.size()]);
}
/**
@@ -164,21 +177,22 @@
s.append("TupleBatch; beginning row="); //$NON-NLS-1$
s.append(rowOffset);
s.append(", number of rows="); //$NON-NLS-1$
- s.append(tuples.length);
+ s.append(tuples.size());
s.append(", lastBatch="); //$NON-NLS-1$
s.append(this.terminationFlag);
return s.toString();
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
{
- //rowOffset = in.readInt();
terminationFlag = in.readBoolean();
- tuples = BatchSerializer.readBatch(in, types);
+ tuples = new ArrayList<List>();
+ for (List tuple : BatchSerializer.readBatch(in, types)) {
+ tuples.add(tuple);
+ }
}
public void writeExternal(ObjectOutput out) throws IOException {
- //out.writeInt(rowOffset);
out.writeBoolean(terminationFlag);
- BatchSerializer.writeBatch(out, types, tuples);
+ BatchSerializer.writeBatch(out, types, getAllTuples());
}
public void setRowOffset(int rowOffset) {
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/TupleBuffer.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/TupleBuffer.java 2010-07-23
20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/TupleBuffer.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -106,7 +106,7 @@
public void addTuple(List<?> tuple) throws TeiidComponentException {
if (lobs) {
- correctLobReferences(new List[] {tuple});
+ correctLobReferences(schema.size(), tuple);
}
this.rowCount++;
if (batchBuffer == null) {
@@ -126,12 +126,12 @@
public void addTupleBatch(TupleBatch batch, boolean save) throws TeiidComponentException
{
setRowCount(batch.getBeginRow() - 1);
if (save) {
- for (List<?> tuple : batch.getAllTuples()) {
+ for (List<?> tuple : batch.getTuples()) {
addTuple(tuple);
}
} else {
//add the lob references only, since they may still be referenced later
- correctLobReferences(batch.getAllTuples());
+ correctLobReferences(batch.getTuples());
}
}
@@ -210,7 +210,7 @@
BatchManager.ManagedBatch batch = entry.getValue();
result = batch.getBatch(!forwardOnly, types);
if (lobs && result.getDataTypes() == null) {
- correctLobReferences(result.getAllTuples());
+ correctLobReferences(result.getTuples());
}
result.setDataTypes(types);
if (forwardOnly) {
@@ -277,42 +277,51 @@
* @throws TeiidComponentException
*/
@SuppressWarnings("unchecked")
- private void correctLobReferences(List[] rows) throws TeiidComponentException {
+ private void correctLobReferences(List<List> rows) throws TeiidComponentException
{
int columns = schema.size();
// walk through the results and find all the lobs
- for (int row = 0; row < rows.length; row++) {
- for (int col = 0; col < columns; col++) {
- Object anObj = rows[row].get(col);
-
- if (!(anObj instanceof Streamable<?>)) {
- continue;
- }
- Streamable lob = (Streamable)anObj;
- String id = lob.getReferenceStreamId();
- if (id == null) {
- id = String.valueOf(LOB_ID.getAndIncrement());
- lob.setReferenceStreamId(id);
- }
- if (this.lobReferences == null) {
- this.lobReferences = new ConcurrentHashMap<String,
Streamable<?>>();
- }
- this.lobReferences.put(id, lob);
- if (lob.getReference() == null) {
-
lob.setReference(getLobReference(lob.getReferenceStreamId()).getReference());
- }
- }
+ for (List list : rows) {
+ correctLobReferences(columns, list);
}
}
+
+ private void correctLobReferences(int columns, List list)
+ throws TeiidComponentException {
+ for (int col = 0; col < columns; col++) {
+ Object anObj = list.get(col);
+
+ if (!(anObj instanceof Streamable<?>)) {
+ continue;
+ }
+ Streamable lob = (Streamable)anObj;
+ String id = lob.getReferenceStreamId();
+ if (id == null) {
+ id = String.valueOf(LOB_ID.getAndIncrement());
+ lob.setReferenceStreamId(id);
+ }
+ if (this.lobReferences == null) {
+ this.lobReferences = new ConcurrentHashMap<String, Streamable<?>>();
+ }
+ this.lobReferences.put(id, lob);
+ if (lob.getReference() == null) {
+ lob.setReference(getLobReference(lob.getReferenceStreamId()).getReference());
+ }
+ }
+ }
public void setForwardOnly(boolean forwardOnly) {
this.forwardOnly = forwardOnly;
}
+ public IndexedTupleSource createIndexedTupleSource() {
+ return createIndexedTupleSource(false);
+ }
+
/**
* Create a new iterator for this buffer
* @return
*/
- public IndexedTupleSource createIndexedTupleSource() {
+ public IndexedTupleSource createIndexedTupleSource(final boolean singleUse) {
return new AbstractTupleSource() {
@Override
@@ -337,6 +346,14 @@
protected TupleBatch getBatch(int row) throws TeiidComponentException {
return TupleBuffer.this.getBatch(row);
}
+
+ @Override
+ public void closeSource() {
+ super.closeSource();
+ if (singleUse) {
+ remove();
+ }
+ }
};
}
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/impl/BufferManagerImpl.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/common/buffer/impl/BufferManagerImpl.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/common/buffer/impl/BufferManagerImpl.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -30,21 +30,29 @@
import java.io.OutputStream;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.xml.transform.Source;
import org.teiid.common.buffer.BatchManager;
import org.teiid.common.buffer.BufferManager;
import org.teiid.common.buffer.FileStore;
+import org.teiid.common.buffer.STree;
import org.teiid.common.buffer.StorageManager;
import org.teiid.common.buffer.TupleBatch;
import org.teiid.common.buffer.TupleBuffer;
@@ -62,6 +70,7 @@
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.query.execution.QueryExecPlugin;
+import org.teiid.query.processor.relational.ListNestedSortComparator;
import org.teiid.query.processor.xml.XMLUtil;
@@ -84,7 +93,87 @@
public class BufferManagerImpl implements BufferManager, StorageManager {
private static final int IO_BUFFER_SIZE = 1 << 14;
+ private static final int COMPACTION_THRESHOLD = 1 << 25; //start checking at 32
megs
+ private final class BatchManagerImpl implements BatchManager {
+ private final String id;
+ private final int columnCount;
+ private volatile FileStore store;
+ private Map<Long, long[]> physicalMapping = new ConcurrentHashMap<Long,
long[]>();
+ private Map<Long, String[]> types = new ConcurrentSkipListMap<Long,
String[]>();
+ private ReadWriteLock compactionLock = new ReentrantReadWriteLock();
+ private AtomicLong unusedSpace = new AtomicLong();
+
+ private BatchManagerImpl(String newID, int columnCount) {
+ this.id = newID;
+ this.columnCount = columnCount;
+ this.store = createFileStore(id);
+ this.store.setCleanupReference(this);
+ }
+
+ @Override
+ public ManagedBatch createManagedBatch(TupleBatch batch)
+ throws TeiidComponentException {
+ ManagedBatchImpl mbi = new ManagedBatchImpl(batch, this);
+ mbi.addToCache(false);
+ persistBatchReferences();
+ return mbi;
+ }
+
+ private boolean shouldCompact(long offset) {
+ return offset > COMPACTION_THRESHOLD && unusedSpace.get() * 4 > offset *
3;
+ }
+
+ private long getOffset() throws TeiidComponentException {
+ long offset = store.getLength();
+ if (!shouldCompact(offset)) {
+ return offset;
+ }
+ try {
+ this.compactionLock.writeLock().lock();
+ offset = store.getLength();
+ //retest the condition to ensure that compaction is still needed
+ if (!shouldCompact(offset)) {
+ return offset;
+ }
+ FileStore newStore = createFileStore(id);
+ newStore.setCleanupReference(this);
+ byte[] buffer = new byte[IO_BUFFER_SIZE];
+ List<long[]> values = new ArrayList<long[]>(physicalMapping.values());
+ Collections.sort(values, new Comparator<long[]>() {
+ @Override
+ public int compare(long[] o1, long[] o2) {
+ return Long.signum(o1[0] - o2[0]);
+ }
+ });
+ for (long[] info : values) {
+ long oldOffset = info[0];
+ info[0] = newStore.getLength();
+ int size = (int)info[1];
+ while (size > 0) {
+ int toWrite = Math.min(IO_BUFFER_SIZE, size);
+ store.readFully(oldOffset, buffer, 0, toWrite);
+ newStore.write(buffer, 0, toWrite);
+ size -= toWrite;
+ }
+ }
+ store.remove();
+ store = newStore;
+ long oldOffset = offset;
+ offset = store.getLength();
+ LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, "Compacted store", id,
"pre-size", oldOffset, "post-size", offset); //$NON-NLS-1$
//$NON-NLS-2$ //$NON-NLS-3$
+ return offset;
+ } finally {
+ this.compactionLock.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public void remove() {
+ this.store.remove();
+ }
+ }
+
/**
* Holder for active batches
*/
@@ -95,33 +184,26 @@
ManagedBatchImpl removeBatch(int row) {
ManagedBatchImpl result = batches.remove(row);
if (result != null) {
- activeBatchColumnCount -= result.columnCount;
+ activeBatchColumnCount -= result.batchManager.columnCount;
}
return result;
}
}
private final class ManagedBatchImpl implements ManagedBatch {
- final private String id;
- final private FileStore store;
-
- private long offset = -1;
private boolean persistent;
private volatile TupleBatch activeBatch;
private volatile Reference<TupleBatch> batchReference;
private int beginRow;
- private int columnCount;
+ private BatchManagerImpl batchManager;
+ private long id;
- public ManagedBatchImpl(String id, FileStore store, TupleBatch batch) {
- LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, "Add batch to
BufferManager", batchAdded.incrementAndGet()); //$NON-NLS-1$
- this.id = id;
- this.store = store;
+ public ManagedBatchImpl(TupleBatch batch, BatchManagerImpl manager) {
+ id = batchAdded.incrementAndGet();
+ LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, "Add batch to
BufferManager", id); //$NON-NLS-1$
this.activeBatch = batch;
this.beginRow = batch.getBeginRow();
- List[] allTuples = batch.getAllTuples();
- if (allTuples.length > 0) {
- columnCount = allTuples[0].size();
- }
+ this.batchManager = manager;
}
private void addToCache(boolean update) {
@@ -130,19 +212,19 @@
if (batch == null) {
return; //already removed
}
- activeBatchColumnCount += columnCount;
+ activeBatchColumnCount += batchManager.columnCount;
TupleBufferInfo tbi = null;
if (update) {
- tbi = activeBatches.remove(this.id);
+ tbi = activeBatches.remove(batchManager.id);
} else {
- tbi = activeBatches.get(this.id);
+ tbi = activeBatches.get(batchManager.id);
}
if (tbi == null) {
tbi = new TupleBufferInfo();
update = true;
}
if (update) {
- activeBatches.put(this.id, tbi);
+ activeBatches.put(batchManager.id, tbi);
}
Assertion.isNull(tbi.batches.put(this.beginRow, this));
}
@@ -151,9 +233,9 @@
@Override
public TupleBatch getBatch(boolean cache, String[] types) throws
TeiidComponentException {
long reads = readAttempts.incrementAndGet();
- LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, id, "getting batch", reads,
"reference hits", referenceHit.get()); //$NON-NLS-1$ //$NON-NLS-2$
+ LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, batchManager.id, "getting
batch", reads, "reference hits", referenceHit.get()); //$NON-NLS-1$
//$NON-NLS-2$
synchronized (activeBatches) {
- TupleBufferInfo tbi = activeBatches.remove(this.id);
+ TupleBufferInfo tbi = activeBatches.remove(batchManager.id);
if (tbi != null) {
boolean put = true;
if (!cache) {
@@ -164,7 +246,7 @@
}
if (put) {
tbi.lastUsed = this.beginRow;
- activeBatches.put(this.id, tbi);
+ activeBatches.put(batchManager.id, tbi);
}
}
}
@@ -188,9 +270,11 @@
}
}
long count = readCount.incrementAndGet();
- LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, id, beginRow, "reading batch
from disk, total reads:", count); //$NON-NLS-1$
+ LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, batchManager.id, id, "reading
batch from disk, total reads:", count); //$NON-NLS-1$
try {
- ObjectInputStream ois = new ObjectInputStream(new
BufferedInputStream(store.createInputStream(this.offset), IO_BUFFER_SIZE));
+ this.batchManager.compactionLock.readLock().lock();
+ long[] info = batchManager.physicalMapping.get(this.id);
+ ObjectInputStream ois = new ObjectInputStream(new
BufferedInputStream(batchManager.store.createInputStream(info[0]), IO_BUFFER_SIZE));
batch = new TupleBatch();
batch.setDataTypes(types);
batch.readExternal(ois);
@@ -202,28 +286,36 @@
}
return batch;
} catch(IOException e) {
- throw new TeiidComponentException(e,
QueryExecPlugin.Util.getString("FileStoreageManager.error_reading", id));
//$NON-NLS-1$
+ throw new TeiidComponentException(e,
QueryExecPlugin.Util.getString("FileStoreageManager.error_reading",
batchManager.id)); //$NON-NLS-1$
} catch (ClassNotFoundException e) {
- throw new TeiidComponentException(e,
QueryExecPlugin.Util.getString("FileStoreageManager.error_reading", id));
//$NON-NLS-1$
+ throw new TeiidComponentException(e,
QueryExecPlugin.Util.getString("FileStoreageManager.error_reading",
batchManager.id)); //$NON-NLS-1$
+ } finally {
+ this.batchManager.compactionLock.readLock().unlock();
}
}
}
public synchronized void persist() throws TeiidComponentException {
+ boolean lockheld = false;
try {
TupleBatch batch = activeBatch;
if (batch != null) {
if (!persistent) {
long count = writeCount.incrementAndGet();
- LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, id, beginRow, "writing batch
to disk, total writes: ", count); //$NON-NLS-1$
- synchronized (store) {
- offset = store.getLength();
- OutputStream fsos = new BufferedOutputStream(store.createOutputStream(),
IO_BUFFER_SIZE);
+ LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, batchManager.id, id, "writing
batch to disk, total writes: ", count); //$NON-NLS-1$
+ long offset = 0;
+ synchronized (batchManager.store) {
+ offset = batchManager.getOffset();
+ OutputStream fsos = new
BufferedOutputStream(batchManager.store.createOutputStream(), IO_BUFFER_SIZE);
ObjectOutputStream oos = new ObjectOutputStream(fsos);
batch.writeExternal(oos);
oos.close();
+ long size = batchManager.store.getLength() - offset;
+ long[] info = new long[] {offset, size};
+ batchManager.physicalMapping.put(this.id, info);
+ batchManager.types.put(this.id, batch.getDataTypes());
}
- LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, id, beginRow, "batch written
starting at:", offset); //$NON-NLS-1$
+ LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, batchManager.id, id, "batch
written starting at:", offset); //$NON-NLS-1$
}
this.batchReference = new WeakReference<TupleBatch>(batch);
}
@@ -232,23 +324,32 @@
} finally {
persistent = true;
activeBatch = null;
+ if (lockheld) {
+ this.batchManager.compactionLock.writeLock().unlock();
+ }
}
}
public void remove() {
synchronized (activeBatches) {
- TupleBufferInfo tbi = activeBatches.get(this.id);
- if (tbi != null && tbi.removeBatch(this.beginRow) != null &&
tbi.batches.isEmpty()) {
- activeBatches.remove(this.id);
+ TupleBufferInfo tbi = activeBatches.get(batchManager.id);
+ if (tbi != null && tbi.removeBatch(this.beginRow) != null) {
+ if (tbi.batches.isEmpty()) {
+ activeBatches.remove(batchManager.id);
+ }
}
}
+ long[] info = batchManager.physicalMapping.remove(id);
+ if (info != null) {
+ batchManager.unusedSpace.addAndGet(info[1]);
+ }
activeBatch = null;
batchReference = null;
}
@Override
public String toString() {
- return "ManagedBatch " + id + " " + activeBatch; //$NON-NLS-1$
//$NON-NLS-2$
+ return "ManagedBatch " + batchManager.id + " " + activeBatch;
//$NON-NLS-1$ //$NON-NLS-2$
}
}
@@ -267,7 +368,7 @@
private StorageManager diskMgr;
- private AtomicLong currentTuple = new AtomicLong();
+ private AtomicLong tsId = new AtomicLong();
private AtomicLong batchAdded = new AtomicLong();
private AtomicLong readCount = new AtomicLong();
private AtomicLong writeCount = new AtomicLong();
@@ -342,37 +443,26 @@
@Override
public TupleBuffer createTupleBuffer(final List elements, String groupName,
TupleSourceType tupleSourceType) {
- final String newID = String.valueOf(this.currentTuple.getAndIncrement());
+ final String newID = String.valueOf(this.tsId.getAndIncrement());
- BatchManager batchManager = new BatchManager() {
- private FileStore store;
-
- @Override
- public ManagedBatch createManagedBatch(TupleBatch batch)
- throws TeiidComponentException {
- if (this.store == null) {
- this.store = createFileStore(newID);
- this.store.setCleanupReference(this);
- }
- ManagedBatchImpl mbi = new ManagedBatchImpl(newID, store, batch);
- mbi.addToCache(false);
- persistBatchReferences();
- return mbi;
- }
-
- @Override
- public void remove() {
- if (this.store != null) {
- this.store.remove();
- this.store = null;
- }
- }
- };
+ BatchManager batchManager = new BatchManagerImpl(newID, elements.size());
TupleBuffer tupleBuffer = new TupleBuffer(batchManager, newID, elements,
getProcessorBatchSize());
LogManager.logDetail(LogConstants.CTX_BUFFER_MGR, "Creating
TupleBuffer:", newID, "of type ", tupleSourceType); //$NON-NLS-1$
//$NON-NLS-2$
return tupleBuffer;
}
+ public STree createSTree(final List elements, String groupName, TupleSourceType
tupleSourceType, int keyLength) {
+ final String newID = String.valueOf(this.tsId.getAndIncrement());
+
+ BatchManager bm = new BatchManagerImpl(newID, elements.size());
+ int[] compareIndexes = new int[keyLength];
+ for (int i = 1; i < compareIndexes.length; i++) {
+ compareIndexes[i] = i;
+ }
+ LogManager.logDetail(LogConstants.CTX_BUFFER_MGR, "Creating STree:",
newID, "of type ", tupleSourceType); //$NON-NLS-1$ //$NON-NLS-2$
+ return new STree(bm, new ListNestedSortComparator(compareIndexes),
getProcessorBatchSize(), keyLength, TupleBuffer.getTypeNames(elements));
+ }
+
@Override
public FileStore createFileStore(String name) {
LogManager.logDetail(LogConstants.CTX_BUFFER_MGR, "Creating
FileStore:", name); //$NON-NLS-1$
Modified:
trunk/engine/src/main/java/org/teiid/common/buffer/impl/MemoryStorageManager.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/common/buffer/impl/MemoryStorageManager.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/common/buffer/impl/MemoryStorageManager.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -43,6 +43,7 @@
public void writeDirect(byte[] bytes, int offset, int length) throws
TeiidComponentException {
if (getLength() + length > buffer.capacity()) {
ByteBuffer newBuffer = ByteBuffer.allocate(buffer.capacity() * 2 + length);
+ buffer.position(0);
newBuffer.put(buffer);
buffer = newBuffer;
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/CodeTableCache.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/dqp/internal/process/CodeTableCache.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/dqp/internal/process/CodeTableCache.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -138,7 +138,7 @@
* @param results QueryResults of <List<List<keyValue, returnValue>>
* @throws TeiidProcessingException
*/
- public synchronized void loadTable(CacheKey cacheKey, List[] records) throws
TeiidProcessingException {
+ public synchronized void loadTable(CacheKey cacheKey, List<List> records)
throws TeiidProcessingException {
// Lookup the existing data
// Map of data: keyValue --> returnValue;
CodeTable table = codeTableCache.get(cacheKey);
@@ -148,7 +148,7 @@
// Determine whether the results should be added to code table cache
// Depends on size of results and available memory and system parameters
- int potentialSize = table.codeMap.size() + records.length;
+ int potentialSize = table.codeMap.size() + records.size();
if (potentialSize > maxCodeTableRecords) {
throw new TeiidProcessingException("ERR.018.005.0100",
DQPPlugin.Util.getString("ERR.018.005.0100", "maxCodeTables"));
//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@@ -158,9 +158,8 @@
}
// Add data: <List<List<keyValue, returnValue>> from results to
the code table cache
- for ( int i = 0; i < records.length; i++ ) {
+ for (List<Object> record : records) {
// each record or row
- List<Object> record = records[i];
Object keyValue = record.get(0);
Object returnValue = record.get(1);
Object existing = table.codeMap.put(keyValue, returnValue);
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java 2010-07-23
20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -72,7 +72,7 @@
import org.teiid.logging.MessageLevel;
import org.teiid.logging.CommandLogMessage.Event;
import org.teiid.query.processor.ProcessorDataManager;
-import org.teiid.query.tempdata.TempTableStoreImpl;
+import org.teiid.query.tempdata.TempTableStore;
/**
@@ -144,9 +144,9 @@
static class ClientState {
List<RequestID> requests;
- TempTableStoreImpl tempTableStoreImpl;
+ TempTableStore tempTableStoreImpl;
- public ClientState(TempTableStoreImpl tableStoreImpl) {
+ public ClientState(TempTableStore tableStoreImpl) {
this.tempTableStoreImpl = tableStoreImpl;
}
@@ -236,7 +236,7 @@
synchronized (clientState) {
ClientState state = clientState.get(key);
if (state == null && create) {
- state = new ClientState(new TempTableStoreImpl(bufferManager, key, null));
+ state = new ClientState(new TempTableStore(bufferManager, key, null));
clientState.put(key, state);
}
return state;
Modified:
trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -406,7 +406,7 @@
processor.setNonBlocking(true); //process lookup as fully blocking
while (true) {
TupleBatch batch = processor.nextBatch();
- codeTableCache.loadTable(codeRequestId, batch.getAllTuples());
+ codeTableCache.loadTable(codeRequestId, batch.getTuples());
if (batch.getTerminationFlag()) {
break;
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -431,11 +431,8 @@
} else if (fromBuffer && isForwardOnly()) {
savedBatch = batch;
}
- int firstOffset = beginRow - batch.getBeginRow();
- List[] memoryRows = batch.getAllTuples();
- List[] rows = new List[count];
- System.arraycopy(memoryRows, firstOffset, rows, 0, endRow - beginRow +
1);
- batch = new TupleBatch(beginRow, rows);
+ List<List> memoryRows = batch.getTuples();
+ batch = new TupleBatch(beginRow, memoryRows.subList(beginRow -
batch.getBeginRow(), endRow - batch.getBeginRow() + 1));
batch.setTerminationFlag(last);
} else if (!fromBuffer){
result = !isForwardOnly();
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -141,7 +141,11 @@
break;
case NodeConstants.Types.GROUP:
- estimateNodeCost(node,
(List)node.getProperty(NodeConstants.Info.GROUP_COLS), metadata);
+ if (!node.hasCollectionProperty(NodeConstants.Info.GROUP_COLS)) {
+ setCardinalityEstimate(node, 1f);
+ } else {
+ estimateNodeCost(node,
(List)node.getProperty(NodeConstants.Info.GROUP_COLS), metadata);
+ }
break;
case NodeConstants.Types.ACCESS:
case NodeConstants.Types.SORT:
@@ -153,7 +157,7 @@
break;
}
case NodeConstants.Types.NULL:
- setCardinalityEstimate(node, new Float(0));
+ setCardinalityEstimate(node, 0f);
break;
case NodeConstants.Types.PROJECT:
@@ -164,7 +168,7 @@
PlanNode child = node.getFirstChild();
childCost =
(Float)child.getProperty(NodeConstants.Info.EST_CARDINALITY);
} else {
- childCost = new Float(1);
+ childCost = 1f;
}
setCardinalityEstimate(node, childCost);
break;
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanJoins.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanJoins.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanJoins.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -268,7 +268,7 @@
* If we failed to find direct criteria, but still have non-pushable
or criteria to
* other groups we'll use additional checks
*/
- if ((!hasJoinCriteria || (hasJoinCriteria &&
joinCriteriaNodes.isEmpty())) && !canPushCrossJoin(metadata, context, accessNode1,
accessNode2)) {
+ if ((!hasJoinCriteria || joinCriteriaNodes.isEmpty()) &&
!canPushCrossJoin(metadata, context, accessNode1, accessNode2)) {
continue;
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/CollectionTupleSource.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/CollectionTupleSource.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/query/processor/CollectionTupleSource.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -35,7 +35,7 @@
public class CollectionTupleSource implements TupleSource {
private Iterator<? extends List<?>> tuples;
- private List<SingleElementSymbol> schema;
+ private List<? extends SingleElementSymbol> schema;
public static CollectionTupleSource createUpdateCountTupleSource(int count) {
return new CollectionTupleSource(Arrays.asList(Arrays.asList(count)).iterator(),
Command.getUpdateCommandSymbol());
@@ -46,7 +46,7 @@
}
public CollectionTupleSource(Iterator<? extends List<?>> tuples,
- List<SingleElementSymbol> schema) {
+ List<? extends SingleElementSymbol> schema) {
this.tuples = tuples;
this.schema = schema;
}
@@ -60,7 +60,7 @@
}
@Override
- public List<SingleElementSymbol> getSchema() {
+ public List<? extends SingleElementSymbol> getSchema() {
return schema;
}
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/batch/BatchedUpdatePlan.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/batch/BatchedUpdatePlan.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/query/processor/batch/BatchedUpdatePlan.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -145,9 +145,9 @@
openPlan();
}
// Execute nextBatch() on each plan in sequence
- List[] currentBatch = updatePlans[planIndex].nextBatch().getAllTuples(); //
Can throw BlockedException
- for (int i = 0; i < currentBatch.length; i++, commandIndex++) {
- updateCounts[commandIndex] = currentBatch[i];
+ List<List> currentBatch =
updatePlans[planIndex].nextBatch().getTuples(); // Can throw BlockedException
+ for (int i = 0; i < currentBatch.size(); i++, commandIndex++) {
+ updateCounts[commandIndex] = currentBatch.get(i);
}
// since we are done with the plan explicitly close it.
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -65,7 +65,7 @@
import org.teiid.query.sql.symbol.Reference;
import org.teiid.query.sql.util.VariableContext;
import org.teiid.query.tempdata.TempTableStore;
-import org.teiid.query.tempdata.TempTableStoreImpl;
+import org.teiid.query.tempdata.TempTableStore;
import org.teiid.query.util.CommandContext;
import org.teiid.query.util.ErrorMessageKeys;
@@ -205,7 +205,7 @@
context.setValue(entry.getKey(), value);
}
}
- tempTableStore = new TempTableStoreImpl(bufferMgr, getContext().getConnectionID(),
null);
+ tempTableStore = new TempTableStore(bufferMgr, getContext().getConnectionID(),
null);
this.dataMgr = new TempTableDataManager(dataMgr, tempTableStore);
}
this.evaluatedParams = true;
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/PlanExecutionNode.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/PlanExecutionNode.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/PlanExecutionNode.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -113,7 +113,7 @@
TupleBatch batch = plan.nextBatch();
- for (List tuple : batch.getAllTuples()) {
+ for (List tuple : batch.getTuples()) {
addBatchRow(tuple);
}
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/ProjectIntoNode.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/ProjectIntoNode.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/ProjectIntoNode.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -116,7 +116,9 @@
currentBatch = getChildren()[0].nextBatch(); // can throw
BlockedException
this.batchRow = currentBatch.getBeginRow();
- if(currentBatch.getRowCount() == 0 &&
!this.intoGroup.isImplicitTempGroupSymbol()) {
+ //normally we would want to skip a 0 sized batch, but it typically
represents the terminal batch
+ //and for implicit temp tables we need to issue an empty insert
+ if(currentBatch.getRowCount() == 0 &&
(!this.intoGroup.isImplicitTempGroupSymbol() || !currentBatch.getTerminationFlag())) {
continue;
}
} else if (currentBatch.getTerminationFlag() && this.batchRow >
currentBatch.getEndRow()) {
@@ -131,10 +133,10 @@
List<Constant> parameters = new
ArrayList<Constant>(intoElements.size());
for (int i = 0; i < intoElements.size(); i++) {
Constant value = new Constant(null,
((ElementSymbol)intoElements.get(i)).getType());
- value.setMultiValued(new
ArrayList<Object>(currentBatch.getAllTuples().length));
+ value.setMultiValued(new ArrayList<Object>(currentBatch.getTuples().size()));
parameters.add(value);
}
- for (List row : currentBatch.getAllTuples()) {
+ for (List row : currentBatch.getTuples()) {
for (int i = 0; i < row.size(); i++) {
((List<Object>)parameters.get(i).getValue()).add(row.get(i));
}
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/UnionAllNode.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/UnionAllNode.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/UnionAllNode.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -117,7 +117,7 @@
TupleBatch outputBatch = null;
if(batch != null) {
// Rebuild the batch to reset the output row
- outputBatch = new TupleBatch(outputRow, batch.getAllTuples());
+ outputBatch = new TupleBatch(outputRow, batch.getTuples());
// This is the last unioned batch if:
// 1) This batch is a termination batch from the child
Modified: trunk/engine/src/main/java/org/teiid/query/processor/xml/XMLPlan.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/xml/XMLPlan.java 2010-07-23
20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/processor/xml/XMLPlan.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -61,7 +61,7 @@
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.tempdata.TempTableStore;
-import org.teiid.query.tempdata.TempTableStoreImpl;
+import org.teiid.query.tempdata.TempTableStore;
import org.teiid.query.util.CommandContext;
import org.teiid.query.util.ErrorMessageKeys;
import org.xml.sax.Attributes;
@@ -108,7 +108,7 @@
*/
public void initialize(CommandContext context, ProcessorDataManager dataMgr,
BufferManager bufferMgr) {
setContext(context);
- TempTableStore tempTableStore = new TempTableStoreImpl(bufferMgr,
context.getConnectionID(), (TempTableStore)context.getTempTableStore());
+ TempTableStore tempTableStore = new TempTableStore(bufferMgr,
context.getConnectionID(), (TempTableStore)context.getTempTableStore());
//this.dataMgr = new StagingTableDataManager(new TempTableDataManager(dataMgr,
tempTableStore), env);
this.dataMgr = new TempTableDataManager(dataMgr, tempTableStore);
this.bufferMgr = bufferMgr;
Modified:
trunk/engine/src/main/java/org/teiid/query/resolver/command/TempTableResolver.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/resolver/command/TempTableResolver.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/query/resolver/command/TempTableResolver.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -80,7 +80,7 @@
ResolverUtil.addTempTable(metadata, group, create.getColumns());
ResolverUtil.resolveGroup(((Create)command).getTable(), metadata);
- Set groups = new HashSet();
+ Set<GroupSymbol> groups = new HashSet<GroupSymbol>();
groups.add(((Create)command).getTable());
ResolverVisitor.resolveLanguageObject(command, groups, metadata);
} else if(command.getType() == Command.TYPE_DROP) {
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -299,10 +299,14 @@
try {
resolveFunction(obj, this.metadata.getFunctionLibrary());
} catch(QueryResolverException e) {
- if (unresolvedFunctions == null) {
- unresolvedFunctions = new LinkedHashMap<Function,
QueryResolverException>();
+ if (ErrorMessageKeys.RESOLVER_0036.equals(e.getCode()) ||
ErrorMessageKeys.RESOLVER_0035.equals(e.getCode())) {
+ if (unresolvedFunctions == null) {
+ unresolvedFunctions = new LinkedHashMap<Function,
QueryResolverException>();
+ }
+ unresolvedFunctions.put(obj, e);
+ } else {
+ handleException(e);
}
- unresolvedFunctions.put(obj, e);
} catch(TeiidComponentException e) {
handleException(e);
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/Create.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/Create.java 2010-07-23 20:47:35
UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/Create.java 2010-07-23 21:44:19
UTC (rev 2371)
@@ -27,6 +27,7 @@
import org.teiid.core.util.EquivalenceUtil;
import org.teiid.core.util.HashCodeUtil;
+import org.teiid.query.sql.LanguageObject;
import org.teiid.query.sql.LanguageVisitor;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.GroupSymbol;
@@ -42,6 +43,8 @@
private List<ElementSymbol> columns = new ArrayList<ElementSymbol>();
+ private List<ElementSymbol> primaryKey = new ArrayList<ElementSymbol>();
+
public GroupSymbol getTable() {
return table;
}
@@ -54,6 +57,10 @@
return columns;
}
+ public List<ElementSymbol> getPrimaryKey() {
+ return primaryKey;
+ }
+
/**
* @see org.teiid.query.sql.lang.Command#getType()
* @since 5.5
@@ -70,7 +77,8 @@
Create copy = new Create();
GroupSymbol copyTable = (GroupSymbol) table.clone();
copy.setTable(copyTable);
- copy.setColumns(columns);
+ copy.setColumns(LanguageObject.Util.deepClone(columns, ElementSymbol.class));
+ copy.primaryKey = LanguageObject.Util.deepClone(primaryKey,
ElementSymbol.class);
copyMetadataState(copy);
return copy;
}
@@ -128,6 +136,7 @@
Create other = (Create) obj;
return EquivalenceUtil.areEqual(getTable(), other.getTable()) &&
- EquivalenceUtil.areEqual(getColumns(), other.getColumns());
+ EquivalenceUtil.areEqual(getColumns(), other.getColumns()) &&
+ EquivalenceUtil.areEqual(getPrimaryKey(), other.getPrimaryKey());
}
}
Modified:
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -306,6 +306,7 @@
preVisitVisitor(obj);
visitNode(obj.getTable());
visitNodes(obj.getColumns());
+ visitNodes(obj.getPrimaryKey());
postVisitVisitor(obj);
}
public void visit(Drop obj) {
Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -442,14 +442,28 @@
Iterator<ElementSymbol> iter = columns.iterator();
while(iter.hasNext()) {
ElementSymbol element = iter.next();
- element.setDisplayMode(ElementSymbol.DisplayMode.SHORT_OUTPUT_NAME);
- parts.add(registerNode(element));
+ outputShortName(element);
parts.add(SPACE);
parts.add(DataTypeManager.getDataTypeName(element.getType()));
if(iter.hasNext()) {
parts.add(", "); //$NON-NLS-1$
}
}
+ if (!obj.getPrimaryKey().isEmpty()) {
+ parts.add(", "); //$NON-NLS-1$
+ parts.add(PRIMARY);
+ parts.add(" "); //$NON-NLS-1$
+ parts.add(NonReserved.KEY);
+ parts.add(Tokens.LPAREN);
+ iter = obj.getPrimaryKey().iterator();
+ while(iter.hasNext()) {
+ outputShortName(iter.next());
+ if (iter.hasNext()) {
+ parts.add(", "); //$NON-NLS-1$
+ }
+ }
+ parts.add(Tokens.RPAREN);
+ }
parts.add(")"); //$NON-NLS-1$
}
@@ -746,8 +760,7 @@
parts.add(SPACE);
for (int i = 0; i < obj.getAsColumns().size(); i++) {
ElementSymbol symbol = (ElementSymbol)obj.getAsColumns().get(i);
- symbol.setDisplayMode(ElementSymbol.DisplayMode.SHORT_OUTPUT_NAME);
- parts.add(registerNode(symbol));
+ outputShortName(symbol);
parts.add(SPACE);
parts.add(DataTypeManager.getDataTypeName(symbol.getType()));
if (i < obj.getAsColumns().size() - 1) {
@@ -794,8 +807,7 @@
public void visit(SetClause obj) {
ElementSymbol symbol = obj.getSymbol();
- symbol.setDisplayMode(ElementSymbol.DisplayMode.SHORT_OUTPUT_NAME);
- parts.add(registerNode(symbol));
+ outputShortName(symbol);
parts.add(" = "); //$NON-NLS-1$
parts.add(registerNode(obj.getValue()));
}
@@ -1187,19 +1199,20 @@
}
public void visit(ElementSymbol obj) {
+ if (obj.getDisplayMode().equals(ElementSymbol.DisplayMode.SHORT_OUTPUT_NAME)) {
+ outputShortName(obj);
+ return;
+ }
String name = obj.getOutputName();
if (obj.getDisplayMode().equals(ElementSymbol.DisplayMode.FULLY_QUALIFIED)) {
name = obj.getName();
- } else if
(obj.getDisplayMode().equals(ElementSymbol.DisplayMode.SHORT_OUTPUT_NAME)) {
- String shortName = SingleElementSymbol.getShortName(name);
- //TODO: this is a hack - since we default to not supporting double quoted
identifiers, we need to fully qualify reserved
- if (!isReservedWord(shortName)) {
- name = shortName;
- }
}
-
outputDisplayName(name);
}
+
+ private void outputShortName(ElementSymbol obj) {
+ outputDisplayName(SingleElementSymbol.getShortName(obj.getOutputName()));
+ }
private void outputDisplayName(String name) {
String[] pathParts = name.split("\\."); //$NON-NLS-1$
Added: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java
(rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java 2010-07-23 21:44:19
UTC (rev 2371)
@@ -0,0 +1,349 @@
+/*
+ * 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.tempdata;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.teiid.api.exception.query.ExpressionEvaluationException;
+import org.teiid.common.buffer.BlockedException;
+import org.teiid.common.buffer.BufferManager;
+import org.teiid.common.buffer.STree;
+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.TupleBrowser;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidException;
+import org.teiid.core.TeiidProcessingException;
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.query.QueryPlugin;
+import org.teiid.query.eval.Evaluator;
+import org.teiid.query.processor.CollectionTupleSource;
+import org.teiid.query.processor.relational.RelationalNode;
+import org.teiid.query.sql.lang.Command;
+import org.teiid.query.sql.lang.Criteria;
+import org.teiid.query.sql.lang.OrderBy;
+import org.teiid.query.sql.lang.SetClauseList;
+import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
+
+/**
+ * A Teiid Temp Table
+ * TODO: an update will not happen unless the tuplesource is accessed
+ * TODO: better handling for blocked exceptions (should be rare)
+ * TODO: non-pk updates/deletes through the browser
+ */
+class TempTable {
+
+ private abstract class UpdateTupleSource implements TupleSource {
+ private TupleSource ts;
+ protected final Map lookup;
+ protected final Evaluator eval;
+ private final Criteria crit;
+ protected int updateCount = 0;
+ protected boolean done;
+ private List currentTuple;
+
+ protected TupleBuffer undoLog;
+
+ UpdateTupleSource(Criteria crit, TupleSource ts) throws TeiidComponentException {
+ this.ts = ts;
+ this.lookup = RelationalNode.createLookupMap(columns);
+ this.eval = new Evaluator(lookup, null, null);
+ this.crit = crit;
+ this.undoLog = bm.createTupleBuffer(columns, sessionID, TupleSourceType.PROCESSOR);
+ }
+
+ void process() throws TeiidComponentException, TeiidProcessingException {
+ //still have to worry about blocked exceptions...
+ while (currentTuple != null || (currentTuple = ts.nextTuple()) != null) {
+ if (crit == null || eval.evaluate(crit, currentTuple)) {
+ tuplePassed(currentTuple);
+ updateCount++;
+ undoLog.addTuple(currentTuple);
+ }
+ currentTuple = null;
+ }
+ }
+
+ @Override
+ public List<?> nextTuple() throws TeiidComponentException,
+ TeiidProcessingException {
+ if (done) {
+ return null;
+ }
+ try {
+ process();
+ done = true;
+ } catch (BlockedException e) {
+ //this is horrible...
+ throw e;
+ } finally {
+ if (!done) {
+ TupleSource undoTs = undoLog.createIndexedTupleSource();
+ List<?> tuple = null;
+ try {
+ while ((tuple = undoTs.nextTuple()) != null) {
+ undo(tuple);
+ }
+ } catch (TeiidException e) {
+
+ }
+ }
+ }
+ return Arrays.asList(updateCount);
+ }
+
+ protected abstract void tuplePassed(List tuple) throws BlockedException,
TeiidComponentException, TeiidProcessingException;
+
+ protected abstract void undo(List tuple) throws TeiidComponentException,
TeiidProcessingException;
+
+ @Override
+ public List<SingleElementSymbol> getSchema() {
+ return Command.getUpdateCommandSymbol();
+ }
+
+ @Override
+ public int available() {
+ return 0;
+ }
+
+ @Override
+ public void closeSource() {
+ ts.closeSource();
+ undoLog.remove();
+ }
+
+ }
+
+ private STree tree;
+ private AtomicInteger rowId;
+ private List<ElementSymbol> columns;
+ private BufferManager bm;
+ private String sessionID;
+
+ TempTable(BufferManager bm, List<ElementSymbol> columns, int primaryKeyLength,
String sessionID) {
+ this.bm = bm;
+ if (primaryKeyLength == 0) {
+ ElementSymbol id = new ElementSymbol("rowId"); //$NON-NLS-1$
+ id.setType(DataTypeManager.DefaultDataClasses.INTEGER);
+ columns.add(0, id);
+ //we start at max, since the default sort order is ascending
+ rowId = new AtomicInteger(Integer.MAX_VALUE);
+ tree = bm.createSTree(columns, sessionID, TupleSourceType.PROCESSOR, 1);
+ } else {
+ tree = bm.createSTree(columns, sessionID, TupleSourceType.PROCESSOR,
primaryKeyLength);
+ }
+ this.columns = columns;
+ this.sessionID = sessionID;
+ }
+
+ public TupleSource createTupleSource(List<Criteria> conditions, OrderBy orderBy)
throws TeiidComponentException {
+ return createTupleSource(conditions, orderBy, true);
+ }
+
+ private TupleSource createTupleSource(List<Criteria> conditions, OrderBy orderBy,
boolean filterRowId) throws TeiidComponentException {
+ TupleBuffer tb = bm.createTupleBuffer(columns, sessionID, TupleSourceType.PROCESSOR);
+ TupleBrowser browser = tree.browse(null, null, OrderBy.ASC);
+ List next = null;
+ while ((next = browser.next()) != null) {
+ if (rowId != null && filterRowId) {
+ next = next.subList(1, next.size());
+ }
+ tb.addTuple(next);
+ }
+ tb.close();
+ return tb.createIndexedTupleSource(true);
+ }
+
+ public int getRowCount() {
+ return tree.getRowCount();
+ }
+
+ public int truncate() {
+ return tree.truncate();
+ }
+
+ public void remove() {
+ tree.remove();
+ }
+
+ public List<ElementSymbol> getColumns() {
+ if (rowId != null) {
+ return columns.subList(1, columns.size());
+ }
+ return columns;
+ }
+
+ public TupleSource insert(List<List<Object>> tuples) throws
TeiidComponentException {
+ UpdateTupleSource uts = new UpdateTupleSource(null, new
CollectionTupleSource(tuples.iterator(), getColumns())) {
+
+ protected void tuplePassed(List tuple)
+ throws BlockedException, TeiidComponentException, TeiidProcessingException {
+ if (rowId != null) {
+ tuple.add(0, rowId.getAndAdd(-1));
+ }
+ insertTuple(tuple);
+ }
+
+ @Override
+ protected void undo(List tuple) throws TeiidComponentException {
+ deleteTuple(tuple);
+ }
+
+ };
+ return uts;
+ }
+
+ public TupleSource update(Criteria crit, final SetClauseList update) throws
TeiidComponentException {
+ final boolean primaryKeyChangePossible = canChangePrimaryKey(update);
+
+ UpdateTupleSource uts = new UpdateTupleSource(crit, createTupleSource(null, null,
false)) {
+
+ protected TupleBuffer changeSet;
+ protected TupleSource changeSetProcessor;
+
+ @Override
+ protected void tuplePassed(List tuple)
+ throws ExpressionEvaluationException,
+ BlockedException, TeiidComponentException {
+ List<Object> newTuple = new ArrayList<Object>(tuple);
+ for (Map.Entry<ElementSymbol, Expression> entry :
update.getClauseMap().entrySet()) {
+ newTuple.set((Integer)lookup.get(entry.getKey()), eval.evaluate(entry.getValue(),
tuple));
+ }
+ if (primaryKeyChangePossible) {
+ deleteTuple(tuple);
+ if (changeSet == null) {
+ changeSet = bm.createTupleBuffer(columns, sessionID,
TupleSourceType.PROCESSOR);
+ }
+ changeSet.addTuple(newTuple);
+ } else {
+ updateTuple(newTuple);
+ }
+ }
+
+ @Override
+ void process() throws TeiidComponentException,
+ TeiidProcessingException {
+ super.process();
+ //existing tuples have been removed
+ //changeSet contains possible updates
+ if (primaryKeyChangePossible) {
+ if (changeSetProcessor == null) {
+ changeSetProcessor = new UpdateTupleSource(null,
changeSet.createIndexedTupleSource(true)) {
+ @Override
+ protected void tuplePassed(List tuple) throws BlockedException,
+ TeiidComponentException, TeiidProcessingException {
+ insertTuple(tuple);
+ }
+
+ @Override
+ protected void undo(List tuple) throws TeiidComponentException,
+ TeiidProcessingException {
+ deleteTuple(tuple);
+ }
+
+ };
+ }
+ changeSetProcessor.nextTuple(); //when this returns, we're up to date
+ }
+ }
+
+ @Override
+ protected void undo(List tuple) throws TeiidComponentException,
TeiidProcessingException {
+ if (primaryKeyChangePossible) {
+ insertTuple(tuple);
+ } else {
+ updateTuple(tuple);
+ }
+ }
+
+ @Override
+ public void closeSource() {
+ super.closeSource();
+ if (changeSetProcessor != null) {
+ changeSetProcessor.closeSource(); // causes a revert of the change set
+ }
+ if (changeSet != null) {
+ changeSet.remove();
+ }
+ }
+
+ };
+ return uts;
+ }
+
+ private boolean canChangePrimaryKey(final SetClauseList update) {
+ if (rowId == null) {
+ Set<ElementSymbol> affectedColumns = new
HashSet<ElementSymbol>(update.getClauseMap().keySet());
+ affectedColumns.retainAll(columns.subList(0, tree.getKeyLength()));
+ if (!affectedColumns.isEmpty()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public TupleSource delete(Criteria crit) throws TeiidComponentException {
+ UpdateTupleSource uts = new UpdateTupleSource(crit, createTupleSource(null, null,
false)) {
+ @Override
+ protected void tuplePassed(List tuple)
+ throws ExpressionEvaluationException,
+ BlockedException, TeiidComponentException {
+ deleteTuple(tuple);
+ }
+
+ @Override
+ protected void undo(List tuple) throws TeiidComponentException,
TeiidProcessingException {
+ insertTuple(tuple);
+ }
+ };
+ return uts;
+ }
+
+ private void insertTuple(List<Object> list) throws TeiidComponentException,
TeiidProcessingException {
+ if (tree.insert(list, false) != null) {
+ throw new
TeiidProcessingException(QueryPlugin.Util.getString("TempTable.duplicate_key"));
//$NON-NLS-1$
+ }
+ }
+
+ private void deleteTuple(List<?> tuple) throws TeiidComponentException {
+ if (tree.remove(tuple) == null) {
+ throw new AssertionError("Delete failed"); //$NON-NLS-1$
+ }
+ }
+
+ private void updateTuple(List<?> tuple) throws TeiidComponentException {
+ if (tree.insert(tuple, true) == null) {
+ throw new AssertionError("Update failed"); //$NON-NLS-1$
+ }
+ }
+
+}
\ No newline at end of file
Property changes on: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java 2010-07-23
20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -22,32 +22,238 @@
package org.teiid.query.tempdata;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
import java.util.Set;
-import org.teiid.common.buffer.TupleBuffer;
+import org.teiid.api.exception.query.ExpressionEvaluationException;
+import org.teiid.api.exception.query.QueryProcessingException;
+import org.teiid.common.buffer.BlockedException;
+import org.teiid.common.buffer.BufferManager;
import org.teiid.common.buffer.TupleSource;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
+import org.teiid.query.eval.Evaluator;
+import org.teiid.query.execution.QueryExecPlugin;
import org.teiid.query.metadata.TempMetadataStore;
+import org.teiid.query.processor.CollectionTupleSource;
import org.teiid.query.sql.lang.Command;
+import org.teiid.query.sql.lang.Create;
+import org.teiid.query.sql.lang.Criteria;
+import org.teiid.query.sql.lang.Delete;
+import org.teiid.query.sql.lang.Drop;
+import org.teiid.query.sql.lang.Insert;
+import org.teiid.query.sql.lang.ProcedureContainer;
+import org.teiid.query.sql.lang.Query;
+import org.teiid.query.sql.lang.Update;
+import org.teiid.query.sql.symbol.Constant;
+import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.GroupSymbol;
-
/**
* @since 5.5
*/
-public interface TempTableStore {
+public class TempTableStore {
+
+ private BufferManager buffer;
+ private TempMetadataStore tempMetadataStore = new TempMetadataStore();
+ private Map<String, TempTable> groupToTupleSourceID = new HashMap<String,
TempTable>();
+ private String sessionID;
+ private TempTableStore parentTempTableStore;
- void removeTempTables() throws TeiidComponentException;
-
- TempMetadataStore getMetadataStore();
+ public TempTableStore(BufferManager buffer, String sessionID, TempTableStore
parentTempTableStore) {
+ this.buffer = buffer;
+ this.sessionID = sessionID;
+ this.parentTempTableStore = parentTempTableStore;
+ }
- public TupleSource registerRequest(Command command) throws TeiidComponentException,
TeiidProcessingException;
+ void addTempTable(Create create, boolean removeExistingTable) throws
QueryProcessingException{
+ String tempTableName = create.getTable().getName().toUpperCase();
+ if(tempMetadataStore.getTempGroupID(tempTableName) != null) {
+ if(!removeExistingTable) {
+ throw new
QueryProcessingException(QueryExecPlugin.Util.getString("TempTableStore.table_exist_error",
tempTableName));//$NON-NLS-1$
+ }
+ removeTempTableByName(tempTableName);
+ }
+ List<ElementSymbol> columns = create.getColumns();
+
+ boolean hasKey = !create.getPrimaryKey().isEmpty();
+ columns = new ArrayList<ElementSymbol>(create.getColumns());
+
+ if (hasKey) {
+ //reorder the columns to put the key in front
+ List<ElementSymbol> primaryKey = create.getPrimaryKey();
+ columns.removeAll(primaryKey);
+ columns.addAll(0, primaryKey);
+ }
+ //add metadata
+ tempMetadataStore.addTempGroup(tempTableName, columns, false, true);
+ TempTable tempTable = new TempTable(buffer, columns,
create.getPrimaryKey().size(), sessionID);
+ groupToTupleSourceID.put(tempTableName, tempTable);
+ }
+
+ public void removeTempTableByName(String tempTableName) {
+ tempMetadataStore.removeTempGroup(tempTableName);
+ TempTable table = this.groupToTupleSourceID.remove(tempTableName);
+ if(table != null) {
+ table.remove();
+ }
+ }
- public boolean hasTempTable(Command command);
+ public TempMetadataStore getMetadataStore() {
+ return tempMetadataStore;
+ }
+
+ public TupleSource registerRequest(Command command) throws TeiidComponentException,
TeiidProcessingException{
+ if (command instanceof Query) {
+ Query query = (Query)command;
+ GroupSymbol group = (GroupSymbol)query.getFrom().getGroups().get(0);
+ if (!group.isTempGroupSymbol()) {
+ return null;
+ }
+ TempTable table = getTempTable(group.getNonCorrelationName().toUpperCase(),
command);
+ return
table.createTupleSource(Criteria.separateCriteriaByAnd(query.getCriteria()),
query.getOrderBy());
+ }
+ if (command instanceof ProcedureContainer) {
+ GroupSymbol group = ((ProcedureContainer)command).getGroup();
+ if (!group.isTempGroupSymbol()) {
+ return null;
+ }
+ final String groupKey = group.getNonCorrelationName().toUpperCase();
+ final TempTable table = getTempTable(groupKey, command);
+ if (command instanceof Insert) {
+ List<List<Object>> tuples = getBulkRows((Insert)command,
table.getColumns());
+ if (tuples.isEmpty()) {
+ return CollectionTupleSource.createUpdateCountTupleSource(0);
+ }
+ return table.insert(tuples);
+ }
+ if (command instanceof Update) {
+ final Update update = (Update)command;
+ final Criteria crit = update.getCriteria();
+ return table.update(crit, update.getChangeList());
+ }
+ if (command instanceof Delete) {
+ final Delete delete = (Delete)command;
+ final Criteria crit = delete.getCriteria();
+ if (crit == null) {
+ //because we are non-transactional, just use a truncate
+ int rows = table.truncate();
+ return CollectionTupleSource.createUpdateCountTupleSource(rows);
+ }
+ return table.delete(crit);
+ }
+ }
+ if (command instanceof Create) {
+ Create create = (Create)command;
+ addTempTable(create, false);
+ return CollectionTupleSource.createUpdateCountTupleSource(0);
+ }
+ if (command instanceof Drop) {
+ String tempTableName = ((Drop)command).getTable().getName().toUpperCase();
+ removeTempTableByName(tempTableName);
+ return CollectionTupleSource.createUpdateCountTupleSource(0);
+ }
+ return null;
+ }
- public Set getAllTempTables();
+ public void removeTempTables() {
+ for (String name : new ArrayList<String>( groupToTupleSourceID.keySet() ))
{
+ removeTempTableByName(name);
+ }
+ }
- public void removeTempTableByName(String tempTableName) throws
TeiidComponentException;
+ private TempTable getTempTable(String tempTableID, Command command) throws
QueryProcessingException{
+ TempTable tsID = groupToTupleSourceID.get(tempTableID);
+ if(tsID != null) {
+ return tsID;
+ }
+ if(this.parentTempTableStore != null){
+ tsID = this.parentTempTableStore.groupToTupleSourceID.get(tempTableID);
+ if(tsID != null) {
+ return tsID;
+ }
+ }
+ //allow implicit temp group definition
+ List<ElementSymbol> columns = null;
+ if (command instanceof Insert) {
+ Insert insert = (Insert)command;
+ GroupSymbol group = insert.getGroup();
+ if(group.isImplicitTempGroupSymbol()) {
+ columns = insert.getVariables();
+ }
+ }
+ if (columns == null) {
+ throw new
QueryProcessingException(QueryExecPlugin.Util.getString("TempTableStore.table_doesnt_exist_error",
tempTableID)); //$NON-NLS-1$
+ }
+ Create create = new Create();
+ create.setTable(new GroupSymbol(tempTableID));
+ create.setColumns(columns);
+ addTempTable(create, true);
+ return groupToTupleSourceID.get(tempTableID);
+ }
+
+ public static List<List<Object>> getBulkRows(Insert insert,
List<ElementSymbol> elements) throws ExpressionEvaluationException,
BlockedException, TeiidComponentException {
+ int bulkRowCount = 1;
+ if (insert.isBulk()) {
+ Constant c = (Constant)insert.getValues().get(0);
+ bulkRowCount = ((List<?>)c.getValue()).size();
+ }
+
+ List<List<Object>> tuples = new
ArrayList<List<Object>>(bulkRowCount);
+
+ for (int row = 0; row < bulkRowCount; row++) {
+ List<Object> currentRow = new
ArrayList<Object>(insert.getValues().size());
+ for (ElementSymbol symbol : elements) {
+ int index = insert.getVariables().indexOf(symbol);
+ Object value = null;
+ if (index != -1) {
+ if (insert.isBulk()) {
+ Constant multiValue = (Constant)insert.getValues().get(index);
+ value = ((List<?>)multiValue.getValue()).get(row);
+ } else {
+ Expression expr = (Expression)insert.getValues().get(index);
+ value = Evaluator.evaluate(expr);
+ }
+ }
+ currentRow.add(value);
+ }
+ tuples.add(currentRow);
+ }
+ return tuples;
+ }
- public TupleBuffer getTupleSourceID(String tempTableName);
+ public boolean hasTempTable(Command command){
+ switch (command.getType()) {
+ case Command.TYPE_INSERT:
+ {
+ Insert insert = (Insert)command;
+ GroupSymbol group = insert.getGroup();
+ return group.isTempGroupSymbol();
+ }
+ case Command.TYPE_QUERY:
+ {
+ if(command instanceof Query) {
+ Query query = (Query)command;
+ GroupSymbol group = (GroupSymbol)query.getFrom().getGroups().get(0);
+ return group.isTempGroupSymbol();
+ }
+ break;
+ }
+ case Command.TYPE_CREATE:
+ return true;
+ case Command.TYPE_DROP:
+ return true;
+ }
+ return false;
+ }
+
+ public Set<String> getAllTempTables() {
+ return new HashSet<String>(this.groupToTupleSourceID.keySet());
+ }
+
}
Deleted: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStoreImpl.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStoreImpl.java 2010-07-23
20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStoreImpl.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -1,373 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.query.tempdata;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.teiid.api.exception.query.ExpressionEvaluationException;
-import org.teiid.api.exception.query.QueryMetadataException;
-import org.teiid.api.exception.query.QueryProcessingException;
-import org.teiid.common.buffer.BlockedException;
-import org.teiid.common.buffer.BufferManager;
-import org.teiid.common.buffer.TupleBuffer;
-import org.teiid.common.buffer.TupleSource;
-import org.teiid.common.buffer.BufferManager.TupleSourceType;
-import org.teiid.core.TeiidComponentException;
-import org.teiid.core.TeiidProcessingException;
-import org.teiid.query.eval.Evaluator;
-import org.teiid.query.execution.QueryExecPlugin;
-import org.teiid.query.metadata.TempMetadataAdapter;
-import org.teiid.query.metadata.TempMetadataStore;
-import org.teiid.query.processor.CollectionTupleSource;
-import org.teiid.query.processor.relational.RelationalNode;
-import org.teiid.query.resolver.util.ResolverUtil;
-import org.teiid.query.sql.lang.Command;
-import org.teiid.query.sql.lang.Create;
-import org.teiid.query.sql.lang.Criteria;
-import org.teiid.query.sql.lang.Delete;
-import org.teiid.query.sql.lang.Drop;
-import org.teiid.query.sql.lang.Insert;
-import org.teiid.query.sql.lang.ProcedureContainer;
-import org.teiid.query.sql.lang.Query;
-import org.teiid.query.sql.lang.Update;
-import org.teiid.query.sql.symbol.Constant;
-import org.teiid.query.sql.symbol.ElementSymbol;
-import org.teiid.query.sql.symbol.Expression;
-import org.teiid.query.sql.symbol.GroupSymbol;
-import org.teiid.query.sql.symbol.SingleElementSymbol;
-
-
-/**
- * @since 5.5
- */
-public class TempTableStoreImpl implements TempTableStore {
-
- private abstract class UpdateTupleSource implements TupleSource {
- private final String groupKey;
- private final TupleBuffer oldBuffer;
- private final TupleSource ts;
- protected final Map lookup;
- private final TupleBuffer newBuffer;
- protected final Evaluator eval;
- private final Criteria crit;
- protected int updateCount = 0;
- private boolean done;
- private List<?> currentTuple;
-
- private UpdateTupleSource(String groupKey, TupleBuffer tsId, Criteria crit) throws
TeiidComponentException {
- this.groupKey = groupKey;
- this.oldBuffer = tsId;
- this.ts = tsId.createIndexedTupleSource();
- List columns = tsId.getSchema();
- this.lookup = RelationalNode.createLookupMap(columns);
- this.newBuffer = buffer.createTupleBuffer(columns, sessionID,
TupleSourceType.PROCESSOR);
- this.eval = new Evaluator(lookup, null, null);
- this.crit = crit;
- }
-
- @Override
- public List<?> nextTuple() throws TeiidComponentException,
- TeiidProcessingException {
- if (done) {
- return null;
- }
-
- //still have to worry about blocked exceptions...
- while (currentTuple != null || (currentTuple = ts.nextTuple()) != null) {
- if (eval.evaluate(crit, currentTuple)) {
- tuplePassed(currentTuple);
- } else {
- tupleFailed(currentTuple);
- }
- currentTuple = null;
- }
- newBuffer.close();
- groupToTupleSourceID.put(groupKey, newBuffer);
- oldBuffer.remove();
- done = true;
- return Arrays.asList(updateCount);
- }
-
- protected void addTuple(List<?> tuple) throws TeiidComponentException {
- newBuffer.addTuple(tuple);
- }
-
- protected abstract void tuplePassed(List<?> tuple) throws
ExpressionEvaluationException, BlockedException, TeiidComponentException;
-
- protected abstract void tupleFailed(List<?> tuple) throws
TeiidComponentException;
-
- @Override
- public List<SingleElementSymbol> getSchema() {
- return Command.getUpdateCommandSymbol();
- }
-
- @Override
- public void closeSource() {
-
- }
-
- @Override
- public int available() {
- return 0;
- }
- }
-
- private BufferManager buffer;
- private TempMetadataStore tempMetadataStore = new TempMetadataStore();
- private Map<String, TupleBuffer> groupToTupleSourceID = new HashMap<String,
TupleBuffer>();
- private String sessionID;
- private TempTableStore parentTempTableStore;
-
- public TempTableStoreImpl(BufferManager buffer, String sessionID, TempTableStore
parentTempTableStore) {
- this.buffer = buffer;
- this.sessionID = sessionID;
- this.parentTempTableStore = parentTempTableStore;
- }
-
- public void addTempTable(String tempTableName, List columns, boolean
removeExistingTable) throws TeiidComponentException, QueryProcessingException{
- if(tempMetadataStore.getTempGroupID(tempTableName) != null) {
- if(!removeExistingTable) {
- throw new
QueryProcessingException(QueryExecPlugin.Util.getString("TempTableStore.table_exist_error",
tempTableName));//$NON-NLS-1$
- }
- removeTempTableByName(tempTableName);
- }
-
- //add metadata
- tempMetadataStore.addTempGroup(tempTableName, columns, false, true);
- //create tuple source
- TupleBuffer tupleBuffer = buffer.createTupleBuffer(columns, sessionID,
TupleSourceType.PROCESSOR);
- tupleBuffer.setFinal(true); //final, but not closed so that we can append on
insert
- groupToTupleSourceID.put(tempTableName, tupleBuffer);
- }
-
- public void removeTempTableByName(String tempTableName) throws
TeiidComponentException {
- tempMetadataStore.removeTempGroup(tempTableName);
- TupleBuffer tsId = this.groupToTupleSourceID.remove(tempTableName);
- if(tsId != null) {
- tsId.remove();
- }
- }
-
- public TempMetadataStore getMetadataStore() {
- return tempMetadataStore;
- }
-
- public TupleSource registerRequest(Command command) throws TeiidComponentException,
ExpressionEvaluationException, QueryProcessingException{
- if (command instanceof Query) {
- Query query = (Query)command;
- GroupSymbol group = (GroupSymbol)query.getFrom().getGroups().get(0);
- if (!group.isTempGroupSymbol()) {
- return null;
- }
- TupleBuffer tsId =
getTupleSourceID(group.getNonCorrelationName().toUpperCase(), command);
- return tsId.createIndexedTupleSource();
- }
- if (command instanceof ProcedureContainer) {
- GroupSymbol group = ((ProcedureContainer)command).getGroup();
- if (!group.isTempGroupSymbol()) {
- return null;
- }
- final String groupKey = group.getNonCorrelationName().toUpperCase();
- final TupleBuffer tsId = getTupleSourceID(groupKey, command);
- if (command instanceof Insert) {
- return addTuple((Insert)command, tsId);
- }
- if (command instanceof Update) {
- final Update update = (Update)command;
- final Criteria crit = update.getCriteria();
- return new UpdateTupleSource(groupKey, tsId, crit) {
- @Override
- protected void tuplePassed(List<?> tuple)
- throws ExpressionEvaluationException,
- BlockedException, TeiidComponentException {
- List<Object> newTuple = new ArrayList<Object>(tuple);
- for (Map.Entry<ElementSymbol, Expression> entry :
update.getChangeList().getClauseMap().entrySet()) {
- newTuple.set((Integer)lookup.get(entry.getKey()),
eval.evaluate(entry.getValue(), tuple));
- }
- updateCount++;
- addTuple(newTuple);
- }
-
- protected void tupleFailed(java.util.List<?> tuple) throws
TeiidComponentException {
- addTuple(tuple);
- }
- };
- }
- if (command instanceof Delete) {
- final Delete delete = (Delete)command;
- final Criteria crit = delete.getCriteria();
- if (crit == null) {
- int rows = tsId.getRowCount();
- addTempTable(groupKey, tsId.getSchema(), true);
- return CollectionTupleSource.createUpdateCountTupleSource(rows);
- }
- return new UpdateTupleSource(groupKey, tsId, crit) {
- @Override
- protected void tuplePassed(List<?> tuple)
- throws ExpressionEvaluationException,
- BlockedException, TeiidComponentException {
- updateCount++;
- }
-
- protected void tupleFailed(java.util.List<?> tuple) throws
TeiidComponentException {
- addTuple(tuple);
- }
- };
- }
- }
- if (command instanceof Create) {
- addTempTable(((Create)command).getTable().getName().toUpperCase(),
((Create)command).getColumns(), false);
- return CollectionTupleSource.createUpdateCountTupleSource(0);
- }
- if (command instanceof Drop) {
- String tempTableName = ((Drop)command).getTable().getName().toUpperCase();
- removeTempTableByName(tempTableName);
- return CollectionTupleSource.createUpdateCountTupleSource(0);
- }
- return null;
- }
-
- public void removeTempTables() throws TeiidComponentException{
- for (String name : new ArrayList<String>( groupToTupleSourceID.keySet() ))
{
- removeTempTableByName(name);
- }
- }
-
- private TupleBuffer getTupleSourceID(String tempTableID, Command command) throws
TeiidComponentException, QueryProcessingException{
- TupleBuffer tsID = groupToTupleSourceID.get(tempTableID);
- if(tsID != null) {
- return tsID;
- }
- if(this.parentTempTableStore != null){
- tsID = this.parentTempTableStore.getTupleSourceID(tempTableID);
- if(tsID != null) {
- return tsID;
- }
- }
- //allow implicit temp group definition
- List columns = null;
- if (command instanceof Insert) {
- Insert insert = (Insert)command;
- GroupSymbol group = insert.getGroup();
- if(group.isImplicitTempGroupSymbol()) {
- columns = insert.getVariables();
- }
- }
- if (columns == null) {
- throw new
QueryProcessingException(QueryExecPlugin.Util.getString("TempTableStore.table_doesnt_exist_error",
tempTableID)); //$NON-NLS-1$
- }
- addTempTable(tempTableID, columns, true);
- return groupToTupleSourceID.get(tempTableID);
- }
-
- private TupleSource addTuple(Insert insert, TupleBuffer tsId) throws
TeiidComponentException, ExpressionEvaluationException {
- GroupSymbol group = insert.getGroup();
- int tuplesAdded = 0;
- try {
- List<ElementSymbol> elements =
ResolverUtil.resolveElementsInGroup(group, new TempMetadataAdapter(null,
tempMetadataStore));
-
- List<List<Object>> tuples = getBulkRows(insert, elements);
-
- for (List<Object> list : tuples) {
- tsId.addTuple(list);
- }
- //TODO: this leads to fragmented batches, which may require recreating the
table
- tsId.saveBatch();
-
- tuplesAdded = tuples.size();
- } catch (QueryMetadataException err) {
- throw new TeiidComponentException(err);
- }
-
- return CollectionTupleSource.createUpdateCountTupleSource(tuplesAdded);
- }
-
- public static List<List<Object>> getBulkRows(Insert insert,
List<ElementSymbol> elements) throws ExpressionEvaluationException,
BlockedException, TeiidComponentException {
- int bulkRowCount = 1;
- if (insert.isBulk()) {
- Constant c = (Constant)insert.getValues().get(0);
- bulkRowCount = ((List<?>)c.getValue()).size();
- }
-
- List<List<Object>> tuples = new
ArrayList<List<Object>>(bulkRowCount);
-
- for (int row = 0; row < bulkRowCount; row++) {
- List<Object> currentRow = new
ArrayList<Object>(insert.getValues().size());
- for (ElementSymbol symbol : elements) {
- int index = insert.getVariables().indexOf(symbol);
- Object value = null;
- if (index != -1) {
- if (insert.isBulk()) {
- Constant multiValue = (Constant)insert.getValues().get(index);
- value = ((List<?>)multiValue.getValue()).get(row);
- } else {
- Expression expr = (Expression)insert.getValues().get(index);
- value = Evaluator.evaluate(expr);
- }
- }
- currentRow.add(value);
- }
- tuples.add(currentRow);
- }
- return tuples;
- }
-
- public boolean hasTempTable(Command command){
- switch (command.getType()) {
- case Command.TYPE_INSERT:
- {
- Insert insert = (Insert)command;
- GroupSymbol group = insert.getGroup();
- return group.isTempGroupSymbol();
- }
- case Command.TYPE_QUERY:
- {
- if(command instanceof Query) {
- Query query = (Query)command;
- GroupSymbol group = (GroupSymbol)query.getFrom().getGroups().get(0);
- return group.isTempGroupSymbol();
- }
- break;
- }
- case Command.TYPE_CREATE:
- return true;
- case Command.TYPE_DROP:
- return true;
- }
- return false;
- }
-
- public Set<String> getAllTempTables() {
- return new HashSet<String>(this.groupToTupleSourceID.keySet());
- }
-
- public TupleBuffer getTupleSourceID(String tempTableName) {
- return groupToTupleSourceID.get(tempTableName.toUpperCase());
- }
-}
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2010-07-23 20:47:35
UTC (rev 2370)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2010-07-23 21:44:19
UTC (rev 2371)
@@ -500,6 +500,7 @@
Create create = new Create();
String table = null;
List columns = null;
+ String pkId = null;
}
{
<CREATE> <LOCAL> <TEMPORARY> <TABLE>
@@ -512,6 +513,18 @@
{
create.setColumns(columns);
}
+ [<COMMA> <PRIMARY> nonReserved("KEY") <LPAREN>
+ pkId = id()
+ {
+ create.getPrimaryKey().add(new ElementSymbol(validateElementName(pkId)));
+ }
+ (<COMMA> pkId = id()
+ {
+ create.getPrimaryKey().add(new ElementSymbol(validateElementName(pkId)));
+ }
+ )*
+ <RPAREN>
+ ]
<RPAREN>
{
return create;
@@ -1087,7 +1100,7 @@
symbol.setType(DataTypeManager.getDataTypeClass(type.getValue().toString()));
elements.add(symbol);
}
- (<COMMA>
+ (LOOKAHEAD(2) <COMMA>
element = id()
type = dataType()
{
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-07-23 20:47:35
UTC (rev 2370)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-07-23 21:44:19
UTC (rev 2371)
@@ -945,4 +945,6 @@
WorkerPool.New_thread=Created worker thread "{0}".
WorkerPool.uncaughtException=Uncaught exception processing work
-XMLSystemFunctions.invalid_namespaces=Invalid namespaces supplied for XPath expression -
''{0}''
\ No newline at end of file
+XMLSystemFunctions.invalid_namespaces=Invalid namespaces supplied for XPath expression -
''{0}''
+
+TempTable.duplicate_key=Duplicate key
\ No newline at end of file
Added: trunk/engine/src/test/java/org/teiid/common/buffer/impl/TestSTree.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/common/buffer/impl/TestSTree.java
(rev 0)
+++ trunk/engine/src/test/java/org/teiid/common/buffer/impl/TestSTree.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -0,0 +1,62 @@
+/*
+ * 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.common.buffer.impl;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.teiid.common.buffer.BufferManager;
+import org.teiid.common.buffer.BufferManagerFactory;
+import org.teiid.common.buffer.STree;
+import org.teiid.common.buffer.BufferManager.TupleSourceType;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.query.sql.symbol.ElementSymbol;
+
+public class TestSTree {
+
+ @Test public void testRemoveAll() throws TeiidComponentException, IOException {
+ BufferManager bm = BufferManagerFactory.getStandaloneBufferManager();
+ ElementSymbol e1 = new ElementSymbol("x");
+ e1.setType(Integer.class);
+ ElementSymbol e2 = new ElementSymbol("y");
+ e2.setType(String.class);
+ List elements = Arrays.asList(e1, e2);
+ STree map = bm.createSTree(elements, "1", TupleSourceType.PROCESSOR, 1);
+
+ for (int i = 20000; i > 0; i--) {
+ map.insert(Arrays.asList(i, String.valueOf(i)), true);
+ }
+
+ for (int i = 20000; i > 0; i--) {
+ map.remove(Arrays.asList(i));
+ }
+
+ assertEquals(0, map.getRowCount());
+ assertNull(map.insert(Arrays.asList(1, String.valueOf(1)), true));
+ }
+
+}
Property changes on:
trunk/engine/src/test/java/org/teiid/common/buffer/impl/TestSTree.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified:
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestCodeTableCache.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestCodeTableCache.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestCodeTableCache.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -69,7 +69,7 @@
// r2--> 'Germany', 'GM'
try {
- ctc.loadTable(nodeId, results);
+ ctc.loadTable(nodeId, Arrays.asList(results));
} catch (TeiidProcessingException e) {
throw new RuntimeException(e);
}
@@ -90,7 +90,7 @@
// r2--> 'Germany', 'GM'
try {
- ctc.loadTable(nodeId, results);
+ ctc.loadTable(nodeId, Arrays.asList(results));
} catch (TeiidProcessingException e) {
throw new RuntimeException(e);
}
@@ -203,7 +203,7 @@
};
try {
- ctc.loadTable(nodeId, results);
+ ctc.loadTable(nodeId, Arrays.asList(results));
fail("expected exception"); //$NON-NLS-1$
} catch (TeiidProcessingException e) {
assertEquals("Duplicate code table 'table' key 'value' value
'1'", e.getMessage()); //$NON-NLS-1$
@@ -221,7 +221,7 @@
};
try {
- ctc.loadTable(nodeId, results);
+ ctc.loadTable(nodeId, Arrays.asList(results));
fail("expected exception"); //$NON-NLS-1$
} catch (TeiidProcessingException e) {
assertEquals("Error Code:ERR.018.005.0100 Message:Unable to load code table for
because result sizes exceeds the allowed parameter - maxCodeTableRecords.",
e.getMessage()); //$NON-NLS-1$
@@ -239,7 +239,7 @@
};
try {
- ctc.loadTable(nodeId, results);
+ ctc.loadTable(nodeId, Arrays.asList(results));
fail("expected exception"); //$NON-NLS-1$
} catch (TeiidProcessingException e) {
assertEquals("Error Code:ERR.018.005.0100 Message:Unable to load code table for
because result sizes exceeds the allowed parameter - maxCodeTables.",
e.getMessage()); //$NON-NLS-1$
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptionalJoins.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptionalJoins.java 2010-07-23
20:47:35 UTC (rev 2370)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptionalJoins.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -304,7 +304,7 @@
0, // Null
0, // PlanExecution
3, // Project
- 0, // Select
+ 1, // Select
0, // Sort
0 // UnionAll
});
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2010-07-23 20:47:35
UTC (rev 2370)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2010-07-23 21:44:19
UTC (rev 2371)
@@ -6569,6 +6569,21 @@
helpException("Create local TEMPORARY table tempTable (c1.x boolean, c2
byte)" ,"Parsing error: Invalid simple identifier format: [c1.x]");
//$NON-NLS-1$ //$NON-NLS-2$
}
+ @Test public void testCreateTempTableWithPrimaryKey() {
+ Create create = new Create();
+ create.setTable(new GroupSymbol("tempTable")); //$NON-NLS-1$
+ List columns = new ArrayList();
+ ElementSymbol column = new ElementSymbol("c1");//$NON-NLS-1$
+ column.setType(DataTypeManager.DefaultDataClasses.BOOLEAN);
+ columns.add(column);
+ column = new ElementSymbol("c2");//$NON-NLS-1$
+ column.setType(DataTypeManager.DefaultDataClasses.BYTE);
+ columns.add(column);
+ create.setColumns(columns);
+ create.getPrimaryKey().add(column);
+ helpTest("Create local TEMPORARY table tempTable(c1 boolean, c2 byte,
primary key (c2))", "CREATE LOCAL TEMPORARY TABLE tempTable (c1 boolean, c2
byte, PRIMARY KEY(c2))", create); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
@Test public void testDropTable() {
Drop drop = new Drop();
drop.setTable(new GroupSymbol("tempTable")); //$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 2010-07-23
20:47:35 UTC (rev 2370)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -297,8 +297,8 @@
props.setProperty("soap_host", "my.host.com"); //$NON-NLS-1$
//$NON-NLS-2$
props.setProperty("soap_port", "12345"); //$NON-NLS-1$
//$NON-NLS-2$
CommandContext context = new CommandContext("0", "test",
"user", null, "myvdb", 1, props, DEBUG, false); //$NON-NLS-1$
//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
- context.setProcessorBatchSize(2000);
- context.setConnectorBatchSize(2000);
+ context.setProcessorBatchSize(BufferManager.DEFAULT_PROCESSOR_BATCH_SIZE);
+ context.setConnectorBatchSize(BufferManager.DEFAULT_CONNECTOR_BATCH_SIZE);
context.setBufferManager(BufferManagerFactory.getStandaloneBufferManager());
context.setProcessDebug(DEBUG);
return context;
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-23
20:47:35 UTC (rev 2370)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -28,10 +28,9 @@
import org.junit.Before;
import org.junit.Test;
import org.teiid.common.buffer.BufferManagerFactory;
-import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
import org.teiid.query.metadata.TempMetadataAdapter;
-import org.teiid.query.processor.TempTableDataManager;
-import org.teiid.query.tempdata.TempTableStoreImpl;
+import org.teiid.query.tempdata.TempTableStore;
import org.teiid.query.unittest.FakeMetadataFactory;
@@ -44,8 +43,8 @@
TestProcessor.doProcess(TestProcessor.helpGetPlan(sql, metadata), dataManager,
expectedResults, TestProcessor.createCommandContext());
}
- @Before public void setUp() throws TeiidComponentException {
- TempTableStoreImpl tempStore = new
TempTableStoreImpl(BufferManagerFactory.getStandaloneBufferManager(), "1",
null); //$NON-NLS-1$
+ @Before public void setUp() {
+ TempTableStore tempStore = new
TempTableStore(BufferManagerFactory.getStandaloneBufferManager(), "1", null);
//$NON-NLS-1$
metadata = new TempMetadataAdapter(FakeMetadataFactory.example1Cached(),
tempStore.getMetadataStore());
FakeDataManager fdm = new FakeDataManager();
TestProcessor.sampleData1(fdm);
@@ -90,5 +89,37 @@
execute("delete from x", new List[] {Arrays.asList(6)}); //$NON-NLS-1$
execute("select e1 from x order by e1", new List[] {}); //$NON-NLS-1$
}
-
+
+ @Test(expected=TeiidProcessingException.class) public void testDuplicatePrimaryKey()
throws Exception {
+ execute("create local temporary table x (e1 string, e2 integer, primary key
(e2))", new List[] {Arrays.asList(0)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (1, 'one')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (1, 'one')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ }
+
+ @Test public void testAtomicUpdate() throws Exception {
+ execute("create local temporary table x (e1 string, e2 integer, primary key
(e2))", new List[] {Arrays.asList(0)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (1, 'one')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (2, 'one')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ try {
+ execute("update x set e2 = 3", new List[] {Arrays.asList(1)});
//$NON-NLS-1$
+ } catch (TeiidProcessingException e) {
+ //should be a duplicate key
+ }
+ //should revert back to original
+ execute("select count(*) from x", new List[] {Arrays.asList(2)});
//$NON-NLS-1$
+ }
+
+ @Test public void testAtomicDelete() throws Exception {
+ execute("create local temporary table x (e1 string, e2 integer, primary key
(e2))", new List[] {Arrays.asList(0)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (1, 'one')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (2, 'one')", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ try {
+ execute("delete from x where 1/(e2 - 2) <> 4", new List[]
{Arrays.asList(1)}); //$NON-NLS-1$
+ } catch (TeiidProcessingException e) {
+ //should be a duplicate key
+ }
+ //should revert back to original
+ execute("select count(*) from x", new List[] {Arrays.asList(2)});
//$NON-NLS-1$
+ }
+
}
Modified:
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -64,7 +64,7 @@
import org.teiid.query.validator.ValidatorFailure;
import org.teiid.query.validator.ValidatorReport;
-
+@SuppressWarnings("unchecked")
public class TestProcedureProcessor {
public static ProcessorPlan getProcedurePlan(String userQuery, FakeMetadataFacade
metadata) throws Exception {
@@ -111,25 +111,25 @@
}
}
- private void helpTestProcessFailure(boolean optimistic, ProcessorPlan procPlan,
- FakeDataManager dataMgr, String failMessage) throws
Exception {
+ private void helpTestProcessFailure(ProcessorPlan procPlan, FakeDataManager dataMgr,
+ String failMessage) throws Exception {
try {
- helpTestProcess(optimistic, procPlan, new List[] {}, dataMgr, true);
+ helpTestProcess(procPlan, new List[] {}, dataMgr, true);
} catch(TeiidException ex) {
assertEquals(failMessage, ex.getMessage());
}
}
public static void helpTestProcess(ProcessorPlan procPlan, List[] expectedResults,
ProcessorDataManager dataMgr) throws Exception {
- helpTestProcess(false, procPlan, expectedResults, dataMgr, false);
+ helpTestProcess(procPlan, expectedResults, dataMgr, false);
}
private void helpTestProcess(ProcessorPlan procPlan, int expectedRows,
FakeDataManager dataMgr) throws Exception {
helpTestProcess(procPlan, expectedRows, null, false, dataMgr, null);
}
- static void helpTestProcess(boolean optimistic, ProcessorPlan procPlan, List[]
expectedResults,
- ProcessorDataManager dataMgr, boolean shouldFail) throws Exception {
+ static void helpTestProcess(ProcessorPlan procPlan, List[] expectedResults,
ProcessorDataManager dataMgr,
+ boolean shouldFail) throws Exception {
helpTestProcess(procPlan, 0, expectedResults, shouldFail, dataMgr, null);
}
@@ -451,7 +451,7 @@
ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
- helpTestProcessFailure(false, plan, dataMgr, "Error Code:ERR.015.006.0058
Message:Unable to evaluate (SELECT pm1.g1.e2 FROM pm1.g1): Error Code:ERR.015.006.0058
Message:The command of this scalar subquery returned more than one value: SELECT pm1.g1.e2
FROM pm1.g1"); //$NON-NLS-1$
+ helpTestProcessFailure(plan, dataMgr, "Error Code:ERR.015.006.0058
Message:Unable to evaluate (SELECT pm1.g1.e2 FROM pm1.g1): Error Code:ERR.015.006.0058
Message:The command of this scalar subquery returned more than one value: SELECT pm1.g1.e2
FROM pm1.g1"); //$NON-NLS-1$
}
// error statement
@@ -488,7 +488,7 @@
ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
- helpTestProcessFailure(false, plan, dataMgr, ErrorInstruction.ERROR_PREFIX +
"5MY ERROR"); //$NON-NLS-1$
+ helpTestProcessFailure(plan, dataMgr, ErrorInstruction.ERROR_PREFIX + "5MY
ERROR"); //$NON-NLS-1$
}
private void helpTestErrorStatment(String errorValue, String expected) throws
Exception {
@@ -508,7 +508,7 @@
ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
- helpTestProcessFailure(false, plan, dataMgr, ErrorInstruction.ERROR_PREFIX +
expected);
+ helpTestProcessFailure(plan, dataMgr, ErrorInstruction.ERROR_PREFIX + expected);
}
/** test if statement's if block with lookup in if condition */
@@ -1502,8 +1502,7 @@
ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
- helpTestProcessFailure(false,
- plan,
+ helpTestProcessFailure(plan,
dataMgr,
"Couldn't execute the dynamic SQL command
\"EXECUTE STRING 'EXEC pm1.sq2(''First'')' AS e1 string, e2
integer\" with the SQL statement \"'EXEC
pm1.sq2(''First'')'\" due to: There is a recursive invocation of
group 'PM1.SQ2'. Please correct the SQL."); //$NON-NLS-1$
}
@@ -1535,7 +1534,7 @@
ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
- helpTestProcessFailure(false, plan, dataMgr, "Couldn't execute the
dynamic SQL command \"EXECUTE STRING 'EXEC
pm1.sq1(''First'')' AS e1 string, e2 integer\" with the SQL
statement \"'EXEC pm1.sq1(''First'')'\" due to: The
dynamic sql string contains an incorrect number of elements."); //$NON-NLS-1$
+ helpTestProcessFailure(plan, dataMgr, "Couldn't execute the dynamic SQL
command \"EXECUTE STRING 'EXEC pm1.sq1(''First'')' AS e1
string, e2 integer\" with the SQL statement \"'EXEC
pm1.sq1(''First'')'\" due to: The dynamic sql string contains an
incorrect number of elements."); //$NON-NLS-1$
}
@Test public void testDynamicCommandPositional() throws Exception {
@@ -1587,7 +1586,7 @@
ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
- helpTestProcessFailure(false, plan, dataMgr, "Couldn't execute the
dynamic SQL command \"EXECUTE STRING 'select e1 from pm1.g1'\" with the
SQL statement \"'select e1 from pm1.g1'\" due to: The datatype
'string' for element 'E1' in the dynamic SQL cannot be implicitly
converted to 'integer'."); //$NON-NLS-1$
+ helpTestProcessFailure(plan, dataMgr, "Couldn't execute the dynamic SQL
command \"EXECUTE STRING 'select e1 from pm1.g1'\" with the SQL
statement \"'select e1 from pm1.g1'\" due to: The datatype
'string' for element 'E1' in the dynamic SQL cannot be implicitly
converted to 'integer'."); //$NON-NLS-1$
}
@Test public void testDynamicCommandWithTwoDynamicStatements() throws Exception {
@@ -1877,7 +1876,7 @@
ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
- helpTestProcessFailure(false, plan, dataMgr, "Temporary table
\"T1\" already exists."); //$NON-NLS-1$
+ helpTestProcessFailure(plan, dataMgr, "Temporary table \"T1\"
already exists."); //$NON-NLS-1$
}
/**
Modified:
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestProjectIntoNode.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestProjectIntoNode.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestProjectIntoNode.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -42,7 +42,7 @@
import org.teiid.query.sql.symbol.Constant;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.GroupSymbol;
-import org.teiid.query.tempdata.TempTableStoreImpl;
+import org.teiid.query.tempdata.TempTableStore;
import org.teiid.query.util.CommandContext;
import junit.framework.TestCase;
@@ -140,7 +140,7 @@
if (command instanceof Insert) {
Insert insert = (Insert)command;
if (insert.isBulk()) {
- List batch = TempTableStoreImpl.getBulkRows(insert,
insert.getVariables());
+ List batch = TempTableStore.getBulkRows(insert,
insert.getVariables());
batchSize = batch.size();
assertEquals("Unexpected batch on call " + callCount,
expectedBatchSize, batchSize); //$NON-NLS-1$
Modified: trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java 2010-07-23
20:47:35 UTC (rev 2370)
+++ trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -38,6 +38,7 @@
import java.util.Map;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.api.exception.query.QueryResolverException;
@@ -94,8 +95,9 @@
import org.teiid.query.unittest.FakeMetadataObject;
import org.teiid.query.unittest.FakeMetadataStore;
import org.teiid.query.unittest.TimestampUtil;
+import org.teiid.query.util.ErrorMessageKeys;
-
+@SuppressWarnings("nls")
public class TestResolver {
private FakeMetadataFacade metadata;
@@ -2400,6 +2402,16 @@
helpResolveException(sql, "Cannot create temporary table
\"pm1.g1\". Local temporary tables must be created with unqualified
names."); //$NON-NLS-1$
}
+ @Test public void testCreatePk() {
+ String sql = "CREATE LOCAL TEMPORARY TABLE foo (column1 string, column2
integer, primary key (column1, column2))"; //$NON-NLS-1$
+ helpResolve(sql);
+ }
+
+ @Test public void testCreateUnknownPk() {
+ String sql = "CREATE LOCAL TEMPORARY TABLE foo (column1 string, primary key
(column2))"; //$NON-NLS-1$
+ helpResolveException(sql, "Element \"column2\" is not defined by
any relevant group."); //$NON-NLS-1$
+ }
+
@Test public void testCreateAlreadyExists() {
String sql = "CREATE LOCAL TEMPORARY TABLE g1 (column1 string)";
//$NON-NLS-1$
helpResolveException(sql, "Cannot create temporary table \"g1\". A
table with the same name already exists."); //$NON-NLS-1$
@@ -2863,6 +2875,21 @@
@Test public void testSecondPassFunctionResolving() {
helpResolve("SELECT pm1.g1.e1 FROM pm1.g1 where lower(?) = e1 ");
//$NON-NLS-1$
}
+
+ @Test public void testSecondPassFunctionResolving1() {
+ try {
+ helpResolve("SELECT pm1.g1.e1 FROM pm1.g1 where 1/(e1 - 2) <> 4 ");
//$NON-NLS-1$
+ fail("expected exception");
+ } catch (RuntimeException e) {
+ QueryResolverException qre = (QueryResolverException)e.getCause();
+ assertEquals(ErrorMessageKeys.RESOLVER_0040, qre.getCode());
+ }
+ }
+
+ @Ignore("currently not supported - we get type hints from the criteria not from
the possible signatures")
+ @Test public void testSecondPassFunctionResolving2() {
+ helpResolve("SELECT pm1.g1.e1 FROM pm1.g1 where (lower(?) || 1) = e1 ");
//$NON-NLS-1$
+ }
/**
* Test <code>QueryResolver</code>'s ability to resolve a query that
Modified:
trunk/engine/src/test/java/org/teiid/query/sql/util/TestElementSymbolOptimizer.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/sql/util/TestElementSymbolOptimizer.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/test/java/org/teiid/query/sql/util/TestElementSymbolOptimizer.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -183,7 +183,7 @@
helpTestOptimize("EXEC pm1.sq2(pm1.sq3.in)", //$NON-NLS-1$
FakeMetadataFactory.example1Cached(),
- "EXEC pm1.sq2(pm1.sq3.\"in\")",
//$NON-NLS-1$
+ "EXEC pm1.sq2(\"in\")", //$NON-NLS-1$
externalMetadata);
}
Modified:
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java 2010-07-23
20:47:35 UTC (rev 2370)
+++
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java 2010-07-23
21:44:19 UTC (rev 2371)
@@ -1127,7 +1127,7 @@
public void testElementSymbol5() {
ElementSymbol es = new ElementSymbol("m.g.select", false); //$NON-NLS-1$
es.setGroupSymbol(new GroupSymbol("m.g")); //$NON-NLS-1$
- helpTest(es, "m.g.\"select\""); //$NON-NLS-1$
+ helpTest(es, "\"select\""); //$NON-NLS-1$
}
public void testExpressionSymbol1() {