use of org.teiid.query.optimizer.capabilities.SourceCapabilities in project teiid by teiid.
the class TestConnectorCapabilitiesFinder method testFindRequiresSource.
@Test
public void testFindRequiresSource() throws Exception {
// $NON-NLS-1$
String modelName = "model";
// $NON-NLS-1$
String functionName = "fakeFunction";
ArrayList<String> bindings = new ArrayList<String>();
bindings.add(modelName);
VDBMetaData vdb = Mockito.mock(VDBMetaData.class);
ModelMetaData model = Mockito.mock(ModelMetaData.class);
Mockito.stub(vdb.getModel(modelName)).toReturn(model);
Mockito.stub(model.getSourceNames()).toReturn(bindings);
BasicSourceCapabilities basicSourceCapabilities = new BasicSourceCapabilities();
basicSourceCapabilities.setFunctionSupport(functionName, true);
ConnectorManagerRepository repo = Mockito.mock(ConnectorManagerRepository.class);
ConnectorManager cm = Mockito.mock(ConnectorManager.class);
Mockito.stub(cm.getCapabilities()).toThrow(new TranslatorException());
Mockito.stub(repo.getConnectorManager(Mockito.anyString())).toReturn(cm);
CachedFinder finder = new CachedFinder(repo, vdb);
// Test
SourceCapabilities actual = finder.findCapabilities(modelName);
// $NON-NLS-1$
assertNotNull(actual);
assertFalse(finder.isValid(modelName));
}
use of org.teiid.query.optimizer.capabilities.SourceCapabilities in project teiid by teiid.
the class SubqueryAwareEvaluator method evaluatePushdown.
/**
* Implements must pushdown function handling if supported by the source.
*
* The basic strategy is to create a dummy subquery to represent the evaluation
*/
@Override
protected Object evaluatePushdown(Function function, List<?> tuple, Object[] values) throws TeiidComponentException, TeiidProcessingException {
final FunctionDescriptor fd = function.getFunctionDescriptor();
if (fd.getMethod() == null) {
throw new FunctionExecutionException(QueryPlugin.Event.TEIID30341, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30341, fd.getFullName()));
}
String schema = null;
if (fd.getMethod().getParent() == null || !fd.getMethod().getParent().isPhysical()) {
// find a suitable target
// TODO: do better than a linear search
VDBMetaData vdb = this.context.getVdb();
CapabilitiesFinder capabiltiesFinder = this.context.getQueryProcessorFactory().getCapabiltiesFinder();
for (ModelMetaData mmd : vdb.getModelMetaDatas().values()) {
if (!mmd.isSource()) {
continue;
}
SourceCapabilities caps = capabiltiesFinder.findCapabilities(mmd.getName());
if (caps.supportsCapability(Capability.SELECT_WITHOUT_FROM) && caps.supportsFunction(fd.getMethod().getFullName())) {
schema = mmd.getName();
break;
}
}
if (schema == null) {
throw new FunctionExecutionException(QueryPlugin.Event.TEIID30341, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30341, fd.getFullName()));
}
} else {
if (!CapabilitiesUtil.supports(Capability.SELECT_WITHOUT_FROM, fd.getMethod().getParent(), context.getMetadata(), context.getQueryProcessorFactory().getCapabiltiesFinder())) {
if (elements != null) {
Integer index = (Integer) elements.get(function);
if (index != null) {
return tuple.get(index.intValue());
}
}
throw new FunctionExecutionException(QueryPlugin.Event.TEIID30341, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30341, fd.getFullName()));
}
schema = fd.getSchema();
}
ScalarSubquery ss = null;
if (functionState != null) {
ss = functionState.get(function);
}
Expression[] functionArgs = new Expression[values.length];
for (int i = 0; i < values.length; i++) {
functionArgs[i] = new Constant(values[i]);
}
if (ss == null) {
final Query command = new Query();
Select select = new Select();
command.setSelect(select);
Function f = new Function(function.getName(), functionArgs);
f.setType(function.getType());
f.setFunctionDescriptor(fd);
select.addSymbol(f);
ss = new ScalarSubquery(command);
SymbolMap correlatedReferences = new SymbolMap();
Collection<ElementSymbol> elements = ElementCollectorVisitor.getElements(function, true);
if (!elements.isEmpty()) {
for (ElementSymbol es : elements) {
correlatedReferences.addMapping(es, es);
}
command.setCorrelatedReferences(correlatedReferences);
}
command.setProcessorPlan(new SimpleProcessorPlan(command, schema, fd, Arrays.asList(new Constant(null, fd.getReturnType()))));
} else {
((Function) ((ExpressionSymbol) ss.getCommand().getProjectedSymbols().get(0)).getExpression()).setArgs(functionArgs);
}
if (functionState == null) {
this.functionState = new HashMap<Function, ScalarSubquery>(2);
}
functionState.put(function, ss);
return internalEvaluate(ss, tuple);
}
use of org.teiid.query.optimizer.capabilities.SourceCapabilities in project teiid by teiid.
the class CachedFinder method findCapabilities.
/**
* Find capabilities used the cache if possible, otherwise do the lookup.
*/
public SourceCapabilities findCapabilities(String modelName) throws TeiidComponentException {
SourceCapabilities caps = userCache.get(modelName);
if (caps != null) {
return caps;
}
ModelMetaData model = vdb.getModel(modelName);
List<String> sourceNames = model.getSourceNames();
if (sourceNames.isEmpty()) {
throw new TeiidRuntimeException(QueryPlugin.Event.TEIID30499, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30499, modelName));
}
TeiidException cause = null;
for (String sourceName : sourceNames) {
// TOOD: in multi-source mode it may be necessary to compute minimal capabilities across the sources
ConnectorManager mgr = this.connectorRepo.getConnectorManager(sourceName);
if (mgr == null) {
throw new TeiidComponentException(QueryPlugin.Event.TEIID30497, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30497, sourceName, modelName, sourceName));
}
try {
caps = mgr.getCapabilities();
break;
} catch (TeiidException e) {
cause = e;
// $NON-NLS-1$
LogManager.logDetail(LogConstants.CTX_DQP, e, "Could not obtain capabilities for" + sourceName);
}
}
if (caps == null) {
InvalidCaps ic = new InvalidCaps();
ic.setSourceProperty(Capability.INVALID_EXCEPTION, cause);
caps = ic;
}
userCache.put(modelName, caps);
return caps;
}
use of org.teiid.query.optimizer.capabilities.SourceCapabilities in project teiid by teiid.
the class CapabilitiesUtil method supportsScalarFunction.
public static boolean supportsScalarFunction(Object modelID, Function function, QueryMetadataInterface metadata, CapabilitiesFinder capFinder) throws QueryMetadataException, TeiidComponentException {
FunctionMethod method = function.getFunctionDescriptor().getMethod();
if (metadata.isVirtualModel(modelID) || method.getPushdown() == PushDown.CANNOT_PUSHDOWN) {
return false;
}
SourceCapabilities caps = getCapabilities(modelID, metadata, capFinder);
// capabilities check is only valid for non-schema scoped functions
// technically the other functions are scoped to SYS or their function model, but that's
// not formally part of their metadata yet
Schema schema = method.getParent();
// TODO: this call should be functionDescriptor.getFullName - but legacy function models are parsed without setting the parent model as the schema
String fullName = method.getFullName();
if (schema == null || !schema.isPhysical()) {
if (!caps.supportsFunction(fullName)) {
if (SourceSystemFunctions.CONCAT2.equalsIgnoreCase(fullName)) {
// special handling for delayed rewrite of concat2
return (schema == null && caps.supportsFunction(SourceSystemFunctions.CONCAT) && caps.supportsFunction(SourceSystemFunctions.IFNULL) && caps.supportsCapability(Capability.QUERY_SEARCHED_CASE));
} else if (SourceSystemFunctions.FROM_UNIXTIME.equalsIgnoreCase(fullName)) {
return (schema == null && caps.supportsFunction(SourceSystemFunctions.TIMESTAMPADD));
} else if (SourceSystemFunctions.FROM_UNIXTIME.equalsIgnoreCase(fullName)) {
return (schema == null && caps.supportsFunction(SourceSystemFunctions.TIMESTAMPDIFF));
} else {
return false;
}
}
if (FunctionLibrary.isConvert(function)) {
Class<?> fromType = function.getArg(0).getType();
Class<?> targetType = function.getType();
if (fromType == targetType) {
// this should be removed in rewrite
return true;
}
return caps.supportsConvert(DataTypeManager.getTypeCode(fromType), DataTypeManager.getTypeCode(targetType));
}
} else if (!isSameConnector(modelID, schema, metadata, capFinder)) {
return caps.supportsFunction(fullName);
}
return true;
}
use of org.teiid.query.optimizer.capabilities.SourceCapabilities in project teiid by teiid.
the class CapabilitiesUtil method isSameConnector.
public static boolean isSameConnector(Object modelID, Object modelID1, QueryMetadataInterface metadata, CapabilitiesFinder capFinder) throws QueryMetadataException, TeiidComponentException {
if (modelID == null || modelID1 == null || metadata.isVirtualModel(modelID) || metadata.isVirtualModel(modelID1)) {
return false;
}
if (modelID.equals(modelID1)) {
return true;
}
if (capFinder == null) {
return false;
}
// Find capabilities
SourceCapabilities caps = getCapabilities(modelID, metadata, capFinder);
SourceCapabilities caps1 = getCapabilities(modelID1, metadata, capFinder);
Object connectorID = caps.getSourceProperty(Capability.CONNECTOR_ID);
return connectorID != null && connectorID.equals(caps1.getSourceProperty(Capability.CONNECTOR_ID));
}
Aggregations