Skip to content

Commit

Permalink
TEIID-2381 modifying support for the source hint
Browse files Browse the repository at this point in the history
  • Loading branch information
shawkins authored and johnathonlee committed Sep 11, 2014
1 parent 2e8202c commit 4f874a6
Show file tree
Hide file tree
Showing 23 changed files with 229 additions and 150 deletions.
19 changes: 16 additions & 3 deletions api/src/main/java/org/teiid/translator/ExecutionContext.java
Expand Up @@ -24,6 +24,7 @@

import java.io.Serializable;
import java.sql.Statement;
import java.util.Collection;

import javax.security.auth.Subject;

Expand Down Expand Up @@ -123,17 +124,29 @@ public interface ExecutionContext {
Serializable getExecutionPayload();

/**
* Get the general hint passed to all executions under the user query.
* Get the collection of general hints as a space concatinated string.
* @return the general hint or null if none was specified
*/
String getGeneralHint();

/**
* Get the hint designated for this source.
* Get the collection of hints designated for this source as a space concatinated string.
* @return the source hint or null if none was specified
*/
String getSourceHint();


/**
* Get the general hints.
* @return the general hint or null if none was specified
*/
Collection<String> getGeneralHints();

/**
* Get the hints designated for this source.
* @return the source hint or null if none was specified
*/
Collection<String> getSourceHints();

/**
* Get the identifier for the connection through which
* the command is being executed. This represents the original user
Expand Down
23 changes: 5 additions & 18 deletions common-core/src/main/java/org/teiid/core/util/StringUtil.java
Expand Up @@ -119,33 +119,20 @@ public static String getLineSeparator() {
* @param delimiter Delimiter to put between string pieces
* @return One merged string
*/
public static String join(List<String> strings, String delimiter) {
public static String join(Collection<String> strings, String delimiter) {
if(strings == null || delimiter == null) {
return null;
}

StringBuffer str = new StringBuffer();

// This is the standard problem of not putting a delimiter after the last
// string piece but still handling the special cases. A typical way is to check every
// iteration if it is the last one and skip the delimiter - this is avoided by
// looping up to the last one, then appending just the last one.

// First we loop through all but the last one (if there are at least 2) and
// put the piece and a delimiter after it. An iterator is used to walk the list.
int most = strings.size()-1;
if(strings.size() > 1) {
Iterator<String> iter = strings.iterator();
for(int i=0; i<most; i++) {
str.append(iter.next());
Iterator<String> iter = strings.iterator();
while (iter.hasNext()) {
str.append(iter.next());
if (iter.hasNext()) {
str.append(delimiter);
}
}

// If there is at least one element, put the last one on with no delimiter after.
if(strings.size() > 0) {
str.append(strings.get(most));
}

return str.toString();
}
Expand Down
Expand Up @@ -88,13 +88,13 @@ private void helpTestVisitor(String input, String expectedOutput) throws Transla

@Test public void testSourceHint() throws Exception {
ExecutionContextImpl impl = new FakeExecutionContextImpl();
impl.setHint("hello world");
impl.setHints(Arrays.asList("hello world"));
helpTestVisitor(getTestVDB(), "select part_name from parts", impl, null, "SELECT /*+ hello world */ g_0.PART_NAME FROM PARTS g_0", true);
}

@Test public void testSourceHint1() throws Exception {
ExecutionContextImpl impl = new FakeExecutionContextImpl();
impl.setHint("hello world");
impl.setHints(Arrays.asList("hello world"));
helpTestVisitor(getTestVDB(), "select part_name from parts union select part_id from parts", impl, null, "SELECT /*+ hello world */ g_1.PART_NAME AS c_0 FROM PARTS g_1 UNION SELECT g_0.PART_ID AS c_0 FROM PARTS g_0", true);
}

Expand Down
Expand Up @@ -72,6 +72,7 @@
import org.teiid.query.metadata.TempMetadataStore;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.lang.QueryCommand;
import org.teiid.query.sql.lang.SourceHint;
import org.teiid.query.sql.lang.StoredProcedure;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.resource.spi.WrappedConnection;
Expand Down Expand Up @@ -128,8 +129,11 @@ public class ConnectorWorkItem implements ConnectorWork {
Integer.toString(requestID.getNodeID()),
Integer.toString(requestID.getExecutionId())
);
this.securityContext.setGeneralHint(message.getGeneralHint());
this.securityContext.setHint(message.getHint());
SourceHint hint = message.getCommand().getSourceHint();
if (hint != null) {
this.securityContext.setGeneralHints(hint.getGeneralHints());
this.securityContext.setHints(hint.getSpecificHint(message.getConnectorName()).getHints());
}
this.securityContext.setBatchSize(this.requestMsg.getFetchSize());
this.securityContext.setSession(requestMsg.getWorkContext().getSession());

Expand Down
Expand Up @@ -25,6 +25,7 @@
import java.io.Serializable;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

Expand All @@ -34,6 +35,7 @@
import org.teiid.common.buffer.BufferManager;
import org.teiid.core.util.EquivalenceUtil;
import org.teiid.core.util.HashCodeUtil;
import org.teiid.core.util.StringUtil;
import org.teiid.dqp.internal.process.RequestWorkItem;
import org.teiid.dqp.message.RequestID;
import org.teiid.query.util.CommandContext;
Expand All @@ -59,8 +61,8 @@ public class ExecutionContextImpl implements ExecutionContext {
private List<Exception> warnings = new LinkedList<Exception>();
private Session session;
private boolean dataAvailable;
private String generalHint;
private String hint;
private Collection<String> generalHint;
private Collection<String> hint;
private CommandContext commandContext;
private CacheDirective cacheDirective;

Expand Down Expand Up @@ -225,19 +227,29 @@ public synchronized boolean isDataAvailable() {

@Override
public String getGeneralHint() {
return generalHint;
return StringUtil.join(generalHint, " ");
}

@Override
public String getSourceHint() {
return StringUtil.join(hint, " ");
}

@Override
public Collection<String> getGeneralHints() {
return generalHint;
}

@Override
public Collection<String> getSourceHints() {
return hint;
}

public void setGeneralHint(String generalHint) {
public void setGeneralHints(Collection<String> generalHint) {
this.generalHint = generalHint;
}

public void setHint(String hint) {
public void setHints(Collection<String> hint) {
this.hint = hint;
}

Expand Down Expand Up @@ -274,4 +286,5 @@ public CacheDirective getCacheDirective() {
public void setCacheDirective(CacheDirective directive) {
this.cacheDirective = directive;
}

}
Expand Up @@ -87,7 +87,6 @@
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.lang.Criteria;
import org.teiid.query.sql.lang.Query;
import org.teiid.query.sql.lang.SourceHint;
import org.teiid.query.sql.lang.StoredProcedure;
import org.teiid.query.sql.lang.UnaryFromClause;
import org.teiid.query.sql.navigator.PreOrPostOrderNavigator;
Expand Down Expand Up @@ -649,11 +648,6 @@ public TupleSource registerRequest(CommandContext context, Command command, Stri
if (parameterObject.fetchSize > 0) {
aqr.setFetchSize(2*parameterObject.fetchSize);
}
SourceHint sh = context.getSourceHint();
if (sh != null) {
aqr.setGeneralHint(sh.getGeneralHint());
aqr.setHint(sh.getSourceHint(aqr.getConnectorName()));
}
if (parameterObject.limit > 0) {
aqr.setFetchSize(Math.min(parameterObject.limit, aqr.getFetchSize()));
}
Expand Down
Expand Up @@ -83,8 +83,6 @@ public class AtomicRequestMessage {
private boolean serial;

private DQPWorkContext workContext;
private String generalHint;
private String hint;
private CommandContext commandContext;
private BufferManager bufferManager;

Expand Down Expand Up @@ -205,22 +203,6 @@ public DQPWorkContext getWorkContext() {
return workContext;
}

public String getGeneralHint() {
return generalHint;
}

public void setGeneralHint(String generalHint) {
this.generalHint = generalHint;
}

public String getHint() {
return hint;
}

public void setHint(String hint) {
this.hint = hint;
}

public CommandContext getCommandContext() {
return commandContext;
}
Expand Down
Expand Up @@ -372,7 +372,7 @@ protected RelationalNode convertNode(PlanNode node)
boolean aliasColumns = modelID != null && (CapabilitiesUtil.supports(Capability.QUERY_SELECT_EXPRESSION, modelID, metadata, capFinder)
|| CapabilitiesUtil.supports(Capability.QUERY_FROM_INLINE_VIEWS, modelID, metadata, capFinder));
AliasGenerator visitor = new AliasGenerator(aliasGroups, !aliasColumns);
SourceHint sh = context.getSourceHint();
SourceHint sh = command.getSourceHint();
if (sh != null && aliasGroups) {
VDBMetaData vdb = context.getDQPWorkContext().getVDB();
ModelMetaData model = vdb.getModel(aNode.getModelName());
Expand Down
Expand Up @@ -160,7 +160,7 @@ protected HashSet<PlanningStackEntry> initialValue() {
}
};

public ProcessorPlan optimize(
public RelationalPlan optimize(
Command command)
throws
QueryPlannerException,
Expand All @@ -173,6 +173,9 @@ public ProcessorPlan optimize(
analysisRecord.println("GENERATE CANONICAL: \n" + command); //$NON-NLS-1$
}

SourceHint previous = this.sourceHint;
this.sourceHint = SourceHint.combine(previous, command.getSourceHint());

PlanToProcessConverter planToProcessConverter = new PlanToProcessConverter(metadata, idGenerator, analysisRecord, capFinder, context);

//plan with
Expand All @@ -185,11 +188,13 @@ public ProcessorPlan optimize(
if (withList != null) {
for (WithQueryCommand with : withList) {
QueryCommand subCommand = with.getCommand();
ProcessorPlan plan = QueryOptimizer.optimizePlan(subCommand, metadata, idGenerator, capFinder, analysisRecord, context);
if (subCommand instanceof Query && ((Query)subCommand).getIsXML()) {
ProcessorPlan plan = QueryOptimizer.optimizePlan(subCommand, metadata, idGenerator, capFinder, analysisRecord, context);
subCommand.setProcessorPlan(plan);
continue;
}
RelationalPlan plan = optimize(subCommand);
subCommand.setProcessorPlan(plan);
if (!(plan instanceof RelationalPlan)) {
continue;
}
RelationalPlan procPlan = (RelationalPlan) plan;
RelationalNode root = procPlan.getRootNode();
Number planCardinality = root.getEstimateNodeCardinality();
Expand Down Expand Up @@ -223,7 +228,7 @@ public ProcessorPlan optimize(
}
PlanNode plan;
try {
plan = generatePlan(command, true);
plan = generatePlan(command);
} catch (TeiidProcessingException e) {
throw new QueryPlannerException(e);
}
Expand All @@ -240,7 +245,6 @@ public ProcessorPlan optimize(

// Build rule set based on hints
RuleStack rules = buildRules();
context.setSourceHint(sourceHint);
// Run rule-based optimizer
plan = executeRules(rules, plan);

Expand All @@ -262,7 +266,7 @@ public ProcessorPlan optimize(
result.setWith(withList);
}
result.setOutputElements(topCols);
result.setSourceHint(sourceHint);
this.sourceHint = previous;
return result;
}

Expand Down Expand Up @@ -589,10 +593,7 @@ private PlanNode executeRules(RuleStack rules, PlanNode plan)
return plan;
}

public PlanNode generatePlan(Command cmd, boolean useSourceHint) throws TeiidComponentException, TeiidProcessingException {
if (useSourceHint && cmd.getSourceHint() != null && sourceHint == null) {
sourceHint = cmd.getSourceHint();
}
public PlanNode generatePlan(Command cmd) throws TeiidComponentException, TeiidProcessingException {
//cascade the option clause nocache
Option savedOption = option;
option = cmd.getOption();
Expand Down Expand Up @@ -673,7 +674,7 @@ PlanNode createUpdatePlan(Command command) throws TeiidComponentException, Teiid
if(!usingTriggerAction && command instanceof Insert){
Insert insert = (Insert)command;
if (insert.getQueryExpression() != null) {
PlanNode plan = generatePlan(insert.getQueryExpression(), true);
PlanNode plan = generatePlan(insert.getQueryExpression());
attachLast(sourceNode, plan);
mergeTempMetadata(insert.getQueryExpression(), insert);
projectNode.setProperty(NodeConstants.Info.INTO_GROUP, insert.getGroup());
Expand Down Expand Up @@ -864,12 +865,8 @@ PlanNode createQueryPlan(QueryCommand command)
} else {
hints.hasSetQuery = true;
SetQuery query = (SetQuery)command;
boolean hasSourceHint = sourceHint != null;
PlanNode leftPlan = createQueryPlan( query.getLeftQuery());
PlanNode rightPlan = createQueryPlan( query.getRightQuery());
if (!hasSourceHint) {
sourceHint = null;
}
node = NodeFactory.getNewNode(NodeConstants.Types.SET_OP);
node.setProperty(NodeConstants.Info.SET_OPERATION, query.getOperation());
node.setProperty(NodeConstants.Info.USE_ALL, query.isAll());
Expand Down Expand Up @@ -1022,10 +1019,14 @@ void buildTree(FromClause clause, PlanNode parent)
if (info != null && info.getPartitionInfo() != null && !info.getPartitionInfo().isEmpty()) {
node.setProperty(NodeConstants.Info.PARTITION_INFO, info.getPartitionInfo());
}
if (parent.getType() != NodeConstants.Types.JOIN && nestedCommand.getSourceHint() != null && sourceHint == null) {
sourceHint = nestedCommand.getSourceHint();
SourceHint previous = this.sourceHint;
if (nestedCommand.getSourceHint() != null) {
this.sourceHint = SourceHint.combine(previous, nestedCommand.getSourceHint());
}
addNestedCommand(node, group, nestedCommand, nestedCommand, true, true);
this.sourceHint = previous;
} else if (this.sourceHint != null) {
node.setProperty(Info.SOURCE_HINT, this.sourceHint);
}
parent.addLastChild(node);
} else if(clause instanceof JoinPredicate) {
Expand Down Expand Up @@ -1170,7 +1171,7 @@ private void addNestedCommand(PlanNode node,

if (merge) {
mergeTempMetadata(nestedCommand, parentCommand);
PlanNode childRoot = generatePlan(nestedCommand, false);
PlanNode childRoot = generatePlan(nestedCommand);
node.addFirstChild(childRoot);
List<Expression> projectCols = nestedCommand.getProjectedSymbols();
SymbolMap map = SymbolMap.createSymbolMap(group, projectCols, metadata);
Expand Down
Expand Up @@ -158,6 +158,8 @@ public enum Info {
ACCESS_PATTERN_USED, // List <Object element ID>
REQUIRED_ACCESS_PATTERN_GROUPS,

CONSTRAINT
CONSTRAINT,

SOURCE_HINT,
}
}
Expand Up @@ -95,6 +95,7 @@ public PlanNode execute(PlanNode plan, QueryMetadataInterface metadata, Capabili
QueryCommand queryCommand = createQuery(context, capFinder, accessNode, commandRoot);
addDistinct(metadata, capFinder, accessNode, queryCommand);
command = queryCommand;
queryCommand.setSourceHint((SourceHint) accessNode.getProperty(Info.SOURCE_HINT));
if (intoGroup != null) {
Insert insertCommand = (Insert)commandRoot.getParent().getProperty(NodeConstants.Info.VIRTUAL_COMMAND);
if (insertCommand == null) {
Expand Down

0 comments on commit 4f874a6

Please sign in to comment.