use of org.teiid.metadata.FunctionMethod.Determinism in project teiid by teiid.
the class QueryOptimizer method optimizePlan.
public static ProcessorPlan optimizePlan(Command command, QueryMetadataInterface metadata, IDGenerator idGenerator, CapabilitiesFinder capFinder, AnalysisRecord analysisRecord, CommandContext context) throws QueryMetadataException, TeiidComponentException, QueryPlannerException {
if (analysisRecord == null) {
analysisRecord = new AnalysisRecord(false, false);
}
if (context == null) {
context = new CommandContext();
}
if (!(capFinder instanceof TempCapabilitiesFinder)) {
capFinder = new TempCapabilitiesFinder(capFinder);
}
boolean debug = analysisRecord.recordDebug();
if (!(metadata instanceof TempMetadataAdapter)) {
metadata = new TempMetadataAdapter(metadata, new TempMetadataStore());
}
if (context.getMetadata() == null) {
context.setMetadata(metadata);
}
// Create an ID generator that can be used for all plans to generate unique data node IDs
if (idGenerator == null) {
idGenerator = new IDGenerator();
}
if (debug) {
// $NON-NLS-1$
analysisRecord.println("\n----------------------------------------------------------------------------");
// $NON-NLS-1$
analysisRecord.println("OPTIMIZE: \n" + command);
}
if (command instanceof Insert) {
Insert insert = (Insert) command;
if (insert.isUpsert()) {
// if not supported or there are trigger actions, then rewrite as a procedure
// we do this here since we're changing the command type.
// TODO: we could push this back into the rewrite, but it will need to be capabilities aware
GroupSymbol group = insert.getGroup();
Object modelId = metadata.getModelID(group.getMetadataID());
boolean supportsUpsert = CapabilitiesUtil.supports(Capability.UPSERT, modelId, metadata, capFinder);
if (!supportsUpsert) {
try {
command = QueryRewriter.rewriteAsUpsertProcedure(insert, metadata, context);
} catch (TeiidProcessingException e) {
throw new QueryPlannerException(e);
}
if (debug) {
// $NON-NLS-1$
analysisRecord.println("\n----------------------------------------------------------------------------");
// $NON-NLS-1$
analysisRecord.println("OPTIMIZE UPSERT PROCEDURE: \n" + command);
}
}
}
}
ProcessorPlan result = null;
switch(command.getType()) {
case Command.TYPE_UPDATE_PROCEDURE:
CreateProcedureCommand cupc = (CreateProcedureCommand) command;
if (cupc.getUpdateType() != Command.TYPE_UNKNOWN || cupc.getVirtualGroup() == null) {
// row update procedure or anon block
result = planProcedure(command, metadata, idGenerator, capFinder, analysisRecord, context);
} else {
Object pid = cupc.getVirtualGroup().getMetadataID();
if (pid instanceof TempMetadataID) {
TempMetadataID tid = (TempMetadataID) pid;
if (tid.getOriginalMetadataID() != null) {
pid = tid.getOriginalMetadataID();
}
}
String fullName = metadata.getFullName(pid);
// $NON-NLS-1$
fullName = "procedure cache:" + fullName;
PreparedPlan pp = context.getPlan(fullName);
if (pp == null) {
Determinism determinismLevel = context.resetDeterminismLevel();
try {
CommandContext clone = context.clone();
ProcessorPlan plan = planProcedure(command, metadata, idGenerator, capFinder, analysisRecord, clone);
// note that this is not a full prepared plan. It is not usable by user queries.
if (pid instanceof Procedure) {
clone.accessedPlanningObject(pid);
}
pp = new PreparedPlan();
pp.setPlan(plan, clone);
context.putPlan(fullName, pp, context.getDeterminismLevel());
} finally {
context.setDeterminismLevel(determinismLevel);
}
}
result = pp.getPlan().clone();
for (Object id : pp.getAccessInfo().getObjectsAccessed()) {
context.accessedPlanningObject(id);
}
}
break;
case Command.TYPE_BATCHED_UPDATE:
result = BATCHED_UPDATE_PLANNER.optimize(command, idGenerator, metadata, capFinder, analysisRecord, context);
break;
case Command.TYPE_ALTER_PROC:
case Command.TYPE_ALTER_TRIGGER:
case Command.TYPE_ALTER_VIEW:
result = DDL_PLANNER.optimize(command, idGenerator, metadata, capFinder, analysisRecord, context);
break;
case Command.TYPE_SOURCE_EVENT:
result = SOURCE_EVENT_PLANNER.optimize(command, idGenerator, metadata, capFinder, analysisRecord, context);
break;
default:
try {
RelationalPlanner planner = new RelationalPlanner();
planner.initialize(command, idGenerator, metadata, capFinder, analysisRecord, context);
result = planner.optimize(command);
} catch (QueryResolverException e) {
throw new TeiidRuntimeException(QueryPlugin.Event.TEIID30245, e);
}
}
if (debug) {
// $NON-NLS-1$
analysisRecord.println("\n----------------------------------------------------------------------------");
// $NON-NLS-1$
analysisRecord.println("OPTIMIZATION COMPLETE:");
// $NON-NLS-1$
analysisRecord.println("PROCESSOR PLAN:\n" + result);
// $NON-NLS-1$
analysisRecord.println("============================================================================");
}
return result;
}
use of org.teiid.metadata.FunctionMethod.Determinism in project teiid by teiid.
the class TempTableDataManager method handleCachedProcedure.
private TupleSource handleCachedProcedure(final CommandContext context, StoredProcedure proc) throws TeiidComponentException, QueryMetadataException, TeiidProcessingException {
String fullName = context.getMetadata().getFullName(proc.getProcedureID());
// $NON-NLS-1$
LogManager.logDetail(LogConstants.CTX_DQP, "processing cached procedure request for", fullName);
LinkedList<Object> vals = new LinkedList<Object>();
for (SPParameter param : proc.getInputParameters()) {
vals.add(((Constant) param.getExpression()).getValue());
}
// collapse the hash to single byte for the key to restrict the possible results to 256
int hash = vals.hashCode();
hash |= (hash >>> 16);
hash |= (hash >>> 8);
hash &= 0x000000ff;
final CacheID cid = new CacheID(new ParseInfo(), fullName + hash, context.getVdbName(), context.getVdbVersion(), context.getConnectionId(), context.getUserName());
cid.setParameters(vals);
CachedResults results = cache.get(cid);
if (results != null) {
TupleBuffer buffer = results.getResults();
return buffer.createIndexedTupleSource();
}
// construct a query with a no cache hint
final CacheHint hint = proc.getCacheHint();
proc.setCacheHint(null);
Option option = new Option();
option.setNoCache(true);
option.addNoCacheGroup(fullName);
proc.setOption(option);
StoredProcedure cloneProc = (StoredProcedure) proc.clone();
int i = 0;
for (SPParameter param : cloneProc.getInputParameters()) {
param.setExpression(new Reference(i++));
}
final QueryProcessor qp = context.getQueryProcessorFactory().createQueryProcessor(cloneProc.toString(), fullName.toUpperCase(), context, vals.toArray());
final BatchCollector bc = qp.createBatchCollector();
return new ProxyTupleSource() {
boolean success = false;
@Override
protected TupleSource createTupleSource() throws TeiidComponentException, TeiidProcessingException {
TupleBuffer tb = bc.collectTuples();
CachedResults cr = new CachedResults();
cr.setResults(tb, qp.getProcessorPlan());
Determinism determinismLevel = qp.getContext().getDeterminismLevel();
if (hint != null && hint.getDeterminism() != null) {
// $NON-NLS-1$ //$NON-NLS-2$
LogManager.logTrace(LogConstants.CTX_DQP, new Object[] { "Cache hint modified the query determinism from ", determinismLevel, " to ", hint.getDeterminism() });
determinismLevel = hint.getDeterminism();
}
cache.put(cid, determinismLevel, cr, hint != null ? hint.getTtl() : null);
context.setDeterminismLevel(determinismLevel);
success = true;
return tb.createIndexedTupleSource();
}
@Override
public void closeSource() {
super.closeSource();
qp.closeProcessing();
if (!success && bc.getTupleBuffer() != null) {
bc.getTupleBuffer().remove();
}
}
};
}
use of org.teiid.metadata.FunctionMethod.Determinism in project teiid by teiid.
the class TempTableDataManager method loadGlobalTable.
private TupleSource loadGlobalTable(final CommandContext context, final GroupSymbol group, final String tableName, final GlobalTableStore globalStore) throws TeiidComponentException, TeiidProcessingException {
LogManager.logInfo(LogConstants.CTX_MATVIEWS, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30013, tableName));
final QueryMetadataInterface metadata = context.getMetadata();
final List<ElementSymbol> allColumns = ResolverUtil.resolveElementsInGroup(group, metadata);
final TempTable table = globalStore.createMatTable(tableName, group);
table.setUpdatable(false);
return new ProxyTupleSource() {
TupleSource insertTupleSource;
boolean success;
QueryProcessor qp;
boolean closed;
boolean errored;
@Override
protected TupleSource createTupleSource() throws TeiidComponentException, TeiidProcessingException {
long rowCount = -1;
try {
if (insertTupleSource == null) {
String fullName = metadata.getFullName(group.getMetadataID());
String transformation = metadata.getVirtualPlan(group.getMetadataID()).getQuery();
qp = context.getQueryProcessorFactory().createQueryProcessor(transformation, fullName, context);
insertTupleSource = new BatchCollector.BatchProducerTupleSource(qp);
}
table.insert(insertTupleSource, allColumns, false, false, null);
table.getTree().compact();
rowCount = table.getRowCount();
Determinism determinism = qp.getContext().getDeterminismLevel();
context.setDeterminismLevel(determinism);
// TODO: could pre-process indexes to remove overlap
for (Object index : metadata.getIndexesInGroup(group.getMetadataID())) {
List<ElementSymbol> columns = GlobalTableStoreImpl.resolveIndex(metadata, allColumns, index);
table.addIndex(columns, false);
}
for (Object key : metadata.getUniqueKeysInGroup(group.getMetadataID())) {
List<ElementSymbol> columns = GlobalTableStoreImpl.resolveIndex(metadata, allColumns, key);
table.addIndex(columns, true);
}
CacheHint hint = table.getCacheHint();
if (hint != null && table.getPkLength() > 0) {
table.setUpdatable(hint.isUpdatable(false));
}
if (determinism.compareTo(Determinism.VDB_DETERMINISTIC) < 0 && (hint == null || hint.getScope() == null || Scope.VDB.compareTo(hint.getScope()) <= 0)) {
// $NON-NLS-1$
LogManager.logInfo(LogConstants.CTX_DQP, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31143, determinism, tableName));
}
globalStore.loaded(tableName, table);
success = true;
LogManager.logInfo(LogConstants.CTX_MATVIEWS, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30014, tableName, rowCount));
return CollectionTupleSource.createUpdateCountTupleSource((int) Math.min(Integer.MAX_VALUE, rowCount));
} catch (BlockedException e) {
throw e;
} catch (Exception e) {
errored = true;
if (executor == null || !executor.isShutdown()) {
// if we're shutting down, no need to log
LogManager.logError(LogConstants.CTX_MATVIEWS, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30015, tableName));
}
closeSource();
rethrow(e);
throw new AssertionError();
}
}
@Override
public void closeSource() {
if (closed) {
return;
}
if (!errored && !success) {
LogManager.logInfo(LogConstants.CTX_MATVIEWS, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31153, tableName));
}
closed = true;
if (!success) {
globalStore.failedLoad(tableName);
table.remove();
}
if (qp != null) {
qp.closeProcessing();
}
super.closeSource();
}
};
}
use of org.teiid.metadata.FunctionMethod.Determinism in project teiid by teiid.
the class CommandContext method resetDeterminismLevel.
public Determinism resetDeterminismLevel(boolean detach) {
Determinism result = determinismLevel[0];
if (detach) {
determinismLevel = new Determinism[1];
}
determinismLevel[0] = Determinism.DETERMINISTIC;
return result;
}
Aggregations