/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.query.optimizer.relational.rules; import org.teiid.api.exception.query.QueryMetadataException; import org.teiid.api.exception.query.QueryPlannerException; import org.teiid.core.TeiidComponentException; import org.teiid.query.QueryPlugin; import org.teiid.query.analysis.AnalysisRecord; import org.teiid.query.metadata.QueryMetadataInterface; import org.teiid.query.optimizer.capabilities.CapabilitiesFinder; import org.teiid.query.optimizer.relational.OptimizerRule; import org.teiid.query.optimizer.relational.RuleStack; import org.teiid.query.optimizer.relational.plantree.NodeConstants; import org.teiid.query.optimizer.relational.plantree.NodeEditor; import org.teiid.query.optimizer.relational.plantree.PlanNode; import org.teiid.query.sql.lang.Command; import org.teiid.query.sql.lang.Delete; import org.teiid.query.sql.lang.Query; import org.teiid.query.sql.lang.SetQuery; import org.teiid.query.sql.lang.Update; import org.teiid.query.util.CommandContext; /** * Validates that the any atomic query being sent to a model where the model * requires a criteria actually has a criteria. This rule will detect this * case and throw an exception. This rule does not actually modify anything * in the plan itself. */ public final class RuleValidateWhereAll implements OptimizerRule { /** * Verifies that a model with "supports where all" is being passed an atomic * query with a criteria. * @throws QueryPlannerException if property is not satisfied */ public PlanNode execute( PlanNode plan, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, RuleStack rules, AnalysisRecord analysisRecord, CommandContext context) throws QueryPlannerException, QueryMetadataException, TeiidComponentException { for (PlanNode node : NodeEditor.findAllNodes(plan, NodeConstants.Types.ACCESS)) { Object modelID = RuleRaiseAccess.getModelIDFromAccess(node, metadata); if(CapabilitiesUtil.requiresCriteria(modelID, metadata, capFinder) && hasNoCriteria((Command) node.getProperty(NodeConstants.Info.ATOMIC_REQUEST))) { String modelName = metadata.getFullName(modelID); throw new QueryPlannerException(QueryPlugin.Event.TEIID30268, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30268, modelName)); } } return plan; } /** * Determine whether a command is a query without a criteria * @param command * @return */ static boolean hasNoCriteria(Command command) { if(command instanceof Query) { Query query = (Query) command; return query.getCriteria() == null; } if (command instanceof Delete) { Delete query = (Delete) command; return query.getCriteria() == null; } if (command instanceof Update) { Update query = (Update) command; return query.getCriteria() == null; } if (command instanceof SetQuery) { SetQuery query = (SetQuery)command; return hasNoCriteria(query.getLeftQuery()) || hasNoCriteria(query.getRightQuery()); } return false; } public String toString() { return "ValidateWhereAll"; //$NON-NLS-1$ } }