use of org.apache.asterix.lang.common.statement.FunctionDecl in project asterixdb by apache.
the class FunctionUtil method retrieveUsedStoredFunctions.
/**
* Retrieve stored functions (from CREATE FUNCTION statements) that have been used in an expression.
*
* @param metadataProvider,
* the metadata provider
* @param expression,
* the expression for analysis
* @param declaredFunctions,
* a set of declared functions in the query, which can potentially override stored functions.
* @param functionCollector,
* for collecting function calls in the <code>expression</code>
* @param functionParser,
* for parsing stored functions in the string represetnation.
* @param functionNormalizer,
* for normalizing function names.
* @throws CompilationException
*/
public static List<FunctionDecl> retrieveUsedStoredFunctions(MetadataProvider metadataProvider, Expression expression, List<FunctionSignature> declaredFunctions, List<FunctionDecl> inputFunctionDecls, IFunctionCollector functionCollector, IFunctionParser functionParser, IFunctionNormalizer functionNormalizer) throws CompilationException {
List<FunctionDecl> functionDecls = inputFunctionDecls == null ? new ArrayList<>() : new ArrayList<>(inputFunctionDecls);
if (expression == null) {
return functionDecls;
}
String value = metadataProvider.getConfig().get(FunctionUtil.IMPORT_PRIVATE_FUNCTIONS);
boolean includePrivateFunctions = (value != null) ? Boolean.valueOf(value.toLowerCase()) : false;
Set<FunctionSignature> functionCalls = functionCollector.getFunctionCalls(expression);
for (FunctionSignature signature : functionCalls) {
if (declaredFunctions != null && declaredFunctions.contains(signature)) {
continue;
}
if (signature.getNamespace() == null) {
signature.setNamespace(metadataProvider.getDefaultDataverseName());
}
String namespace = signature.getNamespace();
// Checks the existence of the referred dataverse.
if (metadataProvider.findDataverse(namespace) == null && !namespace.equals(FunctionConstants.ASTERIX_NS)) {
throw new CompilationException("In function call \"" + namespace + "." + signature.getName() + "(...)\", the dataverse \"" + namespace + "\" cannot be found!");
}
Function function = lookupUserDefinedFunctionDecl(metadataProvider.getMetadataTxnContext(), signature);
if (function == null) {
FunctionSignature normalizedSignature = functionNormalizer == null ? signature : functionNormalizer.normalizeBuiltinFunctionSignature(signature);
if (BuiltinFunctions.isBuiltinCompilerFunction(normalizedSignature, includePrivateFunctions)) {
continue;
}
StringBuilder messageBuilder = new StringBuilder();
if (!functionDecls.isEmpty()) {
messageBuilder.append("function " + functionDecls.get(functionDecls.size() - 1).getSignature() + " depends upon function " + signature + " which is undefined");
} else {
messageBuilder.append("function " + signature + " is not defined");
}
throw new CompilationException(messageBuilder.toString());
}
if (function.getLanguage().equalsIgnoreCase(Function.LANGUAGE_AQL)) {
FunctionDecl functionDecl = functionParser.getFunctionDecl(function);
if (functionDecl != null) {
if (functionDecls.contains(functionDecl)) {
throw new CompilationException("Recursive invocation " + functionDecls.get(functionDecls.size() - 1).getSignature() + " <==> " + functionDecl.getSignature());
}
functionDecls.add(functionDecl);
functionDecls = retrieveUsedStoredFunctions(metadataProvider, functionDecl.getFuncBody(), declaredFunctions, functionDecls, functionCollector, functionParser, functionNormalizer);
}
}
}
return functionDecls;
}
use of org.apache.asterix.lang.common.statement.FunctionDecl in project asterixdb by apache.
the class AqlQueryRewriter method inlineDeclaredUdfs.
private void inlineDeclaredUdfs() throws CompilationException {
if (topStatement == null) {
return;
}
List<FunctionSignature> funIds = new ArrayList<FunctionSignature>();
for (FunctionDecl fdecl : declaredFunctions) {
funIds.add(fdecl.getSignature());
}
List<FunctionDecl> storedFunctionDecls = new ArrayList<>();
for (Expression topLevelExpr : topStatement.getDirectlyEnclosedExpressions()) {
storedFunctionDecls.addAll(FunctionUtil.retrieveUsedStoredFunctions(metadataProvider, topLevelExpr, funIds, null, expr -> getFunctionCalls(expr), func -> functionParser.getFunctionDecl(func), signature -> CommonFunctionMapUtil.normalizeBuiltinFunctionSignature(signature)));
declaredFunctions.addAll(storedFunctionDecls);
}
if (!declaredFunctions.isEmpty()) {
AQLInlineUdfsVisitor visitor = new AQLInlineUdfsVisitor(context, new AQLRewriterFactory(), declaredFunctions, metadataProvider);
while (topStatement.accept(visitor, declaredFunctions)) {
// loop until no more changes
}
}
declaredFunctions.removeAll(storedFunctionDecls);
}
use of org.apache.asterix.lang.common.statement.FunctionDecl in project asterixdb by apache.
the class ParserTestExecutor method testSQLPPParser.
// Tests the SQL++ parser.
public void testSQLPPParser(File queryFile, File actualResultFile, File expectedFile) throws Exception {
actualResultFile.getParentFile().mkdirs();
PrintWriter writer = new PrintWriter(new FileOutputStream(actualResultFile));
IParser parser = sqlppParserFactory.createParser(readTestFile(queryFile));
GlobalConfig.ASTERIX_LOGGER.info(queryFile.toString());
try {
List<Statement> statements = parser.parse();
List<FunctionDecl> functions = getDeclaredFunctions(statements);
String dvName = getDefaultDataverse(statements);
MetadataProvider metadataProvider = mock(MetadataProvider.class);
@SuppressWarnings("unchecked") Map<String, String> config = mock(Map.class);
when(metadataProvider.getDefaultDataverseName()).thenReturn(dvName);
when(metadataProvider.getConfig()).thenReturn(config);
when(config.get(FunctionUtil.IMPORT_PRIVATE_FUNCTIONS)).thenReturn("true");
when(metadataProvider.findDataset(anyString(), anyString())).thenReturn(mock(Dataset.class));
for (Statement st : statements) {
if (st.getKind() == Statement.Kind.QUERY) {
Query query = (Query) st;
IQueryRewriter rewriter = sqlppRewriterFactory.createQueryRewriter();
rewrite(rewriter, functions, query, metadataProvider, new LangRewritingContext(query.getVarCounter()));
// Tests deep copy and deep equality.
Query copiedQuery = (Query) SqlppRewriteUtil.deepCopy(query);
Assert.assertEquals(query.hashCode(), copiedQuery.hashCode());
Assert.assertEquals(query, copiedQuery);
}
SqlppAstPrintUtil.print(st, writer);
}
writer.close();
// Compares the actual result and the expected result.
runScriptAndCompareWithResult(queryFile, new PrintWriter(System.err), expectedFile, actualResultFile, ComparisonEnum.TEXT);
} catch (Exception e) {
GlobalConfig.ASTERIX_LOGGER.warning("Failed while testing file " + queryFile);
throw e;
} finally {
writer.close();
}
}
Aggregations