Search in sources :

Example 1 with StoredProcedureInfo

use of org.teiid.query.metadata.StoredProcedureInfo in project teiid by teiid.

the class ExecResolver method findCommandMetadata.

/**
 * @see org.teiid.query.resolver.CommandResolver#findCommandMetadata(org.teiid.query.sql.lang.Command,
 * org.teiid.query.metadata.QueryMetadataInterface)
 */
private void findCommandMetadata(Command command, TempMetadataStore discoveredMetadata, QueryMetadataInterface metadata) throws QueryMetadataException, QueryResolverException, TeiidComponentException {
    StoredProcedure storedProcedureCommand = (StoredProcedure) command;
    StoredProcedureInfo storedProcedureInfo = null;
    try {
        storedProcedureInfo = metadata.getStoredProcedureInfoForProcedure(storedProcedureCommand.getProcedureName());
    } catch (QueryMetadataException e) {
        // $NON-NLS-1$
        String[] parts = storedProcedureCommand.getProcedureName().split("\\.", 2);
        if (parts.length > 1 && parts[0].equalsIgnoreCase(metadata.getVirtualDatabaseName())) {
            try {
                storedProcedureInfo = metadata.getStoredProcedureInfoForProcedure(parts[1]);
                storedProcedureCommand.setProcedureName(parts[1]);
            } catch (QueryMetadataException e1) {
            }
        }
        if (storedProcedureInfo == null) {
            throw e;
        }
    }
    storedProcedureCommand.setUpdateCount(storedProcedureInfo.getUpdateCount());
    storedProcedureCommand.setModelID(storedProcedureInfo.getModelID());
    storedProcedureCommand.setProcedureID(storedProcedureInfo.getProcedureID());
    storedProcedureCommand.setProcedureCallableName(storedProcedureInfo.getProcedureCallableName());
    // Get old parameters as they may have expressions set on them - collect
    // those expressions to copy later into the resolved parameters
    Collection<SPParameter> oldParams = storedProcedureCommand.getParameters();
    boolean namedParameters = storedProcedureCommand.displayNamedParameters();
    // of relying on all default values of all optional parameters.
    if (oldParams.size() == 0 || (oldParams.size() == 1 && storedProcedureCommand.isCalledWithReturn())) {
        storedProcedureCommand.setDisplayNamedParameters(true);
        namedParameters = true;
    }
    // Cache original input parameter expressions.  Depending on whether
    // the procedure was parsed with named or unnamed parameters, the keys
    // for this map will either be the String names of the parameters or
    // the Integer indices, as entered in the user query
    Map<Integer, Expression> positionalExpressions = new TreeMap<Integer, Expression>();
    Map<String, Expression> namedExpressions = new TreeMap<String, Expression>(String.CASE_INSENSITIVE_ORDER);
    int adjustIndex = 0;
    for (SPParameter param : oldParams) {
        if (param.getExpression() == null) {
            if (param.getParameterType() == SPParameter.RESULT_SET) {
                // If this was already resolved, just pretend the result set param doesn't exist
                adjustIndex--;
            }
            continue;
        }
        if (namedParameters && param.getParameterType() != SPParameter.RETURN_VALUE) {
            if (namedExpressions.put(param.getParameterSymbol().getShortName(), param.getExpression()) != null) {
                throw new QueryResolverException(QueryPlugin.Event.TEIID30138, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30138, param.getName()));
            }
        } else {
            positionalExpressions.put(param.getIndex() + adjustIndex, param.getExpression());
        }
    }
    storedProcedureCommand.clearParameters();
    int origInputs = positionalExpressions.size() + namedExpressions.size();
    /*
         * Take the values set from the stored procedure implementation, and match up with the
         * types of parameter it is from the metadata and then reset the newly joined parameters
         * into the stored procedure command.  If it is a result set get those columns and place
         * them into the stored procedure command as well.
         */
    List<SPParameter> metadataParams = storedProcedureInfo.getParameters();
    List<SPParameter> clonedMetadataParams = new ArrayList<SPParameter>(metadataParams.size());
    int inputParams = 0;
    int optionalParams = 0;
    int outParams = 0;
    boolean hasReturnValue = false;
    boolean optional = false;
    boolean varargs = false;
    for (int i = 0; i < metadataParams.size(); i++) {
        SPParameter metadataParameter = metadataParams.get(i);
        if ((metadataParameter.getParameterType() == ParameterInfo.IN) || (metadataParameter.getParameterType() == ParameterInfo.INOUT)) {
            if (ResolverUtil.hasDefault(metadataParameter.getMetadataID(), metadata) || metadataParameter.isVarArg()) {
                optional = true;
                optionalParams++;
            } else {
                inputParams++;
                if (optional) {
                    optional = false;
                    inputParams += optionalParams;
                    optionalParams = 0;
                }
            }
            if (metadataParameter.isVarArg()) {
                varargs = true;
            }
        } else if (metadataParameter.getParameterType() == ParameterInfo.OUT) {
            outParams++;
        /*
            	 * TODO: it would consistent to do the following, but it is a breaking change for procedures that have intermixed out params with in.
            	 * we may need to revisit this later
            	 */
        // optional = true;
        // optionalParams++;
        } else if (metadataParameter.getParameterType() == ParameterInfo.RETURN_VALUE) {
            hasReturnValue = true;
        }
        SPParameter clonedParam = (SPParameter) metadataParameter.clone();
        clonedMetadataParams.add(clonedParam);
        storedProcedureCommand.setParameter(clonedParam);
    }
    if (storedProcedureCommand.isCalledWithReturn() && !hasReturnValue) {
        throw new QueryResolverException(QueryPlugin.Event.TEIID30139, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30139, storedProcedureCommand.getGroup()));
    }
    if (!namedParameters && (inputParams > positionalExpressions.size())) {
        // $NON-NLS-1$ //$NON-NLS-2$
        throw new QueryResolverException(QueryPlugin.Event.TEIID30140, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30140, inputParams, inputParams + optionalParams + (varargs ? "+" : ""), origInputs, storedProcedureCommand.getGroup()));
    }
    // Walk through the resolved parameters and set the expressions from the
    // input parameters
    int exprIndex = 1;
    HashSet<String> expected = new HashSet<String>();
    if (storedProcedureCommand.isCalledWithReturn() && hasReturnValue) {
        for (SPParameter param : clonedMetadataParams) {
            if (param.getParameterType() == SPParameter.RETURN_VALUE) {
                Expression expr = positionalExpressions.remove(exprIndex++);
                param.setExpression(expr);
                break;
            }
        }
    }
    for (SPParameter param : clonedMetadataParams) {
        if (param.getParameterType() == SPParameter.RESULT_SET || param.getParameterType() == SPParameter.RETURN_VALUE) {
            continue;
        }
        if (namedParameters) {
            String nameKey = param.getParameterSymbol().getShortName();
            Expression expr = namedExpressions.remove(nameKey);
            // With named parameters, have to check on optional params and default values
            if (expr == null) {
                if (param.getParameterType() != ParameterInfo.OUT) {
                    param.setUsingDefault(true);
                    expected.add(nameKey);
                    if (!param.isVarArg()) {
                        expr = ResolverUtil.getDefault(param.getParameterSymbol(), metadata);
                    } else {
                        // zero length array
                        List<Expression> exprs = new ArrayList<Expression>(0);
                        Array array = new Array(exprs);
                        array.setImplicit(true);
                        array.setType(param.getClassType());
                        expr = array;
                    }
                }
            }
            param.setExpression(expr);
        } else {
            Expression expr = positionalExpressions.remove(exprIndex++);
            if (param.getParameterType() == SPParameter.OUT) {
                if (expr != null) {
                    boolean isRef = expr instanceof Reference;
                    if (!isRef || exprIndex <= inputParams + 1) {
                        // for backwards compatibility, this should be treated instead as an input
                        exprIndex--;
                        positionalExpressions.put(exprIndex, expr);
                    } else if (isRef) {
                        // mimics the hack that was in PreparedStatementRequest.
                        Reference ref = (Reference) expr;
                        // may be an out
                        ref.setOptional(true);
                    /*
	                		 * Note that there is a corner case here with out parameters intermixed with optional parameters
	                		 * there's not a good way around this.
	                		 */
                    }
                }
                continue;
            }
            if (expr == null) {
                if (!param.isVarArg()) {
                    expr = ResolverUtil.getDefault(param.getParameterSymbol(), metadata);
                }
                param.setUsingDefault(true);
            }
            if (param.isVarArg()) {
                List<Expression> exprs = new ArrayList<Expression>(positionalExpressions.size() + 1);
                if (expr != null) {
                    exprs.add(expr);
                }
                exprs.addAll(positionalExpressions.values());
                positionalExpressions.clear();
                Array array = new Array(exprs);
                array.setImplicit(true);
                array.setType(param.getClassType());
                expr = array;
            }
            param.setExpression(expr);
        }
    }
    // Check for leftovers, i.e. params entered by user w/ wrong/unknown names
    if (!namedExpressions.isEmpty()) {
        throw new QueryResolverException(QueryPlugin.Event.TEIID30141, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30141, namedExpressions.keySet(), expected));
    }
    if (!positionalExpressions.isEmpty()) {
        throw new QueryResolverException(QueryPlugin.Event.TEIID31113, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31113, positionalExpressions.size(), origInputs, storedProcedureCommand.getGroup().toString()));
    }
    // Create temporary metadata that defines a group based on either the stored proc
    // name or the stored query name - this will be used later during planning
    String procName = storedProcedureCommand.getProcedureName();
    List tempElements = storedProcedureCommand.getProjectedSymbols();
    boolean isVirtual = storedProcedureInfo.getQueryPlan() != null;
    discoveredMetadata.addTempGroup(procName, tempElements, isVirtual);
    // Resolve tempElements against new metadata
    GroupSymbol procGroup = new GroupSymbol(storedProcedureInfo.getProcedureCallableName());
    procGroup.setProcedure(true);
    TempMetadataID tid = discoveredMetadata.getTempGroupID(procName);
    tid.setOriginalMetadataID(storedProcedureCommand.getProcedureID());
    procGroup.setMetadataID(tid);
    storedProcedureCommand.setGroup(procGroup);
}
Also used : SPParameter(org.teiid.query.sql.lang.SPParameter) Reference(org.teiid.query.sql.symbol.Reference) ArrayList(java.util.ArrayList) TempMetadataID(org.teiid.query.metadata.TempMetadataID) QueryMetadataException(org.teiid.api.exception.query.QueryMetadataException) TreeMap(java.util.TreeMap) QueryResolverException(org.teiid.api.exception.query.QueryResolverException) StoredProcedureInfo(org.teiid.query.metadata.StoredProcedureInfo) Array(org.teiid.query.sql.symbol.Array) StoredProcedure(org.teiid.query.sql.lang.StoredProcedure) Expression(org.teiid.query.sql.symbol.Expression) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet)

Example 2 with StoredProcedureInfo

use of org.teiid.query.metadata.StoredProcedureInfo in project teiid by teiid.

the class ExecResolver method getPlan.

/**
 * @throws QueryResolverException
 * @see org.teiid.query.resolver.ProcedureContainerResolver#getPlan(org.teiid.query.metadata.QueryMetadataInterface, org.teiid.query.sql.symbol.GroupSymbol)
 */
protected String getPlan(QueryMetadataInterface metadata, GroupSymbol group) throws TeiidComponentException, QueryMetadataException, QueryResolverException {
    StoredProcedureInfo storedProcedureInfo = metadata.getStoredProcedureInfoForProcedure(group.getName());
    // if there is a query plan associated with the procedure, get it.
    QueryNode plan = storedProcedureInfo.getQueryPlan();
    if (plan.getQuery() == null) {
        throw new QueryResolverException(QueryPlugin.Event.TEIID30146, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30146, group));
    }
    return plan.getQuery();
}
Also used : StoredProcedureInfo(org.teiid.query.metadata.StoredProcedureInfo) QueryNode(org.teiid.query.mapping.relational.QueryNode) QueryResolverException(org.teiid.api.exception.query.QueryResolverException)

Example 3 with StoredProcedureInfo

use of org.teiid.query.metadata.StoredProcedureInfo in project teiid by teiid.

the class ResolverUtil method resolveGroup.

public static void resolveGroup(GroupSymbol symbol, QueryMetadataInterface metadata) throws TeiidComponentException, QueryResolverException {
    if (symbol.getMetadataID() != null) {
        return;
    }
    // determine the "metadataID" part of the symbol to look up
    String potentialID = symbol.getNonCorrelationName();
    String name = symbol.getName();
    String definition = symbol.getDefinition();
    Object groupID = null;
    try {
        // get valid GroupID for possibleID - this may throw exceptions if group is invalid
        groupID = metadata.getGroupID(potentialID);
    } catch (QueryMetadataException e) {
    // didn't find this group ID
    }
    // If that didn't work, try to strip a vdb name from potentialID
    if (groupID == null) {
        // $NON-NLS-1$
        String[] parts = potentialID.split("\\.", 2);
        if (parts.length > 1 && parts[0].equalsIgnoreCase(metadata.getVirtualDatabaseName())) {
            try {
                groupID = metadata.getGroupID(parts[1]);
            } catch (QueryMetadataException e) {
            // ignore - just didn't find it
            }
            if (groupID != null) {
                potentialID = parts[1];
            }
        }
    }
    // and there is only one group that matches the given partial name
    if (groupID == null) {
        Collection groupNames = null;
        try {
            groupNames = metadata.getGroupsForPartialName(potentialID);
        } catch (QueryMetadataException e) {
        // ignore - just didn't find it
        }
        if (groupNames != null) {
            int matches = groupNames.size();
            if (matches == 1) {
                potentialID = (String) groupNames.iterator().next();
                try {
                    // get valid GroupID for possibleID - this may throw exceptions if group is invalid
                    groupID = metadata.getGroupID(potentialID);
                } catch (QueryMetadataException e) {
                // didn't find this group ID
                }
            } else if (matches > 1) {
                // $NON-NLS-1$
                throw handleUnresolvedGroup(symbol, QueryPlugin.Util.getString("ERR.015.008.0055"));
            }
        }
    }
    if (groupID == null || metadata.isProcedure(groupID)) {
        // try procedure relational resolving
        try {
            StoredProcedureInfo storedProcedureInfo = metadata.getStoredProcedureInfoForProcedure(potentialID);
            symbol.setProcedure(true);
            groupID = storedProcedureInfo.getProcedureID();
        } catch (QueryMetadataException e) {
        // just ignore
        }
    }
    if (groupID == null) {
        // $NON-NLS-1$
        throw handleUnresolvedGroup(symbol, QueryPlugin.Util.getString("ERR.015.008.0056"));
    }
    // set real metadata ID in the symbol
    symbol.setMetadataID(groupID);
    potentialID = metadata.getFullName(groupID);
    if (symbol.getDefinition() == null) {
        symbol.setName(potentialID);
    } else {
        symbol.setDefinition(potentialID);
    }
    try {
        if (!symbol.isProcedure()) {
            symbol.setIsTempTable(metadata.isTemporaryTable(groupID));
        }
    } catch (QueryMetadataException e) {
    // should not come here
    }
    if (metadata.useOutputName()) {
        symbol.setOutputDefinition(definition);
        symbol.setOutputName(name);
    }
}
Also used : StoredProcedureInfo(org.teiid.query.metadata.StoredProcedureInfo) LanguageObject(org.teiid.query.sql.LanguageObject) QueryMetadataException(org.teiid.api.exception.query.QueryMetadataException)

Example 4 with StoredProcedureInfo

use of org.teiid.query.metadata.StoredProcedureInfo in project teiid by teiid.

the class ProcedureContainerResolver method findChildCommandMetadata.

/**
 * Set the appropriate "external" metadata for the given command
 * @param inferProcedureResultSetColumns
 * @throws QueryResolverException
 */
public static void findChildCommandMetadata(Command currentCommand, GroupSymbol container, int type, QueryMetadataInterface metadata, boolean inferProcedureResultSetColumns) throws QueryMetadataException, TeiidComponentException, QueryResolverException {
    // find the childMetadata using a clean metadata store
    TempMetadataStore childMetadata = new TempMetadataStore();
    TempMetadataAdapter tma = new TempMetadataAdapter(metadata, childMetadata);
    GroupContext externalGroups = new GroupContext();
    if (currentCommand instanceof TriggerAction) {
        TriggerAction ta = (TriggerAction) currentCommand;
        ta.setView(container);
        // TODO: it seems easier to just inline the handling here rather than have each of the resolvers check for trigger actions
        List<ElementSymbol> viewElements = ResolverUtil.resolveElementsInGroup(ta.getView(), metadata);
        if (type == Command.TYPE_UPDATE || type == Command.TYPE_INSERT) {
            ProcedureContainerResolver.addChanging(tma.getMetadataStore(), externalGroups, viewElements);
            ProcedureContainerResolver.addScalarGroup(SQLConstants.Reserved.NEW, tma.getMetadataStore(), externalGroups, viewElements, false);
            if (type == Command.TYPE_INSERT) {
                List<ElementSymbol> key = InsertResolver.getAutoIncrementKey(ta.getView().getMetadataID(), viewElements, metadata);
                if (key != null) {
                    ProcedureContainerResolver.addScalarGroup(SQLConstants.NonReserved.KEY, tma.getMetadataStore(), externalGroups, key, true);
                }
            }
        }
        if (type == Command.TYPE_UPDATE || type == Command.TYPE_DELETE) {
            ProcedureContainerResolver.addScalarGroup(SQLConstants.Reserved.OLD, tma.getMetadataStore(), externalGroups, viewElements, false);
        }
    } else if (currentCommand instanceof CreateProcedureCommand) {
        CreateProcedureCommand cupc = (CreateProcedureCommand) currentCommand;
        cupc.setVirtualGroup(container);
        if (type == Command.TYPE_STORED_PROCEDURE) {
            StoredProcedureInfo info = metadata.getStoredProcedureInfoForProcedure(container.getName());
            // Create temporary metadata that defines a group based on either the stored proc
            // name or the stored query name - this will be used later during planning
            String procName = info.getProcedureCallableName();
            // Look through parameters to find input elements - these become child metadata
            List<ElementSymbol> tempElements = new ArrayList<ElementSymbol>(info.getParameters().size());
            boolean[] updatable = new boolean[info.getParameters().size()];
            int i = 0;
            List<ElementSymbol> rsColumns = Collections.emptyList();
            for (SPParameter param : info.getParameters()) {
                if (param.getParameterType() != ParameterInfo.RESULT_SET) {
                    ElementSymbol symbol = param.getParameterSymbol();
                    tempElements.add(symbol);
                    updatable[i++] = param.getParameterType() != ParameterInfo.IN;
                    if (param.getParameterType() == ParameterInfo.RETURN_VALUE) {
                        cupc.setReturnVariable(symbol);
                    }
                } else {
                    rsColumns = param.getResultSetColumns();
                }
            }
            if (inferProcedureResultSetColumns) {
                rsColumns = null;
            }
            GroupSymbol gs = ProcedureContainerResolver.addScalarGroup(procName, childMetadata, externalGroups, tempElements, updatable);
            if (cupc.getReturnVariable() != null) {
                ResolverVisitor.resolveLanguageObject(cupc.getReturnVariable(), Arrays.asList(gs), metadata);
            }
            cupc.setResultSetColumns(rsColumns);
            // the relational planner will override this with the appropriate value
            cupc.setProjectedSymbols(rsColumns);
        } else {
            cupc.setUpdateType(type);
        }
    }
    QueryResolver.setChildMetadata(currentCommand, childMetadata, externalGroups);
}
Also used : TempMetadataAdapter(org.teiid.query.metadata.TempMetadataAdapter) ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) TriggerAction(org.teiid.query.sql.proc.TriggerAction) CreateProcedureCommand(org.teiid.query.sql.proc.CreateProcedureCommand) SPParameter(org.teiid.query.sql.lang.SPParameter) StoredProcedureInfo(org.teiid.query.metadata.StoredProcedureInfo) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) ArrayList(java.util.ArrayList) List(java.util.List) TempMetadataStore(org.teiid.query.metadata.TempMetadataStore) GroupContext(org.teiid.query.sql.lang.GroupContext)

Example 5 with StoredProcedureInfo

use of org.teiid.query.metadata.StoredProcedureInfo in project teiid by teiid.

the class ValidationVisitor method visit.

@Override
public void visit(AlterProcedure obj) {
    GroupSymbol gs = obj.getTarget();
    validateAlterTarget(obj);
    try {
        if (!gs.isProcedure() || !getMetadata().isVirtualModel(getMetadata().getModelID(gs.getMetadataID()))) {
            // $NON-NLS-1$
            handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.not_a_procedure", gs), gs);
            return;
        }
        Validator.validate(obj.getDefinition(), getMetadata(), this);
        StoredProcedureInfo info = getMetadata().getStoredProcedureInfoForProcedure(gs.getName());
        for (SPParameter param : info.getParameters()) {
            if (param.getParameterType() == SPParameter.RESULT_SET) {
                QueryResolver.validateProjectedSymbols(gs, param.getResultSetColumns(), obj.getDefinition().getProjectedSymbols());
                break;
            }
        }
    } catch (QueryValidatorException e) {
        handleValidationError(e.getMessage(), obj.getDefinition().getBlock());
    } catch (TeiidComponentException e) {
        handleException(e);
    }
}
Also used : StoredProcedureInfo(org.teiid.query.metadata.StoredProcedureInfo) QueryValidatorException(org.teiid.api.exception.query.QueryValidatorException) TeiidComponentException(org.teiid.core.TeiidComponentException)

Aggregations

StoredProcedureInfo (org.teiid.query.metadata.StoredProcedureInfo)6 ArrayList (java.util.ArrayList)2 List (java.util.List)2 QueryMetadataException (org.teiid.api.exception.query.QueryMetadataException)2 QueryResolverException (org.teiid.api.exception.query.QueryResolverException)2 SPParameter (org.teiid.query.sql.lang.SPParameter)2 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)2 HashSet (java.util.HashSet)1 TreeMap (java.util.TreeMap)1 QueryValidatorException (org.teiid.api.exception.query.QueryValidatorException)1 TeiidComponentException (org.teiid.core.TeiidComponentException)1 QueryNode (org.teiid.query.mapping.relational.QueryNode)1 TempMetadataAdapter (org.teiid.query.metadata.TempMetadataAdapter)1 TempMetadataID (org.teiid.query.metadata.TempMetadataID)1 TempMetadataStore (org.teiid.query.metadata.TempMetadataStore)1 LanguageObject (org.teiid.query.sql.LanguageObject)1 GroupContext (org.teiid.query.sql.lang.GroupContext)1 StoredProcedure (org.teiid.query.sql.lang.StoredProcedure)1 CreateProcedureCommand (org.teiid.query.sql.proc.CreateProcedureCommand)1 TriggerAction (org.teiid.query.sql.proc.TriggerAction)1