/* * 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.dqp.internal.process; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import org.teiid.adminapi.impl.VDBMetaData; import org.teiid.api.exception.query.QueryMetadataException; import org.teiid.common.buffer.TupleSource; import org.teiid.core.TeiidComponentException; import org.teiid.core.TeiidProcessingException; import org.teiid.dqp.internal.process.RecordTable.ExpandingSimpleIterator; import org.teiid.dqp.internal.process.RecordTable.SimpleIterator; import org.teiid.dqp.internal.process.RecordTable.SimpleIteratorWrapper; import org.teiid.metadata.AbstractMetadataRecord; import org.teiid.query.eval.Evaluator; import org.teiid.query.metadata.TransformationMetadata; import org.teiid.query.processor.relational.RelationalNode; import org.teiid.query.sql.lang.Criteria; import org.teiid.query.sql.lang.Query; import org.teiid.query.sql.symbol.ElementSymbol; import org.teiid.query.sql.symbol.Expression; import org.teiid.query.tempdata.BaseIndexInfo; import org.teiid.query.util.CommandContext; abstract class BaseExtractionTable<T> { static final class ExtractionTupleSource<T> implements TupleSource { private final Criteria condition; private final SimpleIterator<T> iter; private final CommandContext cc; private final VDBMetaData vdb; private final TransformationMetadata metadata; private ArrayList<Object> rowBuffer; private BaseExtractionTable<T> extraction; ExtractionTupleSource(Criteria condition, SimpleIterator<T> iter, CommandContext cc, VDBMetaData vdb, TransformationMetadata metadata, BaseExtractionTable<T> extraction) { this.condition = condition; this.iter = iter; this.cc = cc; this.vdb = vdb; this.metadata = metadata; this.extraction = extraction; } @Override public List<?> nextTuple() throws TeiidComponentException, TeiidProcessingException { while (true) { T val = iter.next(); if (val == null) { return null; } if (rowBuffer == null) { rowBuffer = new ArrayList<Object>(extraction.cols); } else { rowBuffer.clear(); } extraction.fillRow(rowBuffer, val, vdb, metadata, cc, iter); if (condition == null || extraction.eval.evaluate(condition, rowBuffer)) { List<?> result = rowBuffer; rowBuffer = null; return result; } } } @Override public void closeSource() { } } private Evaluator eval; private int cols; public BaseExtractionTable(List<ElementSymbol> columns) { Map<Expression, Integer> map = RelationalNode.createLookupMap(columns); this.eval = new Evaluator(map, null, null); this.cols = columns.size(); } public TupleSource processQuery(Query query, final VDBMetaData vdb, final TransformationMetadata metadata, final CommandContext cc) throws QueryMetadataException, TeiidComponentException { return new ExtractionTupleSource(query.getCriteria(), createIterator(vdb, metadata, cc), cc, vdb, metadata, this); } protected SimpleIterator<T> createIterator(final VDBMetaData vdb, final TransformationMetadata metadata, final CommandContext cc) throws QueryMetadataException, TeiidComponentException { return null; } protected abstract void fillRow(List<Object> row, T record, VDBMetaData vdb, TransformationMetadata metadata, CommandContext cc, SimpleIterator<T> iter); } abstract class RecordExtractionTable<T extends AbstractMetadataRecord> extends BaseExtractionTable<T> { private RecordTable<T> baseTable; public RecordExtractionTable(RecordTable<T> baseTable, List<ElementSymbol> columns) { super(columns); this.baseTable = baseTable; } @Override public TupleSource processQuery(Query query, VDBMetaData vdb, TransformationMetadata metadata, CommandContext cc) { BaseIndexInfo<?> ii = baseTable.planQuery(query, query.getCriteria(), cc); final SimpleIterator<T> iter = baseTable.processQuery(vdb, metadata.getMetadataStore(), ii, metadata, cc); return new ExtractionTupleSource<T>(ii.getNonCoveredCriteria(), iter, cc, vdb, metadata, this); } } abstract class ChildRecordExtractionTable<P extends AbstractMetadataRecord, T> extends BaseExtractionTable<T> { private RecordTable<P> baseTable; public ChildRecordExtractionTable(RecordTable<P> baseTable, List<ElementSymbol> columns) { super(columns); this.baseTable = baseTable; } protected boolean isValid(T result, CommandContext cc) { return !(result instanceof AbstractMetadataRecord) || cc.getDQPWorkContext().isAdmin() || cc.getAuthorizationValidator().isAccessible((AbstractMetadataRecord)result, cc); } @Override public TupleSource processQuery(Query query, VDBMetaData vdb, final TransformationMetadata metadata, final CommandContext cc) { BaseIndexInfo<?> ii = baseTable.planQuery(query, query.getCriteria(), cc); final SimpleIterator<P> iter = baseTable.processQuery(vdb, metadata.getMetadataStore(), ii, metadata, cc); while (ii.next != null) { ii = ii.next; } return new ExtractionTupleSource<T>(ii.getNonCoveredCriteria(), new ExpandingSimpleIterator<P, T>(iter) { SimpleIteratorWrapper<T> wrapper = new SimpleIteratorWrapper<T>(null) { @Override protected boolean isValid(T result) { return ChildRecordExtractionTable.this.isValid(result, cc); } }; protected RecordTable.SimpleIterator<T> getChildIterator(P parent) { Collection<? extends T> children = getChildren(parent, cc); if (children.isEmpty()) { return RecordTable.emptyIterator(); } wrapper.setIterator(children.iterator()); return wrapper; } }, cc, vdb, metadata, this); } protected abstract Collection<? extends T> getChildren(P parent, CommandContext cc); }