Search in sources :

Example 1 with SourceCapabilities

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));
}
Also used : BasicSourceCapabilities(org.teiid.query.optimizer.capabilities.BasicSourceCapabilities) ConnectorManagerRepository(org.teiid.dqp.internal.datamgr.ConnectorManagerRepository) VDBMetaData(org.teiid.adminapi.impl.VDBMetaData) ArrayList(java.util.ArrayList) TranslatorException(org.teiid.translator.TranslatorException) ConnectorManager(org.teiid.dqp.internal.datamgr.ConnectorManager) SourceCapabilities(org.teiid.query.optimizer.capabilities.SourceCapabilities) BasicSourceCapabilities(org.teiid.query.optimizer.capabilities.BasicSourceCapabilities) ModelMetaData(org.teiid.adminapi.impl.ModelMetaData) Test(org.junit.Test)

Example 2 with SourceCapabilities

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);
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) ScalarSubquery(org.teiid.query.sql.symbol.ScalarSubquery) Query(org.teiid.query.sql.lang.Query) Constant(org.teiid.query.sql.symbol.Constant) SymbolMap(org.teiid.query.sql.util.SymbolMap) FunctionDescriptor(org.teiid.query.function.FunctionDescriptor) ModelMetaData(org.teiid.adminapi.impl.ModelMetaData) Function(org.teiid.query.sql.symbol.Function) CapabilitiesFinder(org.teiid.query.optimizer.capabilities.CapabilitiesFinder) FunctionExecutionException(org.teiid.api.exception.query.FunctionExecutionException) Expression(org.teiid.query.sql.symbol.Expression) VDBMetaData(org.teiid.adminapi.impl.VDBMetaData) Select(org.teiid.query.sql.lang.Select) SourceCapabilities(org.teiid.query.optimizer.capabilities.SourceCapabilities)

Example 3 with SourceCapabilities

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;
}
Also used : TeiidComponentException(org.teiid.core.TeiidComponentException) SourceCapabilities(org.teiid.query.optimizer.capabilities.SourceCapabilities) BasicSourceCapabilities(org.teiid.query.optimizer.capabilities.BasicSourceCapabilities) TeiidRuntimeException(org.teiid.core.TeiidRuntimeException) ConnectorManager(org.teiid.dqp.internal.datamgr.ConnectorManager) ModelMetaData(org.teiid.adminapi.impl.ModelMetaData) TeiidException(org.teiid.core.TeiidException)

Example 4 with SourceCapabilities

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;
}
Also used : Schema(org.teiid.metadata.Schema) FunctionMethod(org.teiid.metadata.FunctionMethod) SourceCapabilities(org.teiid.query.optimizer.capabilities.SourceCapabilities)

Example 5 with SourceCapabilities

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));
}
Also used : LanguageObject(org.teiid.query.sql.LanguageObject) SourceCapabilities(org.teiid.query.optimizer.capabilities.SourceCapabilities)

Aggregations

SourceCapabilities (org.teiid.query.optimizer.capabilities.SourceCapabilities)16 ArrayList (java.util.ArrayList)4 ModelMetaData (org.teiid.adminapi.impl.ModelMetaData)4 VDBMetaData (org.teiid.adminapi.impl.VDBMetaData)4 List (java.util.List)3 TeiidComponentException (org.teiid.core.TeiidComponentException)3 ConnectorManager (org.teiid.dqp.internal.datamgr.ConnectorManager)3 BasicSourceCapabilities (org.teiid.query.optimizer.capabilities.BasicSourceCapabilities)3 Constant (org.teiid.query.sql.symbol.Constant)3 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)3 Expression (org.teiid.query.sql.symbol.Expression)3 Test (org.junit.Test)2 QueryMetadataException (org.teiid.api.exception.query.QueryMetadataException)2 TeiidRuntimeException (org.teiid.core.TeiidRuntimeException)2 ConnectorManagerRepository (org.teiid.dqp.internal.datamgr.ConnectorManagerRepository)2 CapabilitiesFinder (org.teiid.query.optimizer.capabilities.CapabilitiesFinder)2 ProcessorPlan (org.teiid.query.processor.ProcessorPlan)2 RelationalPlan (org.teiid.query.processor.relational.RelationalPlan)2 BatchedUpdateCommand (org.teiid.query.sql.lang.BatchedUpdateCommand)2 Command (org.teiid.query.sql.lang.Command)2