Search in sources :

Example 6 with Expression

use of org.teiid.query.sql.symbol.Expression in project teiid by teiid.

the class TestResolvedFunctions method getFunctionResult.

private Object getFunctionResult(String sql) throws QueryParserException, ExpressionEvaluationException, BlockedException, TeiidComponentException, QueryResolverException {
    Expression expr = QueryParser.getQueryParser().parseExpression(sql);
    ResolverVisitor.resolveLanguageObject(expr, RealMetadataFactory.example1Cached());
    return Evaluator.evaluate(expr);
}
Also used : Expression(org.teiid.query.sql.symbol.Expression)

Example 7 with Expression

use of org.teiid.query.sql.symbol.Expression in project teiid by teiid.

the class TestJoinWithFunction method testDeterministicPrePostJoin.

/**
 * <p>Test the use of a deterministic function on the sub-command of a user
 * command and the user command itself, which performs a JOIN of two sources.</p>
 *
 * <p>This test combines the PostJoin and PreJoin test cases.</p>
 * @throws TeiidComponentException
 * @throws QueryValidatorException
 * @throws QueryResolverException
 * @throws QueryParserException
 * @see #testDeterministicPostJoin
 * @see #testDeterministicPreJoin
 */
public void testDeterministicPrePostJoin() throws Exception {
    // sub-query for one side of a JOIN
    String leftQuery = // $NON-NLS-1$
    "SELECT pm1.g1.e1 as ID, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4, SQRT(100) AS SqrtLeft " + // $NON-NLS-1$
    "FROM pm1.g1";
    // sub-query for other side of a JOIN
    String rightQuery = // $NON-NLS-1$
    "SELECT pm2.g2.e1 as ID, pm2.g2.e2, pm2.g2.e3, pm2.g2.e4 " + // $NON-NLS-1$
    "FROM pm2.g2";
    // User Command
    /*
		 * Return everything from the JOIN. SqrtTop is the use of SQRT(100) on
		 * the user command while SqrtLeft is the use of SQRT() within a
		 * source node.
		 */
    String sql = // $NON-NLS-1$
    "SELECT l.ID, l.e2, l.e3, l.e4, r.ID, r.e2, r.e3, r.e4, l.SqrtLeft, SQRT(100) AS SqrtTop " + "FROM (" + leftQuery + // $NON-NLS-1$ //$NON-NLS-2$
    ") AS l, " + "(" + rightQuery + // $NON-NLS-1$ //$NON-NLS-2$
    ") AS r " + // $NON-NLS-1$
    "WHERE l.ID = r.ID";
    // The user command should result in two atomic commands
    String[] expected = new String[] { // $NON-NLS-1$
    "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm1.g1 AS g_0 ORDER BY c_0", // $NON-NLS-1$
    "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm2.g2 AS g_0 ORDER BY c_0" };
    // create a plan and assert our atomic queries
    ProcessorPlan plan = TestOptimizer.helpPlan(sql, TestOptimizer.example1(), expected, ComparisonMode.EXACT_COMMAND_STRING);
    TestOptimizer.checkNodeTypes(plan, new int[] { // Access
    2, // DependentAccess
    0, // DependentSelect
    0, // DependentProject
    0, // DupRemove
    0, // Grouping
    0, // NestedLoopJoinStrategy
    0, // MergeJoinStrategy
    1, // Null
    0, // PlanExecution
    0, // Project
    1, // Select
    0, // Sort
    0, // UnionAll
    0 });
    /*
		 * Retrieve root nodes elements to assert that a constant has 
		 * replaced the SQRT() function for both SqrtTop and SqrtLeft. 
		 */
    List<?> elem = ((RelationalPlan) plan).getRootNode().getElements();
    Constant expectedConst = new Constant(new Double(10.0));
    assertEquals(// $NON-NLS-1$
    "Did not get expected constant value for SqrtLeft in root node of plan: ", expectedConst, // should be a AliasSymbol containing an expression
    SymbolMap.getExpression((Expression) elem.get(8)));
    assertEquals(// $NON-NLS-1$
    "Did not get expected constant value for SqrtTop in root node of plan: ", expectedConst, // should be a AliasSymbol containing an expression
    SymbolMap.getExpression((Expression) elem.get(9)));
}
Also used : Expression(org.teiid.query.sql.symbol.Expression) Constant(org.teiid.query.sql.symbol.Constant) ProcessorPlan(org.teiid.query.processor.ProcessorPlan)

Example 8 with Expression

use of org.teiid.query.sql.symbol.Expression 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 9 with Expression

use of org.teiid.query.sql.symbol.Expression in project teiid by teiid.

the class ExecResolver method resolveProceduralCommand.

/**
 * @see org.teiid.query.resolver.ProcedureContainerResolver#resolveProceduralCommand(org.teiid.query.sql.lang.Command, org.teiid.query.metadata.TempMetadataAdapter)
 */
public void resolveProceduralCommand(Command command, TempMetadataAdapter metadata) throws QueryMetadataException, QueryResolverException, TeiidComponentException {
    findCommandMetadata(command, metadata.getMetadataStore(), metadata);
    // Resolve expressions on input parameters
    StoredProcedure storedProcedureCommand = (StoredProcedure) command;
    GroupContext externalGroups = storedProcedureCommand.getExternalGroupContexts();
    for (SPParameter param : storedProcedureCommand.getParameters()) {
        Expression expr = param.getExpression();
        if (expr == null) {
            continue;
        }
        for (SubqueryContainer<?> container : ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(expr)) {
            QueryResolver.setChildMetadata(container.getCommand(), command);
            QueryResolver.resolveCommand(container.getCommand(), metadata.getMetadata());
        }
        try {
            ResolverVisitor.resolveLanguageObject(expr, null, externalGroups, metadata);
        } catch (QueryResolverException e) {
            if (!checkForArray(param, expr)) {
                throw e;
            }
            continue;
        }
        Class<?> paramType = param.getClassType();
        ResolverUtil.setDesiredType(expr, paramType, storedProcedureCommand);
        // Compare type of parameter expression against parameter type
        // and add implicit conversion if necessary
        Class<?> exprType = expr.getType();
        if (paramType == null || exprType == null) {
            throw new QueryResolverException(QueryPlugin.Event.TEIID30143, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30143, storedProcedureCommand.getProcedureName(), param.getName()));
        }
        String tgtType = DataTypeManager.getDataTypeName(paramType);
        String srcType = DataTypeManager.getDataTypeName(exprType);
        Expression result = null;
        if (param.getParameterType() == SPParameter.RETURN_VALUE || param.getParameterType() == SPParameter.OUT) {
            if (!ResolverUtil.canImplicitlyConvert(tgtType, srcType)) {
                throw new QueryResolverException(QueryPlugin.Event.TEIID30144, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30144, param.getParameterSymbol(), tgtType, srcType));
            }
        } else {
            try {
                result = ResolverUtil.convertExpression(expr, tgtType, metadata);
            } catch (QueryResolverException e) {
                throw new QueryResolverException(QueryPlugin.Event.TEIID30145, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30145, new Object[] { param.getParameterSymbol(), srcType, tgtType }));
            }
            param.setExpression(result);
        }
    }
}
Also used : StoredProcedure(org.teiid.query.sql.lang.StoredProcedure) Expression(org.teiid.query.sql.symbol.Expression) SPParameter(org.teiid.query.sql.lang.SPParameter) GroupContext(org.teiid.query.sql.lang.GroupContext) QueryResolverException(org.teiid.api.exception.query.QueryResolverException)

Example 10 with Expression

use of org.teiid.query.sql.symbol.Expression in project teiid by teiid.

the class InsertResolver method resolveProceduralCommand.

/**
 * Resolve an INSERT.  Need to resolve elements, constants, types, etc.
 * @see org.teiid.query.resolver.ProcedureContainerResolver#resolveProceduralCommand(org.teiid.query.sql.lang.Command, org.teiid.query.metadata.TempMetadataAdapter)
 */
public void resolveProceduralCommand(Command command, TempMetadataAdapter metadata) throws QueryMetadataException, QueryResolverException, TeiidComponentException {
    // Cast to known type
    Insert insert = (Insert) command;
    if (insert.getValues() != null) {
        QueryResolver.resolveSubqueries(command, metadata, null);
        // variables and values must be resolved separately to account for implicitly defined temp groups
        resolveList(insert.getValues(), metadata, insert.getExternalGroupContexts(), null);
    }
    boolean usingQuery = insert.getQueryExpression() != null;
    // resolve subquery if there
    if (usingQuery) {
        QueryResolver.setChildMetadata(insert.getQueryExpression(), command);
        QueryResolver.resolveCommand(insert.getQueryExpression(), metadata.getMetadata(), false);
    }
    Set<GroupSymbol> groups = new HashSet<GroupSymbol>();
    groups.add(insert.getGroup());
    // resolve any functions in the values
    List values = insert.getValues();
    if (usingQuery) {
        values = insert.getQueryExpression().getProjectedSymbols();
    }
    if (insert.getVariables().isEmpty()) {
        if (insert.getGroup().isResolved()) {
            List<ElementSymbol> variables = ResolverUtil.resolveElementsInGroup(insert.getGroup(), metadata);
            for (Iterator<ElementSymbol> i = variables.iterator(); i.hasNext(); ) {
                insert.addVariable(i.next().clone());
            }
        } else {
            for (int i = 0; i < values.size(); i++) {
                if (usingQuery) {
                    Expression ses = (Expression) values.get(i);
                    ElementSymbol es = new ElementSymbol(Symbol.getShortName(ses));
                    es.setType(ses.getType());
                    insert.addVariable(es);
                } else {
                    // $NON-NLS-1$
                    insert.addVariable(new ElementSymbol("expr" + i));
                }
            }
        }
    } else if (insert.getGroup().isResolved()) {
        resolveVariables(metadata, insert, groups);
    }
    resolveTypes(insert, metadata, values, usingQuery);
    if (usingQuery && insert.getQueryExpression() instanceof SetQuery) {
        // now that the first branch is set, we need to make sure that all branches conform
        QueryResolver.resolveCommand(insert.getQueryExpression(), metadata.getMetadata(), false);
        resolveTypes(insert, metadata, values, usingQuery);
    }
    if (!insert.getGroup().isResolved()) {
        // define the implicit temp group
        ResolverUtil.resolveImplicitTempGroup(metadata, insert.getGroup(), insert.getVariables());
        resolveVariables(metadata, insert, groups);
        // ensure that the types match
        resolveTypes(insert, metadata, values, usingQuery);
    }
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) SetQuery(org.teiid.query.sql.lang.SetQuery) Expression(org.teiid.query.sql.symbol.Expression) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) ArrayList(java.util.ArrayList) List(java.util.List) Insert(org.teiid.query.sql.lang.Insert) HashSet(java.util.HashSet)

Aggregations

Expression (org.teiid.query.sql.symbol.Expression)257 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)104 ArrayList (java.util.ArrayList)74 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)54 Test (org.junit.Test)53 PlanNode (org.teiid.query.optimizer.relational.plantree.PlanNode)50 List (java.util.List)49 Constant (org.teiid.query.sql.symbol.Constant)38 SymbolMap (org.teiid.query.sql.util.SymbolMap)37 HashMap (java.util.HashMap)22 LinkedList (java.util.LinkedList)22 Criteria (org.teiid.query.sql.lang.Criteria)22 Map (java.util.Map)21 ClobType (org.teiid.core.types.ClobType)16 CompareCriteria (org.teiid.query.sql.lang.CompareCriteria)16 HashSet (java.util.HashSet)13 LinkedHashSet (java.util.LinkedHashSet)13 AliasSymbol (org.teiid.query.sql.symbol.AliasSymbol)13 SearchedCaseExpression (org.teiid.query.sql.symbol.SearchedCaseExpression)13 OrderBy (org.teiid.query.sql.lang.OrderBy)12