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);
}
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)));
}
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);
}
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);
}
}
}
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);
}
}
Aggregations