use of org.teiid.query.metadata.TempMetadataStore in project teiid by teiid.
the class RelationalPlanner method buildGroupingNode.
/**
* Build a grouping node that introduces a anon group (without a inline view source node)
*/
public static SymbolMap buildGroupingNode(Collection<AggregateSymbol> aggs, List<? extends Expression> groupingCols, PlanNode groupNode, CommandContext cc, IDGenerator idGenerator) throws QueryMetadataException, TeiidComponentException {
SymbolMap map = new SymbolMap();
aggs = LanguageObject.Util.deepClone(aggs, AggregateSymbol.class);
groupingCols = LanguageObject.Util.deepClone(groupingCols, Expression.class);
// $NON-NLS-1$
GroupSymbol group = new GroupSymbol("anon_grp" + idGenerator.nextInt());
if (!cc.getGroups().add(group.getName())) {
group = RulePlaceAccess.recontextSymbol(group, cc.getGroups());
}
TempMetadataStore tms = new TempMetadataStore();
int i = 0;
List<AliasSymbol> symbols = new LinkedList<AliasSymbol>();
List<Expression> targets = new LinkedList<Expression>();
if (groupingCols != null) {
groupNode.setProperty(NodeConstants.Info.GROUP_COLS, groupingCols);
groupNode.addGroups(GroupsUsedByElementsVisitor.getGroups(groupingCols));
for (Expression ex : groupingCols) {
// $NON-NLS-1$ //$NON-NLS-2$
AliasSymbol as = new AliasSymbol("gcol" + i++, new ExpressionSymbol("expr", ex));
targets.add(ex);
symbols.add(as);
}
}
i = 0;
for (AggregateSymbol ex : aggs) {
// $NON-NLS-1$ //$NON-NLS-2$
AliasSymbol as = new AliasSymbol("agg" + i++, new ExpressionSymbol("expr", ex));
targets.add(ex);
symbols.add(as);
}
group.setMetadataID(tms.addTempGroup(group.getName(), symbols, true, false));
Iterator<Expression> targetIter = targets.iterator();
for (ElementSymbol es : ResolverUtil.resolveElementsInGroup(group, new TempMetadataAdapter(new BasicQueryMetadata(), tms))) {
Expression target = targetIter.next();
es.setAggregate(target instanceof AggregateSymbol);
map.addMapping(es, target);
}
groupNode.setProperty(NodeConstants.Info.SYMBOL_MAP, map);
groupNode.addGroup(group);
return map;
}
use of org.teiid.query.metadata.TempMetadataStore 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.query.metadata.TempMetadataStore in project teiid by teiid.
the class ResolverUtil method addTempGroup.
public static TempMetadataID addTempGroup(TempMetadataAdapter metadata, GroupSymbol symbol, List<? extends Expression> symbols, boolean tempTable) throws QueryResolverException {
Set<String> names = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
for (Expression ses : symbols) {
if (!names.add(Symbol.getShortName(ses))) {
throw new QueryResolverException(QueryPlugin.Event.TEIID30091, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30091, symbol, Symbol.getShortName(ses)));
}
}
if (tempTable) {
resolveNullLiterals(symbols);
}
TempMetadataStore store = metadata.getMetadataStore();
return store.addTempGroup(symbol.getName(), symbols, !tempTable, tempTable);
}
use of org.teiid.query.metadata.TempMetadataStore in project teiid by teiid.
the class QueryRewriter method rewriteCommand.
/**
* Rewrites the command and all of its subcommands (both embedded and non-embedded)
*
* @param command
* @param removeOrderBy
* @return
* @throws QueryValidatorException
*/
private Command rewriteCommand(Command command, boolean removeOrderBy) throws TeiidComponentException, TeiidProcessingException {
boolean oldRewriteAggs = rewriteAggs;
QueryMetadataInterface oldMetadata = metadata;
TempMetadataStore tempMetadata = command.getTemporaryMetadata();
if (tempMetadata != null) {
metadata = new TempMetadataAdapter(metadata, tempMetadata);
}
switch(command.getType()) {
case Command.TYPE_QUERY:
QueryCommand queryCommand = (QueryCommand) command;
if (removeOrderBy && queryCommand.getLimit() == null) {
queryCommand.setOrderBy(null);
}
List<WithQueryCommand> withList = queryCommand.getWith();
if (withList != null) {
queryCommand.setWith(null);
List<UnaryFromClause> clauses = getUnaryFromClauses(queryCommand);
queryCommand.setWith(withList);
outer: for (int i = withList.size() - 1; i >= 0; i--) {
WithQueryCommand withQueryCommand = withList.get(i);
if (withQueryCommand.getColumns() == null) {
List<ElementSymbol> columns = ResolverUtil.resolveElementsInGroup(withQueryCommand.getGroupSymbol(), metadata);
withQueryCommand.setColumns(LanguageObject.Util.deepClone(columns, ElementSymbol.class));
}
Collection<UnaryFromClause> all = new ArrayList<UnaryFromClause>(clauses);
List<UnaryFromClause> current = getUnaryFromClauses(withQueryCommand.getCommand());
clauses.addAll(current);
rewriteSubqueryContainer(withQueryCommand, true);
// can't inline with a hint or once it's planned
if (withQueryCommand.isNoInline() || withQueryCommand.getCommand().getProcessorPlan() != null || processing) {
// pushing them down
continue;
}
boolean removeOnly = false;
// check for scalar with clauses
boolean replaceScalar = replaceScalar(withQueryCommand);
if (!replaceScalar) {
int referenceCount = 0;
for (UnaryFromClause ufc : all) {
if (ufc.getGroup().getMetadataID() != withQueryCommand.getGroupSymbol().getMetadataID()) {
continue;
}
referenceCount++;
if (referenceCount > 1) {
// referenced in more than 1 location
continue outer;
}
}
if (referenceCount == 0) {
removeOnly = true;
} else if (withQueryCommand.isRecursive()) {
// can't inline if recursive
continue;
}
}
withList.remove(i);
if (withList.isEmpty()) {
queryCommand.setWith(null);
}
if (removeOnly) {
clauses = clauses.subList(0, clauses.size() - current.size());
continue;
}
for (UnaryFromClause clause : all) {
// we match on equality as the name can be redefined
if (clause.getGroup().getMetadataID() != withQueryCommand.getGroupSymbol().getMetadataID()) {
continue;
}
if (!replaceScalar) {
// use the original since we need to keep the references
// to nested unaryfromclause instances
clause.setExpandedCommand(withQueryCommand.getCommand());
break;
}
clause.setExpandedCommand((Command) withQueryCommand.getCommand().clone());
}
}
}
if (command instanceof Query) {
command = rewriteQuery((Query) command);
} else {
command = rewriteSetQuery((SetQuery) command);
}
break;
case Command.TYPE_STORED_PROCEDURE:
command = rewriteExec((StoredProcedure) command);
break;
case Command.TYPE_INSERT:
command = rewriteInsert((Insert) command);
break;
case Command.TYPE_UPDATE:
command = rewriteUpdate((Update) command);
break;
case Command.TYPE_DELETE:
command = rewriteDelete((Delete) command);
break;
case Command.TYPE_UPDATE_PROCEDURE:
command = rewriteUpdateProcedure((CreateProcedureCommand) command);
break;
case Command.TYPE_BATCHED_UPDATE:
List subCommands = ((BatchedUpdateCommand) command).getUpdateCommands();
for (int i = 0; i < subCommands.size(); i++) {
Command subCommand = (Command) subCommands.get(i);
subCommand = rewriteCommand(subCommand, false);
subCommands.set(i, subCommand);
}
break;
case Command.TYPE_TRIGGER_ACTION:
TriggerAction ta = (TriggerAction) command;
ta.setBlock(rewriteBlock(ta.getBlock()));
break;
}
this.rewriteAggs = oldRewriteAggs;
this.metadata = oldMetadata;
return command;
}
use of org.teiid.query.metadata.TempMetadataStore in project teiid by teiid.
the class ExecDynamicSqlInstruction method process.
/**
* <p>
* Processing this instruction executes the ProcessorPlan for the command on
* the CommandStatement of the update procedure language. Executing this
* plan does not effect the values of any of the variables defined as part
* of the update procedure and hence the results of the ProcessPlan
* execution need not be stored for further processing. The results are
* removed from the buffer manager immediately after execution. The program
* counter is incremented after execution of the plan.
* </p>
*
* @throws BlockedException
* if this processing the plan throws a currentVarContext
*/
public void process(ProcedurePlan procEnv) throws BlockedException, TeiidComponentException, TeiidProcessingException {
VariableContext localContext = procEnv.getCurrentVariableContext();
String query = null;
try {
Clob value = (Clob) procEnv.evaluateExpression(dynamicCommand.getSql());
if (value == null) {
throw new QueryProcessingException(QueryPlugin.Util.getString(// $NON-NLS-1$
"ExecDynamicSqlInstruction.0"));
}
if (value.length() > MAX_SQL_LENGTH) {
throw new QueryProcessingException(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31204, MAX_SQL_LENGTH));
}
query = value.getSubString(1, MAX_SQL_LENGTH);
LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, // $NON-NLS-1$
new Object[] { "Executing dynamic sql ", query });
Command command = QueryParser.getQueryParser().parseCommand(query);
// special handling for dynamic anon blocks
if (command instanceof CreateProcedureCommand) {
if (dynamicCommand.getIntoGroup() != null || returnable) {
// and the creation of an inline view
throw new QueryProcessingException(QueryPlugin.Event.TEIID31250, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31250));
}
((CreateProcedureCommand) command).setResultSetColumns(Collections.EMPTY_LIST);
}
command.setExternalGroupContexts(dynamicCommand.getExternalGroupContexts());
command.setTemporaryMetadata(dynamicCommand.getTemporaryMetadata().clone());
updateContextWithUsingValues(procEnv, localContext);
TempMetadataStore metadataStore = command.getTemporaryMetadata();
if (dynamicCommand.getUsing() != null && !dynamicCommand.getUsing().isEmpty()) {
metadataStore.addTempGroup(Reserved.USING, new LinkedList<ElementSymbol>(dynamicCommand.getUsing().getClauseMap().keySet()));
GroupSymbol using = new GroupSymbol(Reserved.USING);
using.setMetadataID(metadataStore.getTempGroupID(Reserved.USING));
command.addExternalGroupToContext(using);
metadataStore.addTempGroup(ProcedureReservedWords.DVARS, new LinkedList<ElementSymbol>(dynamicCommand.getUsing().getClauseMap().keySet()));
using = new GroupSymbol(ProcedureReservedWords.DVARS);
using.setMetadataID(metadataStore.getTempGroupID(ProcedureReservedWords.DVARS));
command.addExternalGroupToContext(using);
}
QueryResolver.resolveCommand(command, metadata.getDesignTimeMetadata());
validateDynamicCommand(procEnv, command, value.toString());
// create a new set of variables including vars
Map<ElementSymbol, Expression> nameValueMap = createVariableValuesMap(localContext);
ValidationVisitor visitor = new ValidationVisitor();
Request.validateWithVisitor(visitor, metadata, command);
boolean insertInto = false;
boolean updateCommand = false;
if (!command.returnsResultSet() && !(command instanceof StoredProcedure)) {
if (dynamicCommand.isAsClauseSet()) {
if (dynamicCommand.getProjectedSymbols().size() != 1 || ((Expression) dynamicCommand.getProjectedSymbols().get(0)).getType() != DataTypeManager.DefaultDataClasses.INTEGER) {
throw new QueryProcessingException(QueryPlugin.Event.TEIID31157, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31157));
}
}
updateCommand = true;
} else if (dynamicCommand.getAsColumns() != null && !dynamicCommand.getAsColumns().isEmpty()) {
// $NON-NLS-1$
command = QueryRewriter.createInlineViewQuery(new GroupSymbol("X"), command, metadata, dynamicCommand.getAsColumns());
if (dynamicCommand.getIntoGroup() != null) {
Insert insert = new Insert(dynamicCommand.getIntoGroup(), dynamicCommand.getAsColumns(), Collections.emptyList());
insert.setQueryExpression((Query) command);
command = insert;
insertInto = true;
}
}
// if this is an update procedure, it could reassign variables
command = QueryRewriter.rewrite(command, metadata, procEnv.getContext(), command instanceof CreateProcedureCommand ? Collections.EMPTY_MAP : nameValueMap);
ProcessorPlan commandPlan = QueryOptimizer.optimizePlan(command, metadata, idGenerator, capFinder, AnalysisRecord.createNonRecordingRecord(), procEnv.getContext());
if (command instanceof CreateProcedureCommand && commandPlan instanceof ProcedurePlan) {
((ProcedurePlan) commandPlan).setValidateAccess(procEnv.isValidateAccess());
}
CreateCursorResultSetInstruction inst = new CreateCursorResultSetInstruction(null, commandPlan, (insertInto || updateCommand) ? Mode.UPDATE : returnable ? Mode.HOLD : Mode.NOHOLD) {
@Override
public void process(ProcedurePlan procEnv) throws BlockedException, TeiidComponentException, TeiidProcessingException {
boolean done = true;
try {
super.process(procEnv);
} catch (BlockedException e) {
done = false;
throw e;
} finally {
if (done) {
procEnv.getContext().popCall();
}
}
}
};
dynamicProgram = new Program(false);
dynamicProgram.addInstruction(inst);
if (dynamicCommand.getIntoGroup() != null) {
String groupName = dynamicCommand.getIntoGroup().getName();
if (!procEnv.getTempTableStore().hasTempTable(groupName, true)) {
// create the temp table in the parent scope
Create create = new Create();
create.setTable(new GroupSymbol(groupName));
for (ElementSymbol es : (List<ElementSymbol>) dynamicCommand.getAsColumns()) {
Column c = new Column();
c.setName(es.getShortName());
c.setRuntimeType(DataTypeManager.getDataTypeName(es.getType()));
create.getColumns().add(c);
}
procEnv.getDataManager().registerRequest(procEnv.getContext(), create, TempMetadataAdapter.TEMP_MODEL.getName(), new RegisterRequestParameter());
}
// backwards compatibility to support into with a rowcount
if (updateCommand) {
Insert insert = new Insert();
insert.setGroup(new GroupSymbol(groupName));
for (ElementSymbol es : (List<ElementSymbol>) dynamicCommand.getAsColumns()) {
ElementSymbol col = new ElementSymbol(es.getShortName(), insert.getGroup());
col.setType(es.getType());
insert.addVariable(col);
}
insert.addValue(new Constant(procEnv.getCurrentVariableContext().getValue(ProcedurePlan.ROWCOUNT)));
QueryResolver.resolveCommand(insert, metadata.getDesignTimeMetadata());
TupleSource ts = procEnv.getDataManager().registerRequest(procEnv.getContext(), insert, TempMetadataAdapter.TEMP_MODEL.getName(), new RegisterRequestParameter());
ts.nextTuple();
ts.closeSource();
}
}
// Add group to recursion stack
if (parentProcCommand.getUpdateType() != Command.TYPE_UNKNOWN) {
// $NON-NLS-1$
procEnv.getContext().pushCall(Command.getCommandToken(parentProcCommand.getUpdateType()) + " " + parentProcCommand.getVirtualGroup());
} else {
if (parentProcCommand.getVirtualGroup() != null) {
procEnv.getContext().pushCall(parentProcCommand.getVirtualGroup().toString());
}
}
procEnv.push(dynamicProgram);
} catch (SQLException e) {
Object[] params = { dynamicCommand, dynamicCommand.getSql(), e.getMessage() };
throw new QueryProcessingException(QueryPlugin.Event.TEIID30168, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30168, params));
} catch (TeiidProcessingException e) {
Object[] params = { dynamicCommand, query == null ? dynamicCommand.getSql() : query, e.getMessage() };
throw new QueryProcessingException(QueryPlugin.Event.TEIID30168, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30168, params));
}
}
Aggregations