Merge branch 'cheshire-cat'
Change-Id: I1f21eca41175d3b18f7fb0f639988d59a7d35434
diff --git a/asterixdb/asterix-active/src/main/java/org/apache/asterix/active/ActiveManager.java b/asterixdb/asterix-active/src/main/java/org/apache/asterix/active/ActiveManager.java
index 08e1be4..b99e4f2 100644
--- a/asterixdb/asterix-active/src/main/java/org/apache/asterix/active/ActiveManager.java
+++ b/asterixdb/asterix-active/src/main/java/org/apache/asterix/active/ActiveManager.java
@@ -140,7 +140,8 @@
IActiveRuntime runtime = runtimes.get(runtimeId);
long reqId = message.getReqId();
if (runtime == null) {
- LOGGER.warn("Request stats of a runtime that is not registered " + runtimeId);
+ LOGGER.warn("Request stats of a runtime that is not registered {}; sending failure response",
+ runtimeId);
// Send a failure message
((NodeControllerService) serviceCtx.getControllerService()).sendApplicationMessageToCC(
message.getCcId(),
@@ -150,9 +151,10 @@
return;
}
String stats = runtime.getStats();
+ LOGGER.debug("Sending stats response for {} ", runtimeId);
ActiveStatsResponse response = new ActiveStatsResponse(reqId, stats, null);
- ((NodeControllerService) serviceCtx.getControllerService()).sendApplicationMessageToCC(message.getCcId(),
- JavaSerializationUtils.serialize(response), null);
+ ((NodeControllerService) serviceCtx.getControllerService()).sendRealTimeApplicationMessageToCC(
+ message.getCcId(), JavaSerializationUtils.serialize(response), null);
} catch (Exception e) {
throw HyracksDataException.create(e);
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
index da07acb..16d5878 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
@@ -18,6 +18,7 @@
*/
package org.apache.asterix.translator;
+import static org.apache.asterix.common.api.IIdentifierMapper.Modifier.PLURAL;
import static org.apache.asterix.common.utils.IdentifierUtil.dataset;
import java.io.IOException;
@@ -209,7 +210,7 @@
List<List<String>> partitionKeys = targetDatasource.getDataset().getPrimaryKeys();
if (dataset.hasMetaPart()) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc, dataset.getDatasetName() + ": load "
- + dataset() + " is not supported on " + dataset() + "s with meta records");
+ + dataset() + " is not supported on " + dataset(PLURAL) + " with meta records");
}
LoadableDataSource lds;
@@ -433,7 +434,7 @@
if (targetDatasource.getDataset().hasMetaPart()) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc,
targetDatasource.getDataset().getDatasetName() + ": delete from " + dataset()
- + " is not supported on " + dataset() + "s with meta records");
+ + " is not supported on " + dataset(PLURAL) + " with meta records");
}
List<String> filterField = DatasetUtil.getFilterField(targetDatasource.getDataset());
@@ -464,7 +465,7 @@
if (!targetDatasource.getDataset().allow(topOp, DatasetUtil.OP_UPSERT)) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc,
targetDatasource.getDataset().getDatasetName() + ": upsert into " + dataset()
- + " is not supported on " + dataset() + "s with meta records");
+ + " is not supported on " + dataset(PLURAL) + " with meta records");
}
ProjectOperator project = (ProjectOperator) topOp;
CompiledUpsertStatement compiledUpsert = (CompiledUpsertStatement) stmt;
@@ -476,7 +477,7 @@
if (targetDatasource.getDataset().hasMetaPart()) {
if (returnExpression != null) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc,
- "Returning not allowed on " + dataset() + "s with meta records");
+ "Returning not allowed on " + dataset(PLURAL) + " with meta records");
}
List<LogicalVariable> metaAndKeysVars;
List<Mutable<ILogicalExpression>> metaAndKeysExprs;
@@ -588,7 +589,7 @@
if (targetDatasource.getDataset().hasMetaPart()) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc,
targetDatasource.getDataset().getDatasetName() + ": insert into " + dataset()
- + " is not supported on " + dataset() + "s with meta records");
+ + " is not supported on " + dataset(PLURAL) + " with meta records");
}
List<String> filterField = DatasetUtil.getFilterField(targetDatasource.getDataset());
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
index ccd38d3..0141cc5 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
@@ -185,8 +185,9 @@
}
public Pair<IReturningStatement, Integer> reWriteQuery(List<FunctionDecl> declaredFunctions,
- MetadataProvider metadataProvider, IReturningStatement q, SessionOutput output, boolean inlineUdfs,
- Collection<VarIdentifier> externalVars, IWarningCollector warningCollector) throws CompilationException {
+ MetadataProvider metadataProvider, IReturningStatement q, SessionOutput output,
+ boolean allowNonStoredUdfCalls, boolean inlineUdfs, Collection<VarIdentifier> externalVars,
+ IWarningCollector warningCollector) throws CompilationException {
if (q == null) {
return null;
}
@@ -195,8 +196,9 @@
generateExpressionTree(q);
}
IQueryRewriter rw = rewriterFactory.createQueryRewriter();
- rw.rewrite(new ArrayList<>(declaredFunctions), q, metadataProvider,
- new LangRewritingContext(q.getVarCounter(), warningCollector), inlineUdfs, externalVars);
+ LangRewritingContext rwCtx =
+ new LangRewritingContext(metadataProvider, declaredFunctions, warningCollector, q.getVarCounter());
+ rw.rewrite(rwCtx, q, allowNonStoredUdfCalls, inlineUdfs, externalVars);
return new Pair<>(q, q.getVarCounter());
}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/AbstractNCUdfServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/AbstractNCUdfServlet.java
index a234b9f..eb424af 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/AbstractNCUdfServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/AbstractNCUdfServlet.java
@@ -28,21 +28,18 @@
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
import java.util.concurrent.ConcurrentMap;
import org.apache.asterix.common.api.IApplicationContext;
import org.apache.asterix.common.api.INcApplicationContext;
-import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.exceptions.RuntimeDataException;
import org.apache.asterix.common.functions.ExternalFunctionLanguage;
import org.apache.asterix.common.metadata.DataverseName;
-import org.apache.asterix.compiler.provider.ILangCompilationProvider;
-import org.apache.asterix.lang.common.base.IParserFactory;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.api.application.INCServiceContext;
import org.apache.hyracks.api.client.IHyracksClientConnection;
import org.apache.hyracks.api.exceptions.IFormattedException;
@@ -61,7 +58,6 @@
public abstract class AbstractNCUdfServlet extends AbstractServlet {
- private final IParserFactory parserFactory;
INcApplicationContext appCtx;
INCServiceContext srvCtx;
@@ -70,80 +66,37 @@
private final int httpServerPort;
public static final String GET_UDF_DIST_ENDPOINT = "/dist";
- public static final String DATAVERSE_PARAMETER = "dataverse";
- public static final String NAME_PARAMETER = "name";
public static final String TYPE_PARAMETER = "type";
- public static final String DELETE_PARAMETER = "delete";
- public static final String IFEXISTS_PARAMETER = "ifexists";
public static final String DATA_PARAMETER = "data";
+ public static final String NAME_KEY = "name";
+ public static final String DATAVERSE_KEY = "dataverse";
- protected enum LibraryOperation {
- UPSERT,
- DELETE
- }
-
- protected final static class LibraryUploadData {
-
- final LibraryOperation op;
- final DataverseName dataverse;
- final String name;
+ protected static final class LibraryUploadData {
final ExternalFunctionLanguage type;
final boolean replaceIfExists;
final FileUpload fileUpload;
- private LibraryUploadData(LibraryOperation op, List<InterfaceHttpData> dataverse, MixedAttribute name,
- MixedAttribute type, boolean replaceIfExists, InterfaceHttpData fileUpload) throws IOException {
- this.op = op;
- List<String> dataverseParts = new ArrayList<>(dataverse.size());
- for (InterfaceHttpData attr : dataverse) {
- dataverseParts.add(((MixedAttribute) attr).getValue());
- }
- this.dataverse = DataverseName.create(dataverseParts);
- this.name = name.getValue();
+ private LibraryUploadData(MixedAttribute type, boolean replaceIfExists, InterfaceHttpData fileUpload)
+ throws IOException {
this.type = type != null ? getLanguageByTypeParameter(type.getValue()) : null;
this.replaceIfExists = replaceIfExists;
this.fileUpload = (FileUpload) fileUpload;
}
- private LibraryUploadData(LibraryOperation op, DataverseName dataverse, MixedAttribute name,
- MixedAttribute type, boolean replaceIfExists, InterfaceHttpData fileUpload) throws IOException {
- this.op = op;
- this.dataverse = dataverse;
- this.name = name.getValue();
- this.type = type != null ? getLanguageByTypeParameter(type.getValue()) : null;
- this.replaceIfExists = replaceIfExists;
- this.fileUpload = (FileUpload) fileUpload;
+ public static LibraryUploadData libraryCreationUploadData(MixedAttribute type, InterfaceHttpData fileUpload)
+ throws IOException {
+ //POST imples replaceIfExists
+ return new LibraryUploadData(type, true, fileUpload);
}
- public static LibraryUploadData libraryCreationUploadData(List<InterfaceHttpData> dataverse,
- MixedAttribute name, MixedAttribute type, InterfaceHttpData fileUpload) throws IOException {
- return new LibraryUploadData(LibraryOperation.UPSERT, dataverse, name, type, true, fileUpload);
- }
-
- public static LibraryUploadData libraryDeletionUploadData(List<InterfaceHttpData> dataverse,
- MixedAttribute name, boolean replaceIfExists) throws IOException {
- return new LibraryUploadData(LibraryOperation.DELETE, dataverse, name, null, replaceIfExists, null);
- }
-
- public static LibraryUploadData libraryCreationUploadData(DataverseName dataverse, MixedAttribute name,
- MixedAttribute type, InterfaceHttpData fileUpload) throws IOException {
- return new LibraryUploadData(LibraryOperation.UPSERT, dataverse, name, type, true, fileUpload);
- }
-
- public static LibraryUploadData libraryDeletionUploadData(DataverseName dataverse, MixedAttribute name,
- boolean replaceIfExists) throws IOException {
- return new LibraryUploadData(LibraryOperation.DELETE, dataverse, name, null, replaceIfExists, null);
- }
}
public AbstractNCUdfServlet(ConcurrentMap<String, Object> ctx, String[] paths, IApplicationContext appCtx,
- ILangCompilationProvider compilationProvider, HttpScheme httpServerProtocol, int httpServerPort) {
-
+ HttpScheme httpServerProtocol, int httpServerPort) {
super(ctx, paths);
this.plainAppCtx = appCtx;
this.httpServerProtocol = httpServerProtocol;
this.httpServerPort = httpServerPort;
- this.parserFactory = compilationProvider.getParserFactory();
}
void readFromFile(Path filePath, IServletResponse response, String contentType, OpenOption opt) throws Exception {
@@ -176,6 +129,10 @@
}
}
+ protected String getDataverseKey() {
+ return DATAVERSE_KEY;
+ }
+
URI createDownloadURI(Path file) throws Exception {
String path = paths[0].substring(0, trims[0]) + GET_UDF_DIST_ENDPOINT + '/' + file.getFileName();
String host = getHyracksClientConnection().getHost();
@@ -190,67 +147,29 @@
return hcc;
}
- protected String getDisplayFormDataverseParameter() {
- return null;
- }
-
- protected String getDataverseParameter() {
- return DATAVERSE_PARAMETER;
- }
-
private boolean isNotAttribute(InterfaceHttpData field) {
return field == null || !field.getHttpDataType().equals(InterfaceHttpData.HttpDataType.Attribute);
}
- private boolean areNotAttributes(List<InterfaceHttpData> fields) {
- return fields == null || fields.stream().map(InterfaceHttpData::getHttpDataType)
- .anyMatch(httpDataType -> !httpDataType.equals(InterfaceHttpData.HttpDataType.Attribute));
+ protected Pair<DataverseName, String> decodeDvAndLibFromLocalPath(String localPath) throws RuntimeDataException {
+ String[] pathSegments = StringUtils.split(localPath, '/');
+ if (pathSegments.length != 2) {
+ throw RuntimeDataException.create(ErrorCode.PARAMETERS_REQUIRED,
+ "The URL-encoded " + getDataverseKey() + " name and library name in the request path");
+ }
+ DataverseName dvName = DataverseName.createFromCanonicalForm(ServletUtil.decodeUriSegment(pathSegments[0]));
+ String libName = ServletUtil.decodeUriSegment(pathSegments[1]);
+ return new Pair<>(dvName, libName);
}
protected LibraryUploadData decodeMultiPartLibraryOptions(HttpPostRequestDecoder requestDecoder)
- throws IOException, CompilationException {
- List<InterfaceHttpData> dataverseAttributeParts = requestDecoder.getBodyHttpDatas(DATAVERSE_PARAMETER);
- InterfaceHttpData displayFormDataverseAttribute = null;
- if (getDisplayFormDataverseParameter() != null) {
- displayFormDataverseAttribute = requestDecoder.getBodyHttpData(getDisplayFormDataverseParameter());
- }
- if (displayFormDataverseAttribute != null && dataverseAttributeParts != null) {
- throw RuntimeDataException.create(ErrorCode.PARAMETERS_NOT_ALLOWED_AT_SAME_TIME,
- getDisplayFormDataverseParameter(), getDataverseParameter());
- }
- InterfaceHttpData nameAtrribute = requestDecoder.getBodyHttpData(NAME_PARAMETER);
+ throws IOException {
InterfaceHttpData typeAttribute = requestDecoder.getBodyHttpData(TYPE_PARAMETER);
- InterfaceHttpData deleteAttribute = requestDecoder.getBodyHttpData(DELETE_PARAMETER);
- InterfaceHttpData replaceIfExistsAttribute = requestDecoder.getBodyHttpData(IFEXISTS_PARAMETER);
- if ((isNotAttribute(displayFormDataverseAttribute)) && (areNotAttributes(dataverseAttributeParts))) {
- throw RuntimeDataException.create(ErrorCode.PARAMETERS_REQUIRED, getDataverseParameter());
- } else if (isNotAttribute(nameAtrribute)) {
- throw RuntimeDataException.create(ErrorCode.PARAMETERS_REQUIRED, NAME_PARAMETER);
- } else if ((typeAttribute == null && deleteAttribute == null)) {
- throw RuntimeDataException.create(ErrorCode.PARAMETERS_REQUIRED,
- TYPE_PARAMETER + " or " + DELETE_PARAMETER);
- } else if (typeAttribute != null && deleteAttribute != null) {
- throw RuntimeDataException.create(ErrorCode.PARAMETERS_NOT_ALLOWED_AT_SAME_TIME, TYPE_PARAMETER,
- DELETE_PARAMETER);
+ if (typeAttribute == null) {
+ throw RuntimeDataException.create(ErrorCode.PARAMETERS_REQUIRED, TYPE_PARAMETER);
}
- if (!isNotAttribute(deleteAttribute)) {
- boolean replace = false;
- if (replaceIfExistsAttribute != null) {
- replace = Boolean.TRUE.toString()
- .equalsIgnoreCase(((MixedAttribute) replaceIfExistsAttribute).getValue());
- }
- if (displayFormDataverseAttribute == null) {
- return LibraryUploadData.libraryDeletionUploadData(dataverseAttributeParts,
- (MixedAttribute) nameAtrribute, replace);
- } else {
- DataverseName dataverseName = DataverseName
- .create(parserFactory.createParser(((MixedAttribute) displayFormDataverseAttribute).getValue())
- .parseMultipartIdentifier());
- return LibraryUploadData.libraryDeletionUploadData(dataverseName, (MixedAttribute) nameAtrribute,
- replace);
- }
- } else if (!isNotAttribute(typeAttribute)) {
+ else if (!isNotAttribute(typeAttribute)) {
InterfaceHttpData libraryData = requestDecoder.getBodyHttpData(DATA_PARAMETER);
if (libraryData == null) {
throw RuntimeDataException.create(ErrorCode.PARAMETERS_REQUIRED, DATA_PARAMETER);
@@ -258,27 +177,15 @@
throw RuntimeDataException.create(ErrorCode.INVALID_REQ_PARAM_VAL, DATA_PARAMETER,
libraryData.getHttpDataType());
}
- LibraryUploadData uploadData;
- if (displayFormDataverseAttribute == null) {
- uploadData = LibraryUploadData.libraryCreationUploadData(dataverseAttributeParts,
- (MixedAttribute) nameAtrribute, (MixedAttribute) typeAttribute, libraryData);
- } else {
- DataverseName dataverseName = DataverseName
- .create(parserFactory.createParser(((MixedAttribute) displayFormDataverseAttribute).getValue())
- .parseMultipartIdentifier());
- uploadData = LibraryUploadData.libraryCreationUploadData(dataverseName, (MixedAttribute) nameAtrribute,
- (MixedAttribute) typeAttribute, libraryData);
- }
+ LibraryUploadData uploadData =
+ LibraryUploadData.libraryCreationUploadData((MixedAttribute) typeAttribute, libraryData);
if (uploadData.type == null) {
throw RuntimeDataException.create(ErrorCode.LIBRARY_EXTERNAL_FUNCTION_UNSUPPORTED_KIND,
((MixedAttribute) typeAttribute).getValue());
}
return uploadData;
} else {
- if (!typeAttribute.getHttpDataType().equals(InterfaceHttpData.HttpDataType.Attribute)) {
- throw RuntimeDataException.create(ErrorCode.PARAMETERS_REQUIRED, TYPE_PARAMETER);
- }
- throw RuntimeDataException.create(ErrorCode.PARAMETERS_REQUIRED, DELETE_PARAMETER);
+ throw RuntimeDataException.create(ErrorCode.PARAMETERS_REQUIRED, TYPE_PARAMETER);
}
}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCUdfApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCUdfApiServlet.java
index 717ebf8..fec0b38 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCUdfApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCUdfApiServlet.java
@@ -20,6 +20,7 @@
import static org.apache.asterix.api.http.server.ServletConstants.SYS_AUTH_HEADER;
import static org.apache.asterix.common.library.LibraryDescriptor.FIELD_HASH;
+import static org.apache.hyracks.api.exceptions.IFormattedException.getError;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -53,11 +54,11 @@
import org.apache.asterix.common.messaging.api.INCMessageBroker;
import org.apache.asterix.common.messaging.api.MessageFuture;
import org.apache.asterix.common.metadata.DataverseName;
-import org.apache.asterix.compiler.provider.ILangCompilationProvider;
import org.apache.asterix.external.util.ExternalLibraryUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
+import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.http.api.IServletRequest;
import org.apache.hyracks.http.api.IServletResponse;
import org.apache.hyracks.http.server.utils.HttpUtil;
@@ -77,7 +78,6 @@
public class NCUdfApiServlet extends AbstractNCUdfServlet {
- protected final ILangCompilationProvider compilationProvider;
protected final IReceptionist receptionist;
protected Path workingDir;
@@ -88,13 +88,17 @@
private static final Logger LOGGER = LogManager.getLogger();
public NCUdfApiServlet(ConcurrentMap<String, Object> ctx, String[] paths, IApplicationContext appCtx,
- ILangCompilationProvider compilationProvider, HttpScheme httpServerProtocol, int httpServerPort) {
- super(ctx, paths, appCtx, compilationProvider, httpServerProtocol, httpServerPort);
- this.compilationProvider = compilationProvider;
+ HttpScheme httpServerProtocol, int httpServerPort) {
+ super(ctx, paths, appCtx, httpServerProtocol, httpServerPort);
this.receptionist = appCtx.getReceptionist();
this.timeout = appCtx.getExternalProperties().getLibraryDeployTimeout();
}
+ private enum LibraryOperation {
+ UPSERT,
+ DELETE
+ }
+
@Override
public void init() throws IOException {
appCtx = (INcApplicationContext) plainAppCtx;
@@ -183,11 +187,8 @@
for (Map.Entry<DataverseName, Map<String, String>> dvAndLibs : dvToLibHashes.entrySet()) {
for (Map.Entry<String, String> libsInDv : dvAndLibs.getValue().entrySet()) {
Map<String, Object> libraryEntry = new HashMap<>();
- List<String> dvParts = dvAndLibs.getKey().getParts();
- String dvKey = getDisplayFormDataverseParameter() == null ? getDataverseParameter()
- : getDisplayFormDataverseParameter();
- libraryEntry.put(dvKey, dvParts.size() > 1 ? dvParts : dvAndLibs.getKey().toString());
- libraryEntry.put(NAME_PARAMETER, libsInDv.getKey());
+ libraryEntry.put(getDataverseKey(), dvAndLibs.getKey().getCanonicalForm());
+ libraryEntry.put(NAME_KEY, libsInDv.getKey());
libraryEntry.put(FIELD_HASH, libsInDv.getValue());
libraryList.add(libraryEntry);
}
@@ -217,37 +218,29 @@
response.setStatus(HttpResponseStatus.NOT_FOUND);
}
} catch (Exception e) {
- response.setStatus(toHttpErrorStatus(e));
- PrintWriter responseWriter = response.writer();
- Map<String, String> error = Collections.singletonMap("error", e.getMessage());
- String errorJson = "";
- try {
- errorJson = OBJECT_MAPPER.writeValueAsString(error);
- } catch (JsonProcessingException ex) {
- responseWriter.write("{ \"error\": \"Unable to process error message!\" }");
- }
- responseWriter.write(errorJson);
- responseWriter.flush();
+ writeException(e, response);
LOGGER.error("Error reading library", e);
}
}
- @Override
- protected void post(IServletRequest request, IServletResponse response) {
+ private void handleModification(IServletRequest request, IServletResponse response, LibraryOperation op) {
HttpRequest httpRequest = request.getHttpRequest();
Path libraryTempFile = null;
FileOutputStream libTmpOut = null;
- HttpPostRequestDecoder requestDecoder = new HttpPostRequestDecoder(httpRequest);
+ HttpPostRequestDecoder requestDecoder = null;
+ String localPath = localPath(request);
try {
- LibraryUploadData uploadData = decodeMultiPartLibraryOptions(requestDecoder);
+ Pair<DataverseName, String> dvAndName = decodeDvAndLibFromLocalPath(localPath);
IRequestReference requestReference = receptionist.welcome(request);
- if (uploadData.op == LibraryOperation.UPSERT) {
+ if (op == LibraryOperation.UPSERT) {
+ requestDecoder = new HttpPostRequestDecoder(httpRequest);
+ LibraryUploadData uploadData = decodeMultiPartLibraryOptions(requestDecoder);
ExternalFunctionLanguage language = uploadData.type;
String fileExt = FilenameUtils.getExtension(uploadData.fileUpload.getFilename());
libraryTempFile = Files.createTempFile(workingDir, "lib_", '.' + fileExt);
if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Created temporary file " + libraryTempFile + " for library " + uploadData.dataverse
- + "." + uploadData.name);
+ LOGGER.debug("Created temporary file " + libraryTempFile + " for library "
+ + dvAndName.getFirst().getCanonicalForm() + "." + dvAndName.getSecond());
}
MessageDigest digest = MessageDigest.getInstance("MD5");
libTmpOut = new FileOutputStream(libraryTempFile.toFile());
@@ -256,11 +249,12 @@
IOUtils.copyLarge(ui, os);
}
URI downloadURI = createDownloadURI(libraryTempFile);
- doCreate(uploadData.dataverse, uploadData.name, language,
+ doCreate(dvAndName.getFirst(), dvAndName.getSecond(), language,
ExternalLibraryUtils.digestToHexString(digest), downloadURI, true, sysAuthHeader,
requestReference, request);
- } else if (uploadData.op == LibraryOperation.DELETE) {
- doDrop(uploadData.dataverse, uploadData.name, uploadData.replaceIfExists, requestReference, request);
+ } else if (op == LibraryOperation.DELETE) {
+ //DELETE semantics imply ifExists
+ doDrop(dvAndName.getFirst(), dvAndName.getSecond(), false, requestReference, request);
}
response.setStatus(HttpResponseStatus.OK);
PrintWriter responseWriter = response.writer();
@@ -268,20 +262,12 @@
responseWriter.write(emptyJson);
responseWriter.flush();
} catch (Exception e) {
- response.setStatus(toHttpErrorStatus(e));
- PrintWriter responseWriter = response.writer();
- Map<String, String> error = Collections.singletonMap("error", e.getMessage());
- String errorJson = "";
- try {
- errorJson = OBJECT_MAPPER.writeValueAsString(error);
- } catch (JsonProcessingException ex) {
- responseWriter.write("{ \"error\": \"Unable to process error message!\" }");
- }
- responseWriter.write(errorJson);
- responseWriter.flush();
- LOGGER.error("Error modifying library", e);
+ writeException(e, response);
+ LOGGER.info("Error modifying library", e);
} finally {
- requestDecoder.destroy();
+ if (requestDecoder != null) {
+ requestDecoder.destroy();
+ }
try {
if (libraryTempFile != null) {
if (libTmpOut != null) {
@@ -295,4 +281,28 @@
}
}
+ private void writeException(Exception e, IServletResponse response) {
+ response.setStatus(toHttpErrorStatus(e));
+ PrintWriter responseWriter = response.writer();
+ Map<String, String> error = Collections.singletonMap("error", e.getMessage());
+ String errorJson = "";
+ try {
+ errorJson = OBJECT_MAPPER.writeValueAsString(error);
+ } catch (JsonProcessingException ex) {
+ responseWriter.write("{ \"error\": \"Unable to process error message!\" }");
+ }
+ responseWriter.write(errorJson);
+ responseWriter.flush();
+ }
+
+ @Override
+ protected void post(IServletRequest request, IServletResponse response) {
+ handleModification(request, response, LibraryOperation.UPSERT);
+ }
+
+ @Override
+ protected void delete(IServletRequest request, IServletResponse response) {
+ handleModification(request, response, LibraryOperation.DELETE);
+ }
+
}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCUdfRecoveryServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCUdfRecoveryServlet.java
index 1563833..2c29d14 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCUdfRecoveryServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCUdfRecoveryServlet.java
@@ -24,7 +24,6 @@
import org.apache.asterix.common.api.IApplicationContext;
import org.apache.asterix.common.api.INcApplicationContext;
-import org.apache.asterix.compiler.provider.ILangCompilationProvider;
import org.apache.asterix.external.library.ExternalLibraryManager;
import org.apache.hyracks.http.api.IServletRequest;
import org.apache.hyracks.http.api.IServletResponse;
@@ -39,8 +38,8 @@
public static final String GET_ALL_UDF_ENDPOINT = "/all";
public NCUdfRecoveryServlet(ConcurrentMap<String, Object> ctx, String[] paths, IApplicationContext appCtx,
- ILangCompilationProvider compilationProvider, HttpScheme httpServerProtocol, int httpServerPort) {
- super(ctx, paths, appCtx, compilationProvider, httpServerProtocol, httpServerPort);
+ HttpScheme httpServerProtocol, int httpServerPort) {
+ super(ctx, paths, appCtx, httpServerProtocol, httpServerPort);
}
@Override
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ServletUtil.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ServletUtil.java
index b97d88a..51fa326 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ServletUtil.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ServletUtil.java
@@ -20,12 +20,15 @@
import static org.apache.asterix.api.http.server.ServletConstants.RESULTSET_ATTR;
+import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import org.apache.asterix.app.result.ResultReader;
import org.apache.asterix.common.api.IApplicationContext;
import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.net.URLCodec;
import org.apache.hyracks.api.client.IHyracksClientConnection;
import org.apache.hyracks.api.result.IResultSet;
import org.apache.hyracks.client.result.ResultSet;
@@ -54,4 +57,13 @@
List<String> values = request.getParameterValues(dataverseParameterName);
return !values.isEmpty() ? DataverseName.create(values) : null;
}
+
+ public static String decodeUriSegment(String uriSegment) {
+ try {
+ return new String(URLCodec.decodeUrl(uriSegment.getBytes(StandardCharsets.US_ASCII)),
+ StandardCharsets.UTF_8);
+ } catch (DecoderException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/active/ActiveEntityEventsListener.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/active/ActiveEntityEventsListener.java
index 5f7d65e..cc4b25f 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/active/ActiveEntityEventsListener.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/active/ActiveEntityEventsListener.java
@@ -44,12 +44,14 @@
import org.apache.asterix.active.message.ActivePartitionMessage.Event;
import org.apache.asterix.active.message.ActiveStatsRequestMessage;
import org.apache.asterix.active.message.StopRuntimeParameters;
+import org.apache.asterix.common.api.IMetadataLockManager;
import org.apache.asterix.common.cluster.IClusterStateManager;
import org.apache.asterix.common.dataflow.ICcApplicationContext;
import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.exceptions.RuntimeDataException;
import org.apache.asterix.common.messaging.api.ICCMessageBroker;
import org.apache.asterix.common.messaging.api.INcAddressedMessage;
+import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.common.metadata.IDataset;
import org.apache.asterix.external.feed.watch.WaitForStateSubscriber;
import org.apache.asterix.metadata.api.IActiveEntityController;
@@ -58,6 +60,7 @@
import org.apache.asterix.translator.IStatementExecutor;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.hyracks.algebricks.common.constraints.AlgebricksAbsolutePartitionConstraint;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.api.client.IHyracksClientConnection;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.api.job.JobId;
@@ -704,6 +707,29 @@
return new RecoveryTask(appCtx, this, retryPolicyFactory);
}
+ public void acquireSuspendLocks(MetadataProvider metadataProvider, Dataset targetDataset)
+ throws AlgebricksException {
+ // write lock the listener
+ // exclusive lock all the datasets (except the target dataset)
+ IMetadataLockManager lockManager = metadataProvider.getApplicationContext().getMetadataLockManager();
+ DataverseName dataverseName = entityId.getDataverseName();
+ String entityName = entityId.getEntityName();
+ lockManager.acquireActiveEntityWriteLock(metadataProvider.getLocks(), dataverseName, entityName);
+ acquireSuspendDatasetsLocks(metadataProvider, lockManager, targetDataset);
+ }
+
+ protected void acquireSuspendDatasetsLocks(MetadataProvider metadataProvider, IMetadataLockManager lockManager,
+ Dataset targetDataset) throws AlgebricksException {
+ for (Dataset dataset : getDatasets()) {
+ if (targetDataset != null && targetDataset.equals(dataset)) {
+ // DDL operation already acquired the proper lock for the operation
+ continue;
+ }
+ lockManager.acquireDatasetExclusiveModificationLock(metadataProvider.getLocks(), dataset.getDataverseName(),
+ dataset.getDatasetName());
+ }
+ }
+
@Override
public String toString() {
return "{\"class\":\"" + getClass().getSimpleName() + "\"," + "\"entityId\":\"" + entityId + "\","
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/active/ActiveNotificationHandler.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/active/ActiveNotificationHandler.java
index 8b74e07..0d63bca 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/active/ActiveNotificationHandler.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/active/ActiveNotificationHandler.java
@@ -22,7 +22,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import org.apache.asterix.active.ActiveEvent;
import org.apache.asterix.active.ActiveEvent.Kind;
@@ -30,10 +29,8 @@
import org.apache.asterix.active.IActiveEntityEventsListener;
import org.apache.asterix.active.IActiveNotificationHandler;
import org.apache.asterix.active.message.ActivePartitionMessage;
-import org.apache.asterix.common.api.IMetadataLockManager;
import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.exceptions.RuntimeDataException;
-import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.metadata.declared.MetadataProvider;
import org.apache.asterix.metadata.entities.Dataset;
import org.apache.commons.lang3.tuple.Pair;
@@ -278,30 +275,13 @@
public void suspendForDdlOrHalt(IActiveEntityEventsListener listener, MetadataProvider metadataProvider,
Dataset targetDataset) {
try {
- // write lock the listener
- // exclusive lock all the datasets (except the target dataset)
- IMetadataLockManager lockManager = metadataProvider.getApplicationContext().getMetadataLockManager();
- DataverseName dataverseName = listener.getEntityId().getDataverseName();
- String entityName = listener.getEntityId().getEntityName();
- if (LOGGER.isEnabled(level)) {
- LOGGER.log(level, "Suspending " + listener.getEntityId());
- }
- LOGGER.log(level, "Acquiring locks");
- lockManager.acquireActiveEntityWriteLock(metadataProvider.getLocks(), dataverseName, entityName);
- Set<Dataset> datasets = ((ActiveEntityEventsListener) listener).getDatasets();
- for (Dataset dataset : datasets) {
- if (targetDataset != null && targetDataset.equals(dataset)) {
- // DDL operation already acquired the proper lock for the operation
- continue;
- }
- lockManager.acquireDatasetExclusiveModificationLock(metadataProvider.getLocks(),
- dataset.getDataverseName(), dataset.getDatasetName());
- }
- LOGGER.log(level, "locks acquired");
+ EntityId entityId = listener.getEntityId();
+ LOGGER.log(level, "Suspending {}", entityId);
+ LOGGER.log(level, "Acquiring locks for {}", entityId);
+ ((ActiveEntityEventsListener) listener).acquireSuspendLocks(metadataProvider, targetDataset);
+ LOGGER.log(level, "locks acquired for {}", entityId);
((ActiveEntityEventsListener) listener).suspend(metadataProvider);
- if (LOGGER.isEnabled(level)) {
- LOGGER.log(level, listener.getEntityId() + " suspended");
- }
+ LOGGER.log(level, "{} suspended", entityId);
} catch (Throwable th) { // NOSONAR must halt in case of any failure
LOGGER.error("Suspend active failed", th);
ExitUtil.halt(ExitUtil.EC_ACTIVE_SUSPEND_FAILURE);
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DatasetRewriter.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DatasetRewriter.java
index 0d20d51..6944b25 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DatasetRewriter.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DatasetRewriter.java
@@ -18,6 +18,7 @@
*/
package org.apache.asterix.app.function;
+import static org.apache.asterix.common.api.IIdentifierMapper.Modifier.PLURAL;
import static org.apache.asterix.common.utils.IdentifierUtil.dataset;
import java.util.ArrayList;
@@ -69,7 +70,7 @@
if (unnest.getPositionalVariable() != null) {
// TODO remove this after enabling the support of positional variables in data scan
throw new CompilationException(ErrorCode.COMPILATION_ERROR, unnest.getSourceLocation(),
- "No positional variables are allowed over " + dataset() + "s");
+ "No positional variables are allowed over " + dataset(PLURAL));
}
MetadataProvider metadataProvider = (MetadataProvider) context.getMetadataProvider();
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/FeedRewriter.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/FeedRewriter.java
index b01ea65..cc1b3ea 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/FeedRewriter.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/FeedRewriter.java
@@ -18,6 +18,7 @@
*/
package org.apache.asterix.app.function;
+import static org.apache.asterix.common.api.IIdentifierMapper.Modifier.SINGULAR;
import static org.apache.asterix.common.utils.IdentifierUtil.dataset;
import java.util.ArrayList;
@@ -132,7 +133,7 @@
String metaTypeName = FeedUtils.getFeedMetaTypeName(sourceFeed.getConfiguration());
if (metaTypeName == null) {
throw new AlgebricksException(
- "Feed to a " + dataset() + " with metadata doesn't have meta type specified");
+ "Feed to " + dataset(SINGULAR) + " with metadata doesn't have meta type specified");
}
metaType = (ARecordType) metadataProvider.findType(id.getDataverseName(), metaTypeName);
}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
index d2e9284..777f4d5 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
@@ -18,6 +18,7 @@
*/
package org.apache.asterix.app.translator;
+import static org.apache.asterix.common.api.IIdentifierMapper.Modifier.PLURAL;
import static org.apache.asterix.common.utils.IdentifierUtil.dataset;
import static org.apache.asterix.common.utils.IdentifierUtil.dataverse;
import static org.apache.asterix.lang.common.statement.CreateFullTextFilterStatement.FIELD_TYPE_STOPWORDS;
@@ -97,13 +98,17 @@
import org.apache.asterix.external.operators.FeedIntakeOperatorNodePushable;
import org.apache.asterix.external.util.ExternalDataConstants;
import org.apache.asterix.external.util.ExternalDataUtils;
+import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.base.IReturningStatement;
import org.apache.asterix.lang.common.base.IRewriterFactory;
import org.apache.asterix.lang.common.base.IStatementRewriter;
import org.apache.asterix.lang.common.base.Statement;
+import org.apache.asterix.lang.common.expression.CallExpr;
import org.apache.asterix.lang.common.expression.IndexedTypeExpression;
+import org.apache.asterix.lang.common.expression.LiteralExpr;
import org.apache.asterix.lang.common.expression.TypeExpression;
import org.apache.asterix.lang.common.expression.TypeReferenceExpression;
+import org.apache.asterix.lang.common.literal.MissingLiteral;
import org.apache.asterix.lang.common.statement.AdapterDropStatement;
import org.apache.asterix.lang.common.statement.CompactStatement;
import org.apache.asterix.lang.common.statement.ConnectFeedStatement;
@@ -607,7 +612,7 @@
(ILSMMergePolicyFactory) Class.forName(compactionPolicyFactoryClassName).newInstance();
if (isExternalDataset && mergePolicyFactory.getName().compareTo("correlated-prefix") == 0) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc,
- "The correlated-prefix merge policy cannot be used with external " + dataset() + "s");
+ "The correlated-prefix merge policy cannot be used with external " + dataset(PLURAL));
}
if (compactionPolicyProperties == null) {
if (mergePolicyFactory.getName().compareTo("no-merge") != 0) {
@@ -2563,16 +2568,30 @@
}
}
- //Check whether the function is use-able
+ // Check whether the function is usable:
+ // create a function declaration for this function,
+ // and a query body calls this function with each argument set to 'missing'
+ FunctionDecl fd = new FunctionDecl(functionSignature, paramVars, cfs.getFunctionBodyExpression(), true);
+ fd.setSourceLocation(sourceLoc);
+ CallExpr fcall = new CallExpr(functionSignature,
+ Collections.nCopies(paramVars.size(), new LiteralExpr(MissingLiteral.INSTANCE)));
+ fcall.setSourceLocation(sourceLoc);
metadataProvider.setDefaultDataverse(dv);
Query wrappedQuery = new Query(false);
wrappedQuery.setSourceLocation(sourceLoc);
- wrappedQuery.setBody(cfs.getFunctionBodyExpression());
+ wrappedQuery.setBody(fcall);
wrappedQuery.setTopLevel(false);
- apiFramework.reWriteQuery(declaredFunctions, metadataProvider, wrappedQuery, sessionOutput, false,
- paramVars, warningCollector);
- List<List<Triple<DataverseName, String, String>>> dependencies = FunctionUtil.getFunctionDependencies(
- rewriterFactory.createQueryRewriter(), cfs.getFunctionBodyExpression());
+ List<FunctionDecl> fdList = new ArrayList<>(declaredFunctions);
+ fdList.add(fd);
+ apiFramework.reWriteQuery(fdList, metadataProvider, wrappedQuery, sessionOutput, false, false,
+ Collections.emptyList(), warningCollector);
+ Expression fdNormBody = fd.getNormalizedFuncBody();
+ if (fdNormBody == null) {
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc,
+ functionSignature.toString());
+ }
+ List<List<Triple<DataverseName, String, String>>> dependencies =
+ FunctionUtil.getFunctionDependencies(rewriterFactory.createQueryRewriter(), fdNormBody);
newInlineTypes = Collections.emptyMap();
function = new Function(functionSignature, paramNames, null, null, cfs.getFunctionBody(),
@@ -3269,7 +3288,7 @@
// Query Rewriting (happens under the same ongoing metadata transaction)
Pair<IReturningStatement, Integer> rewrittenResult = apiFramework.reWriteQuery(declaredFunctions,
- metadataProvider, query, sessionOutput, true, externalVars.keySet(), warningCollector);
+ metadataProvider, query, sessionOutput, true, true, externalVars.keySet(), warningCollector);
// Query Compilation (happens under the same ongoing metadata transaction)
return apiFramework.compileQuery(clusterInfoCollector, metadataProvider, (Query) rewrittenResult.first,
@@ -3286,7 +3305,7 @@
// Insert/upsert statement rewriting (happens under the same ongoing metadata transaction)
Pair<IReturningStatement, Integer> rewrittenResult = apiFramework.reWriteQuery(declaredFunctions,
- metadataProvider, insertUpsert, sessionOutput, true, externalVars.keySet(), warningCollector);
+ metadataProvider, insertUpsert, sessionOutput, true, true, externalVars.keySet(), warningCollector);
InsertStatement rewrittenInsertUpsert = (InsertStatement) rewrittenResult.first;
DataverseName dataverseName = getActiveDataverseName(rewrittenInsertUpsert.getDataverseName());
@@ -3454,7 +3473,7 @@
(ActiveEntityEventsListener) activeNotificationHandler.getListener(feedId);
if (listener != null && listener.getState() != ActivityState.STOPPED) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc,
- "Feed " + feedId + " is currently active and connected to the following " + dataset() + "(s) \n"
+ "Feed " + feedId + " is currently active and connected to the following " + dataset(PLURAL) + "\n"
+ listener.toString());
} else if (listener != null) {
listener.unregister();
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java
index c27b3b1..c148c92 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java
@@ -224,13 +224,14 @@
parseCredentialMap(((NodeControllerService) ncServiceCtx.getControllerService()).getConfiguration()
.getCredentialFilePath()));
Pair<Map<String, String>, Map<String, String>> auth = BasicAuthServlet.generateSysAuthHeader(apiServer.ctx());
- apiServer.addServlet(new BasicAuthServlet(apiServer.ctx(),
- new NCUdfApiServlet(apiServer.ctx(), new String[] { UDF }, getApplicationContext(),
- sqlppCompilationProvider, apiServer.getScheme(), apiServer.getAddress().getPort()),
- auth.getFirst(), auth.getSecond()));
- apiServer.addServlet(new BasicAuthServlet(apiServer.ctx(),
- new NCUdfRecoveryServlet(apiServer.ctx(), new String[] { UDF_RECOVERY }, getApplicationContext(),
- sqlppCompilationProvider, apiServer.getScheme(), apiServer.getAddress().getPort()),
+ apiServer
+ .addServlet(new BasicAuthServlet(apiServer.ctx(),
+ new NCUdfApiServlet(apiServer.ctx(), new String[] { UDF }, getApplicationContext(),
+ apiServer.getScheme(), apiServer.getAddress().getPort()),
+ auth.getFirst(), auth.getSecond()));
+ apiServer.addServlet(new BasicAuthServlet(
+ apiServer.ctx(), new NCUdfRecoveryServlet(apiServer.ctx(), new String[] { UDF_RECOVERY },
+ getApplicationContext(), apiServer.getScheme(), apiServer.getAddress().getPort()),
auth.getFirst(), auth.getSecond()));
apiServer.addServlet(new QueryStatusApiServlet(apiServer.ctx(), getApplicationContext(), QUERY_STATUS));
apiServer.addServlet(new QueryResultApiServlet(apiServer.ctx(), getApplicationContext(), QUERY_RESULT));
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/external/ExternalUDFLibrarian.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/external/ExternalUDFLibrarian.java
index 88277e4..2450025 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/external/ExternalUDFLibrarian.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/external/ExternalUDFLibrarian.java
@@ -23,7 +23,6 @@
import java.net.URI;
import org.apache.asterix.common.exceptions.AsterixException;
-import org.apache.asterix.common.metadata.DataverseName;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
@@ -31,6 +30,7 @@
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.ContentType;
@@ -56,20 +56,11 @@
}
@Override
- public void install(URI path, String dataverseKey, DataverseName dataverse, boolean useDisplayForm, String name,
- String type, String libPath, Pair<String, String> credentials) throws Exception {
+ public void install(URI path, String type, String libPath, Pair<String, String> credentials) throws Exception {
HttpClientContext hcCtx = createHttpClientContext(path, credentials);
HttpPost post = new HttpPost(path);
File lib = new File(libPath);
MultipartEntityBuilder entity = MultipartEntityBuilder.create().setMode(HttpMultipartMode.STRICT);
- if (!useDisplayForm) {
- for (String dvPart : dataverse.getParts()) {
- entity.addTextBody(dataverseKey, dvPart);
- }
- } else {
- entity.addTextBody(dataverseKey, dataverse.toString());
- }
- entity.addTextBody("name", name);
entity.addTextBody("type", type);
entity.addBinaryBody("data", lib, ContentType.DEFAULT_BINARY, lib.getName()).build();
post.setEntity(entity.build());
@@ -78,22 +69,10 @@
}
@Override
- public void uninstall(URI path, String dataverseKey, DataverseName dataverse, boolean useDisplayForm, String name,
- Pair<String, String> credentials) throws IOException, AsterixException {
+ public void uninstall(URI path, Pair<String, String> credentials) throws IOException, AsterixException {
HttpClientContext hcCtx = createHttpClientContext(path, credentials);
- HttpPost post = new HttpPost(path);
- MultipartEntityBuilder entity = MultipartEntityBuilder.create().setMode(HttpMultipartMode.STRICT);
- if (!useDisplayForm) {
- for (String dvPart : dataverse.getParts()) {
- entity.addTextBody(dataverseKey, dvPart);
- }
- } else {
- entity.addTextBody(dataverseKey, dataverse.toString());
- }
- entity.addTextBody("name", name);
- entity.addTextBody("delete", "true");
- post.setEntity(entity.build());
- HttpResponse response = hc.execute(post, hcCtx);
+ HttpDelete del = new HttpDelete(path);
+ HttpResponse response = hc.execute(del, hcCtx);
handleResponse(response);
}
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/external/IExternalUDFLibrarian.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/external/IExternalUDFLibrarian.java
index 639475b..998fa78 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/external/IExternalUDFLibrarian.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/external/IExternalUDFLibrarian.java
@@ -22,14 +22,10 @@
import java.net.URI;
import org.apache.asterix.common.exceptions.AsterixException;
-import org.apache.asterix.common.metadata.DataverseName;
import org.apache.hyracks.algebricks.common.utils.Pair;
public interface IExternalUDFLibrarian {
+ void install(URI path, String type, String libPath, Pair<String, String> credentials) throws Exception;
- void install(URI path, String dataverseKey, DataverseName dataverse, boolean useDisplayForm, String name,
- String type, String libPath, Pair<String, String> credentials) throws Exception;
-
- void uninstall(URI path, String dataverseKey, DataverseName dataverse, boolean useDisplayForm, String name,
- Pair<String, String> credentials) throws IOException, AsterixException;
+ void uninstall(URI path, Pair<String, String> credentials) throws IOException, AsterixException;
}
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
index 453ed59..f347b77 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
@@ -41,8 +41,10 @@
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
+import java.net.URLEncoder;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.MessageFormat;
@@ -82,8 +84,6 @@
import org.apache.asterix.common.config.GlobalConfig;
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.common.utils.Servlets;
-import org.apache.asterix.lang.common.base.IParserFactory;
-import org.apache.asterix.lang.sqlpp.parser.SqlppParserFactory;
import org.apache.asterix.lang.sqlpp.util.SqlppStatementUtil;
import org.apache.asterix.metadata.bootstrap.MetadataBuiltinEntities;
import org.apache.asterix.metadata.utils.MetadataConstants;
@@ -1326,10 +1326,12 @@
// TODO: make this case work well with entity names containing spaces by
// looking for \"
lines = stripAllComments(statement).trim().split("\n");
- IParserFactory parserFactory = new SqlppParserFactory();
for (String line : lines) {
String[] command = line.trim().split(" ");
- URI path = createEndpointURI("/admin/udf/");
+ //TODO: this is not right. URLEncoder does not properly encode paths.
+ String dataverse = URLEncoder.encode(command[1], StandardCharsets.US_ASCII.name());
+ String library = URLEncoder.encode(command[2], StandardCharsets.US_ASCII.name());
+ URI path = createEndpointURI("/admin/udf/" + dataverse + "/" + library);
if (command.length < 2) {
throw new Exception("invalid library command: " + line);
}
@@ -1338,25 +1340,19 @@
if (command.length != 7) {
throw new Exception("invalid library format");
}
- List<String> dataverse = parserFactory.createParser(command[1]).parseMultipartIdentifier();
- String library = command[2];
String type = command[3];
String username = command[4];
String pw = command[5];
String libPath = command[6];
- librarian.install(path, "dataverse", DataverseName.create(dataverse), false, library, type,
- libPath, new Pair<>(username, pw));
+ librarian.install(path, type, libPath, new Pair<>(username, pw));
break;
case "uninstall":
if (command.length != 5) {
throw new Exception("invalid library format");
}
- dataverse = parserFactory.createParser(command[1]).parseMultipartIdentifier();
- library = command[2];
username = command[3];
pw = command[4];
- librarian.uninstall(path, "dataverse", DataverseName.create(dataverse), false, library,
- new Pair<>(username, pw));
+ librarian.uninstall(path, new Pair<>(username, pw));
break;
default:
throw new Exception("invalid library format");
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java
index 8b6f05f..98f328d 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java
@@ -27,15 +27,17 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
+import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.stream.Collectors;
import org.apache.asterix.common.config.GlobalConfig;
-import org.apache.asterix.common.exceptions.AsterixException;
import org.apache.asterix.common.functions.FunctionSignature;
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.lang.common.base.IParser;
@@ -187,8 +189,9 @@
if (st.getKind() == Statement.Kind.QUERY) {
Query query = (Query) st;
IQueryRewriter rewriter = sqlppRewriterFactory.createQueryRewriter();
- rewrite(rewriter, functions, query, metadataProvider,
- new LangRewritingContext(query.getVarCounter(), TestUtils.NOOP_WARNING_COLLECTOR));
+ LangRewritingContext rwContext = new LangRewritingContext(metadataProvider, functions,
+ TestUtils.NOOP_WARNING_COLLECTOR, query.getVarCounter());
+ rewrite(rewriter, query, rwContext);
// Tests deep copy and deep equality.
Query copiedQuery = (Query) SqlppRewriteUtil.deepCopy(query);
@@ -254,28 +257,38 @@
}
// Rewrite queries.
- // Note: we do not do inline function rewriting here because this needs real
- // metadata access.
- private void rewrite(IQueryRewriter rewriter, List<FunctionDecl> declaredFunctions, Query topExpr,
- MetadataProvider metadataProvider, LangRewritingContext context) throws AsterixException {
- PA.invokeMethod(rewriter,
- "setup(java.util.List, org.apache.asterix.lang.common.base.IReturningStatement, "
- + "org.apache.asterix.metadata.declared.MetadataProvider, "
- + "org.apache.asterix.lang.common.rewrites.LangRewritingContext, " + "java.util.Collection)",
- declaredFunctions, topExpr, metadataProvider, context, null);
- PA.invokeMethod(rewriter, "resolveFunctionCalls()");
- PA.invokeMethod(rewriter, "generateColumnNames()");
- PA.invokeMethod(rewriter, "substituteGroupbyKeyExpression()");
- PA.invokeMethod(rewriter, "rewriteGroupBys()");
- PA.invokeMethod(rewriter, "rewriteSetOperations()");
- PA.invokeMethod(rewriter, "inlineColumnAlias()");
- PA.invokeMethod(rewriter, "rewriteWindowExpressions()");
- PA.invokeMethod(rewriter, "rewriteGroupingSets()");
- PA.invokeMethod(rewriter, "variableCheckAndRewrite()");
- PA.invokeMethod(rewriter, "extractAggregatesFromCaseExpressions()");
- PA.invokeMethod(rewriter, "rewriteGroupByAggregationSugar()");
- PA.invokeMethod(rewriter, "rewriteWindowAggregationSugar()");
- PA.invokeMethod(rewriter, "rewriteSpecialFunctionNames()");
+ // Note: we do not do inline function rewriting here because this needs real metadata access.
+ private void rewrite(IQueryRewriter rewriter, Query topExpr, LangRewritingContext context) throws Exception {
+ invokeMethod(rewriter, "setup", context, topExpr, null, true, false);
+ invokeMethod(rewriter, "resolveFunctionCalls");
+ invokeMethod(rewriter, "generateColumnNames");
+ invokeMethod(rewriter, "substituteGroupbyKeyExpression");
+ invokeMethod(rewriter, "rewriteGroupBys");
+ invokeMethod(rewriter, "rewriteSetOperations");
+ invokeMethod(rewriter, "inlineColumnAlias");
+ invokeMethod(rewriter, "rewriteWindowExpressions");
+ invokeMethod(rewriter, "rewriteGroupingSets");
+ invokeMethod(rewriter, "variableCheckAndRewrite");
+ invokeMethod(rewriter, "extractAggregatesFromCaseExpressions");
+ invokeMethod(rewriter, "rewriteGroupByAggregationSugar");
+ invokeMethod(rewriter, "rewriteWindowAggregationSugar");
+ invokeMethod(rewriter, "rewriteSpecialFunctionNames");
+ invokeMethod(rewriter, "rewriteOperatorExpression");
+ invokeMethod(rewriter, "rewriteCaseExpressions");
+ invokeMethod(rewriter, "rewriteListInputFunctions");
+ invokeMethod(rewriter, "rewriteRightJoins");
}
+ private static void invokeMethod(Object instance, String methodName, Object... args) throws Exception {
+ PA.invokeMethod(instance, getMethodSignature(instance.getClass(), methodName), args);
+ }
+
+ private static String getMethodSignature(Class<?> cls, String methodName) throws Exception {
+ Method[] methods = cls.getDeclaredMethods();
+ Method method = Arrays.stream(methods).filter(m -> m.getName().equals(methodName)).findFirst()
+ .orElseThrow(NoSuchMethodException::new);
+ String parameterTypes =
+ Arrays.stream(method.getParameterTypes()).map(Class::getName).collect(Collectors.joining(","));
+ return String.format("%s(%s)", method.getName(), parameterTypes);
+ }
}
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfInFLOWGR.ast b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfInFLOWGR.ast
index 58fe98b..2e1d5a8 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfInFLOWGR.ast
+++ b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfInFLOWGR.ast
@@ -1,17 +1,15 @@
Query:
SELECT ELEMENT [
-CASE LiteralExpr [TRUE]
-
-WHEN OperatorExpr [
- Variable [ Name=$i ]
- >
- Variable [ Name=$j ]
- ]
-THEN Variable [ Name=$i ]
-
-ELSE Variable [ Name=$j ]
-
-END
+FunctionCall asterix.switch-case[
+ LiteralExpr [TRUE]
+ OperatorExpr [
+ Variable [ Name=$i ]
+ >
+ Variable [ Name=$j ]
+ ]
+ Variable [ Name=$i ]
+ Variable [ Name=$j ]
+]
]
FROM [ OrderedListConstructor [
LiteralExpr [LONG] [1]
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfThenElse.ast b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfThenElse.ast
index cf95780..eeed914 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfThenElse.ast
+++ b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfThenElse.ast
@@ -1,15 +1,9 @@
Query:
SELECT ELEMENT [
-CASE OperatorExpr [
- LiteralExpr [LONG] [2]
- >
- LiteralExpr [LONG] [1]
- ]
-
-WHEN LiteralExpr [TRUE]
-THEN LiteralExpr [LONG] [20]
-
-ELSE LiteralExpr [LONG] [10]
-
-END
+FunctionCall asterix.switch-case[
+ LiteralExpr [TRUE]
+ LiteralExpr [TRUE]
+ LiteralExpr [LONG] [20]
+ LiteralExpr [LONG] [10]
+]
]
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR1.ast b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR1.ast
index 42831c4..5fb51ac 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR1.ast
+++ b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR1.ast
@@ -4,18 +4,12 @@
SELECT ELEMENT [
Variable [ Name=$k ]
]
- FROM [ CASE OperatorExpr [
- Variable [ Name=$i ]
- >
- Variable [ Name=$j ]
- ]
-
- WHEN LiteralExpr [TRUE]
- THEN Variable [ Name=$i ]
-
- ELSE Variable [ Name=$j ]
-
- END
+ FROM [ FunctionCall asterix.switch-case[
+ LiteralExpr [TRUE]
+ LiteralExpr [TRUE]
+ Variable [ Name=$i ]
+ Variable [ Name=$j ]
+ ]
AS Variable [ Name=$k ]
]
Where
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR2.ast b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR2.ast
index 3434965..d40210f 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR2.ast
+++ b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR2.ast
@@ -4,18 +4,16 @@
SELECT ELEMENT [
Variable [ Name=$k ]
]
- FROM [ CASE LiteralExpr [TRUE]
-
- WHEN OperatorExpr [
- Variable [ Name=$i ]
- >
- Variable [ Name=$j ]
- ]
- THEN Variable [ Name=$i ]
-
- ELSE Variable [ Name=$j ]
-
- END
+ FROM [ FunctionCall asterix.switch-case[
+ LiteralExpr [TRUE]
+ OperatorExpr [
+ Variable [ Name=$i ]
+ >
+ Variable [ Name=$j ]
+ ]
+ Variable [ Name=$i ]
+ Variable [ Name=$j ]
+ ]
AS Variable [ Name=$k ]
]
Where
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.1.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/invalid_library_requests.1.post.http
similarity index 91%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.1.post.http
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/invalid_library_requests.1.post.http
index 185d282..a9e043a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.1.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/invalid_library_requests.1.post.http
@@ -17,9 +17,7 @@
* under the License.
*/
# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
# param type:multipart_text=badType
# param data:multipart_binary=target/data/externallib/asterix-external-data-testlib.zip
-/admin/udf
+/admin/udf/Default/testlib
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/invalid_library_requests.2.delete.http
similarity index 86%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/invalid_library_requests.2.delete.http
index e8de108..43a40a2 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/invalid_library_requests.2.delete.http
@@ -17,8 +17,5 @@
* under the License.
*/
# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-/admin/udf
+/admin/udf/Default/testlib
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.3.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/invalid_library_requests.3.post.http
similarity index 90%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.3.post.http
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/invalid_library_requests.3.post.http
index 01c05d2..9815651 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.3.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/invalid_library_requests.3.post.http
@@ -17,8 +17,6 @@
* under the License.
*/
# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
# param data:multipart_binary=target/data/externallib/asterix-external-data-testlib.zip
-/admin/udf
+/admin/udf/Default/testlib
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/invalid_library_requests.4.post.http
similarity index 90%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/invalid_library_requests.4.post.http
index 0b6d882..5353086 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/invalid_library_requests.4.post.http
@@ -17,9 +17,7 @@
* under the License.
*/
# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
# param type:multipart_text=java
# param data:multipart_text=bogus
-/admin/udf
+/admin/udf/Default/testlib
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/invalid_library_requests.5.post.http
similarity index 90%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/invalid_library_requests.5.post.http
index e8de108..28b64f8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/invalid_library_requests.5.post.http
@@ -17,8 +17,6 @@
* under the License.
*/
# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
# param type:multipart_text=java
-/admin/udf
+/admin/udf/Default/testlib
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.2.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.2.post.http
deleted file mode 100644
index 01b4982..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.2.post.http
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-# param delete:multipart_text=true
-# param data:multipart_binary=target/data/externallib/asterix-external-data-testlib.zip
-
-/admin/udf
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api/library_list_api.1.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api/library_list_api.1.post.http
index de72c49..d9d6236 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api/library_list_api.1.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api/library_list_api.1.post.http
@@ -17,9 +17,7 @@
* under the License.
*/
# auth admin:admin
-# param dataverse:multipart_text=externallibtest
-# param name:multipart_text=testlib
# param type:multipart_text=java
# param data:multipart_binary=target/data/externallib/asterix-external-data-testlib.zip
-/admin/udf
+/admin/udf/externallibtest/testlib
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.1.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.1.post.http
index c097ccc..3f7bdb0 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.1.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.1.post.http
@@ -17,10 +17,7 @@
* under the License.
*/
# auth admin:admin
-# param dataverse:multipart_text=externallibtest
-# param dataverse:multipart_text=foo
-# param name:multipart_text=testlib
# param type:multipart_text=java
# param data:multipart_binary=target/data/externallib/asterix-external-data-testlib.zip
-/admin/udf
+/admin/udf/externallibtest%2Ffoo/testlib
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.2.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.2.post.http
index de72c49..d9d6236 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.2.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.2.post.http
@@ -17,9 +17,7 @@
* under the License.
*/
# auth admin:admin
-# param dataverse:multipart_text=externallibtest
-# param name:multipart_text=testlib
# param type:multipart_text=java
# param data:multipart_binary=target/data/externallib/asterix-external-data-testlib.zip
-/admin/udf
+/admin/udf/externallibtest/testlib
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.3.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.3.post.http
index 16b3596..9ad58b1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.3.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.3.post.http
@@ -17,11 +17,7 @@
* under the License.
*/
# auth admin:admin
-# param dataverse:multipart_text=external
-# param dataverse:multipart_text=lib
-# param dataverse:multipart_text=test
-# param name:multipart_text=testlib
# param type:multipart_text=java
# param data:multipart_binary=target/data/externallib/asterix-external-data-testlib.zip
-/admin/udf
+/admin/udf/external%2Flib%2Ftest/testlib
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.4.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.4.post.http
index 97a3c27..a731831 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.4.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/library_list_api_multipart/library_list_api_multipart.4.post.http
@@ -17,11 +17,7 @@
* under the License.
*/
# auth admin:admin
-# param dataverse:multipart_text=externallibtest
-# param dataverse:multipart_text=foo
-# param dataverse:multipart_text=bar
-# param name:multipart_text=testlib
# param type:multipart_text=java
# param data:multipart_binary=target/data/externallib/asterix-external-data-testlib.zip
-/admin/udf
+/admin/udf/externallibtest%2Ffoo%2Fbar/testlib
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysentiment_multipart/mysentiment_multipart.1.lib.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysentiment_multipart/mysentiment_multipart.1.lib.sqlpp
index 67e22cb..c1aa309 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysentiment_multipart/mysentiment_multipart.1.lib.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysentiment_multipart/mysentiment_multipart.1.lib.sqlpp
@@ -16,4 +16,4 @@
* specific language governing permissions and limitations
* under the License.
*/
-install externallib.test testlib python admin admin target/TweetSent.pyz
+install externallib/test testlib python admin admin target/TweetSent.pyz
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.1.ddl.sqlpp
similarity index 84%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.1.ddl.sqlpp
index e8de108..cf1603e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.1.ddl.sqlpp
@@ -16,9 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-
-/admin/udf
+/*
+ * Description : Test illegal recursive function calls
+ */
+drop dataverse test if exists;
+create dataverse test;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.2.ddl.sqlpp
similarity index 84%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.2.ddl.sqlpp
index e8de108..ee465fa 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.2.ddl.sqlpp
@@ -16,9 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-
-/admin/udf
+/*
+ * Description : Recursion in CREATE FUNCTION
+ * Expected Res : Failure
+ */
+use test;
+create function f2a(a) { - f2a(a) };
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.3.ddl.sqlpp
similarity index 82%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.3.ddl.sqlpp
index e8de108..79fc6bb 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.3.ddl.sqlpp
@@ -16,9 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-
-/admin/udf
+/*
+ * Description : Recursion in CREATE FUNCTION
+ * Expected Res : Failure
+ */
+use test;
+create function f3a(a) { -a };
+create or replace function f3a(a) { f3a(a) };
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.4.ddl.sqlpp
similarity index 79%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.4.ddl.sqlpp
index 0b6d882..24af0d4 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.4.ddl.sqlpp
@@ -16,10 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-# param data:multipart_text=bogus
-
-/admin/udf
+/*
+ * Description : Recursion in CREATE FUNCTION
+ * Expected Res : Failure
+ */
+use test;
+create function f4a(a) { -a };
+create function f4b(b) { f4a(b) };
+create or replace function f4a(a) { f4b(a) };
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.5.query.sqlpp
similarity index 84%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.5.query.sqlpp
index e8de108..c6ded74 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.5.query.sqlpp
@@ -16,9 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
+/*
+ * Description : Recursion in DECLARE FUNCTION
+ * Expected Res : Failure
+ */
+use test;
-/admin/udf
+declare function f5a(a) { - f5a(a) };
+
+f5a(1);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.6.query.sqlpp
similarity index 80%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.6.query.sqlpp
index 0b6d882..f47b781 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.6.query.sqlpp
@@ -16,10 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-# param data:multipart_text=bogus
+/*
+ * Description : Recursion in DECLARE FUNCTION
+ * Expected Res : Failure
+ */
+use test;
-/admin/udf
+declare function f6a(a) { f6b(a) + f6b(-a) };
+declare function f6b(b) { f6a(-b) + f6a(b) };
+
+f6a(1);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.7.query.sqlpp
similarity index 77%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.7.query.sqlpp
index 0b6d882..0c89f14b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.7.query.sqlpp
@@ -16,10 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-# param data:multipart_text=bogus
+/*
+ * Description : Recursion in DECLARE FUNCTION
+ * Expected Res : Failure
+ */
+use test;
-/admin/udf
+declare function f7a(a) { f7b(a) + f7b(-a) };
+declare function f7b(b) { f7a(-b) + f7a(b) };
+declare function f7c(c) { f7b(c) };
+
+f7c(1);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.8.ddl.sqlpp
similarity index 72%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.8.ddl.sqlpp
index 0b6d882..bf5ca06 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.8.ddl.sqlpp
@@ -16,10 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-# param data:multipart_text=bogus
+/*
+ * Description : Recursion in CREATE FUNCTION (varargs)
+ * Expected Res : Failure
+ */
-/admin/udf
+use test;
+
+create function f8a(...) { - args[0] - args[1] };
+
+create function f8b(...) { f8a(args[0], args[1]) + f8a(args[1], args[0]) };
+
+create or replace function f8a(...) { f8b(args[0], args[1]) };
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.9.query.sqlpp
similarity index 73%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.9.query.sqlpp
index 0b6d882..e5d4e98 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf37_recursion/udf37_recursion.9.query.sqlpp
@@ -16,10 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-# param data:multipart_text=bogus
+/*
+ * Description : Recursion in DECLARE FUNCTION (varargs)
+ * Expected Res : Failure
+ */
+use test;
-/admin/udf
+declare function f9a(...) { f9b(args[0]) + f9b(-args[1]) };
+
+declare function f9b(...) { f9a(-args[0]) + f9a(args[1]) };
+
+declare function f9c(...) { f9b(args[0], args[1]) };
+
+f9c(1, 2);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.1.ddl.sqlpp
similarity index 81%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.1.ddl.sqlpp
index 0b6d882..f237df5 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.1.ddl.sqlpp
@@ -16,10 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-# param data:multipart_text=bogus
-/admin/udf
+/*
+ * Description : No recursion
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use test;
+
+create function f1a(a) { -a };
+
+create function f1b(b) { f1a(b) + f1a(b) };
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.2.query.sqlpp
similarity index 84%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.2.query.sqlpp
index e8de108..2c4236b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.2.query.sqlpp
@@ -16,9 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-/admin/udf
+/*
+ * Description : No recursion
+ */
+
+use test;
+
+select r, f1a(r) f1a, f1b(r) f1b
+from range(1,2) r
+order by r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.3.ddl.sqlpp
similarity index 69%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.3.ddl.sqlpp
index 0b6d882..0ab206d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.3.ddl.sqlpp
@@ -16,10 +16,21 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-# param data:multipart_text=bogus
-/admin/udf
+/*
+ * Description : No recursion
+ */
+
+use test;
+
+create function f3a(a) { -a };
+
+create function f3b(b) { f3a(b) };
+
+create function f3c(c) { f3a(c) + f3b(c) };
+
+create function f3d(d) { f3a(d) + f3b(d) + f3c(d) };
+
+create function f3e(e) { f3a(e) + f3b(e) + f3c(e) + f3d(e) };
+
+create function f3f(f) { f3a(f) + f3b(f) + f3c(f) + f3d(f) + f3e(f) };
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.4.query.sqlpp
similarity index 82%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.4.query.sqlpp
index e8de108..2ad1f20 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.5.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.4.query.sqlpp
@@ -16,9 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-/admin/udf
+/*
+ * Description : No recursion
+ */
+
+use test;
+
+select r, f3a(r) f3a, f3b(r) f3b, f3c(r) f3c, f3d(r) f3d, f3e(r) f3e, f3f(r) f3f
+from range(1,2) r
+order by r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.5.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.5.ddl.sqlpp
new file mode 100644
index 0000000..e4ce3f7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.5.ddl.sqlpp
@@ -0,0 +1,37 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Description : No recursion (vararg functions)
+ */
+
+use test;
+
+create function f5a(...) { - args[0] - args[1] };
+
+create function f5b(...) { f5a(args[0], args[1]) };
+
+create function f5c(...) { f5a(args[0], args[1]) + f5b(args[0], args[1]) };
+
+create function f5d(...) { f5a(args[0], args[1]) + f5b(args[0], args[1]) + f5c(args[0], args[1]) };
+
+create function f5e(...) { f5a(args[0], args[1]) + f5b(args[0], args[1]) + f5c(args[0], args[1]) + f5d(args[0], args[1]) };
+
+create function f5f(...) { f5a(args[0], args[1]) + f5b(args[0], args[1]) + f5c(args[0], args[1]) + f5d(args[0], args[1]) + f5e(args[0], args[1]) };
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.6.query.sqlpp
similarity index 80%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.6.query.sqlpp
index 0b6d882..5e8087b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf38_no_recursion/udf38_no_recursion.6.query.sqlpp
@@ -16,10 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-# param data:multipart_text=bogus
-/admin/udf
+/*
+ * Description : No recursion
+ */
+
+use test;
+
+select r, f5a(r, r+1) f5a, f5b(r, r+1) f5b, f5c(r, r+1) f5c, f5d(r, r+1) f5d, f5e(r, r+1) f5e, f5f(r, r+1) f5f
+from range(1,2) r
+order by r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf39_illegal_call/udf39_illegal_call.1.ddl.sqlpp
similarity index 76%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf39_illegal_call/udf39_illegal_call.1.ddl.sqlpp
index 0b6d882..b7e7b81 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf39_illegal_call/udf39_illegal_call.1.ddl.sqlpp
@@ -16,10 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-# param data:multipart_text=bogus
-/admin/udf
+/*
+ * Description : Cannot call a declared function from
+ * a stored function
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use test;
+
+declare function f1a(a) { -a };
+
+create function f1b(b) { f1a(b) + f1a(b) };
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf39_illegal_call/udf39_illegal_call.2.ddl.sqlpp
similarity index 75%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf39_illegal_call/udf39_illegal_call.2.ddl.sqlpp
index 0b6d882..0ebb577 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/invalid_library_requests/library_list_api_multipart.4.post.http
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf39_illegal_call/udf39_illegal_call.2.ddl.sqlpp
@@ -16,10 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-# auth admin:admin
-# param dataverse:multipart_text=Default
-# param name:multipart_text=testlib
-# param type:multipart_text=java
-# param data:multipart_text=bogus
-/admin/udf
+/*
+ * Description : Cannot call a declared function from
+ * a stored function (varargs)
+ */
+
+use test;
+
+declare function f2a(...) { - args[0] - args[1] };
+
+create function f2b(...) { f2a(args[0], args[1]) + f2a(args[1], args[0]) };
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/library_list_api_multipart/library_list_api.5.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/library_list_api_multipart/library_list_api.5.regexjson
index c896e0d..f0cb7cf 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/library_list_api_multipart/library_list_api.5.regexjson
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/library_list_api_multipart/library_list_api.5.regexjson
@@ -1,5 +1,5 @@
[{
- "dataverse": ["external", "lib", "test"],
+ "dataverse": "external/lib/test",
"hash_md5": "R{[a-zA-Z0-9-]+}",
"name": "testlib"
},
@@ -9,12 +9,12 @@
"name": "testlib"
},
{
- "dataverse": ["externallibtest", "foo"],
+ "dataverse": "externallibtest/foo",
"hash_md5": "R{[a-zA-Z0-9-]+}",
"name": "testlib"
},
{
- "dataverse": ["externallibtest", "foo", "bar"],
+ "dataverse": "externallibtest/foo/bar",
"hash_md5": "R{[a-zA-Z0-9-]+}",
"name": "testlib"
}]
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf38_no_recursion/udf38_no_recursion.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf38_no_recursion/udf38_no_recursion.2.adm
new file mode 100644
index 0000000..c82ed63
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf38_no_recursion/udf38_no_recursion.2.adm
@@ -0,0 +1,2 @@
+{ "r": 1, "f1a": -1, "f1b": -2 }
+{ "r": 2, "f1a": -2, "f1b": -4 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf38_no_recursion/udf38_no_recursion.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf38_no_recursion/udf38_no_recursion.4.adm
new file mode 100644
index 0000000..5c663b8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf38_no_recursion/udf38_no_recursion.4.adm
@@ -0,0 +1,2 @@
+{ "r": 1, "f3a": -1, "f3b": -1, "f3c": -2, "f3d": -4, "f3e": -8, "f3f": -16 }
+{ "r": 2, "f3a": -2, "f3b": -2, "f3c": -4, "f3d": -8, "f3e": -16, "f3f": -32 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf38_no_recursion/udf38_no_recursion.6.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf38_no_recursion/udf38_no_recursion.6.adm
new file mode 100644
index 0000000..6389c0d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf38_no_recursion/udf38_no_recursion.6.adm
@@ -0,0 +1,2 @@
+{ "r": 1, "f5a": -3, "f5b": -3, "f5c": -6, "f5d": -12, "f5e": -24, "f5f": -48 }
+{ "r": 2, "f5a": -5, "f5b": -5, "f5c": -10, "f5d": -20, "f5e": -40, "f5f": -80 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/group-by/grouping-sets-2/grouping-sets-2.17.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/group-by/grouping-sets-2/grouping-sets-2.17.ast
index f57186c..3523c8e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/group-by/grouping-sets-2/grouping-sets-2.17.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/group-by/grouping-sets-2/grouping-sets-2.17.ast
@@ -8,32 +8,32 @@
]
FROM [ (
SELECT [
- OperatorExpr [
- FunctionCall asterix.to-string@1[
- FunctionCall asterix.if-null[
- Variable [ Name=$four ]
- LiteralExpr [STRING] [null]
+ FunctionCall asterix.string-concat@1[
+ OrderedListConstructor [
+ FunctionCall asterix.to-string@1[
+ FunctionCall asterix.if-null[
+ Variable [ Name=$four ]
+ LiteralExpr [STRING] [null]
+ ]
]
- ]
- ||
- LiteralExpr [STRING] [,]
- ||
- FunctionCall asterix.to-string@1[
- FunctionCall asterix.sql-sum@1[
- (
- SELECT ELEMENT [
- FieldAccessor [
+ LiteralExpr [STRING] [,]
+ FunctionCall asterix.to-string@1[
+ FunctionCall asterix.sql-sum@1[
+ (
+ SELECT ELEMENT [
FieldAccessor [
- Variable [ Name=#5 ]
- Field=tenk
+ FieldAccessor [
+ Variable [ Name=#5 ]
+ Field=tenk
+ ]
+ Field=two
]
- Field=two
- ]
- ]
- FROM [ Variable [ Name=#1 ]
- AS Variable [ Name=#5 ]
- ]
- )
+ ]
+ FROM [ Variable [ Name=#1 ]
+ AS Variable [ Name=#5 ]
+ ]
+ )
+ ]
]
]
]
@@ -60,32 +60,32 @@
UNION
SELECT [
- OperatorExpr [
- FunctionCall asterix.to-string@1[
- FunctionCall asterix.if-null[
- Variable [ Name=$four ]
- LiteralExpr [STRING] [null]
+ FunctionCall asterix.string-concat@1[
+ OrderedListConstructor [
+ FunctionCall asterix.to-string@1[
+ FunctionCall asterix.if-null[
+ Variable [ Name=$four ]
+ LiteralExpr [STRING] [null]
+ ]
]
- ]
- ||
- LiteralExpr [STRING] [,]
- ||
- FunctionCall asterix.to-string@1[
- FunctionCall asterix.sql-sum@1[
- (
- SELECT ELEMENT [
- FieldAccessor [
+ LiteralExpr [STRING] [,]
+ FunctionCall asterix.to-string@1[
+ FunctionCall asterix.sql-sum@1[
+ (
+ SELECT ELEMENT [
FieldAccessor [
- Variable [ Name=#6 ]
- Field=tenk
+ FieldAccessor [
+ Variable [ Name=#6 ]
+ Field=tenk
+ ]
+ Field=two
]
- Field=two
- ]
- ]
- FROM [ Variable [ Name=#1 ]
- AS Variable [ Name=#6 ]
- ]
- )
+ ]
+ FROM [ Variable [ Name=#1 ]
+ AS Variable [ Name=#6 ]
+ ]
+ )
+ ]
]
]
]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/group-by/grouping-sets-2/grouping-sets-2.8.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/group-by/grouping-sets-2/grouping-sets-2.8.ast
index a7b455a..c3b4dec 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/group-by/grouping-sets-2/grouping-sets-2.8.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/group-by/grouping-sets-2/grouping-sets-2.8.ast
@@ -8,20 +8,20 @@
]
FROM [ (
SELECT [
- OperatorExpr [
- FunctionCall asterix.to-string@1[
- FunctionCall asterix.if-null[
- Variable [ Name=$two ]
- LiteralExpr [STRING] [null]
+ FunctionCall asterix.string-concat@1[
+ OrderedListConstructor [
+ FunctionCall asterix.to-string@1[
+ FunctionCall asterix.if-null[
+ Variable [ Name=$two ]
+ LiteralExpr [STRING] [null]
+ ]
]
- ]
- ||
- LiteralExpr [STRING] [,]
- ||
- FunctionCall asterix.to-string@1[
- FunctionCall asterix.if-null[
- Variable [ Name=$four ]
- LiteralExpr [STRING] [null]
+ LiteralExpr [STRING] [,]
+ FunctionCall asterix.to-string@1[
+ FunctionCall asterix.if-null[
+ Variable [ Name=$four ]
+ LiteralExpr [STRING] [null]
+ ]
]
]
]
@@ -72,20 +72,20 @@
]
UNION
SELECT [
- OperatorExpr [
- FunctionCall asterix.to-string@1[
- FunctionCall asterix.if-null[
- Variable [ Name=$two ]
- LiteralExpr [STRING] [null]
+ FunctionCall asterix.string-concat@1[
+ OrderedListConstructor [
+ FunctionCall asterix.to-string@1[
+ FunctionCall asterix.if-null[
+ Variable [ Name=$two ]
+ LiteralExpr [STRING] [null]
+ ]
]
- ]
- ||
- LiteralExpr [STRING] [,]
- ||
- FunctionCall asterix.to-string@1[
- FunctionCall asterix.if-null[
- Variable [ Name=$four ]
- LiteralExpr [STRING] [null]
+ LiteralExpr [STRING] [,]
+ FunctionCall asterix.to-string@1[
+ FunctionCall asterix.if-null[
+ Variable [ Name=$four ]
+ LiteralExpr [STRING] [null]
+ ]
]
]
]
@@ -134,20 +134,20 @@
]
UNION
SELECT [
- OperatorExpr [
- FunctionCall asterix.to-string@1[
- FunctionCall asterix.if-null[
- Variable [ Name=$two ]
- LiteralExpr [STRING] [null]
+ FunctionCall asterix.string-concat@1[
+ OrderedListConstructor [
+ FunctionCall asterix.to-string@1[
+ FunctionCall asterix.if-null[
+ Variable [ Name=$two ]
+ LiteralExpr [STRING] [null]
+ ]
]
- ]
- ||
- LiteralExpr [STRING] [,]
- ||
- FunctionCall asterix.to-string@1[
- FunctionCall asterix.if-null[
- Variable [ Name=$four ]
- LiteralExpr [STRING] [null]
+ LiteralExpr [STRING] [,]
+ FunctionCall asterix.to-string@1[
+ FunctionCall asterix.if-null[
+ Variable [ Name=$four ]
+ LiteralExpr [STRING] [null]
+ ]
]
]
]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/misc/ifthenelse_01/ifthenelse_01.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/misc/ifthenelse_01/ifthenelse_01.3.ast
index f16c720..981cc39 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/misc/ifthenelse_01/ifthenelse_01.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/misc/ifthenelse_01/ifthenelse_01.3.ast
@@ -1,16 +1,10 @@
DataverseUse test
Query:
SELECT ELEMENT [
-CASE OperatorExpr [
- LiteralExpr [LONG] [2]
- >
- LiteralExpr [LONG] [1]
- ]
-
-WHEN LiteralExpr [TRUE]
-THEN LiteralExpr [LONG] [20]
-
-ELSE LiteralExpr [LONG] [10]
-
-END
+FunctionCall asterix.switch-case[
+ LiteralExpr [TRUE]
+ LiteralExpr [TRUE]
+ LiteralExpr [LONG] [20]
+ LiteralExpr [LONG] [10]
+]
]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/string/like_01/like_01.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/string/like_01/like_01.3.ast
index ac04a07..d5c1517 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/string/like_01/like_01.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/string/like_01/like_01.3.ast
@@ -2,24 +2,20 @@
Query:
SELECT ELEMENT [
OrderedListConstructor [
- OperatorExpr [
+ FunctionCall asterix.like@2[
LiteralExpr [STRING] [A6BBB]
- like
LiteralExpr [STRING] [_6%]
]
- OperatorExpr [
+ FunctionCall asterix.like@2[
LiteralExpr [STRING] [A8BBB]
- like
LiteralExpr [STRING] [_6%]
]
- OperatorExpr [
+ FunctionCall asterix.like@2[
LiteralExpr [STRING] [+0300]
- like
LiteralExpr [STRING] [+03%]
]
- OperatorExpr [
+ FunctionCall asterix.like@2[
LiteralExpr [STRING] [?0300]
- like
LiteralExpr [STRING] [?03%]
]
]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/string/like_null/like_null.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/string/like_null/like_null.3.ast
index a829f6b..649e47d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/string/like_null/like_null.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/string/like_null/like_null.3.ast
@@ -4,18 +4,16 @@
(
LiteralExpr [STRING] [field1]
:
- OperatorExpr [
+ FunctionCall asterix.like@2[
LiteralExpr [STRING] [A8BBB]
- like
LiteralExpr [NULL]
]
)
(
LiteralExpr [STRING] [field2]
:
- OperatorExpr [
+ FunctionCall asterix.like@2[
LiteralExpr [NULL]
- like
LiteralExpr [STRING] [_6%]
]
)
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q08_national_market_share/q08_national_market_share.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q08_national_market_share/q08_national_market_share.3.ast
index 30243af..05c1b37 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q08_national_market_share/q08_national_market_share.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q08_national_market_share/q08_national_market_share.3.ast
@@ -14,30 +14,28 @@
FunctionCall asterix.sum@1[
(
SELECT ELEMENT [
- CASE LiteralExpr [TRUE]
-
- WHEN OperatorExpr [
- FieldAccessor [
- FieldAccessor [
- Variable [ Name=$i ]
- Field=t
- ]
- Field=s_name
- ]
- =
- LiteralExpr [STRING] [BRAZIL]
- ]
- THEN FieldAccessor [
+ FunctionCall asterix.switch-case[
+ LiteralExpr [TRUE]
+ OperatorExpr [
+ FieldAccessor [
FieldAccessor [
Variable [ Name=$i ]
Field=t
]
- Field=revenue
+ Field=s_name
]
-
- ELSE LiteralExpr [DOUBLE] [0.0]
-
- END
+ =
+ LiteralExpr [STRING] [BRAZIL]
+ ]
+ FieldAccessor [
+ FieldAccessor [
+ Variable [ Name=$i ]
+ Field=t
+ ]
+ Field=revenue
+ ]
+ LiteralExpr [DOUBLE] [0.0]
+ ]
]
FROM [ Variable [ Name=$g ]
AS Variable [ Name=$i ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.ast
index f6b7ea4..d18bf81 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.ast
@@ -13,41 +13,14 @@
FunctionCall asterix.sum@1[
(
SELECT ELEMENT [
- CASE OperatorExpr [
- OperatorExpr [
- FieldAccessor [
- FieldAccessor [
- Variable [ Name=$i ]
- Field=o
- ]
- Field=o_orderpriority
- ]
- =
- LiteralExpr [STRING] [1-URGENT]
- ]
- or
- OperatorExpr [
- FieldAccessor [
- FieldAccessor [
- Variable [ Name=$i ]
- Field=o
- ]
- Field=o_orderpriority
- ]
- =
- LiteralExpr [STRING] [2-HIGH]
- ]
- ]
-
- WHEN LiteralExpr [TRUE]
- THEN LiteralExpr [LONG] [1]
-
- WHEN LiteralExpr [FALSE]
- THEN LiteralExpr [LONG] [0]
-
- ELSE LiteralExpr [NULL]
-
- END
+ FunctionCall asterix.switch-case[
+ LiteralExpr [TRUE]
+ LiteralExpr [TRUE]
+ LiteralExpr [LONG] [1]
+ LiteralExpr [FALSE]
+ LiteralExpr [LONG] [0]
+ LiteralExpr [NULL]
+ ]
]
FROM [ Variable [ Name=$g ]
AS Variable [ Name=$i ]
@@ -61,41 +34,14 @@
FunctionCall asterix.sum@1[
(
SELECT ELEMENT [
- CASE OperatorExpr [
- OperatorExpr [
- FieldAccessor [
- FieldAccessor [
- Variable [ Name=$i ]
- Field=o
- ]
- Field=o_orderpriority
- ]
- =
- LiteralExpr [STRING] [1-URGENT]
- ]
- or
- OperatorExpr [
- FieldAccessor [
- FieldAccessor [
- Variable [ Name=$i ]
- Field=o
- ]
- Field=o_orderpriority
- ]
- =
- LiteralExpr [STRING] [2-HIGH]
- ]
- ]
-
- WHEN LiteralExpr [TRUE]
- THEN LiteralExpr [LONG] [0]
-
- WHEN LiteralExpr [FALSE]
- THEN LiteralExpr [LONG] [1]
-
- ELSE LiteralExpr [NULL]
-
- END
+ FunctionCall asterix.switch-case[
+ LiteralExpr [TRUE]
+ LiteralExpr [TRUE]
+ LiteralExpr [LONG] [0]
+ LiteralExpr [FALSE]
+ LiteralExpr [LONG] [1]
+ LiteralExpr [NULL]
+ ]
]
FROM [ Variable [ Name=$g ]
AS Variable [ Name=$i ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q13_customer_distribution/q13_customer_distribution.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q13_customer_distribution/q13_customer_distribution.3.ast
index d6c8ace..c3cbcfd 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q13_customer_distribution/q13_customer_distribution.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q13_customer_distribution/q13_customer_distribution.3.ast
@@ -93,13 +93,14 @@
]
]
and
- OperatorExpr [
- FieldAccessor [
- Variable [ Name=$o ]
- Field=o_comment
+ FunctionCall algebricks.not@1[
+ FunctionCall asterix.like@2[
+ FieldAccessor [
+ Variable [ Name=$o ]
+ Field=o_comment
+ ]
+ LiteralExpr [STRING] [%special%requests%]
]
- not_like
- LiteralExpr [STRING] [%special%requests%]
]
]
)
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.ast
index 8aaceb4..76cc0a1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.ast
@@ -7,35 +7,26 @@
FunctionCall asterix.sum@1[
(
SELECT ELEMENT [
- CASE OperatorExpr [
+ FunctionCall asterix.switch-case[
+ LiteralExpr [TRUE]
+ LiteralExpr [TRUE]
+ OperatorExpr [
+ FieldAccessor [
+ Variable [ Name=$i ]
+ Field=l_extendedprice
+ ]
+ *
+ OperatorExpr [
+ Variable [ Name=$t ]
+ -
FieldAccessor [
Variable [ Name=$i ]
- Field=p_type
- ]
- like
- LiteralExpr [STRING] [PROMO%]
- ]
-
- WHEN LiteralExpr [TRUE]
- THEN OperatorExpr [
- FieldAccessor [
- Variable [ Name=$i ]
- Field=l_extendedprice
- ]
- *
- OperatorExpr [
- Variable [ Name=$t ]
- -
- FieldAccessor [
- Variable [ Name=$i ]
- Field=l_discount
- ]
+ Field=l_discount
]
]
-
- ELSE LiteralExpr [DOUBLE] [0.0]
-
- END
+ ]
+ LiteralExpr [DOUBLE] [0.0]
+ ]
]
FROM [ (
SELECT ELEMENT [
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q08_national_market_share/q08_national_market_share.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q08_national_market_share/q08_national_market_share.3.ast
index 26016cc..8aae309 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q08_national_market_share/q08_national_market_share.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q08_national_market_share/q08_national_market_share.3.ast
@@ -14,27 +14,17 @@
FunctionCall asterix.sum@1[
(
SELECT ELEMENT [
- CASE OperatorExpr [
- FieldAccessor [
- Variable [ Name=$i ]
- Field=s_name
- ]
- =
- LiteralExpr [STRING] [BRAZIL]
- ]
-
- WHEN LiteralExpr [TRUE]
- THEN FieldAccessor [
- Variable [ Name=$i ]
- Field=revenue
- ]
-
- WHEN LiteralExpr [FALSE]
- THEN LiteralExpr [DOUBLE] [0.0]
-
- ELSE LiteralExpr [NULL]
-
- END
+ FunctionCall asterix.switch-case[
+ LiteralExpr [TRUE]
+ LiteralExpr [TRUE]
+ FieldAccessor [
+ Variable [ Name=$i ]
+ Field=revenue
+ ]
+ LiteralExpr [FALSE]
+ LiteralExpr [DOUBLE] [0.0]
+ LiteralExpr [NULL]
+ ]
]
FROM [ (
SELECT ELEMENT [
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q12_shipping/q12_shipping.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q12_shipping/q12_shipping.3.ast
index 1590d2d..c5ac9cc 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q12_shipping/q12_shipping.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q12_shipping/q12_shipping.3.ast
@@ -13,35 +13,14 @@
FunctionCall asterix.sum@1[
(
SELECT ELEMENT [
- CASE OperatorExpr [
- OperatorExpr [
- FieldAccessor [
- Variable [ Name=$i ]
- Field=o_orderpriority
- ]
- =
- LiteralExpr [STRING] [1-URGENT]
- ]
- or
- OperatorExpr [
- FieldAccessor [
- Variable [ Name=$i ]
- Field=o_orderpriority
- ]
- =
- LiteralExpr [STRING] [2-HIGH]
- ]
- ]
-
- WHEN LiteralExpr [TRUE]
- THEN LiteralExpr [LONG] [1]
-
- WHEN LiteralExpr [FALSE]
- THEN LiteralExpr [LONG] [0]
-
- ELSE LiteralExpr [NULL]
-
- END
+ FunctionCall asterix.switch-case[
+ LiteralExpr [TRUE]
+ LiteralExpr [TRUE]
+ LiteralExpr [LONG] [1]
+ LiteralExpr [FALSE]
+ LiteralExpr [LONG] [0]
+ LiteralExpr [NULL]
+ ]
]
FROM [ (
SELECT ELEMENT [
@@ -65,32 +44,30 @@
FunctionCall asterix.sum@1[
(
SELECT ELEMENT [
- CASE LiteralExpr [TRUE]
-
- WHEN OperatorExpr [
- OperatorExpr [
- FieldAccessor [
- Variable [ Name=$i ]
- Field=o_orderpriority
- ]
- =
- LiteralExpr [STRING] [1-URGENT]
+ FunctionCall asterix.switch-case[
+ LiteralExpr [TRUE]
+ OperatorExpr [
+ OperatorExpr [
+ FieldAccessor [
+ Variable [ Name=$i ]
+ Field=o_orderpriority
]
- or
- OperatorExpr [
- FieldAccessor [
- Variable [ Name=$i ]
- Field=o_orderpriority
- ]
- =
- LiteralExpr [STRING] [2-HIGH]
- ]
+ =
+ LiteralExpr [STRING] [1-URGENT]
]
- THEN LiteralExpr [LONG] [0]
-
- ELSE LiteralExpr [LONG] [1]
-
- END
+ or
+ OperatorExpr [
+ FieldAccessor [
+ Variable [ Name=$i ]
+ Field=o_orderpriority
+ ]
+ =
+ LiteralExpr [STRING] [2-HIGH]
+ ]
+ ]
+ LiteralExpr [LONG] [0]
+ LiteralExpr [LONG] [1]
+ ]
]
FROM [ (
SELECT ELEMENT [
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q13_customer_distribution/q13_customer_distribution.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q13_customer_distribution/q13_customer_distribution.3.ast
index 21dcbf3..9c7dc06 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q13_customer_distribution/q13_customer_distribution.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q13_customer_distribution/q13_customer_distribution.3.ast
@@ -93,13 +93,14 @@
]
]
and
- OperatorExpr [
- FieldAccessor [
- Variable [ Name=$o ]
- Field=o_comment
+ FunctionCall algebricks.not@1[
+ FunctionCall asterix.like@2[
+ FieldAccessor [
+ Variable [ Name=$o ]
+ Field=o_comment
+ ]
+ LiteralExpr [STRING] [%special%requests%]
]
- not_like
- LiteralExpr [STRING] [%special%requests%]
]
]
)
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.ast
index 8aaceb4..76cc0a1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.ast
@@ -7,35 +7,26 @@
FunctionCall asterix.sum@1[
(
SELECT ELEMENT [
- CASE OperatorExpr [
+ FunctionCall asterix.switch-case[
+ LiteralExpr [TRUE]
+ LiteralExpr [TRUE]
+ OperatorExpr [
+ FieldAccessor [
+ Variable [ Name=$i ]
+ Field=l_extendedprice
+ ]
+ *
+ OperatorExpr [
+ Variable [ Name=$t ]
+ -
FieldAccessor [
Variable [ Name=$i ]
- Field=p_type
- ]
- like
- LiteralExpr [STRING] [PROMO%]
- ]
-
- WHEN LiteralExpr [TRUE]
- THEN OperatorExpr [
- FieldAccessor [
- Variable [ Name=$i ]
- Field=l_extendedprice
- ]
- *
- OperatorExpr [
- Variable [ Name=$t ]
- -
- FieldAccessor [
- Variable [ Name=$i ]
- Field=l_discount
- ]
+ Field=l_discount
]
]
-
- ELSE LiteralExpr [DOUBLE] [0.0]
-
- END
+ ]
+ LiteralExpr [DOUBLE] [0.0]
+ ]
]
FROM [ (
SELECT ELEMENT [
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.3.ast
index 86cd5b1..e44fae6 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.3.ast
@@ -198,18 +198,16 @@
]
Let Variable [ Name=$percent_rank_result_delta ]
:=
- CASE LiteralExpr [TRUE]
-
- WHEN OperatorExpr [
- Variable [ Name=$percent_rank_result_delta_raw ]
- <
- LiteralExpr [DOUBLE] [0.001]
- ]
- THEN LiteralExpr [LONG] [0]
-
- ELSE Variable [ Name=$percent_rank_result_delta_raw ]
-
- END
+ FunctionCall asterix.switch-case[
+ LiteralExpr [TRUE]
+ OperatorExpr [
+ Variable [ Name=$percent_rank_result_delta_raw ]
+ <
+ LiteralExpr [DOUBLE] [0.001]
+ ]
+ LiteralExpr [LONG] [0]
+ Variable [ Name=$percent_rank_result_delta_raw ]
+ ]
Group All
GROUP AS Variable [ Name=#1 ]
(
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_it_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_it_sqlpp.xml
index 28bbb98..28cbabb 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_it_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_it_sqlpp.xml
@@ -65,8 +65,8 @@
<compilation-unit name="invalid_library_requests">
<output-dir compare="Text">mysum_bad_credential</output-dir>
<expected-error>ASX3042: Unsupported function language badType</expected-error>
- <expected-error>ASX1110: The parameters \"type\" and \"delete\" cannot be provided at the same time</expected-error>
- <expected-error>ASX0049: Parameter(s) type or delete must be specified</expected-error>
+ <expected-error>ASX1117: Cannot find library with name testlib</expected-error>
+ <expected-error>ASX0049: Parameter(s) type must be specified</expected-error>
<expected-error>ASX0047: Invalid value for parameter \"data\": Attribute</expected-error>
<expected-error>ASX0049: Parameter(s) data must be specified</expected-error>
</compilation-unit>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index 6e212b1..7277c0b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -4855,7 +4855,7 @@
<test-case FilePath="dml">
<compilation-unit name="upsert-dataset-with-meta">
<output-dir compare="Text">upsert-dataset-with-meta</output-dir>
- <expected-error>upsert into dataset is not supported on datasets with meta record</expected-error>
+ <expected-error>upsert into dataset is not supported on datasets with meta records</expected-error>
</compilation-unit>
</test-case>
<test-case FilePath="dml">
@@ -12756,6 +12756,31 @@
</compilation-unit>
</test-case>
<test-case FilePath="user-defined-functions">
+ <compilation-unit name="udf37_recursion">
+ <output-dir compare="Text">none</output-dir>
+ <expected-error>ASX1149: Illegal function recursion (in line 24, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function recursion (in line 25, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function recursion (in line 26, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function recursion (in line 27, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function recursion (in line 28, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function recursion (in line 29, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function recursion (in line 30, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function recursion (in line 31, at column 1)</expected-error>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="user-defined-functions">
+ <compilation-unit name="udf38_no_recursion">
+ <output-dir compare="Text">udf38_no_recursion</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="user-defined-functions">
+ <compilation-unit name="udf39_illegal_call">
+ <output-dir compare="Text">none</output-dir>
+ <expected-error>ASX1150: Illegal use of function test.f1a(1) (in line 32, at column 26)</expected-error>
+ <expected-error>ASX1150: Illegal use of function test.f2a(...) (in line 29, at column 28)</expected-error>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="user-defined-functions">
<compilation-unit name="f01">
<output-dir compare="Text">f01</output-dir>
<expected-error>ASX1081: Cannot find function with signature test.tinyint()</expected-error>
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IIdentifierMapper.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IIdentifierMapper.java
index 8687239..b6bce47 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IIdentifierMapper.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IIdentifierMapper.java
@@ -22,6 +22,12 @@
@FunctionalInterface
public interface IIdentifierMapper {
- String map(String identifier);
+ enum Modifier {
+ SINGULAR,
+ PLURAL,
+ NONE
+ }
+
+ String map(String identifier, Modifier modifier);
}
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/TransactionProperties.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/TransactionProperties.java
index d67e9a6..f7703fb 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/TransactionProperties.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/TransactionProperties.java
@@ -18,6 +18,7 @@
*/
package org.apache.asterix.common.config;
+import static org.apache.asterix.common.api.IIdentifierMapper.Modifier.SINGULAR;
import static org.apache.asterix.common.utils.IdentifierUtil.dataset;
import static org.apache.hyracks.control.common.config.OptionTypes.BOOLEAN;
import static org.apache.hyracks.control.common.config.OptionTypes.INTEGER_BYTE_UNIT;
@@ -42,7 +43,8 @@
TXN_DATASET_CHECKPOINT_INTERVAL(
POSITIVE_INTEGER,
(int) TimeUnit.MINUTES.toSeconds(60),
- "The interval (in seconds) after which a " + dataset() + " is considered idle and persisted to disk"),
+ "The interval (in seconds) after which " + dataset(SINGULAR) + " is considered idle and persisted to "
+ + "disk"),
TXN_LOG_BUFFER_NUMPAGES(POSITIVE_INTEGER, 8, "The number of pages in the transaction log tail"),
TXN_LOG_BUFFER_PAGESIZE(
INTEGER_BYTE_UNIT,
@@ -66,7 +68,7 @@
TXN_LOCK_ESCALATIONTHRESHOLD(
NONNEGATIVE_INTEGER,
1000,
- "The maximum number of entity locks to obtain before upgrading to a " + dataset() + " lock"),
+ "The maximum number of entity locks to obtain before upgrading to " + dataset(SINGULAR) + " lock"),
TXN_LOCK_SHRINKTIMER(
POSITIVE_INTEGER,
5000,
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
index 0406132..1be99f0 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
@@ -233,12 +233,14 @@
UNKNOWN_FEED_POLICY(1146),
CANNOT_DROP_DATAVERSE_DEPENDENT_EXISTS(1147),
CANNOT_DROP_OBJECT_DEPENDENT_EXISTS(1148),
- FULL_TEXT_CONFIG_ALREADY_EXISTS(1149),
- FULL_TEXT_FILTER_ALREADY_EXISTS(1150),
+ ILLEGAL_FUNCTION_RECURSION(1149),
+ ILLEGAL_FUNCTION_USE(1150),
FULL_TEXT_CONFIG_NOT_FOUND(1151),
FULL_TEXT_FILTER_NOT_FOUND(1152),
FULL_TEXT_DEFAULT_CONFIG_CANNOT_BE_DELETED_OR_CREATED(1153),
COMPILATION_INCOMPATIBLE_INDEX_TYPE(1154),
+ FULL_TEXT_CONFIG_ALREADY_EXISTS(1155),
+ FULL_TEXT_FILTER_ALREADY_EXISTS(1156),
// Feed errors
DATAFLOW_ILLEGAL_STATE(3001),
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierMappingUtil.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierMappingUtil.java
index c52f27a..8157125 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierMappingUtil.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierMappingUtil.java
@@ -19,11 +19,48 @@
package org.apache.asterix.common.utils;
+import static org.apache.asterix.common.utils.IdentifierUtil.DATASET;
+import static org.apache.asterix.common.utils.IdentifierUtil.DATAVERSE;
+
import org.apache.asterix.common.api.IIdentifierMapper;
+import org.apache.asterix.common.api.IIdentifierMapper.Modifier;
public class IdentifierMappingUtil {
- private static final IIdentifierMapper DEFAULT_MAPPER = identifier -> identifier;
+ private static final String SINGULAR_DATASET = "a dataset";
+ private static final String PLURAL_DATASET = "datasets";
+
+ private static final String SINGULAR_DATAVERSE = "a dataverse";
+ private static final String PLURAL_DATAVERSE = "dataverses";
+
+ private static final IIdentifierMapper DEFAULT_MAPPER = (identifier, modifier) -> {
+ switch (identifier) {
+ case DATASET:
+ switch (modifier) {
+ case NONE:
+ return DATASET;
+ case SINGULAR:
+ return SINGULAR_DATASET;
+ case PLURAL:
+ return PLURAL_DATASET;
+ default:
+ throw new IllegalArgumentException("unknown modifier " + modifier);
+ }
+ case DATAVERSE:
+ switch (modifier) {
+ case NONE:
+ return DATAVERSE;
+ case SINGULAR:
+ return SINGULAR_DATAVERSE;
+ case PLURAL:
+ return PLURAL_DATAVERSE;
+ default:
+ throw new IllegalArgumentException("unknown modifier " + modifier);
+ }
+ default:
+ throw new IllegalArgumentException("unmapped identifier: " + identifier);
+ }
+ };
private static IIdentifierMapper mapper = DEFAULT_MAPPER;
@@ -34,8 +71,8 @@
IdentifierMappingUtil.mapper = mapper;
}
- public static String map(String key) {
- return mapper.map(key);
+ public static String map(String key, Modifier modifier) {
+ return mapper.map(key, modifier);
}
}
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierUtil.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierUtil.java
index ebdd740..88b7190 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierUtil.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierUtil.java
@@ -19,16 +19,23 @@
package org.apache.asterix.common.utils;
+import static org.apache.asterix.common.api.IIdentifierMapper.Modifier;
+import static org.apache.asterix.common.api.IIdentifierMapper.Modifier.NONE;
+
public class IdentifierUtil {
public static final String DATASET = "dataset";
public static final String DATAVERSE = "dataverse";
public static String dataset() {
- return IdentifierMappingUtil.map(DATASET);
+ return IdentifierMappingUtil.map(DATASET, NONE);
+ }
+
+ public static String dataset(Modifier modifier) {
+ return IdentifierMappingUtil.map(DATASET, modifier);
}
public static String dataverse() {
- return IdentifierMappingUtil.map(DATAVERSE);
+ return IdentifierMappingUtil.map(DATAVERSE, NONE);
}
}
diff --git a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
index 7dc2c56..591fa9a 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -142,7 +142,7 @@
1052 = Cannot create index with the same field \"%1$s\" specified more than once.
1053 = Cannot create primary index on external dataset.
1054 = Compilation failed due to some problem in the query plan.
-1055 = Incompatible function language: %1$s.
+1055 = Incompatible implementation language %1$s for function %2$s. Expected language %3$s.
1056 = Too many options were specified for %1$s
1057 = Expression of type %1$s is not supported in constant record
1058 = Literal of type %1$s is not supported in constant record
@@ -235,12 +235,14 @@
1146 = Cannot find feed policy with name %1$s
1147 = Cannot drop dataverse: %1$s %2$s being used by %3$s %4$s
1148 = Cannot drop %1$s %2$s being used by %3$s %4$s
-1149 = Full-text config %1$s already exists
-1150 = Full-text filter %1$s already exists
+1149 = Illegal function recursion
+1150 = Illegal use of function %1$s
1151 = Full-text config %1$s not found
1152 = Full-text filter %1$s not found
1153 = Default full-text config with a name of null cannot be deleted or created
1154 = Incompatible index type %1$s
+1155 = Full-text config %1$s already exists
+1156 = Full-text filter %1$s already exists
# Feed Errors
3001 = Illegal state.
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
index 0fe58ff..3df490c 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
@@ -35,7 +35,8 @@
List<String> parseMultipartIdentifier() throws CompilationException;
- FunctionDecl parseFunctionBody(FunctionSignature signature, List<String> paramNames) throws CompilationException;
+ FunctionDecl parseFunctionBody(FunctionSignature signature, List<String> paramNames, boolean isStored)
+ throws CompilationException;
/**
* Gets the warnings generated during parsing
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
index 3e1851c..f28de55 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
@@ -19,40 +19,37 @@
package org.apache.asterix.lang.common.base;
import java.util.Collection;
-import java.util.List;
import java.util.Set;
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.lang.common.expression.AbstractCallExpression;
import org.apache.asterix.lang.common.expression.VariableExpr;
import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
-import org.apache.asterix.lang.common.statement.FunctionDecl;
import org.apache.asterix.lang.common.struct.VarIdentifier;
-import org.apache.asterix.metadata.declared.MetadataProvider;
public interface IQueryRewriter {
/**
* Rewrite a query at the AST level.
- * @param declaredFunctions,
- * a list of declared functions associated with the query.
* @param topExpr,
* the query to be rewritten.
- * @param metadataProvider,
- * providing the definition of created (i.e., stored) user-defined functions.
* @param context
* rewriting context
+ * @param allowNonStoredUdfCalls
+ * whether calls to non-stored user-defined functions should be resolved
+ * @param inlineUdfs
+ * whether user defined functions should be inlines
* @param externalVars
- * external variables
+ * statement parameters (external variables)
*/
- void rewrite(List<FunctionDecl> declaredFunctions, IReturningStatement topExpr, MetadataProvider metadataProvider,
- LangRewritingContext context, boolean inlineUdfs, Collection<VarIdentifier> externalVars)
- throws CompilationException;
+ void rewrite(LangRewritingContext context, IReturningStatement topExpr, boolean allowNonStoredUdfCalls,
+ boolean inlineUdfs, Collection<VarIdentifier> externalVars) throws CompilationException;
/**
* Find the function calls used by a given expression
*/
- Set<AbstractCallExpression> getFunctionCalls(Expression expression) throws CompilationException;
+ void getFunctionCalls(Expression expression, Collection<? super AbstractCallExpression> outCalls)
+ throws CompilationException;
/**
* Find all external variables (positional and named variables) in given expression
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/parser/FunctionParser.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/parser/FunctionParser.java
deleted file mode 100644
index d18aa86..0000000
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/parser/FunctionParser.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.asterix.lang.common.parser;
-
-import java.io.StringReader;
-
-import org.apache.asterix.common.exceptions.CompilationException;
-import org.apache.asterix.common.exceptions.ErrorCode;
-import org.apache.asterix.lang.common.base.IParser;
-import org.apache.asterix.lang.common.base.IParserFactory;
-import org.apache.asterix.lang.common.statement.FunctionDecl;
-import org.apache.asterix.metadata.entities.Function;
-import org.apache.hyracks.api.exceptions.IWarningCollector;
-
-public class FunctionParser {
-
- private final IParserFactory parserFactory;
-
- public FunctionParser(IParserFactory parserFactory) {
- this.parserFactory = parserFactory;
- }
-
- public String getLanguage() {
- return parserFactory.getLanguage();
- }
-
- public FunctionDecl getFunctionDecl(Function function, IWarningCollector warningCollector)
- throws CompilationException {
- if (!function.getLanguage().equals(getLanguage())) {
- throw new CompilationException(ErrorCode.COMPILATION_INCOMPATIBLE_FUNCTION_LANGUAGE, getLanguage(),
- function.getLanguage());
- }
- IParser parser = parserFactory.createParser(new StringReader(function.getFunctionBody()));
- try {
- FunctionDecl functionDecl = parser.parseFunctionBody(function.getSignature(), function.getParameterNames());
- if (warningCollector != null) {
- parser.getWarnings(warningCollector);
- }
- return functionDecl;
- } catch (CompilationException e) {
- throw new CompilationException(ErrorCode.COMPILATION_BAD_FUNCTION_DEFINITION, e, function.getSignature(),
- e.getMessage());
- }
- }
-}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/rewrites/LangRewritingContext.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/rewrites/LangRewritingContext.java
index 563e07e..675d0d3 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/rewrites/LangRewritingContext.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/rewrites/LangRewritingContext.java
@@ -19,21 +19,31 @@
package org.apache.asterix.lang.common.rewrites;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import org.apache.asterix.common.functions.FunctionSignature;
+import org.apache.asterix.lang.common.statement.FunctionDecl;
import org.apache.asterix.lang.common.struct.VarIdentifier;
+import org.apache.asterix.lang.common.util.FunctionUtil;
+import org.apache.asterix.metadata.declared.MetadataProvider;
import org.apache.hyracks.algebricks.core.algebra.base.Counter;
import org.apache.hyracks.api.exceptions.IWarningCollector;
public final class LangRewritingContext {
+ private final MetadataProvider metadataProvider;
private final IWarningCollector warningCollector;
- private Counter varCounter;
+ private final Map<FunctionSignature, FunctionDecl> declaredFunctions;
+ private final Counter varCounter;
private int systemVarCounter = 1;
- private Map<Integer, VarIdentifier> oldVarIdToNewVarId = new HashMap<>();
+ private final Map<Integer, VarIdentifier> oldVarIdToNewVarId = new HashMap<>();
- public LangRewritingContext(int varCounter, IWarningCollector warningCollector) {
- this.varCounter = new Counter(varCounter);
+ public LangRewritingContext(MetadataProvider metadataProvider, List<FunctionDecl> declaredFunctions,
+ IWarningCollector warningCollector, int varCounter) {
+ this.metadataProvider = metadataProvider;
this.warningCollector = warningCollector;
+ this.declaredFunctions = FunctionUtil.getFunctionMap(declaredFunctions);
+ this.varCounter = new Counter(varCounter);
}
public Counter getVarCounter() {
@@ -75,4 +85,12 @@
public IWarningCollector getWarningCollector() {
return warningCollector;
}
+
+ public MetadataProvider getMetadataProvider() {
+ return metadataProvider;
+ }
+
+ public Map<FunctionSignature, FunctionDecl> getDeclaredFunctions() {
+ return declaredFunctions;
+ }
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDecl.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDecl.java
index 4161824..2ef11ad 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDecl.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDecl.java
@@ -29,14 +29,18 @@
import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
public class FunctionDecl extends AbstractStatement {
- private FunctionSignature signature;
- private List<VarIdentifier> paramList;
+ private final FunctionSignature signature;
+ private final List<VarIdentifier> paramList;
private Expression funcBody;
+ private Expression funcBodyNormalized;
+ private final boolean isStored;
- public FunctionDecl(FunctionSignature signature, List<VarIdentifier> paramList, Expression funcBody) {
+ public FunctionDecl(FunctionSignature signature, List<VarIdentifier> paramList, Expression funcBody,
+ boolean isStored) {
this.signature = signature;
this.paramList = paramList;
this.funcBody = funcBody;
+ this.isStored = isStored;
}
public FunctionSignature getSignature() {
@@ -53,14 +57,19 @@
public void setFuncBody(Expression funcBody) {
this.funcBody = funcBody;
+ this.funcBodyNormalized = null;
}
- public void setSignature(FunctionSignature signature) {
- this.signature = signature;
+ public Expression getNormalizedFuncBody() {
+ return funcBodyNormalized;
}
- public void setParamList(List<VarIdentifier> paramList) {
- this.paramList = paramList;
+ public void setNormalizedFuncBody(Expression funcBody) {
+ this.funcBodyNormalized = funcBody;
+ }
+
+ public boolean isStored() {
+ return isStored;
}
@Override
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/FunctionUtil.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/FunctionUtil.java
index 7f4e078..50a4bf2 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/FunctionUtil.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/FunctionUtil.java
@@ -19,11 +19,14 @@
package org.apache.asterix.lang.common.util;
+import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiFunction;
@@ -34,6 +37,8 @@
import org.apache.asterix.common.functions.FunctionSignature;
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.base.IParser;
+import org.apache.asterix.lang.common.base.IParserFactory;
import org.apache.asterix.lang.common.base.IQueryRewriter;
import org.apache.asterix.lang.common.expression.AbstractCallExpression;
import org.apache.asterix.lang.common.expression.CallExpr;
@@ -41,8 +46,8 @@
import org.apache.asterix.lang.common.expression.TypeExpression;
import org.apache.asterix.lang.common.expression.TypeReferenceExpression;
import org.apache.asterix.lang.common.expression.UnorderedListTypeDefinition;
-import org.apache.asterix.lang.common.parser.FunctionParser;
import org.apache.asterix.lang.common.statement.FunctionDecl;
+import org.apache.asterix.lang.common.visitor.GatherFunctionCallsVisitor;
import org.apache.asterix.metadata.declared.MetadataProvider;
import org.apache.asterix.metadata.entities.BuiltinTypeMap;
import org.apache.asterix.metadata.entities.Dataverse;
@@ -62,6 +67,10 @@
import org.apache.hyracks.api.exceptions.IWarningCollector;
import org.apache.hyracks.api.exceptions.SourceLocation;
+import com.google.common.graph.GraphBuilder;
+import com.google.common.graph.Graphs;
+import com.google.common.graph.MutableGraph;
+
public class FunctionUtil {
public static final String IMPORT_PRIVATE_FUNCTIONS = "import-private-functions";
@@ -104,54 +113,50 @@
}
}
- @FunctionalInterface
- public interface IFunctionCollector {
- Set<AbstractCallExpression> getFunctionCalls(Expression expression) throws CompilationException;
- }
-
public static FunctionSignature resolveFunctionCall(FunctionSignature fs, SourceLocation sourceLoc,
- MetadataProvider metadataProvider, Set<FunctionSignature> declaredFunctions,
- BiFunction<String, Integer, FunctionSignature> builtinFunctionResolver) throws CompilationException {
- int arity = fs.getArity();
+ MetadataProvider metadataProvider, BiFunction<String, Integer, FunctionSignature> builtinFunctionResolver,
+ boolean searchUdfs, Map<FunctionSignature, FunctionDecl> declaredFunctionMap,
+ boolean allowNonStoredUdfCalls) throws CompilationException {
DataverseName dataverse = fs.getDataverseName();
if (dataverse == null) {
dataverse = metadataProvider.getDefaultDataverseName();
}
- boolean isBuiltinFuncDataverse =
- dataverse.equals(FunctionConstants.ASTERIX_DV) || dataverse.equals(FunctionConstants.ALGEBRICKS_DV);
-
- if (!isBuiltinFuncDataverse) {
+ if (searchUdfs && !isBuiltinFunctionDataverse(dataverse)) {
// attempt to resolve to a user-defined function
FunctionSignature fsWithDv =
- fs.getDataverseName() == null ? new FunctionSignature(dataverse, fs.getName(), arity) : fs;
- if (declaredFunctions.contains(fsWithDv)) {
- return fsWithDv;
- }
+ fs.getDataverseName() == null ? new FunctionSignature(dataverse, fs.getName(), fs.getArity()) : fs;
FunctionSignature fsWithDvVarargs =
new FunctionSignature(fsWithDv.getDataverseName(), fsWithDv.getName(), FunctionIdentifier.VARARGS);
- if (declaredFunctions.contains(fsWithDvVarargs)) {
- return fsWithDvVarargs;
+
+ FunctionDecl fd = declaredFunctionMap.get(fsWithDv);
+ if (fd == null) {
+ fd = declaredFunctionMap.get(fsWithDvVarargs);
+ }
+ if (fd != null) {
+ if (!allowNonStoredUdfCalls && !fd.isStored()) {
+ throw new CompilationException(ErrorCode.ILLEGAL_FUNCTION_USE, sourceLoc,
+ fd.getSignature().toString());
+ }
+ return fd.getSignature();
}
try {
- Function function = metadataProvider.lookupUserDefinedFunction(fsWithDv);
- if (function != null) {
- return fsWithDv;
+ Function fn = metadataProvider.lookupUserDefinedFunction(fsWithDv);
+ if (fn == null) {
+ fn = metadataProvider.lookupUserDefinedFunction(fsWithDvVarargs);
}
- function = metadataProvider.lookupUserDefinedFunction(fsWithDvVarargs);
- if (function != null) {
- return fsWithDvVarargs;
+ if (fn != null) {
+ return fn.getSignature();
}
} catch (AlgebricksException e) {
- throw new CompilationException(ErrorCode.COMPILATION_ERROR, e, sourceLoc, e.getMessage());
+ throw new CompilationException(ErrorCode.UNKNOWN_FUNCTION, e, sourceLoc, fs.toString());
}
-
// fail if the dataverse was specified in the function call but this dataverse does not exist
if (fs.getDataverseName() != null) {
Dataverse dv;
try {
dv = metadataProvider.findDataverse(dataverse);
} catch (AlgebricksException e) {
- throw new CompilationException(ErrorCode.COMPILATION_ERROR, e, sourceLoc, e.getMessage());
+ throw new CompilationException(ErrorCode.UNKNOWN_DATAVERSE, e, sourceLoc, dataverse);
}
if (dv == null) {
throw new CompilationException(ErrorCode.UNKNOWN_DATAVERSE, sourceLoc, dataverse);
@@ -165,13 +170,22 @@
if (mappedName != null) {
name = mappedName;
}
- FunctionSignature fsBuiltin = builtinFunctionResolver.apply(name, arity);
+ FunctionSignature fsBuiltin = builtinFunctionResolver.apply(name, fs.getArity());
if (fsBuiltin == null) {
throw new CompilationException(ErrorCode.UNKNOWN_FUNCTION, sourceLoc, fs.toString());
}
return fsBuiltin;
}
+ public static boolean isBuiltinFunctionSignature(FunctionSignature fs) {
+ return isBuiltinFunctionDataverse(Objects.requireNonNull(fs.getDataverseName()))
+ || BuiltinFunctions.getBuiltinFunctionInfo(fs.createFunctionIdentifier()) != null;
+ }
+
+ private static boolean isBuiltinFunctionDataverse(DataverseName dataverse) {
+ return FunctionConstants.ASTERIX_DV.equals(dataverse) || FunctionConstants.ALGEBRICKS_DV.equals(dataverse);
+ }
+
public static BiFunction<String, Integer, FunctionSignature> createBuiltinFunctionResolver(
MetadataProvider metadataProvider) {
boolean includePrivateFunctions = getImportPrivateFunctions(metadataProvider);
@@ -193,88 +207,38 @@
};
}
- /**
- * 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 warningCollector
- * for reporting warnings encountered during parsing
- * @throws CompilationException
- */
- public static List<FunctionDecl> retrieveUsedStoredFunctions(MetadataProvider metadataProvider,
- Expression expression, List<FunctionSignature> declaredFunctions, List<FunctionDecl> inputFunctionDecls,
- IFunctionCollector functionCollector, FunctionParser functionParser, IWarningCollector warningCollector)
- throws CompilationException {
- if (expression == null) {
- return Collections.emptyList();
- }
- List<FunctionDecl> functionDecls =
- inputFunctionDecls == null ? new ArrayList<>() : new ArrayList<>(inputFunctionDecls);
- Set<AbstractCallExpression> functionCalls = functionCollector.getFunctionCalls(expression);
- Set<FunctionSignature> functionSignatures = new HashSet<>();
- for (AbstractCallExpression functionCall : functionCalls) {
- switch (functionCall.getKind()) {
- case CALL_EXPRESSION:
- FunctionSignature fs = functionCall.getFunctionSignature();
- if (fs.getDataverseName() == null) {
- throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE,
- functionCall.getSourceLocation(), fs);
+ public static void checkFunctionRecursion(Map<FunctionSignature, FunctionDecl> functionDeclMap,
+ java.util.function.Function<Collection<AbstractCallExpression>, GatherFunctionCallsVisitor> gfcFactory,
+ SourceLocation sourceLoc) throws CompilationException {
+ List<AbstractCallExpression> callList = new ArrayList<>();
+ GatherFunctionCallsVisitor gfc = gfcFactory.apply(callList);
+ MutableGraph<FunctionDecl> graph = GraphBuilder.directed().allowsSelfLoops(true).build();
+ for (FunctionDecl fdFrom : functionDeclMap.values()) {
+ callList.clear();
+ fdFrom.getNormalizedFuncBody().accept(gfc, null);
+ for (AbstractCallExpression callExpr : callList) {
+ if (callExpr.getKind() == Expression.Kind.CALL_EXPRESSION) {
+ FunctionSignature callSignature = callExpr.getFunctionSignature();
+ FunctionDecl fdTo = functionDeclMap.get(callSignature);
+ if (fdTo != null) {
+ graph.putEdge(fdFrom, fdTo);
}
- if (!functionSignatures.add(fs)) {
- // already seen this signature
- continue;
- }
- if (declaredFunctions != null && declaredFunctions.contains(fs)) {
- continue;
- }
- Function function;
- try {
- function = metadataProvider.lookupUserDefinedFunction(fs);
- } catch (AlgebricksException e) {
- throw new CompilationException(ErrorCode.COMPILATION_ERROR, e, functionCall.getSourceLocation(),
- e.toString());
- }
- if (function == null || !functionParser.getLanguage().equals(function.getLanguage())) {
- // the function is either unknown, builtin, or in a different language.
- // either way we ignore it here because it will be handled by the function inlining rule later
- continue;
- }
-
- FunctionDecl functionDecl = functionParser.getFunctionDecl(function, warningCollector);
- if (functionDecls.contains(functionDecl)) {
- throw new CompilationException(ErrorCode.COMPILATION_ERROR, functionCall.getSourceLocation(),
- "Recursive invocation " + functionDecls.get(functionDecls.size() - 1).getSignature()
- + " <==> " + functionDecl.getSignature());
- }
- functionDecls.add(functionDecl);
- functionDecls = retrieveUsedStoredFunctions(metadataProvider, functionDecl.getFuncBody(),
- declaredFunctions, functionDecls, functionCollector, functionParser, warningCollector);
- break;
- case WINDOW_EXPRESSION:
- // there cannot be used-defined window functions
- break;
- default:
- throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, expression.getSourceLocation(),
- functionCall.getFunctionSignature().toString(false));
+ }
}
}
- return functionDecls;
+ if (Graphs.hasCycle(graph)) {
+ throw new CompilationException(ErrorCode.ILLEGAL_FUNCTION_RECURSION, sourceLoc);
+ }
}
public static List<List<Triple<DataverseName, String, String>>> getFunctionDependencies(IQueryRewriter rewriter,
Expression expression) throws CompilationException {
- Set<AbstractCallExpression> functionCalls = rewriter.getFunctionCalls(expression);
+ List<AbstractCallExpression> functionCalls = new ArrayList<>();
+ rewriter.getFunctionCalls(expression, functionCalls);
+ // Duplicate elimination
+ Set<FunctionSignature> seenFunctions = new HashSet<>();
+ Set<Pair<DataverseName, String>> seenDatasets = new HashSet<>();
+ Set<Pair<DataverseName, String>> seenSynonyms = new HashSet<>();
//Get the List of used functions and used datasets
List<Triple<DataverseName, String, String>> datasetDependencies = new ArrayList<>();
List<Triple<DataverseName, String, String>> functionDependencies = new ArrayList<>();
@@ -289,17 +253,23 @@
if (callExpr.getExprList().size() > 2) {
// resolved via synonym -> store synonym name as a dependency
Pair<DataverseName, String> synonymReference = parseDatasetFunctionArguments(callExpr, 2);
- synonymDependencies
- .add(new Triple<>(synonymReference.first, synonymReference.second, null));
+ if (seenSynonyms.add(synonymReference)) {
+ synonymDependencies
+ .add(new Triple<>(synonymReference.first, synonymReference.second, null));
+ }
} else {
// resolved directly -> store dataset name as a dependency
Pair<DataverseName, String> datasetReference = parseDatasetFunctionArguments(callExpr, 0);
- datasetDependencies
- .add(new Triple<>(datasetReference.first, datasetReference.second, null));
+ if (seenDatasets.add(datasetReference)) {
+ datasetDependencies
+ .add(new Triple<>(datasetReference.first, datasetReference.second, null));
+ }
}
} else if (BuiltinFunctions.getBuiltinFunctionInfo(signature.createFunctionIdentifier()) == null) {
- functionDependencies.add(new Triple<>(signature.getDataverseName(), signature.getName(),
- Integer.toString(signature.getArity())));
+ if (seenFunctions.add(signature)) {
+ functionDependencies.add(new Triple<>(signature.getDataverseName(), signature.getName(),
+ Integer.toString(signature.getArity())));
+ }
}
break;
case WINDOW_EXPRESSION:
@@ -374,14 +344,35 @@
return (value != null) && Boolean.parseBoolean(value.toLowerCase());
}
- public static Set<FunctionSignature> getFunctionSignatures(List<FunctionDecl> declaredFunctions) {
+ public static Map<FunctionSignature, FunctionDecl> getFunctionMap(List<FunctionDecl> declaredFunctions) {
if (declaredFunctions == null || declaredFunctions.isEmpty()) {
- return Collections.emptySet();
+ return Collections.emptyMap();
}
- Set<FunctionSignature> result = new HashSet<>();
+ Map<FunctionSignature, FunctionDecl> result = new HashMap<>();
for (FunctionDecl fd : declaredFunctions) {
- result.add(fd.getSignature());
+ result.put(fd.getSignature(), fd);
}
return result;
}
+
+ public static FunctionDecl parseStoredFunction(Function function, IParserFactory parserFactory,
+ IWarningCollector warningCollector, SourceLocation sourceLoc) throws CompilationException {
+ if (!function.getLanguage().equals(parserFactory.getLanguage())) {
+ throw new CompilationException(ErrorCode.COMPILATION_INCOMPATIBLE_FUNCTION_LANGUAGE, sourceLoc,
+ function.getLanguage(), function.getSignature().toString(), parserFactory.getLanguage());
+ }
+ IParser parser = parserFactory.createParser(new StringReader(function.getFunctionBody()));
+ try {
+ FunctionDecl functionDecl =
+ parser.parseFunctionBody(function.getSignature(), function.getParameterNames(), true);
+ functionDecl.setSourceLocation(sourceLoc);
+ if (warningCollector != null) {
+ parser.getWarnings(warningCollector);
+ }
+ return functionDecl;
+ } catch (CompilationException e) {
+ throw new CompilationException(ErrorCode.COMPILATION_BAD_FUNCTION_DEFINITION, e, sourceLoc,
+ function.getSignature(), e.getMessage());
+ }
+ }
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
index f1bcb93..cba6bb5 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
@@ -26,12 +26,9 @@
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.functions.FunctionSignature;
-import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.base.Expression.Kind;
import org.apache.asterix.lang.common.base.ILangExpression;
-import org.apache.asterix.lang.common.base.IQueryRewriter;
-import org.apache.asterix.lang.common.base.IRewriterFactory;
import org.apache.asterix.lang.common.clause.GroupbyClause;
import org.apache.asterix.lang.common.clause.LetClause;
import org.apache.asterix.lang.common.clause.LimitClause;
@@ -58,31 +55,26 @@
import org.apache.asterix.lang.common.struct.Identifier;
import org.apache.asterix.lang.common.struct.QuantifiedPair;
import org.apache.asterix.lang.common.struct.VarIdentifier;
+import org.apache.asterix.lang.common.util.FunctionUtil;
import org.apache.asterix.lang.common.visitor.base.AbstractQueryExpressionVisitor;
-import org.apache.asterix.metadata.declared.MetadataProvider;
-import org.apache.asterix.metadata.entities.Dataverse;
import org.apache.asterix.om.functions.BuiltinFunctions;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
import org.apache.hyracks.api.exceptions.SourceLocation;
-public abstract class AbstractInlineUdfsVisitor extends AbstractQueryExpressionVisitor<Boolean, List<FunctionDecl>> {
+public abstract class AbstractInlineUdfsVisitor extends AbstractQueryExpressionVisitor<Boolean, Void> {
protected final LangRewritingContext context;
- protected final CloneAndSubstituteVariablesVisitor cloneVisitor;
- private final IRewriterFactory rewriterFactory;
- private final List<FunctionDecl> declaredFunctions;
- private final MetadataProvider metadataProvider;
- public AbstractInlineUdfsVisitor(LangRewritingContext context, IRewriterFactory rewriterFactory,
- List<FunctionDecl> declaredFunctions, MetadataProvider metadataProvider,
+ protected final Map<FunctionSignature, FunctionDecl> usedUDFs;
+
+ protected final CloneAndSubstituteVariablesVisitor cloneVisitor;
+
+ public AbstractInlineUdfsVisitor(LangRewritingContext context, Map<FunctionSignature, FunctionDecl> usedUDFs,
CloneAndSubstituteVariablesVisitor cloneVisitor) {
this.context = context;
+ this.usedUDFs = usedUDFs;
this.cloneVisitor = cloneVisitor;
- this.rewriterFactory = rewriterFactory;
- this.declaredFunctions = declaredFunctions;
- this.metadataProvider = metadataProvider;
}
/**
@@ -96,36 +88,33 @@
throws CompilationException;
@Override
- public Boolean visit(Query q, List<FunctionDecl> arg) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(q.getBody(), arg);
+ public Boolean visit(Query q, Void arg) throws CompilationException {
+ Pair<Boolean, Expression> p = inlineUdfsInExpr(q.getBody());
q.setBody(p.second);
return p.first;
}
@Override
- public Boolean visit(FunctionDecl fd, List<FunctionDecl> arg) throws CompilationException {
- // Careful, we should only do this after analyzing the graph of function
- // calls.
- Pair<Boolean, Expression> p = inlineUdfsInExpr(fd.getFuncBody(), arg);
- fd.setFuncBody(p.second);
- return p.first;
+ public Boolean visit(FunctionDecl fd, Void arg) throws CompilationException {
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, fd.getSourceLocation(),
+ fd.getSignature().toString());
}
@Override
- public Boolean visit(ListConstructor lc, List<FunctionDecl> arg) throws CompilationException {
- Pair<Boolean, List<Expression>> p = inlineUdfsInExprList(lc.getExprList(), arg);
+ public Boolean visit(ListConstructor lc, Void arg) throws CompilationException {
+ Pair<Boolean, List<Expression>> p = inlineUdfsInExprList(lc.getExprList());
lc.setExprList(p.second);
return p.first;
}
@Override
- public Boolean visit(RecordConstructor rc, List<FunctionDecl> arg) throws CompilationException {
+ public Boolean visit(RecordConstructor rc, Void arg) throws CompilationException {
boolean changed = false;
for (FieldBinding b : rc.getFbList()) {
- Pair<Boolean, Expression> leftExprInlined = inlineUdfsInExpr(b.getLeftExpr(), arg);
+ Pair<Boolean, Expression> leftExprInlined = inlineUdfsInExpr(b.getLeftExpr());
b.setLeftExpr(leftExprInlined.second);
changed = changed || leftExprInlined.first;
- Pair<Boolean, Expression> rightExprInlined = inlineUdfsInExpr(b.getRightExpr(), arg);
+ Pair<Boolean, Expression> rightExprInlined = inlineUdfsInExpr(b.getRightExpr());
b.setRightExpr(rightExprInlined.second);
changed = changed || rightExprInlined.first;
}
@@ -133,12 +122,12 @@
}
@Override
- public Boolean visit(CallExpr callExpr, List<FunctionDecl> arg) throws CompilationException {
- Pair<Boolean, List<Expression>> p = inlineUdfsInExprList(callExpr.getExprList(), arg);
+ public Boolean visit(CallExpr callExpr, Void arg) throws CompilationException {
+ Pair<Boolean, List<Expression>> p = inlineUdfsInExprList(callExpr.getExprList());
callExpr.setExprList(p.second);
boolean changed = p.first;
if (callExpr.hasAggregateFilterExpr()) {
- Pair<Boolean, Expression> be = inlineUdfsInExpr(callExpr.getAggregateFilterExpr(), arg);
+ Pair<Boolean, Expression> be = inlineUdfsInExpr(callExpr.getAggregateFilterExpr());
callExpr.setAggregateFilterExpr(be.second);
changed |= be.first;
}
@@ -146,96 +135,96 @@
}
@Override
- public Boolean visit(OperatorExpr ifbo, List<FunctionDecl> arg) throws CompilationException {
- Pair<Boolean, List<Expression>> p = inlineUdfsInExprList(ifbo.getExprList(), arg);
+ public Boolean visit(OperatorExpr ifbo, Void arg) throws CompilationException {
+ Pair<Boolean, List<Expression>> p = inlineUdfsInExprList(ifbo.getExprList());
ifbo.setExprList(p.second);
return p.first;
}
@Override
- public Boolean visit(FieldAccessor fa, List<FunctionDecl> arg) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(fa.getExpr(), arg);
+ public Boolean visit(FieldAccessor fa, Void arg) throws CompilationException {
+ Pair<Boolean, Expression> p = inlineUdfsInExpr(fa.getExpr());
fa.setExpr(p.second);
return p.first;
}
@Override
- public Boolean visit(IndexAccessor fa, List<FunctionDecl> arg) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(fa.getExpr(), arg);
+ public Boolean visit(IndexAccessor fa, Void arg) throws CompilationException {
+ Pair<Boolean, Expression> p = inlineUdfsInExpr(fa.getExpr());
fa.setExpr(p.second);
return p.first;
}
@Override
- public Boolean visit(IfExpr ifexpr, List<FunctionDecl> arg) throws CompilationException {
- Pair<Boolean, Expression> p1 = inlineUdfsInExpr(ifexpr.getCondExpr(), arg);
+ public Boolean visit(IfExpr ifexpr, Void arg) throws CompilationException {
+ Pair<Boolean, Expression> p1 = inlineUdfsInExpr(ifexpr.getCondExpr());
ifexpr.setCondExpr(p1.second);
- Pair<Boolean, Expression> p2 = inlineUdfsInExpr(ifexpr.getThenExpr(), arg);
+ Pair<Boolean, Expression> p2 = inlineUdfsInExpr(ifexpr.getThenExpr());
ifexpr.setThenExpr(p2.second);
- Pair<Boolean, Expression> p3 = inlineUdfsInExpr(ifexpr.getElseExpr(), arg);
+ Pair<Boolean, Expression> p3 = inlineUdfsInExpr(ifexpr.getElseExpr());
ifexpr.setElseExpr(p3.second);
return p1.first || p2.first || p3.first;
}
@Override
- public Boolean visit(QuantifiedExpression qe, List<FunctionDecl> arg) throws CompilationException {
+ public Boolean visit(QuantifiedExpression qe, Void arg) throws CompilationException {
boolean changed = false;
for (QuantifiedPair t : qe.getQuantifiedList()) {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(t.getExpr(), arg);
+ Pair<Boolean, Expression> p = inlineUdfsInExpr(t.getExpr());
t.setExpr(p.second);
if (p.first) {
changed = true;
}
}
- Pair<Boolean, Expression> p2 = inlineUdfsInExpr(qe.getSatisfiesExpr(), arg);
+ Pair<Boolean, Expression> p2 = inlineUdfsInExpr(qe.getSatisfiesExpr());
qe.setSatisfiesExpr(p2.second);
return changed || p2.first;
}
@Override
- public Boolean visit(LetClause lc, List<FunctionDecl> arg) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(lc.getBindingExpr(), arg);
+ public Boolean visit(LetClause lc, Void arg) throws CompilationException {
+ Pair<Boolean, Expression> p = inlineUdfsInExpr(lc.getBindingExpr());
lc.setBindingExpr(p.second);
return p.first;
}
@Override
- public Boolean visit(WhereClause wc, List<FunctionDecl> arg) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(wc.getWhereExpr(), arg);
+ public Boolean visit(WhereClause wc, Void arg) throws CompilationException {
+ Pair<Boolean, Expression> p = inlineUdfsInExpr(wc.getWhereExpr());
wc.setWhereExpr(p.second);
return p.first;
}
@Override
- public Boolean visit(OrderbyClause oc, List<FunctionDecl> arg) throws CompilationException {
- Pair<Boolean, List<Expression>> p = inlineUdfsInExprList(oc.getOrderbyList(), arg);
+ public Boolean visit(OrderbyClause oc, Void arg) throws CompilationException {
+ Pair<Boolean, List<Expression>> p = inlineUdfsInExprList(oc.getOrderbyList());
oc.setOrderbyList(p.second);
return p.first;
}
@Override
- public Boolean visit(GroupbyClause gc, List<FunctionDecl> arg) throws CompilationException {
+ public Boolean visit(GroupbyClause gc, Void arg) throws CompilationException {
boolean changed = false;
List<List<GbyVariableExpressionPair>> gbyList = gc.getGbyPairList();
List<List<GbyVariableExpressionPair>> newGbyList = new ArrayList<>(gbyList.size());
for (List<GbyVariableExpressionPair> gbyPairList : gbyList) {
- Pair<Boolean, List<GbyVariableExpressionPair>> p1 = inlineUdfsInGbyPairList(gbyPairList, arg);
+ Pair<Boolean, List<GbyVariableExpressionPair>> p1 = inlineUdfsInGbyPairList(gbyPairList);
newGbyList.add(p1.second);
changed |= p1.first;
}
gc.setGbyPairList(newGbyList);
if (gc.hasDecorList()) {
- Pair<Boolean, List<GbyVariableExpressionPair>> p2 = inlineUdfsInGbyPairList(gc.getDecorPairList(), arg);
+ Pair<Boolean, List<GbyVariableExpressionPair>> p2 = inlineUdfsInGbyPairList(gc.getDecorPairList());
gc.setDecorPairList(p2.second);
changed |= p2.first;
}
if (gc.hasGroupFieldList()) {
- Pair<Boolean, List<Pair<Expression, Identifier>>> p3 = inlineUdfsInFieldList(gc.getGroupFieldList(), arg);
+ Pair<Boolean, List<Pair<Expression, Identifier>>> p3 = inlineUdfsInFieldList(gc.getGroupFieldList());
gc.setGroupFieldList(p3.second);
changed |= p3.first;
}
if (gc.hasWithMap()) {
- Pair<Boolean, Map<Expression, VariableExpr>> p4 = inlineUdfsInVarMap(gc.getWithVarMap(), arg);
+ Pair<Boolean, Map<Expression, VariableExpr>> p4 = inlineUdfsInVarMap(gc.getWithVarMap());
gc.setWithVarMap(p4.second);
changed |= p4.first;
}
@@ -243,15 +232,15 @@
}
@Override
- public Boolean visit(LimitClause lc, List<FunctionDecl> arg) throws CompilationException {
+ public Boolean visit(LimitClause lc, Void arg) throws CompilationException {
boolean changed = false;
if (lc.hasLimitExpr()) {
- Pair<Boolean, Expression> p1 = inlineUdfsInExpr(lc.getLimitExpr(), arg);
+ Pair<Boolean, Expression> p1 = inlineUdfsInExpr(lc.getLimitExpr());
lc.setLimitExpr(p1.second);
changed = p1.first;
}
if (lc.hasOffset()) {
- Pair<Boolean, Expression> p2 = inlineUdfsInExpr(lc.getOffset(), arg);
+ Pair<Boolean, Expression> p2 = inlineUdfsInExpr(lc.getOffset());
lc.setOffset(p2.second);
changed |= p2.first;
}
@@ -259,131 +248,132 @@
}
@Override
- public Boolean visit(UnaryExpr u, List<FunctionDecl> arg) throws CompilationException {
+ public Boolean visit(UnaryExpr u, Void arg) throws CompilationException {
return u.getExpr().accept(this, arg);
}
@Override
- public Boolean visit(VariableExpr v, List<FunctionDecl> arg) throws CompilationException {
+ public Boolean visit(VariableExpr v, Void arg) throws CompilationException {
return false;
}
@Override
- public Boolean visit(LiteralExpr l, List<FunctionDecl> arg) throws CompilationException {
+ public Boolean visit(LiteralExpr l, Void arg) throws CompilationException {
return false;
}
@Override
- public Boolean visit(InsertStatement insert, List<FunctionDecl> arg) throws CompilationException {
+ public Boolean visit(InsertStatement insert, Void arg) throws CompilationException {
boolean changed = false;
Expression returnExpression = insert.getReturnExpression();
if (returnExpression != null) {
- Pair<Boolean, Expression> rewrittenReturnExpr = inlineUdfsInExpr(returnExpression, arg);
+ Pair<Boolean, Expression> rewrittenReturnExpr = inlineUdfsInExpr(returnExpression);
insert.setReturnExpression(rewrittenReturnExpr.second);
changed |= rewrittenReturnExpr.first;
}
- Pair<Boolean, Expression> rewrittenBodyExpression = inlineUdfsInExpr(insert.getBody(), arg);
+ Pair<Boolean, Expression> rewrittenBodyExpression = inlineUdfsInExpr(insert.getBody());
insert.setBody(rewrittenBodyExpression.second);
return changed || rewrittenBodyExpression.first;
}
- protected Pair<Boolean, Expression> inlineUdfsInExpr(Expression expr, List<FunctionDecl> arg)
- throws CompilationException {
+ protected Pair<Boolean, Expression> inlineUdfsInExpr(Expression expr) throws CompilationException {
if (expr.getKind() != Kind.CALL_EXPRESSION) {
- boolean r = expr.accept(this, arg);
+ boolean r = expr.accept(this, null);
return new Pair<>(r, expr);
}
CallExpr f = (CallExpr) expr;
- boolean r = expr.accept(this, arg);
- FunctionDecl implem = findFuncDeclaration(f.getFunctionSignature(), arg);
- if (implem == null) {
+ boolean r = expr.accept(this, null);
+ FunctionSignature fs = f.getFunctionSignature();
+ if (FunctionUtil.isBuiltinFunctionSignature(fs)) {
return new Pair<>(r, expr);
- } else {
- if (f.hasAggregateFilterExpr()) {
- throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_USE_OF_FILTER_CLAUSE,
- f.getSourceLocation());
- }
- // Rewrite the function body itself (without setting unbounded variables to dataset access).
- // TODO(buyingyi): throw an exception for recursive function definition or limit the stack depth.
- implem.setFuncBody(rewriteFunctionBody(implem));
- // it's one of the functions we want to inline
- List<Expression> argList = f.getExprList();
- int argCount = argList.size();
- List<LetClause> clauses = new ArrayList<>(argCount + 1);
- List<Expression> argVars = new ArrayList<>(argCount);
- for (Expression e : f.getExprList()) {
- // Obs: we could do smth about passing also literals, or let
- // variable inlining to take care of this.
- VarIdentifier argVar;
- if (e.getKind() == Kind.VARIABLE_EXPRESSION) {
- argVar = ((VariableExpr) e).getVar();
- } else {
- SourceLocation sourceLoc = e.getSourceLocation();
- argVar = context.newVariable();
- Pair<ILangExpression, VariableSubstitutionEnvironment> p1 =
- e.accept(cloneVisitor, new VariableSubstitutionEnvironment());
- VariableExpr newVRef1 = new VariableExpr(argVar);
- newVRef1.setSourceLocation(sourceLoc);
- LetClause c = new LetClause(newVRef1, (Expression) p1.first);
- c.setSourceLocation(sourceLoc);
- clauses.add(c);
- }
-
- VariableExpr argVarExpr = new VariableExpr(argVar);
- argVarExpr.setSourceLocation(e.getSourceLocation());
- argVars.add(argVarExpr);
- }
-
- VariableSubstitutionEnvironment subst = new VariableSubstitutionEnvironment();
- List<VarIdentifier> paramList = implem.getParamList();
- if (implem.getSignature().getArity() == FunctionIdentifier.VARARGS) {
- if (paramList.size() != 1) {
- throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, expr.getSourceLocation(),
- paramList.size());
- }
- VarIdentifier paramVarargs = paramList.get(0);
- CallExpr argsListExpr =
- new CallExpr(new FunctionSignature(BuiltinFunctions.ORDERED_LIST_CONSTRUCTOR), argVars);
- argsListExpr.setSourceLocation(expr.getSourceLocation());
-
- VarIdentifier argsVar = context.newVariable();
- VariableExpr argsVarRef1 = new VariableExpr(argsVar);
- argsVarRef1.setSourceLocation(expr.getSourceLocation());
- LetClause c = new LetClause(argsVarRef1, argsListExpr);
- c.setSourceLocation(expr.getSourceLocation());
- clauses.add(c);
-
- VariableExpr argsVarRef2 = new VariableExpr(argsVar);
- argsVarRef2.setSourceLocation(expr.getSourceLocation());
- subst.addSubstituion(new VariableExpr(paramVarargs), argsVarRef2);
- } else {
- if (paramList.size() != argCount) {
- throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, expr.getSourceLocation(),
- paramList.size());
- }
- for (int i = 0; i < argCount; i++) {
- subst.addSubstituion(new VariableExpr(paramList.get(i)), argVars.get(i));
- }
- }
-
- Pair<ILangExpression, VariableSubstitutionEnvironment> p2 =
- implem.getFuncBody().accept(cloneVisitor, subst);
- Expression resExpr;
- if (clauses.isEmpty()) {
- resExpr = (Expression) p2.first;
- } else {
- resExpr = generateQueryExpression(clauses, (Expression) p2.first);
- }
- return new Pair<>(true, resExpr);
}
+ if (f.hasAggregateFilterExpr()) {
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_USE_OF_FILTER_CLAUSE, f.getSourceLocation());
+ }
+ FunctionDecl implem = usedUDFs.get(fs);
+ if (implem == null) {
+ throw new CompilationException(ErrorCode.UNKNOWN_FUNCTION, f.getSourceLocation(), fs.toString());
+ }
+ // it's one of the functions we want to inline
+ List<Expression> argList = f.getExprList();
+ int argCount = argList.size();
+ List<LetClause> clauses = new ArrayList<>(argCount + 1);
+ List<Expression> argVars = new ArrayList<>(argCount);
+ for (Expression e : f.getExprList()) {
+ // Obs: we could do smth about passing also literals, or let
+ // variable inlining to take care of this.
+ VarIdentifier argVar;
+ if (e.getKind() == Kind.VARIABLE_EXPRESSION) {
+ argVar = ((VariableExpr) e).getVar();
+ } else {
+ SourceLocation sourceLoc = e.getSourceLocation();
+ argVar = context.newVariable();
+ Pair<ILangExpression, VariableSubstitutionEnvironment> p1 =
+ e.accept(cloneVisitor, new VariableSubstitutionEnvironment());
+ VariableExpr newVRef1 = new VariableExpr(argVar);
+ newVRef1.setSourceLocation(sourceLoc);
+ LetClause c = new LetClause(newVRef1, (Expression) p1.first);
+ c.setSourceLocation(sourceLoc);
+ clauses.add(c);
+ }
+
+ VariableExpr argVarExpr = new VariableExpr(argVar);
+ argVarExpr.setSourceLocation(e.getSourceLocation());
+ argVars.add(argVarExpr);
+ }
+
+ VariableSubstitutionEnvironment subst = new VariableSubstitutionEnvironment();
+ List<VarIdentifier> paramList = implem.getParamList();
+ if (implem.getSignature().getArity() == FunctionIdentifier.VARARGS) {
+ if (paramList.size() != 1) {
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, expr.getSourceLocation(),
+ paramList.size());
+ }
+ VarIdentifier paramVarargs = paramList.get(0);
+ CallExpr argsListExpr =
+ new CallExpr(new FunctionSignature(BuiltinFunctions.ORDERED_LIST_CONSTRUCTOR), argVars);
+ argsListExpr.setSourceLocation(expr.getSourceLocation());
+
+ VarIdentifier argsVar = context.newVariable();
+ VariableExpr argsVarRef1 = new VariableExpr(argsVar);
+ argsVarRef1.setSourceLocation(expr.getSourceLocation());
+ LetClause c = new LetClause(argsVarRef1, argsListExpr);
+ c.setSourceLocation(expr.getSourceLocation());
+ clauses.add(c);
+
+ VariableExpr argsVarRef2 = new VariableExpr(argsVar);
+ argsVarRef2.setSourceLocation(expr.getSourceLocation());
+ subst.addSubstituion(new VariableExpr(paramVarargs), argsVarRef2);
+ } else {
+ if (paramList.size() != argCount) {
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, expr.getSourceLocation(),
+ paramList.size());
+ }
+ for (int i = 0; i < argCount; i++) {
+ subst.addSubstituion(new VariableExpr(paramList.get(i)), argVars.get(i));
+ }
+ }
+
+ Expression funcBodyNorm = implem.getNormalizedFuncBody();
+ if (funcBodyNorm == null) {
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, f.getSourceLocation(), fs.toString());
+ }
+ Pair<ILangExpression, VariableSubstitutionEnvironment> p2 = funcBodyNorm.accept(cloneVisitor, subst);
+ Expression resExpr;
+ if (clauses.isEmpty()) {
+ resExpr = (Expression) p2.first;
+ } else {
+ resExpr = generateQueryExpression(clauses, (Expression) p2.first);
+ }
+ return new Pair<>(true, resExpr);
}
- protected Pair<Boolean, List<Expression>> inlineUdfsInExprList(List<Expression> exprList, List<FunctionDecl> fds)
+ protected Pair<Boolean, List<Expression>> inlineUdfsInExprList(List<Expression> exprList)
throws CompilationException {
List<Expression> newList = new ArrayList<>(exprList.size());
boolean changed = false;
for (Expression e : exprList) {
- Pair<Boolean, Expression> be = inlineUdfsInExpr(e, fds);
+ Pair<Boolean, Expression> be = inlineUdfsInExpr(e);
newList.add(be.second);
changed |= be.first;
}
@@ -391,11 +381,11 @@
}
private Pair<Boolean, List<GbyVariableExpressionPair>> inlineUdfsInGbyPairList(
- List<GbyVariableExpressionPair> gbyPairList, List<FunctionDecl> fds) throws CompilationException {
+ List<GbyVariableExpressionPair> gbyPairList) throws CompilationException {
List<GbyVariableExpressionPair> newList = new ArrayList<>(gbyPairList.size());
boolean changed = false;
for (GbyVariableExpressionPair p : gbyPairList) {
- Pair<Boolean, Expression> be = inlineUdfsInExpr(p.getExpr(), fds);
+ Pair<Boolean, Expression> be = inlineUdfsInExpr(p.getExpr());
newList.add(new GbyVariableExpressionPair(p.getVar(), be.second));
changed |= be.first;
}
@@ -403,69 +393,26 @@
}
protected Pair<Boolean, List<Pair<Expression, Identifier>>> inlineUdfsInFieldList(
- List<Pair<Expression, Identifier>> fieldList, List<FunctionDecl> fds) throws CompilationException {
+ List<Pair<Expression, Identifier>> fieldList) throws CompilationException {
List<Pair<Expression, Identifier>> newList = new ArrayList<>(fieldList.size());
boolean changed = false;
for (Pair<Expression, Identifier> p : fieldList) {
- Pair<Boolean, Expression> be = inlineUdfsInExpr(p.first, fds);
+ Pair<Boolean, Expression> be = inlineUdfsInExpr(p.first);
newList.add(new Pair<>(be.second, p.second));
changed |= be.first;
}
return new Pair<>(changed, newList);
}
- private Pair<Boolean, Map<Expression, VariableExpr>> inlineUdfsInVarMap(Map<Expression, VariableExpr> varMap,
- List<FunctionDecl> fds) throws CompilationException {
+ private Pair<Boolean, Map<Expression, VariableExpr>> inlineUdfsInVarMap(Map<Expression, VariableExpr> varMap)
+ throws CompilationException {
Map<Expression, VariableExpr> newMap = new HashMap<>();
boolean changed = false;
for (Map.Entry<Expression, VariableExpr> me : varMap.entrySet()) {
- Pair<Boolean, Expression> be = inlineUdfsInExpr(me.getKey(), fds);
+ Pair<Boolean, Expression> be = inlineUdfsInExpr(me.getKey());
newMap.put(be.second, me.getValue());
changed |= be.first;
}
return new Pair<>(changed, newMap);
}
-
- private Expression rewriteFunctionBody(FunctionDecl fnDecl) throws CompilationException {
- SourceLocation sourceLoc = fnDecl.getSourceLocation();
-
- DataverseName fnDataverseName = fnDecl.getSignature().getDataverseName();
- Dataverse defaultDataverse = metadataProvider.getDefaultDataverse();
- Dataverse fnDataverse;
- if (fnDataverseName == null || fnDataverseName.equals(defaultDataverse.getDataverseName())) {
- fnDataverse = defaultDataverse;
- } else {
- try {
- fnDataverse = metadataProvider.findDataverse(fnDataverseName);
- } catch (AlgebricksException e) {
- throw new CompilationException(ErrorCode.UNKNOWN_DATAVERSE, e, sourceLoc, fnDataverseName);
- }
- }
-
- metadataProvider.setDefaultDataverse(fnDataverse);
- try {
- Query wrappedQuery = new Query(false);
- wrappedQuery.setSourceLocation(sourceLoc);
- wrappedQuery.setBody(fnDecl.getFuncBody());
- wrappedQuery.setTopLevel(false);
- IQueryRewriter queryRewriter = rewriterFactory.createQueryRewriter();
- queryRewriter.rewrite(declaredFunctions, wrappedQuery, metadataProvider, context, true,
- fnDecl.getParamList());
- return wrappedQuery.getBody();
- } catch (CompilationException e) {
- throw new CompilationException(ErrorCode.COMPILATION_BAD_FUNCTION_DEFINITION, e, fnDecl.getSignature(),
- e.getMessage());
- } finally {
- metadataProvider.setDefaultDataverse(defaultDataverse);
- }
- }
-
- private static FunctionDecl findFuncDeclaration(FunctionSignature fid, List<FunctionDecl> sequence) {
- for (FunctionDecl f : sequence) {
- if (f.getSignature().equals(fid)) {
- return f;
- }
- }
- return null;
- }
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
index 1fcf822..4b30c97 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
@@ -178,7 +178,7 @@
}
Pair<ILangExpression, VariableSubstitutionEnvironment> p1 = fd.getFuncBody().accept(this, env);
- FunctionDecl newF = new FunctionDecl(fd.getSignature(), newList, (Expression) p1.first);
+ FunctionDecl newF = new FunctionDecl(fd.getSignature(), newList, (Expression) p1.first, fd.isStored());
newF.setSourceLocation(fd.getSourceLocation());
return new Pair<>(newF, env);
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
index 3ad0f1b..25f4103 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
@@ -19,10 +19,9 @@
package org.apache.asterix.lang.common.visitor;
-import java.util.LinkedHashSet;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.lang.common.base.Expression;
@@ -56,9 +55,13 @@
import org.apache.asterix.lang.common.visitor.base.AbstractQueryExpressionVisitor;
import org.apache.hyracks.algebricks.common.utils.Pair;
-public class GatherFunctionCallsVisitor extends AbstractQueryExpressionVisitor<Void, Void> {
+public abstract class GatherFunctionCallsVisitor extends AbstractQueryExpressionVisitor<Void, Void> {
- protected final Set<AbstractCallExpression> calls = new LinkedHashSet<>();
+ protected final Collection<? super AbstractCallExpression> calls;
+
+ protected GatherFunctionCallsVisitor(Collection<? super AbstractCallExpression> calls) {
+ this.calls = calls;
+ }
@Override
public Void visit(CallExpr callExpr, Void arg) throws CompilationException {
@@ -240,10 +243,6 @@
return null;
}
- public Set<AbstractCallExpression> getCalls() {
- return calls;
- }
-
@Override
public Void visit(FunctionDecl fd, Void arg) throws CompilationException {
return null;
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
index 356a683..8dd206f 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
@@ -19,15 +19,13 @@
package org.apache.asterix.lang.sqlpp.rewrites;
import java.util.Collection;
-import java.util.List;
import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.lang.common.base.IParserFactory;
import org.apache.asterix.lang.common.base.IReturningStatement;
import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
-import org.apache.asterix.lang.common.statement.FunctionDecl;
import org.apache.asterix.lang.common.struct.VarIdentifier;
-import org.apache.asterix.metadata.declared.MetadataProvider;
class SqlppFunctionBodyRewriter extends SqlppQueryRewriter {
@@ -36,11 +34,16 @@
}
@Override
- public void rewrite(List<FunctionDecl> declaredFunctions, IReturningStatement topStatement,
- MetadataProvider metadataProvider, LangRewritingContext context, boolean inlineUdfs,
- Collection<VarIdentifier> externalVars) throws CompilationException {
+ public void rewrite(LangRewritingContext context, IReturningStatement topStatement, boolean allowNonStoredUdfCalls,
+ boolean inlineUdfs, Collection<VarIdentifier> externalVars) throws CompilationException {
+ if (inlineUdfs) {
+ // When rewriting function body we do not inline UDFs into it.
+ // The main query rewriter will inline everything later, when it processes the query
+ throw new CompilationException(ErrorCode.ILLEGAL_STATE, topStatement.getSourceLocation(), "inlineUdfs");
+ }
+
// Sets up parameters.
- setup(declaredFunctions, topStatement, metadataProvider, context, externalVars);
+ setup(context, topStatement, externalVars, allowNonStoredUdfCalls, inlineUdfs);
// Resolves function calls
resolveFunctionCalls();
@@ -93,8 +96,5 @@
// Rewrites RIGHT OUTER JOINs into LEFT OUTER JOINs if possible
rewriteRightJoins();
-
- // Inlines functions recursively.
- inlineDeclaredUdfs(inlineUdfs);
}
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
index af1bb41..a3ff1c6 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
@@ -18,48 +18,31 @@
*/
package org.apache.asterix.lang.sqlpp.rewrites;
-import java.util.ArrayList;
+import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Collections;
+import java.util.Deque;
import java.util.HashSet;
-import java.util.List;
+import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.Set;
import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.functions.FunctionSignature;
-import org.apache.asterix.lang.common.base.AbstractClause;
+import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.base.IParserFactory;
import org.apache.asterix.lang.common.base.IQueryRewriter;
import org.apache.asterix.lang.common.base.IReturningStatement;
-import org.apache.asterix.lang.common.clause.LetClause;
import org.apache.asterix.lang.common.expression.AbstractCallExpression;
-import org.apache.asterix.lang.common.expression.ListSliceExpression;
import org.apache.asterix.lang.common.expression.VariableExpr;
-import org.apache.asterix.lang.common.parser.FunctionParser;
import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
import org.apache.asterix.lang.common.statement.FunctionDecl;
-import org.apache.asterix.lang.common.struct.Identifier;
+import org.apache.asterix.lang.common.statement.Query;
import org.apache.asterix.lang.common.struct.VarIdentifier;
import org.apache.asterix.lang.common.util.FunctionUtil;
-import org.apache.asterix.lang.common.visitor.GatherFunctionCallsVisitor;
import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
-import org.apache.asterix.lang.sqlpp.clause.AbstractBinaryCorrelateClause;
-import org.apache.asterix.lang.sqlpp.clause.FromClause;
-import org.apache.asterix.lang.sqlpp.clause.FromTerm;
-import org.apache.asterix.lang.sqlpp.clause.HavingClause;
-import org.apache.asterix.lang.sqlpp.clause.JoinClause;
-import org.apache.asterix.lang.sqlpp.clause.NestClause;
-import org.apache.asterix.lang.sqlpp.clause.Projection;
-import org.apache.asterix.lang.sqlpp.clause.SelectBlock;
-import org.apache.asterix.lang.sqlpp.clause.SelectClause;
-import org.apache.asterix.lang.sqlpp.clause.SelectElement;
-import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
-import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
-import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
-import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
-import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
-import org.apache.asterix.lang.sqlpp.expression.WindowExpression;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.GenerateColumnNameVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.InlineColumnAliasVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.InlineWithExpressionVisitor;
@@ -68,6 +51,7 @@
import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppCaseAggregateExtractionVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppCaseExpressionVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppFunctionCallResolverVisitor;
+import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppGatherFunctionCallsVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppGroupByAggregationSugarVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppGroupByVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppGroupingSetsVisitor;
@@ -79,12 +63,12 @@
import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppWindowRewriteVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.SubstituteGroupbyExpressionWithVariableVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.VariableCheckAndRewriteVisitor;
-import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
import org.apache.asterix.lang.sqlpp.util.SqlppAstPrintUtil;
import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
-import org.apache.asterix.lang.sqlpp.visitor.base.ISqlppVisitor;
import org.apache.asterix.metadata.declared.MetadataProvider;
-import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.asterix.metadata.entities.Dataverse;
+import org.apache.asterix.metadata.entities.Function;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.util.LogRedactionUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -96,41 +80,38 @@
public static final String INLINE_WITH_OPTION = "inline_with";
private static final boolean INLINE_WITH_OPTION_DEFAULT = true;
private final IParserFactory parserFactory;
- private final FunctionParser functionParser;
- private IReturningStatement topExpr;
- private List<FunctionDecl> declaredFunctions;
+ private SqlppFunctionBodyRewriter functionBodyRewriter;
+ private IReturningStatement topStatement;
private LangRewritingContext context;
private MetadataProvider metadataProvider;
private Collection<VarIdentifier> externalVars;
+ private boolean allowNonStoredUdfCalls;
+ private boolean inlineUdfs;
private boolean isLogEnabled;
public SqlppQueryRewriter(IParserFactory parserFactory) {
this.parserFactory = parserFactory;
- functionParser = new FunctionParser(parserFactory);
}
- protected void setup(List<FunctionDecl> declaredFunctions, IReturningStatement topExpr,
- MetadataProvider metadataProvider, LangRewritingContext context, Collection<VarIdentifier> externalVars)
+ protected void setup(LangRewritingContext context, IReturningStatement topStatement,
+ Collection<VarIdentifier> externalVars, boolean allowNonStoredUdfCalls, boolean inlineUdfs)
throws CompilationException {
- this.topExpr = topExpr;
this.context = context;
- this.declaredFunctions = declaredFunctions;
- this.metadataProvider = metadataProvider;
+ this.metadataProvider = context.getMetadataProvider();
+ this.topStatement = topStatement;
this.externalVars = externalVars != null ? externalVars : Collections.emptyList();
+ this.allowNonStoredUdfCalls = allowNonStoredUdfCalls;
+ this.inlineUdfs = inlineUdfs;
this.isLogEnabled = LOGGER.isTraceEnabled();
logExpression("Starting AST rewrites on", "");
}
@Override
- public void rewrite(List<FunctionDecl> declaredFunctions, IReturningStatement topStatement,
- MetadataProvider metadataProvider, LangRewritingContext context, boolean inlineUdfs,
- Collection<VarIdentifier> externalVars) throws CompilationException {
- if (topStatement == null) {
- return;
- }
+ public void rewrite(LangRewritingContext context, IReturningStatement topStatement, boolean allowNonStoredUdfCalls,
+ boolean inlineUdfs, Collection<VarIdentifier> externalVars) throws CompilationException {
// Sets up parameters.
- setup(declaredFunctions, topStatement, metadataProvider, context, externalVars);
+ setup(context, topStatement, externalVars, allowNonStoredUdfCalls, inlineUdfs);
// Resolves function calls
resolveFunctionCalls();
@@ -182,7 +163,7 @@
rewriteRightJoins();
// Inlines functions.
- inlineDeclaredUdfs(inlineUdfs);
+ loadAndInlineDeclaredUdfs();
// Rewrites SQL++ core aggregate function names into internal names
rewriteSpecialFunctionNames();
@@ -214,7 +195,7 @@
protected void resolveFunctionCalls() throws CompilationException {
SqlppFunctionCallResolverVisitor visitor =
- new SqlppFunctionCallResolverVisitor(metadataProvider, declaredFunctions);
+ new SqlppFunctionCallResolverVisitor(context, allowNonStoredUdfCalls);
rewriteTopExpr(visitor, null);
}
@@ -308,53 +289,40 @@
rewriteTopExpr(visitor, null);
}
- protected void inlineDeclaredUdfs(boolean inlineUdfs) throws CompilationException {
- List<FunctionSignature> funIds = new ArrayList<FunctionSignature>();
- for (FunctionDecl fdecl : declaredFunctions) {
- funIds.add(fdecl.getSignature());
- }
-
- List<FunctionDecl> usedStoredFunctionDecls = new ArrayList<>();
- for (Expression topLevelExpr : topExpr.getDirectlyEnclosedExpressions()) {
- usedStoredFunctionDecls.addAll(FunctionUtil.retrieveUsedStoredFunctions(metadataProvider, topLevelExpr,
- funIds, null, this::getFunctionCalls, functionParser, context.getWarningCollector()));
- }
- declaredFunctions.addAll(usedStoredFunctionDecls);
- if (inlineUdfs && !declaredFunctions.isEmpty()) {
- SqlppFunctionBodyRewriterFactory functionBodyRewriterFactory =
- new SqlppFunctionBodyRewriterFactory(parserFactory);
- SqlppInlineUdfsVisitor visitor = new SqlppInlineUdfsVisitor(context, functionBodyRewriterFactory,
- declaredFunctions, metadataProvider);
- while (rewriteTopExpr(visitor, declaredFunctions)) {
+ protected void loadAndInlineDeclaredUdfs() throws CompilationException {
+ Map<FunctionSignature, FunctionDecl> udfs = fetchUserDefinedSqlppFunctions(topStatement);
+ FunctionUtil.checkFunctionRecursion(udfs, SqlppGatherFunctionCallsVisitor::new,
+ topStatement.getSourceLocation());
+ if (!udfs.isEmpty() && inlineUdfs) {
+ SqlppInlineUdfsVisitor visitor = new SqlppInlineUdfsVisitor(context, udfs);
+ while (rewriteTopExpr(visitor, null)) {
// loop until no more changes
}
}
- declaredFunctions.removeAll(usedStoredFunctionDecls);
}
private <R, T> R rewriteTopExpr(ILangVisitor<R, T> visitor, T arg) throws CompilationException {
- R result = topExpr.accept(visitor, arg);
+ R result = topStatement.accept(visitor, arg);
logExpression(">>>> AST After", visitor.getClass().getSimpleName());
return result;
}
private void logExpression(String p0, String p1) throws CompilationException {
if (isLogEnabled) {
- LOGGER.trace("{} {}\n{}", p0, p1, LogRedactionUtil.userData(SqlppAstPrintUtil.toString(topExpr)));
+ LOGGER.trace("{} {}\n{}", p0, p1, LogRedactionUtil.userData(SqlppAstPrintUtil.toString(topStatement)));
}
}
@Override
- public Set<AbstractCallExpression> getFunctionCalls(Expression expression) throws CompilationException {
- GatherFunctionCalls gfc = new GatherFunctionCalls();
+ public void getFunctionCalls(Expression expression, Collection<? super AbstractCallExpression> outCalls)
+ throws CompilationException {
+ SqlppGatherFunctionCallsVisitor gfc = new SqlppGatherFunctionCallsVisitor(outCalls);
expression.accept(gfc, null);
- return gfc.getCalls();
}
@Override
public Set<VariableExpr> getExternalVariables(Expression expr) throws CompilationException {
Set<VariableExpr> freeVars = SqlppVariableUtil.getFreeVariables(expr);
-
Set<VariableExpr> extVars = new HashSet<>();
for (VariableExpr ve : freeVars) {
if (SqlppVariableUtil.isExternalVariableReference(ve)) {
@@ -364,189 +332,107 @@
return extVars;
}
- private static class GatherFunctionCalls extends GatherFunctionCallsVisitor implements ISqlppVisitor<Void, Void> {
+ private Map<FunctionSignature, FunctionDecl> fetchUserDefinedSqlppFunctions(IReturningStatement topExpr)
+ throws CompilationException {
+ Map<FunctionSignature, FunctionDecl> udfs = new LinkedHashMap<>();
- public GatherFunctionCalls() {
+ Deque<AbstractCallExpression> workQueue = new ArrayDeque<>();
+ SqlppGatherFunctionCallsVisitor gfc = new SqlppGatherFunctionCallsVisitor(workQueue);
+ for (Expression expr : topExpr.getDirectlyEnclosedExpressions()) {
+ expr.accept(gfc, null);
+ }
+ AbstractCallExpression fnCall;
+ while ((fnCall = workQueue.poll()) != null) {
+ switch (fnCall.getKind()) {
+ case CALL_EXPRESSION:
+ FunctionSignature fs = fnCall.getFunctionSignature();
+ DataverseName fsDataverse = fs.getDataverseName();
+ if (fsDataverse == null) {
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, fnCall.getSourceLocation(),
+ fs);
+ }
+ if (FunctionUtil.isBuiltinFunctionSignature(fs) || udfs.containsKey(fs)) {
+ continue;
+ }
+ FunctionDecl fd = context.getDeclaredFunctions().get(fs);
+ if (fd == null) {
+ Function function;
+ try {
+ function = metadataProvider.lookupUserDefinedFunction(fs);
+ } catch (AlgebricksException e) {
+ throw new CompilationException(ErrorCode.UNKNOWN_FUNCTION, fnCall.getSourceLocation(),
+ fs.toString());
+ }
+ if (function == null) {
+ throw new CompilationException(ErrorCode.UNKNOWN_FUNCTION, fnCall.getSourceLocation(),
+ fs.toString());
+ }
+ if (function.isExternal()) {
+ continue;
+ }
+ fd = FunctionUtil.parseStoredFunction(function, parserFactory, context.getWarningCollector(),
+ fnCall.getSourceLocation());
+ }
+ prepareFunction(fd);
+ udfs.put(fs, fd);
+ fd.getNormalizedFuncBody().accept(gfc, null);
+ break;
+ case WINDOW_EXPRESSION:
+ // there cannot be used-defined window functions
+ break;
+ default:
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, fnCall.getSourceLocation(),
+ fnCall.getFunctionSignature().toString(false));
+ }
+ }
+ return udfs;
+ }
+
+ private void prepareFunction(FunctionDecl fd) throws CompilationException {
+ Expression fnNormBody = fd.getNormalizedFuncBody();
+ if (fnNormBody == null) {
+ fnNormBody = rewriteFunctionBody(fd);
+ fd.setNormalizedFuncBody(fnNormBody);
+ }
+ }
+
+ private Expression rewriteFunctionBody(FunctionDecl fnDecl) throws CompilationException {
+ DataverseName fnDataverseName = fnDecl.getSignature().getDataverseName();
+ Dataverse defaultDataverse = metadataProvider.getDefaultDataverse();
+ Dataverse fnDataverse;
+ if (fnDataverseName == null || fnDataverseName.equals(defaultDataverse.getDataverseName())) {
+ fnDataverse = defaultDataverse;
+ } else {
+ try {
+ fnDataverse = metadataProvider.findDataverse(fnDataverseName);
+ } catch (AlgebricksException e) {
+ throw new CompilationException(ErrorCode.UNKNOWN_DATAVERSE, e, fnDecl.getSourceLocation(),
+ fnDataverseName);
+ }
}
- @Override
- public Void visit(FromClause fromClause, Void arg) throws CompilationException {
- for (FromTerm fromTerm : fromClause.getFromTerms()) {
- fromTerm.accept(this, arg);
- }
- return null;
+ metadataProvider.setDefaultDataverse(fnDataverse);
+ try {
+ Query wrappedQuery = new Query(false);
+ wrappedQuery.setSourceLocation(fnDecl.getSourceLocation());
+ wrappedQuery.setBody(fnDecl.getFuncBody());
+ wrappedQuery.setTopLevel(false);
+ boolean allowNonStoredUdfCalls = !fnDecl.isStored();
+ getFunctionBodyRewriter().rewrite(context, wrappedQuery, allowNonStoredUdfCalls, false,
+ fnDecl.getParamList());
+ return wrappedQuery.getBody();
+ } catch (CompilationException e) {
+ throw new CompilationException(ErrorCode.COMPILATION_BAD_FUNCTION_DEFINITION, e, fnDecl.getSignature(),
+ e.getMessage());
+ } finally {
+ metadataProvider.setDefaultDataverse(defaultDataverse);
}
+ }
- @Override
- public Void visit(FromTerm fromTerm, Void arg) throws CompilationException {
- fromTerm.getLeftExpression().accept(this, arg);
- for (AbstractBinaryCorrelateClause correlateClause : fromTerm.getCorrelateClauses()) {
- correlateClause.accept(this, arg);
- }
- return null;
+ protected SqlppFunctionBodyRewriter getFunctionBodyRewriter() {
+ if (functionBodyRewriter == null) {
+ functionBodyRewriter = new SqlppFunctionBodyRewriter(parserFactory);
}
-
- @Override
- public Void visit(JoinClause joinClause, Void arg) throws CompilationException {
- joinClause.getRightExpression().accept(this, arg);
- joinClause.getConditionExpression().accept(this, arg);
- return null;
- }
-
- @Override
- public Void visit(NestClause nestClause, Void arg) throws CompilationException {
- nestClause.getRightExpression().accept(this, arg);
- nestClause.getConditionExpression().accept(this, arg);
- return null;
- }
-
- @Override
- public Void visit(Projection projection, Void arg) throws CompilationException {
- if (!projection.star()) {
- projection.getExpression().accept(this, arg);
- }
- return null;
- }
-
- @Override
- public Void visit(SelectBlock selectBlock, Void arg) throws CompilationException {
- if (selectBlock.hasFromClause()) {
- selectBlock.getFromClause().accept(this, arg);
- }
- if (selectBlock.hasLetWhereClauses()) {
- for (AbstractClause letWhereClause : selectBlock.getLetWhereList()) {
- letWhereClause.accept(this, arg);
- }
- }
- if (selectBlock.hasGroupbyClause()) {
- selectBlock.getGroupbyClause().accept(this, arg);
- }
- if (selectBlock.hasLetHavingClausesAfterGroupby()) {
- for (AbstractClause letHavingClause : selectBlock.getLetHavingListAfterGroupby()) {
- letHavingClause.accept(this, arg);
- }
- }
- selectBlock.getSelectClause().accept(this, arg);
- return null;
- }
-
- @Override
- public Void visit(SelectClause selectClause, Void arg) throws CompilationException {
- if (selectClause.selectElement()) {
- selectClause.getSelectElement().accept(this, arg);
- } else {
- selectClause.getSelectRegular().accept(this, arg);
- }
- return null;
- }
-
- @Override
- public Void visit(SelectElement selectElement, Void arg) throws CompilationException {
- selectElement.getExpression().accept(this, arg);
- return null;
- }
-
- @Override
- public Void visit(SelectRegular selectRegular, Void arg) throws CompilationException {
- for (Projection projection : selectRegular.getProjections()) {
- projection.accept(this, arg);
- }
- return null;
- }
-
- @Override
- public Void visit(SelectSetOperation selectSetOperation, Void arg) throws CompilationException {
- selectSetOperation.getLeftInput().accept(this, arg);
- for (SetOperationRight setOperationRight : selectSetOperation.getRightInputs()) {
- setOperationRight.getSetOperationRightInput().accept(this, arg);
- }
- return null;
- }
-
- @Override
- public Void visit(SelectExpression selectStatement, Void arg) throws CompilationException {
- if (selectStatement.hasLetClauses()) {
- for (LetClause letClause : selectStatement.getLetList()) {
- letClause.accept(this, arg);
- }
- }
- selectStatement.getSelectSetOperation().accept(this, arg);
- if (selectStatement.hasOrderby()) {
- selectStatement.getOrderbyClause().accept(this, arg);
- }
- if (selectStatement.hasLimit()) {
- selectStatement.getLimitClause().accept(this, arg);
- }
- return null;
- }
-
- @Override
- public Void visit(UnnestClause unnestClause, Void arg) throws CompilationException {
- unnestClause.getRightExpression().accept(this, arg);
- return null;
- }
-
- @Override
- public Void visit(HavingClause havingClause, Void arg) throws CompilationException {
- havingClause.getFilterExpression().accept(this, arg);
- return null;
- }
-
- @Override
- public Void visit(CaseExpression caseExpression, Void arg) throws CompilationException {
- caseExpression.getConditionExpr().accept(this, arg);
- for (Expression expr : caseExpression.getWhenExprs()) {
- expr.accept(this, arg);
- }
- for (Expression expr : caseExpression.getThenExprs()) {
- expr.accept(this, arg);
- }
- caseExpression.getElseExpr().accept(this, arg);
- return null;
- }
-
- @Override
- public Void visit(WindowExpression winExpr, Void arg) throws CompilationException {
- calls.add(winExpr);
- if (winExpr.hasPartitionList()) {
- for (Expression expr : winExpr.getPartitionList()) {
- expr.accept(this, arg);
- }
- }
- if (winExpr.hasOrderByList()) {
- for (Expression expr : winExpr.getOrderbyList()) {
- expr.accept(this, arg);
- }
- }
- if (winExpr.hasFrameStartExpr()) {
- winExpr.getFrameStartExpr().accept(this, arg);
- }
- if (winExpr.hasFrameEndExpr()) {
- winExpr.getFrameEndExpr().accept(this, arg);
- }
- if (winExpr.hasWindowFieldList()) {
- for (Pair<Expression, Identifier> p : winExpr.getWindowFieldList()) {
- p.first.accept(this, arg);
- }
- }
- if (winExpr.hasAggregateFilterExpr()) {
- winExpr.getAggregateFilterExpr().accept(this, arg);
- }
- for (Expression expr : winExpr.getExprList()) {
- expr.accept(this, arg);
- }
- return null;
- }
-
- @Override
- public Void visit(ListSliceExpression expression, Void arg) throws CompilationException {
- expression.getExpr().accept(this, arg);
- expression.getStartIndexExpression().accept(this, arg);
-
- if (expression.hasEndExpression()) {
- expression.getEndIndexExpression().accept(this, arg);
- }
- return null;
- }
+ return functionBodyRewriter;
}
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppFunctionCallResolverVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppFunctionCallResolverVisitor.java
index 7666032..38b66e2 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppFunctionCallResolverVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppFunctionCallResolverVisitor.java
@@ -18,8 +18,6 @@
*/
package org.apache.asterix.lang.sqlpp.rewrites.visitor;
-import java.util.List;
-import java.util.Set;
import java.util.function.BiFunction;
import org.apache.asterix.common.exceptions.CompilationException;
@@ -28,35 +26,35 @@
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.base.ILangExpression;
import org.apache.asterix.lang.common.expression.CallExpr;
-import org.apache.asterix.lang.common.statement.FunctionDecl;
+import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
import org.apache.asterix.lang.common.util.FunctionUtil;
import org.apache.asterix.lang.sqlpp.expression.WindowExpression;
import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppSimpleExpressionVisitor;
-import org.apache.asterix.metadata.declared.MetadataProvider;
import org.apache.asterix.om.functions.BuiltinFunctions;
public final class SqlppFunctionCallResolverVisitor extends AbstractSqlppSimpleExpressionVisitor {
- private final MetadataProvider metadataProvider;
+ private final LangRewritingContext context;
- private final Set<FunctionSignature> declaredFunctions;
+ private final boolean allowNonStoredUdfCalls;
private final BiFunction<String, Integer, FunctionSignature> builtinFunctionResolver;
private final BiFunction<String, Integer, FunctionSignature> callExprResolver;
- public SqlppFunctionCallResolverVisitor(MetadataProvider metadataProvider, List<FunctionDecl> declaredFunctions) {
- this.metadataProvider = metadataProvider;
- this.declaredFunctions = FunctionUtil.getFunctionSignatures(declaredFunctions);
- this.builtinFunctionResolver = FunctionUtil.createBuiltinFunctionResolver(metadataProvider);
+ public SqlppFunctionCallResolverVisitor(LangRewritingContext context, boolean allowNonStoredUdfCalls) {
+ this.context = context;
+ this.allowNonStoredUdfCalls = allowNonStoredUdfCalls;
+ this.builtinFunctionResolver = FunctionUtil.createBuiltinFunctionResolver(context.getMetadataProvider());
this.callExprResolver = this::resolveCallExpr;
}
@Override
public Expression visit(CallExpr callExpr, ILangExpression arg) throws CompilationException {
FunctionSignature fs = FunctionUtil.resolveFunctionCall(callExpr.getFunctionSignature(),
- callExpr.getSourceLocation(), metadataProvider, declaredFunctions, callExprResolver);
+ callExpr.getSourceLocation(), context.getMetadataProvider(), callExprResolver, true,
+ context.getDeclaredFunctions(), allowNonStoredUdfCalls);
callExpr.setFunctionSignature(fs);
return super.visit(callExpr, arg);
}
@@ -64,7 +62,7 @@
@Override
public Expression visit(WindowExpression winExpr, ILangExpression arg) throws CompilationException {
FunctionSignature fs = FunctionUtil.resolveFunctionCall(winExpr.getFunctionSignature(),
- winExpr.getSourceLocation(), metadataProvider, declaredFunctions, callExprResolver);
+ winExpr.getSourceLocation(), context.getMetadataProvider(), callExprResolver, false, null, false);
winExpr.setFunctionSignature(fs);
return super.visit(winExpr, arg);
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGatherFunctionCallsVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGatherFunctionCallsVisitor.java
new file mode 100644
index 0000000..8559c96
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGatherFunctionCallsVisitor.java
@@ -0,0 +1,238 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.asterix.lang.sqlpp.rewrites.visitor;
+
+import java.util.Collection;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.lang.common.base.AbstractClause;
+import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.clause.LetClause;
+import org.apache.asterix.lang.common.expression.AbstractCallExpression;
+import org.apache.asterix.lang.common.expression.ListSliceExpression;
+import org.apache.asterix.lang.common.struct.Identifier;
+import org.apache.asterix.lang.common.visitor.GatherFunctionCallsVisitor;
+import org.apache.asterix.lang.sqlpp.clause.AbstractBinaryCorrelateClause;
+import org.apache.asterix.lang.sqlpp.clause.FromClause;
+import org.apache.asterix.lang.sqlpp.clause.FromTerm;
+import org.apache.asterix.lang.sqlpp.clause.HavingClause;
+import org.apache.asterix.lang.sqlpp.clause.JoinClause;
+import org.apache.asterix.lang.sqlpp.clause.NestClause;
+import org.apache.asterix.lang.sqlpp.clause.Projection;
+import org.apache.asterix.lang.sqlpp.clause.SelectBlock;
+import org.apache.asterix.lang.sqlpp.clause.SelectClause;
+import org.apache.asterix.lang.sqlpp.clause.SelectElement;
+import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
+import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
+import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
+import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
+import org.apache.asterix.lang.sqlpp.expression.WindowExpression;
+import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
+import org.apache.asterix.lang.sqlpp.visitor.base.ISqlppVisitor;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+
+public final class SqlppGatherFunctionCallsVisitor extends GatherFunctionCallsVisitor
+ implements ISqlppVisitor<Void, Void> {
+
+ public SqlppGatherFunctionCallsVisitor(Collection<? super AbstractCallExpression> calls) {
+ super(calls);
+ }
+
+ @Override
+ public Void visit(FromClause fromClause, Void arg) throws CompilationException {
+ for (FromTerm fromTerm : fromClause.getFromTerms()) {
+ fromTerm.accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(FromTerm fromTerm, Void arg) throws CompilationException {
+ fromTerm.getLeftExpression().accept(this, arg);
+ for (AbstractBinaryCorrelateClause correlateClause : fromTerm.getCorrelateClauses()) {
+ correlateClause.accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(JoinClause joinClause, Void arg) throws CompilationException {
+ joinClause.getRightExpression().accept(this, arg);
+ joinClause.getConditionExpression().accept(this, arg);
+ return null;
+ }
+
+ @Override
+ public Void visit(NestClause nestClause, Void arg) throws CompilationException {
+ nestClause.getRightExpression().accept(this, arg);
+ nestClause.getConditionExpression().accept(this, arg);
+ return null;
+ }
+
+ @Override
+ public Void visit(Projection projection, Void arg) throws CompilationException {
+ if (!projection.star()) {
+ projection.getExpression().accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(SelectBlock selectBlock, Void arg) throws CompilationException {
+ if (selectBlock.hasFromClause()) {
+ selectBlock.getFromClause().accept(this, arg);
+ }
+ if (selectBlock.hasLetWhereClauses()) {
+ for (AbstractClause letWhereClause : selectBlock.getLetWhereList()) {
+ letWhereClause.accept(this, arg);
+ }
+ }
+ if (selectBlock.hasGroupbyClause()) {
+ selectBlock.getGroupbyClause().accept(this, arg);
+ }
+ if (selectBlock.hasLetHavingClausesAfterGroupby()) {
+ for (AbstractClause letHavingClause : selectBlock.getLetHavingListAfterGroupby()) {
+ letHavingClause.accept(this, arg);
+ }
+ }
+ selectBlock.getSelectClause().accept(this, arg);
+ return null;
+ }
+
+ @Override
+ public Void visit(SelectClause selectClause, Void arg) throws CompilationException {
+ if (selectClause.selectElement()) {
+ selectClause.getSelectElement().accept(this, arg);
+ } else {
+ selectClause.getSelectRegular().accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(SelectElement selectElement, Void arg) throws CompilationException {
+ selectElement.getExpression().accept(this, arg);
+ return null;
+ }
+
+ @Override
+ public Void visit(SelectRegular selectRegular, Void arg) throws CompilationException {
+ for (Projection projection : selectRegular.getProjections()) {
+ projection.accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(SelectSetOperation selectSetOperation, Void arg) throws CompilationException {
+ selectSetOperation.getLeftInput().accept(this, arg);
+ for (SetOperationRight setOperationRight : selectSetOperation.getRightInputs()) {
+ setOperationRight.getSetOperationRightInput().accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(SelectExpression selectStatement, Void arg) throws CompilationException {
+ if (selectStatement.hasLetClauses()) {
+ for (LetClause letClause : selectStatement.getLetList()) {
+ letClause.accept(this, arg);
+ }
+ }
+ selectStatement.getSelectSetOperation().accept(this, arg);
+ if (selectStatement.hasOrderby()) {
+ selectStatement.getOrderbyClause().accept(this, arg);
+ }
+ if (selectStatement.hasLimit()) {
+ selectStatement.getLimitClause().accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(UnnestClause unnestClause, Void arg) throws CompilationException {
+ unnestClause.getRightExpression().accept(this, arg);
+ return null;
+ }
+
+ @Override
+ public Void visit(HavingClause havingClause, Void arg) throws CompilationException {
+ havingClause.getFilterExpression().accept(this, arg);
+ return null;
+ }
+
+ @Override
+ public Void visit(CaseExpression caseExpression, Void arg) throws CompilationException {
+ caseExpression.getConditionExpr().accept(this, arg);
+ for (Expression expr : caseExpression.getWhenExprs()) {
+ expr.accept(this, arg);
+ }
+ for (Expression expr : caseExpression.getThenExprs()) {
+ expr.accept(this, arg);
+ }
+ caseExpression.getElseExpr().accept(this, arg);
+ return null;
+ }
+
+ @Override
+ public Void visit(WindowExpression winExpr, Void arg) throws CompilationException {
+ calls.add(winExpr);
+ if (winExpr.hasPartitionList()) {
+ for (Expression expr : winExpr.getPartitionList()) {
+ expr.accept(this, arg);
+ }
+ }
+ if (winExpr.hasOrderByList()) {
+ for (Expression expr : winExpr.getOrderbyList()) {
+ expr.accept(this, arg);
+ }
+ }
+ if (winExpr.hasFrameStartExpr()) {
+ winExpr.getFrameStartExpr().accept(this, arg);
+ }
+ if (winExpr.hasFrameEndExpr()) {
+ winExpr.getFrameEndExpr().accept(this, arg);
+ }
+ if (winExpr.hasWindowFieldList()) {
+ for (Pair<Expression, Identifier> p : winExpr.getWindowFieldList()) {
+ p.first.accept(this, arg);
+ }
+ }
+ if (winExpr.hasAggregateFilterExpr()) {
+ winExpr.getAggregateFilterExpr().accept(this, arg);
+ }
+ for (Expression expr : winExpr.getExprList()) {
+ expr.accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(ListSliceExpression expression, Void arg) throws CompilationException {
+ expression.getExpr().accept(this, arg);
+ expression.getStartIndexExpression().accept(this, arg);
+
+ if (expression.hasEndExpression()) {
+ expression.getEndIndexExpression().accept(this, arg);
+ }
+ return null;
+ }
+}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java
index 4fb17f0..5200b94 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java
@@ -23,9 +23,9 @@
import java.util.Map;
import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.functions.FunctionSignature;
import org.apache.asterix.lang.common.base.AbstractClause;
import org.apache.asterix.lang.common.base.Expression;
-import org.apache.asterix.lang.common.base.IRewriterFactory;
import org.apache.asterix.lang.common.clause.LetClause;
import org.apache.asterix.lang.common.expression.ListSliceExpression;
import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
@@ -52,26 +52,18 @@
import org.apache.asterix.lang.sqlpp.util.SqlppRewriteUtil;
import org.apache.asterix.lang.sqlpp.visitor.SqlppCloneAndSubstituteVariablesVisitor;
import org.apache.asterix.lang.sqlpp.visitor.base.ISqlppVisitor;
-import org.apache.asterix.metadata.declared.MetadataProvider;
import org.apache.hyracks.algebricks.common.utils.Pair;
-public class SqlppInlineUdfsVisitor extends AbstractInlineUdfsVisitor
- implements ISqlppVisitor<Boolean, List<FunctionDecl>> {
+public class SqlppInlineUdfsVisitor extends AbstractInlineUdfsVisitor implements ISqlppVisitor<Boolean, Void> {
/**
* @param context,
* manages ids of variables and guarantees uniqueness of variables.
- * @param rewriterFactory,
- * a rewrite factory for rewriting user-defined functions.
- * @param declaredFunctions,
- * a list of declared functions associated with the query.
- * @param metadataProvider,
- * providing the definition of created (i.e., stored) user-defined functions.
+ * @param usedUDFs,
+ * user defined functions used by this query.
*/
- public SqlppInlineUdfsVisitor(LangRewritingContext context, IRewriterFactory rewriterFactory,
- List<FunctionDecl> declaredFunctions, MetadataProvider metadataProvider) {
- super(context, rewriterFactory, declaredFunctions, metadataProvider,
- new SqlppCloneAndSubstituteVariablesVisitor(context));
+ public SqlppInlineUdfsVisitor(LangRewritingContext context, Map<FunctionSignature, FunctionDecl> usedUDFs) {
+ super(context, usedUDFs, new SqlppCloneAndSubstituteVariablesVisitor(context));
}
@Override
@@ -82,220 +74,218 @@
}
@Override
- public Boolean visit(FromClause fromClause, List<FunctionDecl> func) throws CompilationException {
+ public Boolean visit(FromClause fromClause, Void arg) throws CompilationException {
boolean changed = false;
for (FromTerm fromTerm : fromClause.getFromTerms()) {
- changed |= fromTerm.accept(this, func);
+ changed |= fromTerm.accept(this, arg);
}
return changed;
}
@Override
- public Boolean visit(FromTerm fromTerm, List<FunctionDecl> func) throws CompilationException {
+ public Boolean visit(FromTerm fromTerm, Void arg) throws CompilationException {
boolean changed = false;
- Pair<Boolean, Expression> p = inlineUdfsInExpr(fromTerm.getLeftExpression(), func);
+ Pair<Boolean, Expression> p = inlineUdfsInExpr(fromTerm.getLeftExpression());
fromTerm.setLeftExpression(p.second);
changed |= p.first;
for (AbstractBinaryCorrelateClause correlateClause : fromTerm.getCorrelateClauses()) {
- changed |= correlateClause.accept(this, func);
+ changed |= correlateClause.accept(this, arg);
}
return changed;
}
@Override
- public Boolean visit(JoinClause joinClause, List<FunctionDecl> funcs) throws CompilationException {
- Pair<Boolean, Expression> p1 = inlineUdfsInExpr(joinClause.getRightExpression(), funcs);
+ public Boolean visit(JoinClause joinClause, Void arg) throws CompilationException {
+ Pair<Boolean, Expression> p1 = inlineUdfsInExpr(joinClause.getRightExpression());
joinClause.setRightExpression(p1.second);
- Pair<Boolean, Expression> p2 = inlineUdfsInExpr(joinClause.getConditionExpression(), funcs);
+ Pair<Boolean, Expression> p2 = inlineUdfsInExpr(joinClause.getConditionExpression());
joinClause.setConditionExpression(p2.second);
return p1.first || p2.first;
}
@Override
- public Boolean visit(NestClause nestClause, List<FunctionDecl> funcs) throws CompilationException {
- Pair<Boolean, Expression> p1 = inlineUdfsInExpr(nestClause.getRightExpression(), funcs);
+ public Boolean visit(NestClause nestClause, Void arg) throws CompilationException {
+ Pair<Boolean, Expression> p1 = inlineUdfsInExpr(nestClause.getRightExpression());
nestClause.setRightExpression(p1.second);
- Pair<Boolean, Expression> p2 = inlineUdfsInExpr(nestClause.getConditionExpression(), funcs);
+ Pair<Boolean, Expression> p2 = inlineUdfsInExpr(nestClause.getConditionExpression());
nestClause.setConditionExpression(p2.second);
return p1.first || p2.first;
}
@Override
- public Boolean visit(Projection projection, List<FunctionDecl> funcs) throws CompilationException {
+ public Boolean visit(Projection projection, Void arg) throws CompilationException {
if (projection.star()) {
return false;
}
- Pair<Boolean, Expression> p = inlineUdfsInExpr(projection.getExpression(), funcs);
+ Pair<Boolean, Expression> p = inlineUdfsInExpr(projection.getExpression());
projection.setExpression(p.second);
return p.first;
}
@Override
- public Boolean visit(SelectBlock selectBlock, List<FunctionDecl> funcs) throws CompilationException {
+ public Boolean visit(SelectBlock selectBlock, Void arg) throws CompilationException {
boolean changed = false;
if (selectBlock.hasFromClause()) {
- changed |= selectBlock.getFromClause().accept(this, funcs);
+ changed |= selectBlock.getFromClause().accept(this, arg);
}
if (selectBlock.hasLetWhereClauses()) {
for (AbstractClause letWhereClause : selectBlock.getLetWhereList()) {
- changed |= letWhereClause.accept(this, funcs);
+ changed |= letWhereClause.accept(this, arg);
}
}
if (selectBlock.hasGroupbyClause()) {
- changed |= selectBlock.getGroupbyClause().accept(this, funcs);
+ changed |= selectBlock.getGroupbyClause().accept(this, arg);
}
if (selectBlock.hasLetHavingClausesAfterGroupby()) {
for (AbstractClause letHavingClause : selectBlock.getLetHavingListAfterGroupby()) {
- changed |= letHavingClause.accept(this, funcs);
+ changed |= letHavingClause.accept(this, arg);
}
}
- changed |= selectBlock.getSelectClause().accept(this, funcs);
+ changed |= selectBlock.getSelectClause().accept(this, arg);
return changed;
}
@Override
- public Boolean visit(SelectClause selectClause, List<FunctionDecl> funcs) throws CompilationException {
+ public Boolean visit(SelectClause selectClause, Void arg) throws CompilationException {
boolean changed = false;
if (selectClause.selectElement()) {
- changed |= selectClause.getSelectElement().accept(this, funcs);
+ changed |= selectClause.getSelectElement().accept(this, arg);
} else {
- changed |= selectClause.getSelectRegular().accept(this, funcs);
+ changed |= selectClause.getSelectRegular().accept(this, arg);
}
return changed;
}
@Override
- public Boolean visit(SelectElement selectElement, List<FunctionDecl> funcs) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(selectElement.getExpression(), funcs);
+ public Boolean visit(SelectElement selectElement, Void arg) throws CompilationException {
+ Pair<Boolean, Expression> p = inlineUdfsInExpr(selectElement.getExpression());
selectElement.setExpression(p.second);
return p.first;
}
@Override
- public Boolean visit(SelectRegular selectRegular, List<FunctionDecl> funcs) throws CompilationException {
+ public Boolean visit(SelectRegular selectRegular, Void arg) throws CompilationException {
boolean changed = false;
for (Projection projection : selectRegular.getProjections()) {
- changed |= projection.accept(this, funcs);
+ changed |= projection.accept(this, arg);
}
return changed;
}
@Override
- public Boolean visit(SelectSetOperation selectSetOperation, List<FunctionDecl> funcs) throws CompilationException {
+ public Boolean visit(SelectSetOperation selectSetOperation, Void arg) throws CompilationException {
boolean changed = false;
- changed |= selectSetOperation.getLeftInput().accept(this, funcs);
+ changed |= selectSetOperation.getLeftInput().accept(this, arg);
for (SetOperationRight right : selectSetOperation.getRightInputs()) {
- changed |= right.getSetOperationRightInput().accept(this, funcs);
+ changed |= right.getSetOperationRightInput().accept(this, arg);
}
return changed;
}
@Override
- public Boolean visit(SelectExpression selectExpression, List<FunctionDecl> funcs) throws CompilationException {
+ public Boolean visit(SelectExpression selectExpression, Void arg) throws CompilationException {
boolean changed = false;
if (selectExpression.hasLetClauses()) {
for (LetClause letClause : selectExpression.getLetList()) {
- changed |= letClause.accept(this, funcs);
+ changed |= letClause.accept(this, arg);
}
}
- changed |= selectExpression.getSelectSetOperation().accept(this, funcs);
+ changed |= selectExpression.getSelectSetOperation().accept(this, arg);
if (selectExpression.hasOrderby()) {
- changed |= selectExpression.getOrderbyClause().accept(this, funcs);
+ changed |= selectExpression.getOrderbyClause().accept(this, arg);
}
if (selectExpression.hasLimit()) {
- changed |= selectExpression.getLimitClause().accept(this, funcs);
+ changed |= selectExpression.getLimitClause().accept(this, arg);
}
return changed;
}
@Override
- public Boolean visit(UnnestClause unnestClause, List<FunctionDecl> funcs) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(unnestClause.getRightExpression(), funcs);
+ public Boolean visit(UnnestClause unnestClause, Void arg) throws CompilationException {
+ Pair<Boolean, Expression> p = inlineUdfsInExpr(unnestClause.getRightExpression());
unnestClause.setRightExpression(p.second);
return p.first;
}
@Override
- public Boolean visit(HavingClause havingClause, List<FunctionDecl> funcs) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(havingClause.getFilterExpression(), funcs);
+ public Boolean visit(HavingClause havingClause, Void arg) throws CompilationException {
+ Pair<Boolean, Expression> p = inlineUdfsInExpr(havingClause.getFilterExpression());
havingClause.setFilterExpression(p.second);
return p.first;
}
@Override
- public Boolean visit(CaseExpression caseExpr, List<FunctionDecl> funcs) throws CompilationException {
- Pair<Boolean, Expression> result = inlineUdfsInExpr(caseExpr.getConditionExpr(), funcs);
+ public Boolean visit(CaseExpression caseExpr, Void arg) throws CompilationException {
+ Pair<Boolean, Expression> result = inlineUdfsInExpr(caseExpr.getConditionExpr());
caseExpr.setConditionExpr(result.second);
boolean inlined = result.first;
- Pair<Boolean, List<Expression>> inlinedList = inlineUdfsInExprList(caseExpr.getWhenExprs(), funcs);
+ Pair<Boolean, List<Expression>> inlinedList = inlineUdfsInExprList(caseExpr.getWhenExprs());
inlined = inlined || inlinedList.first;
caseExpr.setWhenExprs(inlinedList.second);
- inlinedList = inlineUdfsInExprList(caseExpr.getThenExprs(), funcs);
+ inlinedList = inlineUdfsInExprList(caseExpr.getThenExprs());
inlined = inlined || inlinedList.first;
caseExpr.setThenExprs(inlinedList.second);
- result = inlineUdfsInExpr(caseExpr.getElseExpr(), funcs);
+ result = inlineUdfsInExpr(caseExpr.getElseExpr());
caseExpr.setElseExpr(result.second);
return inlined || result.first;
}
@Override
- public Boolean visit(WindowExpression winExpr, List<FunctionDecl> funcs) throws CompilationException {
+ public Boolean visit(WindowExpression winExpr, Void arg) throws CompilationException {
boolean inlined = false;
if (winExpr.hasPartitionList()) {
- Pair<Boolean, List<Expression>> inlinedList = inlineUdfsInExprList(winExpr.getPartitionList(), funcs);
+ Pair<Boolean, List<Expression>> inlinedList = inlineUdfsInExprList(winExpr.getPartitionList());
winExpr.setPartitionList(inlinedList.second);
inlined = inlinedList.first;
}
if (winExpr.hasOrderByList()) {
- Pair<Boolean, List<Expression>> inlinedList = inlineUdfsInExprList(winExpr.getOrderbyList(), funcs);
+ Pair<Boolean, List<Expression>> inlinedList = inlineUdfsInExprList(winExpr.getOrderbyList());
winExpr.setOrderbyList(inlinedList.second);
inlined |= inlinedList.first;
}
if (winExpr.hasFrameStartExpr()) {
- Pair<Boolean, Expression> inlinedExpr = inlineUdfsInExpr(winExpr.getFrameStartExpr(), funcs);
+ Pair<Boolean, Expression> inlinedExpr = inlineUdfsInExpr(winExpr.getFrameStartExpr());
winExpr.setFrameStartExpr(inlinedExpr.second);
inlined |= inlinedExpr.first;
}
if (winExpr.hasFrameEndExpr()) {
- Pair<Boolean, Expression> inlinedExpr = inlineUdfsInExpr(winExpr.getFrameEndExpr(), funcs);
+ Pair<Boolean, Expression> inlinedExpr = inlineUdfsInExpr(winExpr.getFrameEndExpr());
winExpr.setFrameEndExpr(inlinedExpr.second);
inlined |= inlinedExpr.first;
}
if (winExpr.hasWindowFieldList()) {
Pair<Boolean, List<Pair<Expression, Identifier>>> inlinedList =
- inlineUdfsInFieldList(winExpr.getWindowFieldList(), funcs);
+ inlineUdfsInFieldList(winExpr.getWindowFieldList());
winExpr.setWindowFieldList(inlinedList.second);
inlined |= inlinedList.first;
}
if (winExpr.hasAggregateFilterExpr()) {
- Pair<Boolean, Expression> inlinedExpr = inlineUdfsInExpr(winExpr.getAggregateFilterExpr(), funcs);
+ Pair<Boolean, Expression> inlinedExpr = inlineUdfsInExpr(winExpr.getAggregateFilterExpr());
winExpr.setAggregateFilterExpr(inlinedExpr.second);
inlined |= inlinedExpr.first;
}
- Pair<Boolean, List<Expression>> inlinedList = inlineUdfsInExprList(winExpr.getExprList(), funcs);
+ Pair<Boolean, List<Expression>> inlinedList = inlineUdfsInExprList(winExpr.getExprList());
winExpr.setExprList(inlinedList.second);
inlined |= inlinedList.first;
return inlined;
}
@Override
- public Boolean visit(ListSliceExpression expression, List<FunctionDecl> funcs) throws CompilationException {
- Pair<Boolean, Expression> expressionResult = inlineUdfsInExpr(expression.getExpr(), funcs);
+ public Boolean visit(ListSliceExpression expression, Void arg) throws CompilationException {
+ Pair<Boolean, Expression> expressionResult = inlineUdfsInExpr(expression.getExpr());
expression.setExpr(expressionResult.second);
boolean inlined = expressionResult.first;
- Pair<Boolean, Expression> startIndexExpressResult =
- inlineUdfsInExpr(expression.getStartIndexExpression(), funcs);
+ Pair<Boolean, Expression> startIndexExpressResult = inlineUdfsInExpr(expression.getStartIndexExpression());
expression.setStartIndexExpression(startIndexExpressResult.second);
inlined |= startIndexExpressResult.first;
// End index expression can be null (optional)
if (expression.hasEndExpression()) {
- Pair<Boolean, Expression> endIndexExpressionResult =
- inlineUdfsInExpr(expression.getEndIndexExpression(), funcs);
+ Pair<Boolean, Expression> endIndexExpressionResult = inlineUdfsInExpr(expression.getEndIndexExpression());
expression.setEndIndexExpression(endIndexExpressionResult.second);
inlined |= endIndexExpressionResult.first;
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
index b5375d2..998d8e6 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
@@ -257,8 +257,8 @@
@Override
public FunctionDecl visit(FunctionDecl fd, Void arg) throws CompilationException {
- FunctionDecl copy =
- new FunctionDecl(fd.getSignature(), fd.getParamList(), (Expression) fd.getFuncBody().accept(this, arg));
+ FunctionDecl copy = new FunctionDecl(fd.getSignature(), fd.getParamList(),
+ (Expression) fd.getFuncBody().accept(this, arg), fd.isStored());
copy.setSourceLocation(fd.getSourceLocation());
return copy;
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index e1db7b7..d8fd123 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -393,7 +393,7 @@
}
@Override
- public FunctionDecl parseFunctionBody(FunctionSignature signature, List<String> paramNames)
+ public FunctionDecl parseFunctionBody(FunctionSignature signature, List<String> paramNames, boolean isStored)
throws CompilationException {
return parseImpl(new ParseFunction<FunctionDecl>() {
@Override
@@ -408,7 +408,7 @@
Expression functionBodyExpr = SQLPPParser.this.FunctionBody();
removeCurrentScope();
defaultDataverse = dataverse;
- return new FunctionDecl(signature, paramVars, functionBodyExpr);
+ return new FunctionDecl(signature, paramVars, functionBodyExpr, isStored);
}
});
}
@@ -2951,7 +2951,7 @@
for (Pair<VarIdentifier,TypeExpression> p: paramList) {
params.add(p.getFirst());
}
- FunctionDecl stmt = new FunctionDecl(signature, params, funcBody);
+ FunctionDecl stmt = new FunctionDecl(signature, params, funcBody, false);
removeCurrentScope();
return addSourceLocation(stmt, startToken);
}
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java
index 29acbda..f8ba574 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java
@@ -19,6 +19,7 @@
package org.apache.asterix.metadata;
+import static org.apache.asterix.common.api.IIdentifierMapper.Modifier.PLURAL;
import static org.apache.asterix.common.exceptions.ErrorCode.FULL_TEXT_DEFAULT_CONFIG_CANNOT_BE_DELETED_OR_CREATED;
import static org.apache.asterix.common.utils.IdentifierUtil.dataset;
@@ -848,7 +849,7 @@
}
throw new AsterixException(
org.apache.asterix.common.exceptions.ErrorCode.CANNOT_DROP_OBJECT_DEPENDENT_EXISTS, "node group",
- nodeGroupName, dataset() + "(s)",
+ nodeGroupName, dataset(PLURAL),
datasets.stream().map(DatasetUtil::getFullyQualifiedDisplayName).collect(Collectors.joining(", ")));
}
try {
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
index 497b15f..3ab295e 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
@@ -18,6 +18,7 @@
*/
package org.apache.asterix.metadata.declared;
+import static org.apache.asterix.common.api.IIdentifierMapper.Modifier.PLURAL;
import static org.apache.asterix.common.utils.IdentifierUtil.dataset;
import static org.apache.asterix.common.utils.IdentifierUtil.dataverse;
import static org.apache.asterix.metadata.utils.MetadataConstants.METADATA_OBJECT_NAME_INVALID_CHARS;
@@ -1037,7 +1038,7 @@
JobSpecification jobSpec, IAType itemType, ITypedAdapterFactory adapterFactory,
ITupleFilterFactory tupleFilterFactory, long outputLimit) throws AlgebricksException {
if (itemType.getTypeTag() != ATypeTag.OBJECT) {
- throw new AlgebricksException("Can only scan " + dataset() + "s of records.");
+ throw new AlgebricksException("Can only scan " + dataset(PLURAL) + "of records.");
}
ISerializerDeserializer<?> payloadSerde =
@@ -1534,7 +1535,7 @@
// Sanity checks.
if (primaryKeys.size() > 1) {
throw new AlgebricksException(
- "Cannot create inverted index on " + dataset() + "s with composite primary key.");
+ "Cannot create inverted index on " + dataset(PLURAL) + "with composite primary key.");
}
// The size of secondaryKeys can be two if it receives input from its
// TokenizeOperator- [token, number of token]
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/InvertedIndexResourceFactoryProvider.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/InvertedIndexResourceFactoryProvider.java
index d0b7c59..8b69652 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/InvertedIndexResourceFactoryProvider.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/InvertedIndexResourceFactoryProvider.java
@@ -18,6 +18,7 @@
*/
package org.apache.asterix.metadata.utils;
+import static org.apache.asterix.common.api.IIdentifierMapper.Modifier.PLURAL;
import static org.apache.asterix.common.utils.IdentifierUtil.dataset;
import java.util.List;
@@ -80,7 +81,7 @@
}
if (numPrimaryKeys > 1) {
throw new AsterixException(
- "Cannot create inverted index on " + dataset() + "s with composite primary key.");
+ "Cannot create inverted index on " + dataset(PLURAL) + " with composite primary key.");
}
if (numSecondaryKeys > 1) {
throw new AsterixException("Cannot create composite inverted index on multiple fields.");
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerIPCI.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerIPCI.java
index 16e8ed8..d350f61 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerIPCI.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerIPCI.java
@@ -129,8 +129,16 @@
break;
case SEND_APPLICATION_MESSAGE:
CCNCFunctions.SendApplicationMessageFunction rsf = (CCNCFunctions.SendApplicationMessageFunction) fn;
- ccs.getWorkQueue().schedule(
- new ApplicationMessageWork(ccs, rsf.getMessage(), rsf.getDeploymentId(), rsf.getNodeId()));
+ ApplicationMessageWork work =
+ new ApplicationMessageWork(ccs, rsf.getMessage(), rsf.getDeploymentId(), rsf.getNodeId());
+ if (rsf.isRealTime()) {
+ final ExecutorService executor = ccs.getExecutor();
+ if (executor != null) {
+ executor.execute(work);
+ }
+ } else {
+ ccs.getWorkQueue().schedule(work);
+ }
break;
case GET_NODE_CONTROLLERS_INFO:
ccs.getWorkQueue().schedule(new GetNodeControllersInfoWork(ccs.getNodeManager(),
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/base/IClusterController.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/base/IClusterController.java
index c8106e8..1c91183 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/base/IClusterController.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/base/IClusterController.java
@@ -66,6 +66,8 @@
void sendApplicationMessageToCC(byte[] data, DeploymentId deploymentId, String nodeId) throws Exception;
+ void sendRealTimeApplicationMessageToCC(byte[] data, DeploymentId deploymentId, String nodeId) throws Exception;
+
void registerResultPartitionLocation(JobId jobId, ResultSetId rsId, IResultMetadata metadata, boolean emptyResult,
int partition, int nPartitions, NetworkAddress networkAddress) throws Exception;
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/ipc/CCNCFunctions.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/ipc/CCNCFunctions.java
index 6b5b5db..27a8b02 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/ipc/CCNCFunctions.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/ipc/CCNCFunctions.java
@@ -127,9 +127,10 @@
}
public static class SendApplicationMessageFunction extends Function {
- private static final long serialVersionUID = 1L;
- private byte[] serializedMessage;
- private DeploymentId deploymentId;
+ private static final long serialVersionUID = 2L;
+ private final byte[] serializedMessage;
+ private final DeploymentId deploymentId;
+ private final boolean realTime;
private String nodeId;
public DeploymentId getDeploymentId() {
@@ -148,9 +149,14 @@
return serializedMessage;
}
- public SendApplicationMessageFunction(byte[] data, DeploymentId deploymentId, String nodeId) {
+ public boolean isRealTime() {
+ return realTime;
+ }
+
+ public SendApplicationMessageFunction(byte[] data, DeploymentId deploymentId, boolean realTime, String nodeId) {
this.serializedMessage = data;
this.deploymentId = deploymentId;
+ this.realTime = realTime;
this.nodeId = nodeId;
}
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/ipc/ClusterControllerRemoteProxy.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/ipc/ClusterControllerRemoteProxy.java
index 344c3fb..09dc04d 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/ipc/ClusterControllerRemoteProxy.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/ipc/ClusterControllerRemoteProxy.java
@@ -128,7 +128,14 @@
@Override
public void sendApplicationMessageToCC(byte[] data, DeploymentId deploymentId, String nodeId) throws Exception {
- SendApplicationMessageFunction fn = new SendApplicationMessageFunction(data, deploymentId, nodeId);
+ SendApplicationMessageFunction fn = new SendApplicationMessageFunction(data, deploymentId, false, nodeId);
+ ipcHandle.send(-1, fn, null);
+ }
+
+ @Override
+ public void sendRealTimeApplicationMessageToCC(byte[] data, DeploymentId deploymentId, String nodeId)
+ throws Exception {
+ SendApplicationMessageFunction fn = new SendApplicationMessageFunction(data, deploymentId, true, nodeId);
ipcHandle.send(-1, fn, null);
}
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/ipc/NodeControllerRemoteProxy.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/ipc/NodeControllerRemoteProxy.java
index d32ee32..0b85c4e 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/ipc/NodeControllerRemoteProxy.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/ipc/NodeControllerRemoteProxy.java
@@ -129,7 +129,7 @@
@Override
public void sendApplicationMessageToNC(byte[] data, DeploymentId deploymentId, String nodeId) throws Exception {
- SendApplicationMessageFunction fn = new SendApplicationMessageFunction(data, deploymentId, nodeId);
+ SendApplicationMessageFunction fn = new SendApplicationMessageFunction(data, deploymentId, false, nodeId);
ipcHandle.send(-1, fn, null);
}
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java
index 1356f4c..c774317 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java
@@ -633,6 +633,10 @@
getClusterController(ccId).sendApplicationMessageToCC(data, deploymentId, id);
}
+ public void sendRealTimeApplicationMessageToCC(CcId ccId, byte[] data, DeploymentId deploymentId) throws Exception {
+ getClusterController(ccId).sendRealTimeApplicationMessageToCC(data, deploymentId, id);
+ }
+
public IResultPartitionManager getResultPartitionManager() {
return resultPartitionManager;
}