use of org.teiid.common.buffer.TupleBrowser in project teiid by teiid.
the class TempTable method delete.
public TupleSource delete(Criteria crit) throws TeiidComponentException, ExpressionEvaluationException, TeiidProcessingException {
final TupleBrowser browser = createTupleBrower(crit, OrderBy.ASC);
UpdateProcessor up = new UpdateProcessor(crit, browser, true) {
@Override
protected void tuplePassed(List tuple) throws ExpressionEvaluationException, BlockedException, TeiidComponentException {
browser.removed();
deleteTuple(tuple);
}
@Override
protected void undo(List<?> tuple) throws TeiidComponentException, TeiidProcessingException {
insertTuple(tuple, false, true);
}
};
long updateCount = up.process();
tid.setCardinality(tree.getRowCount());
tid.getTableData().dataModified(updateCount);
return CollectionTupleSource.createUpdateCountTupleSource((int) Math.min(Integer.MAX_VALUE, updateCount));
}
use of org.teiid.common.buffer.TupleBrowser in project teiid by teiid.
the class TempTable method update.
public TupleSource update(Criteria crit, final SetClauseList update) throws TeiidComponentException, ExpressionEvaluationException, TeiidProcessingException {
final boolean primaryKeyChangePossible = canChangePrimaryKey(update);
final TupleBrowser browser = createTupleBrower(crit, OrderBy.ASC);
UpdateProcessor up = new UpdateProcessor(crit, browser, true) {
protected TupleBuffer changeSet;
protected UpdateProcessor changeSetProcessor;
@Override
protected void tuplePassed(List tuple) throws BlockedException, TeiidComponentException, TeiidProcessingException {
List<Object> newTuple = new ArrayList<Object>(tuple);
for (Map.Entry<ElementSymbol, Expression> entry : update.getClauseMap().entrySet()) {
newTuple.set(columnMap.get(entry.getKey()), eval.evaluate(entry.getValue(), tuple));
}
validateNotNull(newTuple);
if (primaryKeyChangePossible) {
browser.removed();
deleteTuple(tuple);
if (changeSet == null) {
changeSet = bm.createTupleBuffer(columns, sessionID, TupleSourceType.PROCESSOR);
}
changeSet.addTuple(newTuple);
} else {
browser.update(newTuple);
}
}
@Override
protected void undo(List<?> tuple) throws TeiidComponentException, TeiidProcessingException {
if (primaryKeyChangePossible) {
insertTuple(tuple, false, true);
} else {
updateTuple(tuple);
}
}
@Override
void success() throws TeiidComponentException, ExpressionEvaluationException, TeiidProcessingException {
// changeSet contains possible updates
if (primaryKeyChangePossible) {
changeSet.close();
if (changeSetProcessor == null) {
changeSetProcessor = new InsertUpdateProcessor(changeSet.createIndexedTupleSource(true), false, null, true, false);
}
// when this returns, we're up to date
changeSetProcessor.process();
}
}
@Override
public void close() {
super.close();
changeSetProcessor = null;
if (changeSet != null) {
changeSet.remove();
changeSet = null;
}
}
};
long updateCount = up.process();
tid.getTableData().dataModified(updateCount);
return CollectionTupleSource.createUpdateCountTupleSource((int) Math.min(Integer.MAX_VALUE, updateCount));
}
use of org.teiid.common.buffer.TupleBrowser in project teiid by teiid.
the class TempTable method createTupleSource.
private TupleSource createTupleSource(final List<? extends Expression> projectedCols, final Criteria condition, OrderBy orderBy, IndexInfo ii, boolean agg) throws TeiidComponentException, TeiidProcessingException {
TupleBrowser browser = ii.createTupleBrowser(bm.getOptions().getDefaultNullOrder(), true);
TupleSource ts = new QueryTupleSource(browser, columnMap, agg ? getColumns() : projectedCols, condition);
boolean usingQueryTupleSource = false;
boolean success = false;
TupleBuffer tb = null;
try {
if (ii.ordering == null && orderBy != null) {
SortUtility sort = new SortUtility(ts, orderBy.getOrderByItems(), Mode.SORT, bm, sessionID, projectedCols);
sort.setNonBlocking(true);
tb = sort.sort();
} else if (agg) {
int count = 0;
while (ts.nextTuple() != null) {
count++;
}
success = true;
return new CollectionTupleSource(Arrays.asList(Collections.nCopies(projectedCols.size(), count)).iterator());
} else if (updatable) {
tb = bm.createTupleBuffer(projectedCols, sessionID, TupleSourceType.PROCESSOR);
List<?> next = null;
while ((next = ts.nextTuple()) != null) {
tb.addTuple(next);
}
} else {
usingQueryTupleSource = true;
success = true;
return ts;
}
tb.close();
success = true;
return tb.createIndexedTupleSource(true);
} finally {
if (!success && tb != null) {
tb.remove();
}
if (!usingQueryTupleSource) {
// ensure the buffers get released
ts.closeSource();
}
}
}
use of org.teiid.common.buffer.TupleBrowser in project teiid by teiid.
the class EnhancedSortMergeJoinStrategy method createIndex.
/**
* Create an index of the smaller size
*/
public void createIndex(SourceState state, SortOption sortOption) throws TeiidComponentException, TeiidProcessingException {
// this is inefficient as it fully buffers, then builds the index. if possible
// we should build off of the streaming batches
IndexedTupleSource its = state.getTupleBuffer().createIndexedTupleSource(!joinNode.isDependent());
boolean sorted = sortOption == SortOption.ALREADY_SORTED;
int[] expressionIndexes = state.getExpressionIndexes();
int keyLength = expressionIndexes.length;
List elements = state.getSource().getOutputElements();
// TODO: minimize reordering, or at least detect when it's not necessary
LinkedHashSet<Integer> used = new LinkedHashSet<Integer>();
for (int i : expressionIndexes) {
used.add(i);
}
int[] reorderedSortIndex = Arrays.copyOf(expressionIndexes, keyLength + elements.size() - used.size());
int j = keyLength;
for (int i = 0; i < elements.size(); i++) {
if (!used.contains(i)) {
reorderedSortIndex[j++] = i;
}
}
List<Expression> reordered = RelationalNode.projectTuple(reorderedSortIndex, elements);
if (sortOption == SortOption.SORT_DISTINCT) {
keyLength = elements.size();
} else if (!state.isExpresssionDistinct()) {
// need to add a rowid, just in case
reordered = new ArrayList<Expression>(reordered);
// $NON-NLS-1$
ElementSymbol id = new ElementSymbol("rowId");
id.setType(DataTypeManager.DefaultDataClasses.INTEGER);
reordered.add(keyLength, id);
keyLength++;
}
index = this.joinNode.getBufferManager().createSTree(reordered, this.joinNode.getConnectionID(), keyLength);
index.setPreferMemory(true);
if (sortOption == SortOption.SORT_DISTINCT) {
index.getComparator().setDistinctIndex(expressionIndexes.length);
} else if (!state.isExpresssionDistinct()) {
index.getComparator().setDistinctIndex(keyLength - 2);
}
int rowId = 0;
List<?> lastTuple = null;
boolean sortedDistinct = sorted && !state.isExpresssionDistinct();
int sizeHint = index.getExpectedHeight(state.getRowCount());
index.setBatchInsert(sorted);
outer: while (its.hasNext()) {
// detect if sorted and distinct
List<?> originalTuple = its.nextTuple();
// remove the tuple if it has null
for (int i : expressionIndexes) {
if (originalTuple.get(i) == null) {
continue outer;
}
}
if (sortedDistinct && lastTuple != null && this.compare(lastTuple, originalTuple, expressionIndexes, expressionIndexes) == 0) {
sortedDistinct = false;
}
lastTuple = originalTuple;
List<Object> tuple = (List<Object>) RelationalNode.projectTuple(reorderedSortIndex, originalTuple);
if (!state.isExpresssionDistinct() && sortOption != SortOption.SORT_DISTINCT) {
tuple.add(keyLength - 1, rowId++);
}
index.insert(tuple, sorted ? InsertMode.ORDERED : InsertMode.NEW, sizeHint);
}
if (!sorted) {
index.compact();
} else {
index.setBatchInsert(false);
}
its.closeSource();
this.reverseIndexes = new int[elements.size()];
for (int i = 0; i < reorderedSortIndex.length; i++) {
int oldIndex = reorderedSortIndex[i];
this.reverseIndexes[oldIndex] = i + ((!state.isExpresssionDistinct() && (i >= keyLength - 1) && sortOption != SortOption.SORT_DISTINCT) ? 1 : 0);
}
// TODO: this logic doesn't catch distinct join expressions when using sort distinct very well
if (!state.isExpresssionDistinct() && ((!sorted && index.getComparator().isDistinct()) || (sorted && sortedDistinct))) {
if (sortOption != SortOption.SORT_DISTINCT) {
this.index.removeRowIdFromKey();
}
state.markExpressionsDistinct(true);
}
keyTs = new SingleTupleSource();
keyTs.indexes = this.notSortedSource.getExpressionIndexes();
tb = new TupleBrowser(this.index, keyTs, OrderBy.ASC);
}
use of org.teiid.common.buffer.TupleBrowser in project teiid by teiid.
the class IndexInfo method createTupleBrowser.
TupleBrowser createTupleBrowser(NullOrder nullOrder, boolean readOnly) throws TeiidComponentException {
boolean direction = OrderBy.ASC;
if (ordering != null) {
// $NON-NLS-1$
LogManager.logDetail(LogConstants.CTX_DQP, "Using index for ordering");
direction = ordering;
}
if (valueTs != null) {
// $NON-NLS-1$
LogManager.logDetail(LogConstants.CTX_DQP, "Using index value set");
return new TupleBrowser(this.table.getTree(), valueTs, direction, readOnly);
}
if (!valueSet.isEmpty()) {
// $NON-NLS-1$
LogManager.logDetail(LogConstants.CTX_DQP, "Using index value set");
sortValueSet(direction, nullOrder);
CollectionTupleSource cts = new CollectionTupleSource(valueSet.iterator());
return new TupleBrowser(this.table.getTree(), cts, direction, readOnly);
}
if (lower != null || upper != null) {
// $NON-NLS-1$
LogManager.logDetail(LogConstants.CTX_DQP, "Using index for range query", lower, upper);
}
return new TupleBrowser(this.table.getTree(), lower, upper, direction, readOnly);
}
Aggregations