Search in sources :

Example 31 with QueryMetadataException

use of org.teiid.api.exception.query.QueryMetadataException in project teiid by teiid.

the class CriteriaCapabilityValidatorVisitor method canPushLanguageObject.

public static boolean canPushLanguageObject(LanguageObject obj, Object modelID, final QueryMetadataInterface metadata, CapabilitiesFinder capFinder, AnalysisRecord analysisRecord, boolean isJoin, boolean isSelectClause, final boolean multiValuedReferences) throws QueryMetadataException, TeiidComponentException {
    if (obj == null) {
        return true;
    }
    if (modelID == null || metadata.isVirtualModel(modelID)) {
        // Couldn't determine model ID, so give up
        return false;
    }
    String modelName = metadata.getFullName(modelID);
    SourceCapabilities caps = capFinder.findCapabilities(modelName);
    if (caps == null) {
        // this doesn't seem right, but tests were expecting it...
        return true;
    }
    CriteriaCapabilityValidatorVisitor visitor = new CriteriaCapabilityValidatorVisitor(modelID, metadata, capFinder, caps);
    visitor.setCheckEvaluation(!multiValuedReferences);
    visitor.analysisRecord = analysisRecord;
    visitor.isJoin = isJoin;
    visitor.isSelectClause = isSelectClause;
    // we use an array to represent multiple comparision attributes,
    // but we don't want that to inhibit pushdown as we'll account for that later
    // in criteria processing
    final EvaluatableVisitor ev = new EvaluatableVisitor(modelID, metadata, capFinder);
    PreOrPostOrderNavigator nav = new PreOrPostOrderNavigator(visitor, PreOrPostOrderNavigator.POST_ORDER, false) {

        @Override
        public void visit(DependentSetCriteria obj1) {
            if (obj1.hasMultipleAttributes()) {
                Array array = (Array) obj1.getExpression();
                visitNodes(array.getExpressions());
                super.postVisitVisitor(obj1);
            } else {
                super.visit(obj1);
            }
        }

        @Override
        protected void visitNode(LanguageObject obj) {
            if (obj == null) {
                return;
            }
            Determinism d = ev.getDeterminismLevel();
            boolean pushDown = ev.requiresEvaluation(EvaluationLevel.PUSH_DOWN);
            // decend with clean state, then restore
            ev.reset();
            super.visitNode(obj);
            ev.setDeterminismLevel(d);
            if (pushDown) {
                ev.evaluationNotPossible(EvaluationLevel.PUSH_DOWN);
            }
        }

        @Override
        protected void visitVisitor(LanguageObject obj) {
            if (obj == null) {
                return;
            }
            if (!ev.requiresEvaluation(EvaluationLevel.PUSH_DOWN) && ev.getDeterminismLevel() != Determinism.NONDETERMINISTIC) {
                if (obj instanceof ElementSymbol) {
                    ElementSymbol es = (ElementSymbol) obj;
                    if (es.getMetadataID() != null) {
                        try {
                            if (metadata.isMultiSourceElement(es.getMetadataID())) {
                                // no need to visit
                                return;
                            }
                        } catch (QueryMetadataException e) {
                        } catch (TeiidComponentException e) {
                        }
                    }
                }
                obj.acceptVisitor(ev);
                if (!multiValuedReferences && obj instanceof Expression) {
                    if (obj instanceof Function) {
                        if (!(obj instanceof AggregateSymbol)) {
                            Function f = (Function) obj;
                            if (f.getFunctionDescriptor().getPushdown() != PushDown.MUST_PUSHDOWN && f.getFunctionDescriptor().getDeterministic() != Determinism.NONDETERMINISTIC) {
                                // don't need to consider
                                return;
                            }
                        }
                    } else if (obj instanceof Criteria && !(obj instanceof SubqueryContainer) && !(obj instanceof DependentSetCriteria)) {
                        // don't need to consider
                        return;
                    }
                }
            }
            super.visitVisitor(obj);
        }
    };
    obj.acceptVisitor(nav);
    if (visitor.getException() != null) {
        throw visitor.getException();
    }
    return visitor.isValid();
}
Also used : Determinism(org.teiid.metadata.FunctionMethod.Determinism) QueryMetadataException(org.teiid.api.exception.query.QueryMetadataException) EvaluatableVisitor(org.teiid.query.sql.visitor.EvaluatableVisitor) PreOrPostOrderNavigator(org.teiid.query.sql.navigator.PreOrPostOrderNavigator) TeiidComponentException(org.teiid.core.TeiidComponentException) SourceCapabilities(org.teiid.query.optimizer.capabilities.SourceCapabilities) LanguageObject(org.teiid.query.sql.LanguageObject)

Example 32 with QueryMetadataException

use of org.teiid.api.exception.query.QueryMetadataException in project teiid by teiid.

the class CriteriaCapabilityValidatorVisitor method validateSubqueryPushdown.

/**
 * Return null if the subquery cannot be pushed down, otherwise the model
 * id of the pushdown target.
 * @param subqueryContainer
 * @param critNodeModelID
 * @param metadata
 * @param capFinder
 * @return
 * @throws TeiidComponentException
 */
public static Object validateSubqueryPushdown(SubqueryContainer<?> subqueryContainer, Object critNodeModelID, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, AnalysisRecord analysisRecord) throws TeiidComponentException {
    ProcessorPlan plan = subqueryContainer.getCommand().getProcessorPlan();
    if (plan != null) {
        AccessNode aNode = getAccessNode(plan);
        if (aNode == null) {
            return null;
        }
        critNodeModelID = validateCommandPushdown(critNodeModelID, metadata, capFinder, aNode, true);
    }
    if (critNodeModelID == null) {
        return null;
    }
    // Check whether source supports correlated subqueries and if not, whether criteria has them
    SymbolMap refs = subqueryContainer.getCommand().getCorrelatedReferences();
    try {
        if (refs != null && !refs.asMap().isEmpty()) {
            if (!CapabilitiesUtil.supports(Capability.QUERY_SUBQUERIES_CORRELATED, critNodeModelID, metadata, capFinder)) {
                return null;
            }
            if (!CapabilitiesUtil.supports(Capability.SUBQUERY_CORRELATED_LIMIT, critNodeModelID, metadata, capFinder)) {
                QueryCommand command = (QueryCommand) subqueryContainer.getCommand();
                if (command.getLimit() != null && !command.getLimit().isImplicit()) {
                    return null;
                }
            }
            // but this is only an issue with deeply nested subqueries
            if (!CriteriaCapabilityValidatorVisitor.canPushLanguageObject(subqueryContainer.getCommand(), critNodeModelID, metadata, capFinder, analysisRecord)) {
                return null;
            }
        } else if (CapabilitiesUtil.supports(Capability.QUERY_SUBQUERIES_ONLY_CORRELATED, critNodeModelID, metadata, capFinder)) {
            return null;
        }
    } catch (QueryMetadataException e) {
        throw new TeiidComponentException(QueryPlugin.Event.TEIID30271, e);
    }
    if (!CapabilitiesUtil.supports(Capability.SUBQUERY_COMMON_TABLE_EXPRESSIONS, critNodeModelID, metadata, capFinder) && subqueryContainer.getCommand() instanceof QueryCommand) {
        QueryCommand command = (QueryCommand) subqueryContainer.getCommand();
        if (command.getWith() != null) {
            return null;
        }
    }
    // Found no reason why this node is not eligible
    return critNodeModelID;
}
Also used : SymbolMap(org.teiid.query.sql.util.SymbolMap) TeiidComponentException(org.teiid.core.TeiidComponentException) AccessNode(org.teiid.query.processor.relational.AccessNode) ProcessorPlan(org.teiid.query.processor.ProcessorPlan) QueryMetadataException(org.teiid.api.exception.query.QueryMetadataException)

Example 33 with QueryMetadataException

use of org.teiid.api.exception.query.QueryMetadataException in project teiid by teiid.

the class TempMetadataAdapter method getVirtualPlan.

public QueryNode getVirtualPlan(Object groupID) throws TeiidComponentException, QueryMetadataException {
    if (this.queryNodes != null) {
        QueryNode node = this.queryNodes.get(groupID);
        if (node != null) {
            return node;
        }
    }
    if (groupID instanceof TempMetadataID && !(actualMetadata instanceof TempMetadataAdapter)) {
        TempMetadataID tid = (TempMetadataID) groupID;
        QueryNode queryNode = tid.getQueryNode();
        if (queryNode != null) {
            return queryNode;
        }
        throw new QueryMetadataException(QueryPlugin.Event.TEIID31265, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31265, tid.getName()));
    }
    return this.actualMetadata.getVirtualPlan(groupID);
}
Also used : QueryNode(org.teiid.query.mapping.relational.QueryNode) QueryMetadataException(org.teiid.api.exception.query.QueryMetadataException)

Example 34 with QueryMetadataException

use of org.teiid.api.exception.query.QueryMetadataException in project teiid by teiid.

the class TransformationMetadata method getStoredProcInfoDirect.

private StoredProcedureInfo getStoredProcInfoDirect(final String name) throws TeiidComponentException, QueryMetadataException {
    ArgCheck.isNotEmpty(name);
    String canonicalName = name.toUpperCase();
    Collection<StoredProcedureInfo> results = this.procedureCache.get(canonicalName);
    if (results == null) {
        Collection<Procedure> procRecords = getMetadataStore().getStoredProcedure(canonicalName);
        if (procRecords.isEmpty()) {
            return null;
        }
        results = new ArrayList<StoredProcedureInfo>(procRecords.size());
        for (Procedure procRecord : procRecords) {
            String procedureFullName = procRecord.getFullName();
            // create the storedProcedure info object that would hold procedure's metadata
            StoredProcedureInfo procInfo = new StoredProcedureInfo();
            procInfo.setProcedureCallableName(procedureFullName);
            procInfo.setProcedureID(procRecord);
            // modelID for the procedure
            procInfo.setModelID(procRecord.getParent());
            // get the parameter metadata info
            for (ProcedureParameter paramRecord : procRecord.getParameters()) {
                String runtimeType = paramRecord.getRuntimeType();
                int direction = this.convertParamRecordTypeToStoredProcedureType(paramRecord.getType());
                // create a parameter and add it to the procedure object
                SPParameter spParam = new SPParameter(paramRecord.getPosition(), direction, paramRecord.getFullName());
                spParam.setMetadataID(paramRecord);
                spParam.setClassType(DataTypeManager.getDataTypeClass(runtimeType));
                if (paramRecord.isVarArg()) {
                    spParam.setVarArg(true);
                    spParam.setClassType(DataTypeManager.getArrayType(spParam.getClassType()));
                }
                procInfo.addParameter(spParam);
            }
            // if the procedure returns a resultSet, obtain resultSet metadata
            if (procRecord.getResultSet() != null) {
                ColumnSet<Procedure> resultRecord = procRecord.getResultSet();
                // resultSet is the last parameter in the procedure
                int lastParamIndex = procInfo.getParameters().size() + 1;
                SPParameter param = new SPParameter(lastParamIndex, SPParameter.RESULT_SET, resultRecord.getFullName());
                param.setClassType(java.sql.ResultSet.class);
                param.setMetadataID(resultRecord);
                for (Column columnRecord : resultRecord.getColumns()) {
                    String colType = columnRecord.getRuntimeType();
                    param.addResultSetColumn(columnRecord.getFullName(), DataTypeManager.getDataTypeClass(colType), columnRecord);
                }
                procInfo.addParameter(param);
            }
            // if this is a virtual procedure get the procedure plan
            if (procRecord.isVirtual()) {
                QueryNode queryNode = new LiveQueryNode(procRecord);
                procInfo.setQueryPlan(queryNode);
            }
            procInfo.setUpdateCount(procRecord.getUpdateCount());
            results.add(procInfo);
        }
        this.procedureCache.put(canonicalName, results);
    }
    StoredProcedureInfo result = null;
    for (StoredProcedureInfo storedProcedureInfo : results) {
        Schema schema = (Schema) storedProcedureInfo.getModelID();
        if (name.equalsIgnoreCase(storedProcedureInfo.getProcedureCallableName()) || vdbMetaData == null || vdbMetaData.isVisible(schema.getName())) {
            if (result != null) {
                throw new QueryMetadataException(QueryPlugin.Event.TEIID30358, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30358, name));
            }
            result = storedProcedureInfo;
        }
    }
    return result;
}
Also used : SPParameter(org.teiid.query.sql.lang.SPParameter) QueryMetadataException(org.teiid.api.exception.query.QueryMetadataException) QueryNode(org.teiid.query.mapping.relational.QueryNode)

Example 35 with QueryMetadataException

use of org.teiid.api.exception.query.QueryMetadataException in project teiid by teiid.

the class ResolverUtil method getDefault.

/**
 * Get the default value for the parameter, which could be null
 * if the parameter is set to NULLABLE.  If no default is available,
 * a QueryResolverException will be thrown.
 *
 * @param symbol ElementSymbol retrieved from metadata, fully-resolved
 * @param metadata QueryMetadataInterface
 * @return expr param (if it is non-null) or default value (if there is one)
 * or null Constant (if parameter is optional and therefore allows this)
 * @throws QueryResolverException if expr is null, parameter is required and no
 * default value is defined
 * @throws QueryMetadataException for error retrieving metadata
 * @throws TeiidComponentException
 * @throws QueryParserException
 * @since 4.3
 */
public static Expression getDefault(ElementSymbol symbol, QueryMetadataInterface metadata) throws TeiidComponentException, QueryMetadataException, QueryResolverException {
    // Check if there is a default value, if so use it
    Object mid = symbol.getMetadataID();
    Class<?> type = symbol.getType();
    String defaultValue = metadata.getDefaultValue(mid);
    boolean omit = false;
    String extensionProperty = metadata.getExtensionProperty(mid, BaseColumn.DEFAULT_HANDLING, false);
    if (BaseColumn.EXPRESSION_DEFAULT.equalsIgnoreCase(extensionProperty)) {
        Expression ex = null;
        try {
            ex = QueryParser.getQueryParser().parseExpression(defaultValue);
        } catch (QueryParserException e) {
            // TODO: also validate this at load time
            throw new QueryMetadataException(QueryPlugin.Event.TEIID31170, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31170, symbol));
        }
        List<SubqueryContainer<?>> subqueries = ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(ex);
        ResolverVisitor.resolveLanguageObject(ex, metadata);
        for (SubqueryContainer<?> container : subqueries) {
            QueryResolver.resolveCommand(container.getCommand(), metadata);
        }
        return ResolverUtil.convertExpression(ex, DataTypeManager.getDataTypeName(type), metadata);
    } else if (BaseColumn.OMIT_DEFAULT.equalsIgnoreCase(extensionProperty)) {
        Object id = metadata.getGroupIDForElementID(symbol.getMetadataID());
        if (!metadata.isVirtualGroup(id)) {
            omit = true;
            // for physical procedures we just need a dummy value
            defaultValue = null;
        }
    }
    if (!omit && defaultValue == null && !metadata.elementSupports(mid, SupportConstants.Element.NULL)) {
        throw new QueryResolverException(QueryPlugin.Event.TEIID30089, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30089, symbol.getOutputName()));
    }
    return getProperlyTypedConstant(defaultValue, type);
}
Also used : QueryParserException(org.teiid.api.exception.query.QueryParserException) LanguageObject(org.teiid.query.sql.LanguageObject) QueryMetadataException(org.teiid.api.exception.query.QueryMetadataException) QueryResolverException(org.teiid.api.exception.query.QueryResolverException)

Aggregations

QueryMetadataException (org.teiid.api.exception.query.QueryMetadataException)39 TeiidComponentException (org.teiid.core.TeiidComponentException)18 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)12 LanguageObject (org.teiid.query.sql.LanguageObject)7 QueryResolverException (org.teiid.api.exception.query.QueryResolverException)6 TempMetadataID (org.teiid.query.metadata.TempMetadataID)6 QueryPlannerException (org.teiid.api.exception.query.QueryPlannerException)5 TeiidRuntimeException (org.teiid.core.TeiidRuntimeException)5 ArrayList (java.util.ArrayList)4 HashSet (java.util.HashSet)3 LinkedHashSet (java.util.LinkedHashSet)3 VDBMetaData (org.teiid.adminapi.impl.VDBMetaData)3 TeiidException (org.teiid.core.TeiidException)3 TeiidProcessingException (org.teiid.core.TeiidProcessingException)3 PlanNode (org.teiid.query.optimizer.relational.plantree.PlanNode)3 ProcessorPlan (org.teiid.query.processor.ProcessorPlan)3 ObjectTable (org.teiid.query.sql.lang.ObjectTable)3 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)3 Expression (org.teiid.query.sql.symbol.Expression)3 Collection (java.util.Collection)2