use of org.teiid.core.TeiidProcessingException in project teiid by teiid.
the class RelationalPlanner method planWith.
private void planWith(PlanNode plan, Command command) throws QueryPlannerException, QueryMetadataException, TeiidComponentException, QueryResolverException {
if (this.withPlanningState.withList.isEmpty()) {
return;
}
// TODO: merge this logic inline with the main rule execution.
RuleStack stack = new RuleStack();
stack.push(new RuleAssignOutputElements(false));
if (hints.hasRowBasedSecurity) {
stack.push(new RuleApplySecurity());
}
// use a temporary planner to run just the assign output elements
RelationalPlanner planner = new RelationalPlanner();
// we don't want to trigger the with processing for just projection
planner.processWith = false;
planner.initialize(command, idGenerator, metadata, capFinder, analysisRecord, context);
planner.executeRules(stack, plan);
// discover all of the usage
List<Command> commands = CommandCollectorVisitor.getCommands(command, true);
while (!commands.isEmpty()) {
Command cmd = commands.remove(commands.size() - 1);
commands.addAll(CommandCollectorVisitor.getCommands(cmd, true));
try {
PlanNode temp = planner.generatePlan((Command) cmd.clone());
stack.push(new RuleAssignOutputElements(false));
planner.executeRules(stack, temp);
} catch (TeiidProcessingException e) {
throw new QueryPlannerException(e);
}
}
// plan and minimize projection
for (WithQueryCommand with : this.withPlanningState.withList.values()) {
QueryCommand subCommand = with.getCommand();
TempMetadataID tid = (TempMetadataID) with.getGroupSymbol().getMetadataID();
if (tid.getTableData().getModel() != TempMetadataAdapter.TEMP_MODEL) {
tid.getTableData().setModel(null);
}
List<TempMetadataID> elements = tid.getElements();
List<Integer> toRemove = new ArrayList<Integer>();
for (int i = elements.size() - 1; i >= 0; i--) {
TempMetadataID elem = elements.get(i);
if (!elem.isAccessed()) {
toRemove.add(i);
}
}
// the definition of the with clause consistent
if (!toRemove.isEmpty()) {
if (with.isRecursive()) {
SetQuery setQuery = (SetQuery) subCommand;
setQuery.setLeftQuery(removeUnusedProjection(with, setQuery.getLeftQuery(), elements, toRemove));
setQuery.setRightQuery(removeUnusedProjection(with, setQuery.getRightQuery(), elements, toRemove));
} else {
subCommand = removeUnusedProjection(with, subCommand, elements, toRemove);
with.setCommand(subCommand);
}
}
if (with.isRecursive()) {
SetQuery setQuery = (SetQuery) subCommand;
QueryCommand qc = setQuery.getLeftQuery();
final RelationalPlan subPlan = optimize(qc);
qc.setProcessorPlan(subPlan);
AccessNode aNode = CriteriaCapabilityValidatorVisitor.getAccessNode(subPlan);
Object modelID = null;
QueryCommand withCommand = null;
if (aNode != null) {
modelID = CriteriaCapabilityValidatorVisitor.validateCommandPushdown(null, metadata, capFinder, aNode, false);
if (modelID != null) {
if (with.getGroupSymbol().getModelMetadataId() != null || !CapabilitiesUtil.supports(Capability.RECURSIVE_COMMON_TABLE_EXPRESSIONS, modelID, metadata, capFinder) || with.isMaterialize()) {
modelID = null;
} else {
withCommand = CriteriaCapabilityValidatorVisitor.getQueryCommand(aNode);
if (withCommand != null) {
// provisionally set the source
((TempMetadataID) with.getGroupSymbol().getMetadataID()).getTableData().setModel(modelID);
}
}
}
}
// now that we possibly have a model id, plan the recursive part
QueryCommand qc1 = setQuery.getRightQuery();
RelationalPlan subPlan1 = optimize((Command) qc1.clone());
qc1.setProcessorPlan(subPlan1);
if (!isPushdownValid(with, setQuery, modelID, withCommand, subPlan1) && withCommand != null) {
// reset the source to null and replan
((TempMetadataID) with.getGroupSymbol().getMetadataID()).getTableData().setModel(null);
subPlan1 = optimize(qc1);
qc1.setProcessorPlan(subPlan1);
}
continue;
}
RelationalPlan subPlan = optimize(subCommand);
subCommand.setProcessorPlan(subPlan);
RelationalPlan procPlan = subPlan;
RelationalNode root = procPlan.getRootNode();
Number planCardinality = root.getEstimateNodeCardinality();
if (planCardinality != null) {
((TempMetadataID) with.getGroupSymbol().getMetadataID()).setCardinality(planCardinality.intValue());
}
AccessNode aNode = CriteriaCapabilityValidatorVisitor.getAccessNode(procPlan);
if (aNode == null) {
continue;
}
Object modelID = CriteriaCapabilityValidatorVisitor.validateCommandPushdown(null, metadata, capFinder, aNode, false);
QueryCommand withCommand = CriteriaCapabilityValidatorVisitor.getQueryCommand(aNode);
if (modelID == null || withCommand == null) {
continue;
}
if (with.getGroupSymbol().getModelMetadataId() != null || !CapabilitiesUtil.supports(Capability.COMMON_TABLE_EXPRESSIONS, modelID, metadata, capFinder) || with.isMaterialize()) {
continue;
}
WithQueryCommand wqc = new WithQueryCommand(with.getGroupSymbol(), with.getColumns(), withCommand);
wqc.setNoInline(with.isNoInline());
((TempMetadataID) with.getGroupSymbol().getMetadataID()).getTableData().setModel(modelID);
this.withPlanningState.pushdownWith.put(with.getGroupSymbol().getName(), wqc);
}
}
use of org.teiid.core.TeiidProcessingException in project teiid by teiid.
the class RelationalPlanner method optimize.
public RelationalPlan optimize(Command command) throws QueryPlannerException, QueryMetadataException, TeiidComponentException, QueryResolverException {
boolean debug = analysisRecord.recordDebug();
if (debug) {
// $NON-NLS-1$
analysisRecord.println("\n----------------------------------------------------------------------------");
// $NON-NLS-1$
analysisRecord.println("GENERATE CANONICAL: \n" + command);
}
SourceHint previous = this.sourceHint;
this.sourceHint = SourceHint.combine(previous, command.getSourceHint());
PlanToProcessConverter planToProcessConverter = new PlanToProcessConverter(metadata, idGenerator, analysisRecord, capFinder, context);
WithPlanningState saved = this.withPlanningState;
this.withPlanningState = new WithPlanningState();
Command original = (Command) command.clone();
PlanNode plan;
try {
plan = generatePlan(command);
} catch (TeiidProcessingException e) {
throw new QueryPlannerException(e);
}
planWith(plan, command);
if (plan.getType() == NodeConstants.Types.SOURCE) {
// this was effectively a rewrite
return (RelationalPlan) plan.getProperty(Info.PROCESSOR_PLAN);
}
if (debug) {
// $NON-NLS-1$
analysisRecord.println("\nCANONICAL PLAN: \n" + plan);
}
// Connect ProcessorPlan to SubqueryContainer (if any) of SELECT or PROJECT nodes
// TODO: merge with node creation
connectSubqueryContainers(plan);
// Set top column information on top node
List<Expression> topCols = Util.deepClone(command.getProjectedSymbols(), Expression.class);
// Build rule set based on hints
RuleStack rules = buildRules();
// Run rule-based optimizer
plan = executeRules(rules, plan);
RelationalPlan result = planToProcessConverter.convert(plan);
boolean fullPushdown = false;
if (!this.withPlanningState.pushdownWith.isEmpty()) {
AccessNode aNode = CriteriaCapabilityValidatorVisitor.getAccessNode(result);
if (aNode != null) {
QueryCommand queryCommand = CriteriaCapabilityValidatorVisitor.getQueryCommand(aNode);
if (queryCommand != null) {
fullPushdown = true;
for (SubqueryContainer<?> container : ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(queryCommand)) {
if (container instanceof Evaluatable<?> && ((Evaluatable<?>) container).shouldEvaluate()) {
// we could more deeply check, but we'll just assume that the references are needed
fullPushdown = false;
break;
}
}
}
}
// distribute the appropriate clauses to the pushdowns
assignWithClause(result.getRootNode(), this.withPlanningState.pushdownWith, false);
List<String> toReplan = new ArrayList<String>();
for (Map.Entry<String, Object> entry : this.withPlanningState.pushdownState.entrySet()) {
if (Boolean.TRUE.equals(entry.getValue())) {
GroupSymbol gs = this.withPlanningState.pushdownWith.get(entry.getKey()).getGroupSymbol();
TempMetadataID tmi = (TempMetadataID) gs.getMetadataID();
tmi.getTableData().setModel(TempMetadataAdapter.TEMP_MODEL);
toReplan.add(entry.getKey());
}
}
if (!toReplan.isEmpty()) {
for (WithQueryCommand wqc : this.withPlanningState.withList.values()) {
this.context.getGroups().remove(wqc.getGroupSymbol().getName());
}
this.sourceHint = previous;
this.withPlanningState = saved;
if (debug) {
// $NON-NLS-1$ //$NON-NLS-2$
analysisRecord.println("\nReplanning due to multiple common table references: " + toReplan + "\n");
}
return optimize(original);
}
}
if (!fullPushdown && !this.withPlanningState.withList.isEmpty()) {
// generally any with item associated with a pushdown will not be needed as we're converting to a source query
result.setWith(new ArrayList<WithQueryCommand>(this.withPlanningState.withList.values()));
// assign any with clauses in this subplan
for (WithQueryCommand wqc : this.withPlanningState.withList.values()) {
if (wqc.isRecursive()) {
SetQuery sq = (SetQuery) wqc.getCommand();
assignWithClause(((RelationalPlan) sq.getLeftQuery().getProcessorPlan()).getRootNode(), this.withPlanningState.pushdownWith, false);
assignWithClause(((RelationalPlan) sq.getRightQuery().getProcessorPlan()).getRootNode(), this.withPlanningState.pushdownWith, false);
} else {
assignWithClause(((RelationalPlan) wqc.getCommand().getProcessorPlan()).getRootNode(), this.withPlanningState.pushdownWith, false);
}
}
}
result.setOutputElements(topCols);
this.sourceHint = previous;
this.withPlanningState = saved;
return result;
}
use of org.teiid.core.TeiidProcessingException in project teiid by teiid.
the class ODBCServerRemoteImpl method prepare.
@Override
public void prepare(String prepareName, String sql, int[] paramType) {
if (prepareName == null || prepareName.length() == 0) {
prepareName = UNNAMED;
}
if (sql != null) {
PreparedStatementImpl stmt = null;
try {
// stmt is alive until session ends.
if (prepareName.equals(UNNAMED)) {
this.preparedMap.remove(prepareName);
} else {
Prepared previous = this.preparedMap.get(prepareName);
if (previous != null) {
errorOccurred(RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40110, prepareName));
return;
}
}
// just pull the initial information - leave statement formation until binding
String modfiedSQL = fixSQL(sql);
stmt = this.connection.prepareStatement(modfiedSQL);
Prepared prepared = new Prepared(prepareName, sql, modfiedSQL, paramType, getPgColInfo(stmt.getMetaData()));
this.preparedMap.put(prepareName, prepared);
this.client.prepareCompleted(prepareName);
} catch (SQLException e) {
if (e.getCause() instanceof TeiidProcessingException) {
LogManager.logWarning(LogConstants.CTX_ODBC, e.getCause(), RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40020));
}
errorOccurred(e);
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (SQLException e) {
}
}
}
}
use of org.teiid.core.TeiidProcessingException in project teiid by teiid.
the class DataTierManagerImpl method registerRequest.
public TupleSource registerRequest(CommandContext context, Command command, String modelName, final RegisterRequestParameter parameterObject) throws TeiidComponentException, TeiidProcessingException {
RequestWorkItem workItem = context.getWorkItem();
Assertion.isNotNull(workItem);
if (CoreConstants.SYSTEM_MODEL.equals(modelName) || CoreConstants.SYSTEM_ADMIN_MODEL.equals(modelName)) {
return processSystemQuery(context, command, workItem.getDqpWorkContext());
}
AtomicRequestMessage aqr = createRequest(workItem, command, modelName, parameterObject.connectorBindingId, parameterObject.nodeID);
aqr.setCommandContext(context);
if (parameterObject.fetchSize > 0) {
aqr.setFetchSize(2 * parameterObject.fetchSize);
}
if (parameterObject.limit > 0) {
aqr.setFetchSize(Math.min(parameterObject.limit, aqr.getFetchSize()));
}
aqr.setCopyStreamingLobs(parameterObject.copyStreamingLobs);
Collection<GroupSymbol> accessedGroups = null;
if (context.getDataObjects() != null) {
QueryMetadataInterface metadata = context.getMetadata();
accessedGroups = GroupCollectorVisitor.getGroupsIgnoreInlineViews(command, false);
boolean usedModel = false;
for (GroupSymbol gs : accessedGroups) {
context.accessedDataObject(gs.getMetadataID());
// check the source/tables/procs for determinism level
Object mid = gs.getMetadataID();
if (mid instanceof TempMetadataID) {
TempMetadataID tid = (TempMetadataID) mid;
if (tid.getOriginalMetadataID() != null) {
mid = tid.getOriginalMetadataID();
}
}
String specificProp = metadata.getExtensionProperty(mid, AbstractMetadataRecord.RELATIONAL_URI + DDLConstants.DETERMINISM, false);
if (specificProp == null) {
if (!usedModel) {
Object modelId = metadata.getModelID(mid);
String prop = metadata.getExtensionProperty(modelId, AbstractMetadataRecord.RELATIONAL_URI + DDLConstants.DETERMINISM, false);
if (prop != null) {
usedModel = true;
// set model property
context.setDeterminismLevel(Determinism.valueOf(prop.toUpperCase()));
}
}
continue;
}
context.setDeterminismLevel(Determinism.valueOf(specificProp.toUpperCase()));
}
}
ConnectorManagerRepository cmr = workItem.getDqpWorkContext().getVDB().getAttachment(ConnectorManagerRepository.class);
ConnectorManager connectorManager = cmr.getConnectorManager(aqr.getConnectorName());
if (connectorManager == null) {
// can happen if sources are removed
if (RelationalNodeUtil.hasOutputParams(command)) {
// $NON-NLS-1$
throw new AssertionError("A source is required to execute a procedure returning parameters");
}
// $NON-NLS-1$ //$NON-NLS-2$
LogManager.logDetail(LogConstants.CTX_DQP, "source", aqr.getConnectorName(), "no longer exists, returning dummy results");
return CollectionTupleSource.createNullTupleSource();
}
ConnectorWork work = connectorManager.registerRequest(aqr);
if (!work.isForkable()) {
aqr.setSerial(true);
}
CacheID cid = null;
CacheDirective cd = null;
if (workItem.getRsCache() != null && command.areResultsCachable()) {
CachableVisitor cv = new CachableVisitor();
PreOrPostOrderNavigator.doVisit(command, cv, PreOrPostOrderNavigator.PRE_ORDER, true);
if (cv.cacheable) {
try {
cd = work.getCacheDirective();
} catch (TranslatorException e) {
// $NON-NLS-1$
throw new TeiidProcessingException(QueryPlugin.Event.TEIID30504, e, aqr.getConnectorName() + ": " + e.getMessage());
}
if (cd != null) {
if (cd.getScope() == Scope.NONE) {
parameterObject.doNotCache = true;
} else {
String cmdString = command.toString();
if (cmdString.length() < 100000) {
// TODO: this check won't be needed if keys aren't exclusively held in memory
cid = new CacheID(workItem.getDqpWorkContext(), ParseInfo.DEFAULT_INSTANCE, cmdString);
cid.setParameters(cv.parameters);
if (cd.getInvalidation() == null || cd.getInvalidation() == Invalidation.NONE) {
CachedResults cr = workItem.getRsCache().get(cid);
if (cr != null && (cr.getRowLimit() == 0 || (parameterObject.limit > 0 && cr.getRowLimit() >= parameterObject.limit))) {
parameterObject.doNotCache = true;
// $NON-NLS-1$
LogManager.logDetail(LogConstants.CTX_DQP, "Using cache entry for", cid);
work.close();
return cr.getResults().createIndexedTupleSource();
}
} else if (cd.getInvalidation() == Invalidation.IMMEDIATE) {
workItem.getRsCache().remove(cid, CachingTupleSource.getDeterminismLevel(cd.getScope()));
}
}
}
} else {
// $NON-NLS-1$
LogManager.logTrace(LogConstants.CTX_DQP, aqr.getAtomicRequestID(), "no cache directive");
}
} else {
// $NON-NLS-1$
LogManager.logTrace(LogConstants.CTX_DQP, aqr.getAtomicRequestID(), "command not cachable");
}
}
DataTierTupleSource dtts = new DataTierTupleSource(aqr, workItem, work, this, parameterObject.limit);
TupleSource result = dtts;
TupleBuffer tb = null;
if (cid != null) {
tb = getBufferManager().createTupleBuffer(aqr.getCommand().getProjectedSymbols(), aqr.getCommandContext().getConnectionId(), TupleSourceType.PROCESSOR);
result = new CachingTupleSource(this, tb, (DataTierTupleSource) result, cid, parameterObject, cd, accessedGroups, workItem);
}
if (work.isThreadBound()) {
result = handleThreadBound(workItem, aqr, work, cid, result, dtts, tb);
} else if (!aqr.isSerial()) {
dtts.addWork();
}
return result;
}
use of org.teiid.core.TeiidProcessingException in project teiid by teiid.
the class DataTierManagerImpl method handleThreadBound.
/**
* thread bound work is tricky for our execution model
*
* the strategy here is that
*
* - if the result is not already a copying tuplesource (from caching)
* then wrap in a copying tuple source
*
* - submit a workitem that will pull the results/fill the buffer,
*
* - return a tuplesource off of the buffer for use by the caller
*/
private TupleSource handleThreadBound(final RequestWorkItem workItem, AtomicRequestMessage aqr, ConnectorWork work, CacheID cid, TupleSource result, DataTierTupleSource dtts, TupleBuffer tb) throws AssertionError, TeiidComponentException, TeiidProcessingException {
if (workItem.useCallingThread) {
// in any case we want the underlying work done in the thread accessing the connectorworkitem
aqr.setSerial(true);
// simple case, just rely on the client using the same thread
return result;
}
if (tb == null) {
tb = getBufferManager().createTupleBuffer(aqr.getCommand().getProjectedSymbols(), aqr.getCommandContext().getConnectionId(), TupleSourceType.PROCESSOR);
}
final TupleSource ts = tb.createIndexedTupleSource(cid == null);
if (cid == null) {
result = new CopyOnReadTupleSource(tb, result) {
@Override
public void closeSource() {
ts.closeSource();
}
};
}
final ThreadBoundTask callable = new ThreadBoundTask(workItem, result, dtts);
// but we do so lazily just in case the results aren't needed
if (aqr.isSerial()) {
return new TupleSource() {
boolean processed = false;
@Override
public List<?> nextTuple() throws TeiidComponentException, TeiidProcessingException {
if (!processed) {
callable.call();
callable.onCompletion(null);
processed = true;
}
return ts.nextTuple();
}
@Override
public void closeSource() {
if (!processed) {
callable.onCompletion(null);
processed = true;
}
ts.closeSource();
}
};
}
aqr.setSerial(true);
final FutureWork<Void> future = workItem.addWork(callable, callable, 100);
final TupleBuffer buffer = tb;
// return a thread-safe TupleSource
return new TupleSource() {
boolean checkedDone;
@Override
public List<?> nextTuple() throws TeiidComponentException, TeiidProcessingException {
// TODO: could refactor as completion listener
if (!checkedDone && future.isDone()) {
checkedDone = true;
try {
future.get();
} catch (InterruptedException e) {
throw new TeiidComponentException(e);
} catch (ExecutionException e) {
if (e.getCause() instanceof TeiidComponentException) {
throw (TeiidComponentException) e.getCause();
}
if (e.getCause() instanceof TeiidProcessingException) {
throw (TeiidProcessingException) e.getCause();
}
throw new TeiidComponentException(e);
}
}
synchronized (buffer) {
return ts.nextTuple();
}
}
@Override
public void closeSource() {
synchronized (buffer) {
ts.closeSource();
}
callable.done.set(true);
}
};
}
Aggregations