[ASTERIXDB-2659][API] validate request parameters
- user model changes: yes
- storage format changes: no
- interface changes: no
Details:
- Return 400 BAD request for invalid request parameters.
- Changes in specifying the output format:
HEADER "Accept": application/json;lossless=<BOOLEAN>, text/csv;header=absent/present, application/x-adm
Request parameter "format": csv, json (and above mime types)
- when format is supplied in "Accept", only validate value of attribute if the mime is one of the above
and the attribute name is one of the above (header & lossless).
Change-Id: Ia89fa3179cc36a73fe950f41eab1f0a9d17a541c
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/3767
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
Reviewed-by: Till Westmann <tillw@apache.org>
Contrib: Till Westmann <tillw@apache.org>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java
index 89ffcbe..3fdcc33 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java
@@ -24,9 +24,13 @@
import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
import org.apache.asterix.common.api.IResponsePrinter;
import org.apache.asterix.common.exceptions.ACIDException;
@@ -62,15 +66,32 @@
/**
* Results are returned with the first response
*/
- IMMEDIATE,
+ IMMEDIATE("immediate"),
/**
* Results are produced completely, but only a result handle is returned
*/
- DEFERRED,
+ DEFERRED("deferred"),
/**
* A result handle is returned before the resutlts are complete
*/
- ASYNC
+ ASYNC("async");
+
+ private static final Map<String, ResultDelivery> deliveryNames =
+ Collections.unmodifiableMap(Arrays.stream(ResultDelivery.values())
+ .collect(Collectors.toMap(ResultDelivery::getName, Function.identity())));
+ private final String name;
+
+ ResultDelivery(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public static ResultDelivery fromName(String name) {
+ return deliveryNames.get(name);
+ }
}
class ResultMetadata implements Serializable {
@@ -88,15 +109,32 @@
private static final long serialVersionUID = 5885273238208454611L;
public enum ProfileType {
- COUNTS,
- FULL
+ COUNTS("counts"),
+ FULL("timings"),
+ NONE("off");
+
+ private static final Map<String, ProfileType> profileNames = Collections.unmodifiableMap(Arrays
+ .stream(ProfileType.values()).collect(Collectors.toMap(ProfileType::getName, Function.identity())));
+ private final String name;
+
+ ProfileType(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public static ProfileType fromName(String name) {
+ return profileNames.get(name);
+ }
}
private long count;
private long size;
private long processedObjects;
private Profile profile;
- private ProfileType type;
+ private ProfileType profileType;
private long totalWarningsCount;
public long getCount() {
@@ -141,12 +179,12 @@
return profile != null ? profile.getProfile() : null;
}
- public ProfileType getType() {
- return type;
+ public ProfileType getProfileType() {
+ return profileType;
}
- public void setType(ProfileType type) {
- this.type = type;
+ public void setProfileType(ProfileType profileType) {
+ this.profileType = profileType;
}
}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/CcQueryCancellationServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/CcQueryCancellationServlet.java
index 00aef9e..7ba2867 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/CcQueryCancellationServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/CcQueryCancellationServlet.java
@@ -21,7 +21,7 @@
import java.io.IOException;
import java.util.concurrent.ConcurrentMap;
-import org.apache.asterix.api.http.server.QueryServiceServlet.Parameter;
+import org.apache.asterix.api.http.server.QueryServiceRequestParameters.Parameter;
import org.apache.asterix.common.api.IClientRequest;
import org.apache.asterix.common.api.IRequestTracker;
import org.apache.asterix.common.dataflow.ICcApplicationContext;
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryCancellationServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryCancellationServlet.java
index 053e042..617c937 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryCancellationServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryCancellationServlet.java
@@ -24,7 +24,7 @@
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
-import org.apache.asterix.api.http.server.QueryServiceServlet.Parameter;
+import org.apache.asterix.api.http.server.QueryServiceRequestParameters.Parameter;
import org.apache.asterix.app.message.CancelQueryRequest;
import org.apache.asterix.app.message.CancelQueryResponse;
import org.apache.asterix.common.messaging.api.INCMessageBroker;
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryServiceServlet.java
index acd6784..6953d1f 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryServiceServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryServiceServlet.java
@@ -32,7 +32,6 @@
import org.apache.asterix.app.message.ExecuteStatementResponseMessage;
import org.apache.asterix.app.result.ResponsePrinter;
import org.apache.asterix.app.result.fields.NcResultPrinter;
-import org.apache.asterix.common.api.Duration;
import org.apache.asterix.common.api.IApplicationContext;
import org.apache.asterix.common.api.IRequestReference;
import org.apache.asterix.common.config.GlobalConfig;
@@ -82,17 +81,14 @@
MessageFuture responseFuture = ncMb.registerMessageFuture();
final String handleUrl = getHandleUrl(param.getHost(), param.getPath(), delivery);
try {
- long timeout = ExecuteStatementRequestMessage.DEFAULT_NC_TIMEOUT_MILLIS;
- if (param.getTimeout() != null && !param.getTimeout().trim().isEmpty()) {
- timeout = TimeUnit.NANOSECONDS.toMillis(Duration.parseDurationStringToNanos(param.getTimeout()));
- }
+ long timeout = param.getTimeout();
int stmtCategoryRestrictionMask = org.apache.asterix.app.translator.RequestParameters
.getStatementCategoryRestrictionMask(param.isReadOnly());
- ExecuteStatementRequestMessage requestMsg =
- new ExecuteStatementRequestMessage(ncCtx.getNodeId(), responseFuture.getFutureId(), queryLanguage,
- statementsText, sessionOutput.config(), resultProperties.getNcToCcResultProperties(),
- param.getClientContextID(), handleUrl, optionalParameters, statementParameters,
- param.isMultiStatement(), param.isProfile(), stmtCategoryRestrictionMask, requestReference);
+ ExecuteStatementRequestMessage requestMsg = new ExecuteStatementRequestMessage(ncCtx.getNodeId(),
+ responseFuture.getFutureId(), queryLanguage, statementsText, sessionOutput.config(),
+ resultProperties.getNcToCcResultProperties(), param.getClientContextID(), handleUrl,
+ optionalParameters, statementParameters, param.isMultiStatement(), param.getProfileType(),
+ stmtCategoryRestrictionMask, requestReference);
execution.start();
ncMb.sendMessageToPrimaryCC(requestMsg);
try {
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
index 9664e80..6e70d27 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
@@ -19,42 +19,119 @@
package org.apache.asterix.api.http.server;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import org.apache.asterix.common.api.Duration;
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.RuntimeDataException;
+import org.apache.asterix.translator.IStatementExecutor.ResultDelivery;
+import org.apache.asterix.translator.IStatementExecutor.Stats.ProfileType;
+import org.apache.asterix.translator.SessionConfig.OutputFormat;
+import org.apache.asterix.translator.SessionConfig.PlanFormat;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.http.HttpHeaders;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.server.utils.HttpUtil;
import org.apache.hyracks.util.JSONUtil;
+import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableMap;
public class QueryServiceRequestParameters {
- public static final long DEFAULT_MAX_WARNINGS = 0L;
+ public enum Parameter {
+ ARGS("args"),
+ STATEMENT("statement"),
+ FORMAT("format"),
+ CLIENT_ID("client_context_id"),
+ PRETTY("pretty"),
+ MODE("mode"),
+ TIMEOUT("timeout"),
+ PLAN_FORMAT("plan-format"),
+ MAX_RESULT_READS("max-result-reads"),
+ EXPRESSION_TREE("expression-tree"),
+ REWRITTEN_EXPRESSION_TREE("rewritten-expression-tree"),
+ LOGICAL_PLAN("logical-plan"),
+ OPTIMIZED_LOGICAL_PLAN("optimized-logical-plan"),
+ PARSE_ONLY("parse-only"),
+ READ_ONLY("readonly"),
+ JOB("job"),
+ PROFILE("profile"),
+ SIGNATURE("signature"),
+ MULTI_STATEMENT("multi-statement"),
+ MAX_WARNINGS("max-warnings");
+
+ private final String str;
+
+ Parameter(String str) {
+ this.str = str;
+ }
+
+ public String str() {
+ return str;
+ }
+ }
+
+ private enum Attribute {
+ HEADER("header"),
+ LOSSLESS("lossless");
+
+ private final String str;
+
+ Attribute(String str) {
+ this.str = str;
+ }
+
+ public String str() {
+ return str;
+ }
+ }
+
+ private static final Map<String, PlanFormat> planFormats = ImmutableMap.of(HttpUtil.ContentType.JSON,
+ PlanFormat.JSON, "clean_json", PlanFormat.JSON, "string", PlanFormat.STRING);
+ private static final Map<String, Boolean> booleanValues =
+ ImmutableMap.of(Boolean.TRUE.toString(), Boolean.TRUE, Boolean.FALSE.toString(), Boolean.FALSE);
+ private static final Map<String, Boolean> csvHeaderValues =
+ ImmutableMap.of("present", Boolean.TRUE, "absent", Boolean.FALSE);
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private String host;
private String path;
private String statement;
- private String format;
- private String timeout;
- private boolean pretty;
private String clientContextID;
- private String mode;
- private String maxResultReads;
- private String planFormat;
- private Map<String, JsonNode> statementParams;
- private boolean expressionTree;
- private boolean parseOnly; //don't execute; simply check for syntax correctness and named parameters.
- private boolean readOnly; // only allow statements that belong to QUERY category, fail for all other categories.
- private boolean rewrittenExpressionTree;
- private boolean logicalPlan;
- private boolean optimizedLogicalPlan;
- private boolean job;
- private boolean profile;
- private boolean signature;
- private boolean multiStatement;
- private long maxWarnings = DEFAULT_MAX_WARNINGS;
+ private OutputFormat format = OutputFormat.CLEAN_JSON;
+ private ResultDelivery mode = ResultDelivery.IMMEDIATE;
+ private PlanFormat planFormat = PlanFormat.JSON;
+ private ProfileType profileType = ProfileType.COUNTS;
+ private Map<String, JsonNode> statementParams = null;
+ private boolean pretty = false;
+ private boolean expressionTree = false;
+ private boolean parseOnly = false; // don't execute; simply check for syntax correctness and named parameters.
+ private boolean readOnly = false; // only allow statements belonging to QUERY category, fail for other categories.
+ private boolean rewrittenExpressionTree = false;
+ private boolean logicalPlan = false;
+ private boolean optimizedLogicalPlan = false;
+ private boolean job = false;
+ private boolean isCSVWithHeader = false;
+ private boolean signature = true;
+ private boolean multiStatement = true;
+ private long timeout = TimeUnit.MILLISECONDS.toMillis(Long.MAX_VALUE);
+ private long maxResultReads = 1L;
+ private long maxWarnings = 0L;
public String getHost() {
return host;
@@ -80,19 +157,24 @@
this.statement = statement;
}
- public String getFormat() {
+ public OutputFormat getFormat() {
return format;
}
- public void setFormat(String format) {
- this.format = format;
+ public void setFormat(Pair<OutputFormat, Boolean> formatAndHeader) {
+ Objects.requireNonNull(formatAndHeader);
+ Objects.requireNonNull(formatAndHeader.getLeft());
+ this.format = formatAndHeader.getLeft();
+ if (format == OutputFormat.CSV) {
+ isCSVWithHeader = formatAndHeader.getRight();
+ }
}
- public String getTimeout() {
+ public long getTimeout() {
return timeout;
}
- public void setTimeout(String timeout) {
+ public void setTimeout(long timeout) {
this.timeout = timeout;
}
@@ -112,27 +194,29 @@
this.clientContextID = clientContextID;
}
- public String getMode() {
+ public ResultDelivery getMode() {
return mode;
}
- public void setMode(String mode) {
+ public void setMode(ResultDelivery mode) {
+ Objects.requireNonNull(mode);
this.mode = mode;
}
- public String getMaxResultReads() {
+ public long getMaxResultReads() {
return maxResultReads;
}
- public void setMaxResultReads(String maxResultReads) {
+ public void setMaxResultReads(long maxResultReads) {
this.maxResultReads = maxResultReads;
}
- public String getPlanFormat() {
+ public PlanFormat getPlanFormat() {
return planFormat;
}
- public void setPlanFormat(String planFormat) {
+ public void setPlanFormat(PlanFormat planFormat) {
+ Objects.requireNonNull(planFormat);
this.planFormat = planFormat;
}
@@ -200,12 +284,17 @@
this.job = job;
}
- public void setProfile(boolean profile) {
- this.profile = profile;
+ public void setProfileType(ProfileType profileType) {
+ Objects.requireNonNull(profileType);
+ this.profileType = profileType;
}
- public boolean isProfile() {
- return profile;
+ public ProfileType getProfileType() {
+ return profileType;
+ }
+
+ public boolean isCSVWithHeader() {
+ return format == OutputFormat.CSV && isCSVWithHeader;
}
public boolean isSignature() {
@@ -238,18 +327,18 @@
object.put("path", path);
object.put("statement", statement != null ? JSONUtil.escape(new StringBuilder(), statement).toString() : null);
object.put("pretty", pretty);
- object.put("mode", mode);
+ object.put("mode", mode.getName());
object.put("clientContextID", clientContextID);
- object.put("format", format);
+ object.put("format", format.toString());
object.put("timeout", timeout);
object.put("maxResultReads", maxResultReads);
- object.put("planFormat", planFormat);
+ object.put("planFormat", planFormat.toString());
object.put("expressionTree", expressionTree);
object.put("rewrittenExpressionTree", rewrittenExpressionTree);
object.put("logicalPlan", logicalPlan);
object.put("optimizedLogicalPlan", optimizedLogicalPlan);
object.put("job", job);
- object.put("profile", profile);
+ object.put("profile", profileType.getName());
object.put("signature", signature);
object.put("multiStatement", multiStatement);
object.put("parseOnly", parseOnly);
@@ -272,4 +361,266 @@
return e.toString();
}
}
+
+ public void setParameters(QueryServiceServlet servlet, IServletRequest request, Map<String, String> optionalParams)
+ throws IOException {
+ setHost(servlet.host(request));
+ setPath(servlet.servletPath(request));
+ String contentType = HttpUtil.getContentTypeOnly(request);
+ try {
+ if (HttpUtil.ContentType.APPLICATION_JSON.equals(contentType)) {
+ setParamFromJSON(request, optionalParams);
+ } else {
+ setParamFromRequest(request, optionalParams);
+ }
+ } catch (JsonParseException | JsonMappingException e) {
+ throw new RuntimeDataException(ErrorCode.INVALID_REQ_JSON_VAL);
+ }
+ }
+
+ private void setParamFromJSON(IServletRequest request, Map<String, String> optionalParameters) throws IOException {
+ JsonNode jsonRequest = OBJECT_MAPPER.readTree(HttpUtil.getRequestBody(request));
+ setParams(jsonRequest, request.getHeader(HttpHeaders.ACCEPT), QueryServiceRequestParameters::getParameter);
+ setStatementParams(getOptStatementParameters(jsonRequest, jsonRequest.fieldNames(), JsonNode::get, v -> v));
+ setJsonOptionalParameters(jsonRequest, optionalParameters);
+ }
+
+ private void setParamFromRequest(IServletRequest request, Map<String, String> optionalParameters)
+ throws IOException {
+ setParams(request, request.getHeader(HttpHeaders.ACCEPT), IServletRequest::getParameter);
+ setStatementParams(getOptStatementParameters(request, request.getParameterNames().iterator(),
+ IServletRequest::getParameter, OBJECT_MAPPER::readTree));
+ setOptionalParameters(request, optionalParameters);
+ }
+
+ private <Req> void setParams(Req req, String acceptHeader, BiFunction<Req, String, String> valGetter)
+ throws HyracksDataException {
+ setStatement(valGetter.apply(req, Parameter.STATEMENT.str()));
+ setClientContextID(valGetter.apply(req, Parameter.CLIENT_ID.str()));
+
+ setFormatIfExists(req, acceptHeader, Parameter.FORMAT.str(), valGetter);
+ setMode(parseIfExists(req, Parameter.MODE.str(), valGetter, getMode(), ResultDelivery::fromName));
+ setPlanFormat(parseIfExists(req, Parameter.PLAN_FORMAT.str(), valGetter, getPlanFormat(), planFormats::get));
+ setProfileType(parseIfExists(req, Parameter.PROFILE.str(), valGetter, getProfileType(), ProfileType::fromName));
+
+ setTimeout(parseTime(req, Parameter.TIMEOUT.str(), valGetter, getTimeout()));
+ setMaxResultReads(parseLong(req, Parameter.MAX_RESULT_READS.str(), valGetter, getMaxResultReads()));
+ setMaxWarnings(parseLong(req, Parameter.MAX_WARNINGS.str(), valGetter, getMaxWarnings()));
+
+ setPretty(parseBoolean(req, Parameter.PRETTY.str(), valGetter, isPretty()));
+ setExpressionTree(parseBoolean(req, Parameter.EXPRESSION_TREE.str(), valGetter, isExpressionTree()));
+ setRewrittenExpressionTree(
+ parseBoolean(req, Parameter.REWRITTEN_EXPRESSION_TREE.str(), valGetter, isRewrittenExpressionTree()));
+ setLogicalPlan(parseBoolean(req, Parameter.LOGICAL_PLAN.str(), valGetter, isLogicalPlan()));
+ setParseOnly(parseBoolean(req, Parameter.PARSE_ONLY.str(), valGetter, isParseOnly()));
+ setReadOnly(parseBoolean(req, Parameter.READ_ONLY.str(), valGetter, isReadOnly()));
+ setOptimizedLogicalPlan(
+ parseBoolean(req, Parameter.OPTIMIZED_LOGICAL_PLAN.str(), valGetter, isOptimizedLogicalPlan()));
+ setMultiStatement(parseBoolean(req, Parameter.MULTI_STATEMENT.str(), valGetter, isMultiStatement()));
+ setJob(parseBoolean(req, Parameter.JOB.str(), valGetter, isJob()));
+ setSignature(parseBoolean(req, Parameter.SIGNATURE.str(), valGetter, isSignature()));
+ }
+
+ protected void setJsonOptionalParameters(JsonNode jsonRequest, Map<String, String> optionalParameters)
+ throws HyracksDataException {
+ // allows extensions to set extra parameters
+ }
+
+ protected void setOptionalParameters(IServletRequest request, Map<String, String> optionalParameters)
+ throws HyracksDataException {
+ // allows extensions to set extra parameters
+ }
+
+ @FunctionalInterface
+ interface CheckedFunction<I, O> {
+ O apply(I requestParamValue) throws IOException;
+ }
+
+ private <R, P> Map<String, JsonNode> getOptStatementParameters(R request, Iterator<String> paramNameIter,
+ BiFunction<R, String, P> paramValueAccessor, CheckedFunction<P, JsonNode> paramValueParser)
+ throws IOException {
+ Map<String, JsonNode> result = null;
+ while (paramNameIter.hasNext()) {
+ String paramName = paramNameIter.next();
+ String stmtParamName = extractStatementParameterName(paramName);
+ if (stmtParamName != null) {
+ if (result == null) {
+ result = new HashMap<>();
+ }
+ P paramValue = paramValueAccessor.apply(request, paramName);
+ JsonNode stmtParamValue = paramValueParser.apply(paramValue);
+ result.put(stmtParamName, stmtParamValue);
+ } else if (Parameter.ARGS.str().equals(toLower(paramName))) {
+ if (result == null) {
+ result = new HashMap<>();
+ }
+ P paramValue = paramValueAccessor.apply(request, paramName);
+ JsonNode stmtParamValue = paramValueParser.apply(paramValue);
+ if (!stmtParamValue.isArray()) {
+ throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, paramName, stmtParamValue.asText());
+ }
+ for (int i = 0, ln = stmtParamValue.size(); i < ln; i++) {
+ result.put(String.valueOf(i + 1), stmtParamValue.get(i));
+ }
+ }
+ }
+ return result;
+ }
+
+ public static String extractStatementParameterName(String name) {
+ int ln = name.length();
+ if ((ln == 2 || isStatementParameterNameRest(name, 2)) && name.charAt(0) == '$'
+ && Character.isLetter(name.charAt(1))) {
+ return name.substring(1);
+ }
+ return null;
+ }
+
+ private static boolean isStatementParameterNameRest(CharSequence input, int startIndex) {
+ int i = startIndex;
+ for (int ln = input.length(); i < ln; i++) {
+ char c = input.charAt(i);
+ boolean ok = c == '_' || Character.isLetterOrDigit(c);
+ if (!ok) {
+ return false;
+ }
+ }
+ return i > startIndex;
+ }
+
+ private static <R> boolean parseBoolean(R request, String parameterName,
+ BiFunction<R, String, String> valueAccessor, boolean defaultVal) throws HyracksDataException {
+ String value = toLower(valueAccessor.apply(request, parameterName));
+ if (value == null) {
+ return defaultVal;
+ }
+ Boolean booleanVal = booleanValues.get(value);
+ if (booleanVal == null) {
+ throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, parameterName, value);
+
+ }
+ return booleanVal.booleanValue();
+ }
+
+ private static <R> long parseLong(R request, String parameterName, BiFunction<R, String, String> valueAccessor,
+ long defaultVal) throws HyracksDataException {
+ String value = toLower(valueAccessor.apply(request, parameterName));
+ if (value == null) {
+ return defaultVal;
+ }
+ try {
+ return Long.parseLong(value);
+ } catch (NumberFormatException e) {
+ throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, parameterName, value);
+ }
+ }
+
+ private static <R> long parseTime(R request, String parameterName, BiFunction<R, String, String> valueAccessor,
+ long def) throws HyracksDataException {
+ String value = toLower(valueAccessor.apply(request, parameterName));
+ if (value == null) {
+ return def;
+ }
+ try {
+ return TimeUnit.NANOSECONDS.toMillis(Duration.parseDurationStringToNanos(value));
+ } catch (HyracksDataException e) {
+ throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, parameterName, value);
+ }
+ }
+
+ private <R> void setFormatIfExists(R request, String acceptHeader, String parameterName,
+ BiFunction<R, String, String> valueAccessor) throws HyracksDataException {
+ Pair<OutputFormat, Boolean> formatAndHeader =
+ parseFormatIfExists(request, acceptHeader, parameterName, valueAccessor);
+ if (formatAndHeader != null) {
+ setFormat(formatAndHeader);
+ }
+ }
+
+ protected <R> Pair<OutputFormat, Boolean> parseFormatIfExists(R request, String acceptHeader, String parameterName,
+ BiFunction<R, String, String> valueAccessor) throws HyracksDataException {
+ String value = toLower(valueAccessor.apply(request, parameterName));
+ if (value == null) {
+ // if no value is provided in request parameter "format", then check "Accept" parameter in HEADER
+ // and only validate attribute val if mime and attribute name are known, e.g. application/json;lossless=?
+ if (acceptHeader != null) {
+ String[] mimeTypes = StringUtils.split(acceptHeader, ',');
+ for (int i = 0, size = mimeTypes.length; i < size; i++) {
+ Pair<OutputFormat, Boolean> formatAndHeader = fromMime(mimeTypes[i]);
+ if (formatAndHeader != null) {
+ return formatAndHeader;
+ }
+ }
+ }
+ return null;
+ }
+ // checking value in request parameter "format"
+ if (value.equals(HttpUtil.ContentType.CSV)) {
+ return Pair.of(OutputFormat.CSV, Boolean.FALSE);
+ } else if (value.equals(HttpUtil.ContentType.JSON)) {
+ return Pair.of(OutputFormat.CLEAN_JSON, Boolean.FALSE);
+ } else {
+ Pair<OutputFormat, Boolean> format = fromMime(value);
+ if (format == null) {
+ throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, parameterName, value);
+ }
+ return format;
+ }
+ }
+
+ private static Pair<OutputFormat, Boolean> fromMime(String mimeType) throws HyracksDataException {
+ // find the first match, no preferences for now
+ String[] mimeSplits = StringUtils.split(mimeType, ';');
+ if (mimeSplits.length > 0) {
+ String format = mimeSplits[0].toLowerCase().trim();
+ if (format.equals(HttpUtil.ContentType.APPLICATION_JSON)) {
+ return Pair.of(hasValue(mimeSplits, Attribute.LOSSLESS.str(), booleanValues)
+ ? OutputFormat.LOSSLESS_JSON : OutputFormat.CLEAN_JSON, Boolean.FALSE);
+ } else if (format.equals(HttpUtil.ContentType.TEXT_CSV)) {
+ return Pair.of(OutputFormat.CSV,
+ hasValue(mimeSplits, Attribute.HEADER.str(), csvHeaderValues) ? Boolean.TRUE : Boolean.FALSE);
+ } else if (format.equals(HttpUtil.ContentType.APPLICATION_ADM)) {
+ return Pair.of(OutputFormat.ADM, Boolean.FALSE);
+ }
+ }
+ return null;
+ }
+
+ private static boolean hasValue(String[] mimeTypeParts, String attributeName, Map<String, Boolean> allowedValues)
+ throws HyracksDataException {
+ for (int i = 1, size = mimeTypeParts.length; i < size; i++) {
+ String[] attNameAndVal = StringUtils.split(mimeTypeParts[i], '=');
+ if (attNameAndVal.length == 2 && attNameAndVal[0].toLowerCase().trim().equals(attributeName)) {
+ Boolean value = allowedValues.get(attNameAndVal[1].toLowerCase().trim());
+ if (value == null) {
+ throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, attributeName, attNameAndVal[1]);
+ }
+ return value.booleanValue();
+ }
+ }
+ return false;
+ }
+
+ private static <Req, Param> Param parseIfExists(Req request, String parameterName,
+ BiFunction<Req, String, String> valueAccessor, Param defaultVal, Function<String, Param> parseFunction)
+ throws HyracksDataException {
+ String valueInRequest = toLower(valueAccessor.apply(request, parameterName));
+ if (valueInRequest == null) {
+ return defaultVal;
+ }
+ Param resultValue = parseFunction.apply(valueInRequest);
+ if (resultValue == null) {
+ throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, parameterName, valueInRequest);
+ }
+ return resultValue;
+ }
+
+ protected static String getParameter(JsonNode node, String parameter) {
+ final JsonNode value = node.get(parameter);
+ return value != null ? value.asText() : null;
+ }
+
+ protected static String toLower(String s) {
+ return s != null ? s.toLowerCase() : s;
+ }
}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
index 72557be..63678f8 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
@@ -19,6 +19,8 @@
package org.apache.asterix.api.http.server;
import static org.apache.asterix.common.exceptions.ErrorCode.ASTERIX;
+import static org.apache.asterix.common.exceptions.ErrorCode.INVALID_REQ_JSON_VAL;
+import static org.apache.asterix.common.exceptions.ErrorCode.INVALID_REQ_PARAM_VAL;
import static org.apache.asterix.common.exceptions.ErrorCode.NO_STATEMENT_PROVIDED;
import static org.apache.asterix.common.exceptions.ErrorCode.REJECT_BAD_CLUSTER_STATE;
import static org.apache.asterix.common.exceptions.ErrorCode.REJECT_NODE_UNREGISTERED;
@@ -33,13 +35,10 @@
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
-import java.util.function.BiFunction;
import java.util.function.Function;
import org.apache.asterix.algebra.base.ILangExtension;
@@ -65,7 +64,6 @@
import org.apache.asterix.common.api.ICodedMessage;
import org.apache.asterix.common.api.IReceptionist;
import org.apache.asterix.common.api.IRequestReference;
-import org.apache.asterix.common.config.GlobalConfig;
import org.apache.asterix.common.context.IStorageComponentProvider;
import org.apache.asterix.common.dataflow.ICcApplicationContext;
import org.apache.asterix.common.exceptions.CompilationException;
@@ -97,14 +95,9 @@
import org.apache.hyracks.http.api.IServletResponse;
import org.apache.hyracks.http.server.utils.HttpUtil;
import org.apache.hyracks.util.LogRedactionUtil;
-import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.JsonNode;
-
import io.netty.handler.codec.http.HttpResponseStatus;
public class QueryServiceServlet extends AbstractQueryApiServlet {
@@ -154,54 +147,6 @@
response.setStatus(HttpResponseStatus.OK);
}
- public enum Parameter {
- ARGS("args"),
- STATEMENT("statement"),
- FORMAT("format"),
- CLIENT_ID("client_context_id"),
- PRETTY("pretty"),
- MODE("mode"),
- TIMEOUT("timeout"),
- PLAN_FORMAT("plan-format"),
- MAX_RESULT_READS("max-result-reads"),
- EXPRESSION_TREE("expression-tree"),
- REWRITTEN_EXPRESSION_TREE("rewritten-expression-tree"),
- LOGICAL_PLAN("logical-plan"),
- OPTIMIZED_LOGICAL_PLAN("optimized-logical-plan"),
- PARSE_ONLY("parse-only"),
- READ_ONLY("readonly"),
- JOB("job"),
- PROFILE("profile"),
- SIGNATURE("signature"),
- MULTI_STATEMENT("multi-statement"),
- MAX_WARNINGS("max-warnings");
-
- private final String str;
-
- Parameter(String str) {
- this.str = str;
- }
-
- public String str() {
- return str;
- }
- }
-
- private enum Attribute {
- HEADER("header"),
- LOSSLESS("lossless");
-
- private final String str;
-
- Attribute(String str) {
- this.str = str;
- }
-
- public String str() {
- return str;
- }
- }
-
protected static final class RequestExecutionState {
private long execStart = -1;
private long execEnd = -1;
@@ -242,44 +187,6 @@
}
}
- private static String getParameterValue(String content, String attribute) {
- if (content == null || attribute == null) {
- return null;
- }
- int sc = content.indexOf(';');
- if (sc < 0) {
- return null;
- }
- int eq = content.indexOf('=', sc + 1);
- if (eq < 0) {
- return null;
- }
- if (content.substring(sc + 1, eq).trim().equalsIgnoreCase(attribute)) {
- return content.substring(eq + 1).trim().toLowerCase();
- }
- return null;
- }
-
- private static String toLower(String s) {
- return s != null ? s.toLowerCase() : s;
- }
-
- private static SessionConfig.OutputFormat getFormat(String format) {
- if (format != null) {
- if (format.startsWith(HttpUtil.ContentType.CSV)) {
- return SessionConfig.OutputFormat.CSV;
- }
- if (format.equals(HttpUtil.ContentType.APPLICATION_ADM)) {
- return SessionConfig.OutputFormat.ADM;
- }
- if (isJsonFormat(format)) {
- return Boolean.parseBoolean(getParameterValue(format, Attribute.LOSSLESS.str()))
- ? SessionConfig.OutputFormat.LOSSLESS_JSON : SessionConfig.OutputFormat.CLEAN_JSON;
- }
- }
- return SessionConfig.OutputFormat.CLEAN_JSON;
- }
-
private static SessionOutput createSessionOutput(PrintWriter resultWriter) {
SessionOutput.ResultDecorator resultPrefix = ResultUtil.createPreResultDecorator();
SessionOutput.ResultDecorator resultPostfix = ResultUtil.createPostResultDecorator();
@@ -288,162 +195,9 @@
return new SessionOutput(sessionConfig, resultWriter, resultPrefix, resultPostfix, null, appendStatus);
}
- protected String getOptText(JsonNode node, Parameter parameter) {
- return getOptText(node, parameter.str());
- }
-
- protected String getOptText(JsonNode node, String fieldName) {
- final JsonNode value = node.get(fieldName);
- return value != null ? value.asText() : null;
- }
-
- protected boolean getOptBoolean(JsonNode node, Parameter parameter, boolean defaultValue) {
- return getOptBoolean(node, parameter.str(), defaultValue);
- }
-
- protected boolean getOptBoolean(JsonNode node, String fieldName, boolean defaultValue) {
- final JsonNode value = node.get(fieldName);
- return value != null ? value.asBoolean() : defaultValue;
- }
-
- protected long getOptLong(JsonNode node, Parameter parameter, long defaultValue) {
- final JsonNode value = node.get(parameter.str);
- return value != null ? Integer.parseInt(value.asText()) : defaultValue;
- }
-
- protected long getOptLong(IServletRequest request, Parameter parameter, long defaultValue) {
- String value = getParameter(request, parameter);
- return value == null ? defaultValue : Integer.parseInt(value);
- }
-
- protected boolean getOptBoolean(IServletRequest request, Parameter parameter, boolean defaultValue) {
- String value = getParameter(request, parameter);
- return value == null ? defaultValue : Boolean.parseBoolean(value);
- }
-
- protected String getParameter(IServletRequest request, Parameter parameter) {
- return request.getParameter(parameter.str());
- }
-
- @FunctionalInterface
- interface CheckedFunction<I, O> {
- O apply(I requestParamValue) throws IOException;
- }
-
- private <R, P> Map<String, JsonNode> getOptStatementParameters(R request, Iterator<String> paramNameIter,
- BiFunction<R, String, P> paramValueAccessor, CheckedFunction<P, JsonNode> paramValueParser)
- throws IOException {
- Map<String, JsonNode> result = null;
- while (paramNameIter.hasNext()) {
- String paramName = paramNameIter.next();
- String stmtParamName = extractStatementParameterName(paramName);
- if (stmtParamName != null) {
- if (result == null) {
- result = new HashMap<>();
- }
- P paramValue = paramValueAccessor.apply(request, paramName);
- JsonNode stmtParamValue = paramValueParser.apply(paramValue);
- result.put(stmtParamName, stmtParamValue);
- } else if (Parameter.ARGS.str().equals(paramName)) {
- if (result == null) {
- result = new HashMap<>();
- }
- P paramValue = paramValueAccessor.apply(request, paramName);
- JsonNode stmtParamValue = paramValueParser.apply(paramValue);
- if (stmtParamValue.isArray()) {
- for (int i = 0, ln = stmtParamValue.size(); i < ln; i++) {
- result.put(String.valueOf(i + 1), stmtParamValue.get(i));
- }
- }
- }
- }
- return result;
- }
-
protected void setRequestParam(IServletRequest request, QueryServiceRequestParameters param,
Map<String, String> optionalParams) throws IOException, AlgebricksException {
- param.setHost(host(request));
- param.setPath(servletPath(request));
- String contentType = HttpUtil.getContentTypeOnly(request);
- if (HttpUtil.ContentType.APPLICATION_JSON.equals(contentType)) {
- try {
- setParamFromJSON(request, param, optionalParams);
- } catch (JsonParseException | JsonMappingException e) {
- // if the JSON parsing fails, the statement is empty and we get an empty statement error
- GlobalConfig.ASTERIX_LOGGER.log(Level.ERROR, e.getMessage(), e);
- }
- } else {
- setParamFromRequest(request, param, optionalParams);
- }
- }
-
- private void setParamFromJSON(IServletRequest request, QueryServiceRequestParameters param,
- Map<String, String> optionalParameters) throws IOException {
- JsonNode jsonRequest = OBJECT_MAPPER.readTree(HttpUtil.getRequestBody(request));
- param.setStatement(getOptText(jsonRequest, Parameter.STATEMENT));
- param.setFormat(toLower(getOptText(jsonRequest, Parameter.FORMAT)));
- param.setPretty(getOptBoolean(jsonRequest, Parameter.PRETTY, false));
- param.setMode(toLower(getOptText(jsonRequest, Parameter.MODE)));
- param.setClientContextID(getOptText(jsonRequest, Parameter.CLIENT_ID));
- param.setTimeout(getOptText(jsonRequest, Parameter.TIMEOUT));
- param.setMaxResultReads(getOptText(jsonRequest, Parameter.MAX_RESULT_READS));
- param.setPlanFormat(getOptText(jsonRequest, Parameter.PLAN_FORMAT));
- param.setExpressionTree(getOptBoolean(jsonRequest, Parameter.EXPRESSION_TREE, false));
- param.setRewrittenExpressionTree(getOptBoolean(jsonRequest, Parameter.REWRITTEN_EXPRESSION_TREE, false));
- param.setLogicalPlan(getOptBoolean(jsonRequest, Parameter.LOGICAL_PLAN, false));
- param.setParseOnly(getOptBoolean(jsonRequest, Parameter.PARSE_ONLY, false));
- param.setReadOnly(getOptBoolean(jsonRequest, Parameter.READ_ONLY, false));
- param.setOptimizedLogicalPlan(getOptBoolean(jsonRequest, Parameter.OPTIMIZED_LOGICAL_PLAN, false));
- param.setJob(getOptBoolean(jsonRequest, Parameter.JOB, false));
- param.setProfile(getOptBoolean(jsonRequest, Parameter.PROFILE, false));
- param.setSignature(getOptBoolean(jsonRequest, Parameter.SIGNATURE, true));
- param.setStatementParams(
- getOptStatementParameters(jsonRequest, jsonRequest.fieldNames(), JsonNode::get, v -> v));
- param.setMultiStatement(getOptBoolean(jsonRequest, Parameter.MULTI_STATEMENT, true));
- param.setMaxWarnings(
- getOptLong(jsonRequest, Parameter.MAX_WARNINGS, QueryServiceRequestParameters.DEFAULT_MAX_WARNINGS));
- setJsonOptionalParameters(jsonRequest, param, optionalParameters);
- }
-
- protected void setJsonOptionalParameters(JsonNode jsonRequest, QueryServiceRequestParameters param,
- Map<String, String> optionalParameters) {
- // allows extensions to set extra parameters
- }
-
- private void setParamFromRequest(IServletRequest request, QueryServiceRequestParameters param,
- Map<String, String> optionalParameters) throws IOException {
- param.setStatement(getParameter(request, Parameter.STATEMENT));
- param.setFormat(toLower(getParameter(request, Parameter.FORMAT)));
- param.setPretty(Boolean.parseBoolean(getParameter(request, Parameter.PRETTY)));
- param.setMode(toLower(getParameter(request, Parameter.MODE)));
- param.setClientContextID(getParameter(request, Parameter.CLIENT_ID));
- param.setTimeout(getParameter(request, Parameter.TIMEOUT));
- param.setMaxResultReads(getParameter(request, Parameter.MAX_RESULT_READS));
- param.setPlanFormat(getParameter(request, Parameter.PLAN_FORMAT));
- param.setExpressionTree(getOptBoolean(request, Parameter.EXPRESSION_TREE, false));
- param.setRewrittenExpressionTree(getOptBoolean(request, Parameter.REWRITTEN_EXPRESSION_TREE, false));
- param.setLogicalPlan(getOptBoolean(request, Parameter.LOGICAL_PLAN, false));
- param.setParseOnly(getOptBoolean(request, Parameter.PARSE_ONLY, false));
- param.setReadOnly(getOptBoolean(request, Parameter.READ_ONLY, false));
- param.setOptimizedLogicalPlan(getOptBoolean(request, Parameter.OPTIMIZED_LOGICAL_PLAN, false));
- param.setJob(getOptBoolean(request, Parameter.JOB, false));
- param.setProfile(getOptBoolean(request, Parameter.PROFILE, false));
- param.setSignature(getOptBoolean(request, Parameter.SIGNATURE, true));
- param.setMultiStatement(getOptBoolean(request, Parameter.MULTI_STATEMENT, true));
- param.setMaxWarnings(
- getOptLong(request, Parameter.MAX_WARNINGS, QueryServiceRequestParameters.DEFAULT_MAX_WARNINGS));
- try {
- param.setStatementParams(getOptStatementParameters(request, request.getParameterNames().iterator(),
- IServletRequest::getParameter, OBJECT_MAPPER::readTree));
- } catch (JsonParseException | JsonMappingException e) {
- GlobalConfig.ASTERIX_LOGGER.log(Level.ERROR, e.getMessage(), e);
- }
- setOptionalParameters(request, param, optionalParameters);
- }
-
- protected void setOptionalParameters(IServletRequest request, QueryServiceRequestParameters param,
- Map<String, String> optionalParameters) {
- // allows extensions to set extra parameters
+ param.setParameters(this, request, optionalParams);
}
private void setAccessControlHeaders(IServletRequest request, IServletResponse response) throws IOException {
@@ -454,16 +208,6 @@
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
}
- private static ResultDelivery parseResultDelivery(String mode) {
- if ("async".equals(mode)) {
- return ResultDelivery.ASYNC;
- } else if ("deferred".equals(mode)) {
- return ResultDelivery.DEFERRED;
- } else {
- return ResultDelivery.IMMEDIATE;
- }
- }
-
private static String handlePath(ResultDelivery delivery) {
switch (delivery) {
case ASYNC:
@@ -515,10 +259,9 @@
}
setRequestParam(request, param, optionalParams);
LOGGER.info(() -> "handleRequest: " + LogRedactionUtil.userData(param.toString()));
- delivery = parseResultDelivery(param.getMode());
+ delivery = param.getMode();
setSessionConfig(sessionOutput, param, delivery);
- final ResultProperties resultProperties = param.getMaxResultReads() == null ? new ResultProperties(delivery)
- : new ResultProperties(delivery, Long.parseLong(param.getMaxResultReads()));
+ final ResultProperties resultProperties = new ResultProperties(delivery, param.getMaxResultReads());
buildResponseHeaders(requestRef, sessionOutput, param, responsePrinter, delivery);
responsePrinter.printHeaders();
validateStatement(param.getStatement());
@@ -533,7 +276,7 @@
.serializeParameterValues(param.getStatementParams());
setAccessControlHeaders(request, response);
response.setStatus(execution.getHttpStatus());
- stats.setType(param.isProfile() ? Stats.ProfileType.FULL : Stats.ProfileType.COUNTS);
+ stats.setProfileType(param.getProfileType());
executeStatement(requestRef, statementsText, sessionOutput, resultProperties, stats, param, execution,
optionalParams, statementParams, responsePrinter, warnings);
}
@@ -671,6 +414,8 @@
+ LogRedactionUtil.userData(param.toString()));
state.setStatus(ResultStatus.FATAL, HttpResponseStatus.SERVICE_UNAVAILABLE);
break;
+ case ASTERIX + INVALID_REQ_PARAM_VAL:
+ case ASTERIX + INVALID_REQ_JSON_VAL:
case ASTERIX + NO_STATEMENT_PROVIDED:
case HYRACKS + JOB_REQUIREMENTS_EXCEED_CAPACITY:
state.setStatus(ResultStatus.FATAL, HttpResponseStatus.BAD_REQUEST);
@@ -693,9 +438,8 @@
String handleUrl = getHandleUrl(param.getHost(), param.getPath(), delivery);
sessionOutput.setHandleAppender(ResultUtil.createResultHandleAppender(handleUrl));
SessionConfig sessionConfig = sessionOutput.config();
- SessionConfig.OutputFormat format = getFormat(param.getFormat());
- SessionConfig.PlanFormat planFormat = SessionConfig.PlanFormat.get(param.getPlanFormat(), param.getPlanFormat(),
- SessionConfig.PlanFormat.JSON, LOGGER);
+ SessionConfig.OutputFormat format = param.getFormat();
+ SessionConfig.PlanFormat planFormat = param.getPlanFormat();
sessionConfig.setFmt(format);
sessionConfig.setPlanFormat(planFormat);
sessionConfig.setMaxWarnings(param.getMaxWarnings());
@@ -708,8 +452,7 @@
sessionConfig.set(SessionConfig.FORMAT_INDENT_JSON, param.isPretty());
sessionConfig.set(SessionConfig.FORMAT_QUOTE_RECORD,
format != SessionConfig.OutputFormat.CLEAN_JSON && format != SessionConfig.OutputFormat.LOSSLESS_JSON);
- sessionConfig.set(SessionConfig.FORMAT_CSV_HEADER, format == SessionConfig.OutputFormat.CSV
- && "present".equals(getParameterValue(param.getFormat(), Attribute.HEADER.str())));
+ sessionConfig.set(SessionConfig.FORMAT_CSV_HEADER, param.isCSVWithHeader());
}
protected void requestFailed(Throwable throwable, ResponsePrinter responsePrinter) {
@@ -721,33 +464,7 @@
return new QueryServiceRequestParameters();
}
- private static boolean isJsonFormat(String format) {
- return format.startsWith(HttpUtil.ContentType.APPLICATION_JSON)
- || format.equalsIgnoreCase(HttpUtil.ContentType.JSON);
- }
-
- public static String extractStatementParameterName(String name) {
- int ln = name.length();
- if ((ln == 2 || isStatementParameterNameRest(name, 2)) && name.charAt(0) == '$'
- && Character.isLetter(name.charAt(1))) {
- return name.substring(1);
- }
- return null;
- }
-
- private static boolean isStatementParameterNameRest(CharSequence input, int startIndex) {
- int i = startIndex;
- for (int ln = input.length(); i < ln; i++) {
- char c = input.charAt(i);
- boolean ok = c == '_' || Character.isLetterOrDigit(c);
- if (!ok) {
- return false;
- }
- }
- return i > startIndex;
- }
-
private static boolean isPrintingProfile(IStatementExecutor.Stats stats) {
- return stats.getType() == Stats.ProfileType.FULL && stats.getJobProfile() != null;
+ return stats.getProfileType() == Stats.ProfileType.FULL && stats.getJobProfile() != null;
}
}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java
index e58ad06..94080da 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java
@@ -19,9 +19,6 @@
package org.apache.asterix.app.message;
-import static org.apache.asterix.translator.IStatementExecutor.Stats.ProfileType.COUNTS;
-import static org.apache.asterix.translator.IStatementExecutor.Stats.ProfileType.FULL;
-
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
@@ -53,6 +50,7 @@
import org.apache.asterix.om.base.IAObject;
import org.apache.asterix.translator.IRequestParameters;
import org.apache.asterix.translator.IStatementExecutor;
+import org.apache.asterix.translator.IStatementExecutor.Stats.ProfileType;
import org.apache.asterix.translator.IStatementExecutorFactory;
import org.apache.asterix.translator.ResultProperties;
import org.apache.asterix.translator.SessionConfig;
@@ -87,13 +85,13 @@
private final Map<String, byte[]> statementParameters;
private final boolean multiStatement;
private final int statementCategoryRestrictionMask;
- private final boolean profile;
+ private final ProfileType profileType;
private final IRequestReference requestReference;
public ExecuteStatementRequestMessage(String requestNodeId, long requestMessageId, ILangExtension.Language lang,
String statementsText, SessionConfig sessionConfig, ResultProperties resultProperties,
String clientContextID, String handleUrl, Map<String, String> optionalParameters,
- Map<String, byte[]> statementParameters, boolean multiStatement, boolean profile,
+ Map<String, byte[]> statementParameters, boolean multiStatement, ProfileType profileType,
int statementCategoryRestrictionMask, IRequestReference requestReference) {
this.requestNodeId = requestNodeId;
this.requestMessageId = requestMessageId;
@@ -107,7 +105,7 @@
this.statementParameters = statementParameters;
this.multiStatement = multiStatement;
this.statementCategoryRestrictionMask = statementCategoryRestrictionMask;
- this.profile = profile;
+ this.profileType = profileType;
this.requestReference = requestReference;
}
@@ -147,7 +145,7 @@
IStatementExecutor translator = statementExecutorFactory.create(ccAppCtx, statements, sessionOutput,
compilationProvider, storageComponentProvider, new ResponsePrinter(sessionOutput));
final IStatementExecutor.Stats stats = new IStatementExecutor.Stats();
- stats.setType(profile ? FULL : COUNTS);
+ stats.setProfileType(profileType);
Map<String, IAObject> stmtParams = RequestParameters.deserializeParameterValues(statementParameters);
final IRequestParameters requestParameters = new RequestParameters(requestReference, statementsText, null,
resultProperties, stats, outMetadata, clientContextID, optionalParameters, stmtParams,
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/TypePrinter.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/TypePrinter.java
index 788fbcf..ad3b8d8 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/TypePrinter.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/TypePrinter.java
@@ -18,7 +18,7 @@
*/
package org.apache.asterix.app.result.fields;
-import static org.apache.hyracks.http.server.utils.HttpUtil.ContentType.CSV;
+import static org.apache.hyracks.http.server.utils.HttpUtil.ContentType.TEXT_CSV;
import java.io.PrintWriter;
@@ -43,8 +43,8 @@
ResultUtil.printField(pw, FIELD_NAME, HttpUtil.ContentType.APPLICATION_ADM, false);
break;
case CSV:
- String contentType =
- CSV + "; header=" + (sessionConfig.is(SessionConfig.FORMAT_CSV_HEADER) ? "present" : "absent");
+ String contentType = TEXT_CSV + "; header="
+ + (sessionConfig.is(SessionConfig.FORMAT_CSV_HEADER) ? "present" : "absent");
ResultUtil.printField(pw, FIELD_NAME, contentType, false);
break;
default:
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 6bd876d..ce1a354 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
@@ -393,7 +393,7 @@
metadataProvider.setResultAsyncMode(
resultDelivery == ResultDelivery.ASYNC || resultDelivery == ResultDelivery.DEFERRED);
metadataProvider.setMaxResultReads(maxResultReads);
- if (stats.getType() == Stats.ProfileType.FULL) {
+ if (stats.getProfileType() == Stats.ProfileType.FULL) {
this.jobFlags.add(JobFlag.PROFILE_RUNTIME);
}
handleQuery(metadataProvider, (Query) stmt, hcc, resultSet, resultDelivery, outMetadata, stats,
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 8dc04eb..71ef783 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
@@ -66,7 +66,7 @@
import java.util.regex.Pattern;
import java.util.stream.Stream;
-import org.apache.asterix.api.http.server.QueryServiceServlet;
+import org.apache.asterix.api.http.server.QueryServiceRequestParameters;
import org.apache.asterix.app.external.IExternalUDFLibrarian;
import org.apache.asterix.common.api.Duration;
import org.apache.asterix.common.config.GlobalConfig;
@@ -626,13 +626,14 @@
}
public List<Parameter> constructQueryParameters(String str, OutputFormat fmt, List<Parameter> params) {
- List<Parameter> newParams = upsertParam(params, "format", ParameterTypeEnum.STRING, fmt.mimeType());
+ List<Parameter> newParams = upsertParam(params, QueryServiceRequestParameters.Parameter.FORMAT.str(),
+ ParameterTypeEnum.STRING, fmt.mimeType());
- newParams = upsertParam(newParams, QueryServiceServlet.Parameter.PLAN_FORMAT.str(), ParameterTypeEnum.STRING,
- DEFAULT_PLAN_FORMAT);
+ newParams = upsertParam(newParams, QueryServiceRequestParameters.Parameter.PLAN_FORMAT.str(),
+ ParameterTypeEnum.STRING, DEFAULT_PLAN_FORMAT);
final Optional<String> maxReadsOptional = extractMaxResultReads(str);
if (maxReadsOptional.isPresent()) {
- newParams = upsertParam(newParams, QueryServiceServlet.Parameter.MAX_RESULT_READS.str(),
+ newParams = upsertParam(newParams, QueryServiceRequestParameters.Parameter.MAX_RESULT_READS.str(),
ParameterTypeEnum.STRING, maxReadsOptional.get());
}
return newParams;
@@ -2186,7 +2187,7 @@
protected static boolean containsClientContextID(String statement) {
List<Parameter> httpParams = extractParameters(statement);
return httpParams.stream().map(Parameter::getName)
- .anyMatch(QueryServiceServlet.Parameter.CLIENT_ID.str()::equals);
+ .anyMatch(QueryServiceRequestParameters.Parameter.CLIENT_ID.str()::equals);
}
private static boolean isCancellable(String type) {
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestHelper.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestHelper.java
index 7695698..619ce8c 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestHelper.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestHelper.java
@@ -33,7 +33,7 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
-import org.apache.asterix.api.http.server.QueryServiceServlet;
+import org.apache.asterix.api.http.server.QueryServiceRequestParameters;
import org.apache.asterix.app.translator.RequestParameters;
import org.apache.asterix.om.base.IAObject;
import org.apache.asterix.testframework.xml.ParameterTypeEnum;
@@ -126,10 +126,10 @@
throw new IllegalArgumentException(String.valueOf(paramType));
}
- String name = QueryServiceServlet.extractStatementParameterName(paramName);
+ String name = QueryServiceRequestParameters.extractStatementParameterName(paramName);
if (name != null) {
stmtParams.put(name, paramJsonValue);
- } else if (QueryServiceServlet.Parameter.ARGS.str().equals(paramName)) {
+ } else if (QueryServiceRequestParameters.Parameter.ARGS.str().equals(paramName)) {
if (paramJsonValue.isArray()) {
for (int i = 0, ln = paramJsonValue.size(); i < ln; i++) {
stmtParams.put(String.valueOf(i + 1), paramJsonValue.get(i));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/profiled.xml b/asterixdb/asterix-app/src/test/resources/runtimets/profiled.xml
index 496927e..f3209a1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/profiled.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/profiled.xml
@@ -22,9 +22,21 @@
<test-group name="profile">
<test-case FilePath="profile">
<compilation-unit name="full-scan">
- <parameter name="profile" value="true" />
+ <parameter name="profile" value="timings" type="string"/>
<output-dir compare="Text">full-scan</output-dir>
</compilation-unit>
</test-case>
+ <test-case FilePath="profile">
+ <compilation-unit name="full-scan-2">
+ <parameter name="profile" value="counts" type="string"/>
+ <output-dir compare="Text">full-scan-2</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="profile">
+ <compilation-unit name="full-scan-3">
+ <parameter name="profile" value="off" type="string"/>
+ <output-dir compare="Text">full-scan-3</output-dir>
+ </compilation-unit>
+ </test-case>
</test-group>
</test-suite>
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-01/format-param-in-accept-01.1.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-01/format-param-in-accept-01.1.post.http
new file mode 100644
index 0000000..cf0c800
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-01/format-param-in-accept-01.1.post.http
@@ -0,0 +1,23 @@
+/*
+ * 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: testing specifying application/json as output format in Accept of HEADER
+ */
+/query/service
+--body={"statement": "set `import-private-functions` `true`; `unordered-list-constructor`(\"foo\", \"bar\");"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-02/format-param-in-accept-02.1.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-02/format-param-in-accept-02.1.post.http
new file mode 100644
index 0000000..cf0c800
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-02/format-param-in-accept-02.1.post.http
@@ -0,0 +1,23 @@
+/*
+ * 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: testing specifying application/json as output format in Accept of HEADER
+ */
+/query/service
+--body={"statement": "set `import-private-functions` `true`; `unordered-list-constructor`(\"foo\", \"bar\");"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-03/format-param-in-accept-03.1.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-03/format-param-in-accept-03.1.post.http
new file mode 100644
index 0000000..bb7055a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-03/format-param-in-accept-03.1.post.http
@@ -0,0 +1,23 @@
+/*
+ * 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: testing specifying application/json;lossless=true as output format in Accept of HEADER
+ */
+/query/service
+--body={"statement": "set `import-private-functions` `true`; `unordered-list-constructor`(\"foo\", \"bar\");"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-04/format-param-in-accept-04.1.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-04/format-param-in-accept-04.1.post.http
new file mode 100644
index 0000000..c68fabe
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-04/format-param-in-accept-04.1.post.http
@@ -0,0 +1,24 @@
+/*
+ * 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: testing specifying application/x-adm as output format in Accept of HEADER and json in "format" param
+ * Expected : json format is picked
+ */
+/query/service
+--body={"statement": "set `import-private-functions` `true`; `unordered-list-constructor`(\"foo\", \"bar\");", "format": "json"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-05/format-param-in-accept-05.1.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-05/format-param-in-accept-05.1.post.http
new file mode 100644
index 0000000..720b5f2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-05/format-param-in-accept-05.1.post.http
@@ -0,0 +1,24 @@
+/*
+ * 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: testing specifying unknown mime type, application/x-ast
+ * Expected : json is defaulted since no "format" parameter is specified and format in Accept is unkownn
+ */
+/query/service
+--body={"statement": "set `import-private-functions` `true`; `unordered-list-constructor`(\"foo\", \"bar\");"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation-400-BAD/request-param-validation-400-BAD.01.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation-400-BAD/request-param-validation-400-BAD.01.post.http
new file mode 100644
index 0000000..8c5a4d6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation-400-BAD/request-param-validation-400-BAD.01.post.http
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+// statuscode 400
+/query/service
+--body={"statement": "from [1, 2] as v select v;", "format": "foo"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.001.query.sqlpp
new file mode 100644
index 0000000..69e67be
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.001.query.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * 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: validating that request parameters have proper values
+ */
+
+// requesttype=application/json
+// param format:string=foo
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.002.query.sqlpp
new file mode 100644
index 0000000..0ab2195
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.002.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param pretty:string=bar
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.003.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.003.query.sqlpp
new file mode 100644
index 0000000..24267b1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.003.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param plan-format:string=blah
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.004.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.004.query.sqlpp
new file mode 100644
index 0000000..68ba956
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.004.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param max-result-reads:string=foo
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.005.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.005.query.sqlpp
new file mode 100644
index 0000000..2c8b15e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.005.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param max-result-reads:string=9999999999999999999999999999999999999999
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.006.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.006.query.sqlpp
new file mode 100644
index 0000000..f7adc7a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.006.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param max-warnings:string=baz
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.007.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.007.query.sqlpp
new file mode 100644
index 0000000..6433ae6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.007.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param max-warnings:string=1.5
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.008.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.008.query.sqlpp
new file mode 100644
index 0000000..46cd166
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.008.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param mode:string=asyn
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.009.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.009.query.sqlpp
new file mode 100644
index 0000000..29ef01b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.009.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param timeout:string=12
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.010.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.010.query.sqlpp
new file mode 100644
index 0000000..e56f9a2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.010.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param args:json=12
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.011.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.011.query.sqlpp
new file mode 100644
index 0000000..073a264
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.011.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param args:json=[12,,1]
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.012.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.012.query.sqlpp
new file mode 100644
index 0000000..1bf1146
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.012.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param $var:json={"a":}
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.013.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.013.query.sqlpp
new file mode 100644
index 0000000..837ee28
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.013.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param format:string=foo
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.014.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.014.query.sqlpp
new file mode 100644
index 0000000..25b8eb8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.014.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param pretty:string=bar
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.015.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.015.query.sqlpp
new file mode 100644
index 0000000..bdda7c4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.015.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param plan-format:string=blah
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.016.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.016.query.sqlpp
new file mode 100644
index 0000000..eedad6d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.016.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param max-result-reads:string=foo
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.017.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.017.query.sqlpp
new file mode 100644
index 0000000..fc0c48d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.017.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param max-warnings:string=baz
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.018.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.018.query.sqlpp
new file mode 100644
index 0000000..cbcf381
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.018.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param mode:string=asyn
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.019.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.019.query.sqlpp
new file mode 100644
index 0000000..d682463
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.019.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param args:json=12
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.020.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.020.query.sqlpp
new file mode 100644
index 0000000..0f58953
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.020.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param args:json=[12,,1]
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.021.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.021.query.sqlpp
new file mode 100644
index 0000000..e37d945
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.021.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param $var:json={"a":}
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.022.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.022.query.sqlpp
new file mode 100644
index 0000000..0665e09
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.022.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param profile:string=true
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.023.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.023.query.sqlpp
new file mode 100644
index 0000000..5767812
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.023.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param profile:string=true
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.024.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.024.query.sqlpp
new file mode 100644
index 0000000..e99ec6c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.024.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param profile:string=foo
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.025.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.025.query.sqlpp
new file mode 100644
index 0000000..2ca9df4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.025.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param profile:string=foo
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.001.query.sqlpp
new file mode 100644
index 0000000..f22230e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.001.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param format:string=json
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.002.query.sqlpp
new file mode 100644
index 0000000..b574cc9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.002.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param format:string=csv
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.003.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.003.query.sqlpp
new file mode 100644
index 0000000..ba37336
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.003.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param format:string=application/json
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.004.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.004.query.sqlpp
new file mode 100644
index 0000000..b5d0d64
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.004.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param format:string=text/csv
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.005.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.005.query.sqlpp
new file mode 100644
index 0000000..9d3b964
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.005.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param format:string=application/x-adm
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.006.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.006.query.sqlpp
new file mode 100644
index 0000000..d667f48
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.006.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param format:string=text/csv;header=absent
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.007.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.007.query.sqlpp
new file mode 100644
index 0000000..cba7638
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.007.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param format:string=application/json;lossless=true
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.008.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.008.query.sqlpp
new file mode 100644
index 0000000..7b6c450
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.008.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param format:string=application/json;lossless=false
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.009.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.009.query.sqlpp
new file mode 100644
index 0000000..d483eb3
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.009.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// requesttype=application/json
+// param mode:string=immediate
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.1.ddl.sqlpp
new file mode 100644
index 0000000..c5cab5d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.1.ddl.sqlpp
@@ -0,0 +1,48 @@
+/*
+ * 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 : Testing that "counts" is supplied in request parameter "profile".
+ * Expected Res : Success with expected result not having "profile" field.
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use test;
+
+create type test.AddressType as
+{
+ number : bigint,
+ street : string,
+ city : string
+};
+
+create type test.CustomerType as
+ closed {
+ cid : bigint,
+ name : string,
+ age : bigint?,
+ address : AddressType?,
+ lastorder : {
+ oid : bigint,
+ total : float
+ }
+};
+
+create dataset Customers(CustomerType) primary key cid;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.2.update.sqlpp
new file mode 100644
index 0000000..957c234
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.2.update.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+use test;
+
+load dataset Customers using localfs
+ ((`path`=`asterix_nc1://data/custord-tiny/customer-tiny-neg.adm`),
+ (`format`=`adm`));
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.3.profile.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.3.profile.sqlpp
new file mode 100644
index 0000000..070196a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.3.profile.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+use test;
+
+select count(*) from Customers;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.4.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.4.ddl.sqlpp
new file mode 100644
index 0000000..f12a2b7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.4.ddl.sqlpp
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+drop dataverse test;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.1.ddl.sqlpp
new file mode 100644
index 0000000..da6580a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.1.ddl.sqlpp
@@ -0,0 +1,48 @@
+/*
+ * 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 : Testing that "off" is supplied in request parameter "profile".
+ * Expected Res : Success with expected result not having "profile" field.
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use test;
+
+create type test.AddressType as
+{
+ number : bigint,
+ street : string,
+ city : string
+};
+
+create type test.CustomerType as
+ closed {
+ cid : bigint,
+ name : string,
+ age : bigint?,
+ address : AddressType?,
+ lastorder : {
+ oid : bigint,
+ total : float
+ }
+};
+
+create dataset Customers(CustomerType) primary key cid;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.2.update.sqlpp
new file mode 100644
index 0000000..957c234
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.2.update.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+use test;
+
+load dataset Customers using localfs
+ ((`path`=`asterix_nc1://data/custord-tiny/customer-tiny-neg.adm`),
+ (`format`=`adm`));
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.3.profile.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.3.profile.sqlpp
new file mode 100644
index 0000000..070196a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.3.profile.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+use test;
+
+select count(*) from Customers;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.4.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.4.ddl.sqlpp
new file mode 100644
index 0000000..f12a2b7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.4.ddl.sqlpp
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+drop dataverse test;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-01/format-param-in-accept-01.1.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-01/format-param-in-accept-01.1.regexjson
new file mode 100644
index 0000000..ad8ba0a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-01/format-param-in-accept-01.1.regexjson
@@ -0,0 +1,9 @@
+{
+ "requestID": "R{[a-zA-Z0-9-]+}",
+ "signature": {"*": "*"},
+ "type": "application/x-adm",
+ "results": [ "{{ \"foo\", \"bar\" }}\n" ],
+ "plans":{},
+ "status": "success",
+ "metrics": "R{.*}"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-02/format-param-in-accept-02.1.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-02/format-param-in-accept-02.1.regexjson
new file mode 100644
index 0000000..7443917
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-02/format-param-in-accept-02.1.regexjson
@@ -0,0 +1,8 @@
+{
+ "requestID": "R{[a-zA-Z0-9-]+}",
+ "signature": {"*": "*"},
+ "results": [["foo","bar"]],
+ "plans":{},
+ "status": "success",
+ "metrics": "R{.*}"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-03/format-param-in-accept-03.1.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-03/format-param-in-accept-03.1.regexjson
new file mode 100644
index 0000000..e48a4e1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-03/format-param-in-accept-03.1.regexjson
@@ -0,0 +1,8 @@
+{
+ "requestID": "R{[a-zA-Z0-9-]+}",
+ "signature": {"*": "*"},
+ "results": [{"unorderedlist":["foo","bar"]}],
+ "plans":{},
+ "status": "success",
+ "metrics": "R{.*}"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-04/format-param-in-accept-04.1.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-04/format-param-in-accept-04.1.regexjson
new file mode 100644
index 0000000..7443917
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-04/format-param-in-accept-04.1.regexjson
@@ -0,0 +1,8 @@
+{
+ "requestID": "R{[a-zA-Z0-9-]+}",
+ "signature": {"*": "*"},
+ "results": [["foo","bar"]],
+ "plans":{},
+ "status": "success",
+ "metrics": "R{.*}"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-05/format-param-in-accept-05.1.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-05/format-param-in-accept-05.1.regexjson
new file mode 100644
index 0000000..7443917
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-05/format-param-in-accept-05.1.regexjson
@@ -0,0 +1,8 @@
+{
+ "requestID": "R{[a-zA-Z0-9-]+}",
+ "signature": {"*": "*"},
+ "results": [["foo","bar"]],
+ "plans":{},
+ "status": "success",
+ "metrics": "R{.*}"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param-validation-400-BAD/request-param-validation-400-BAD.01.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param-validation-400-BAD/request-param-validation-400-BAD.01.regexjson
new file mode 100644
index 0000000..f444fa1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param-validation-400-BAD/request-param-validation-400-BAD.01.regexjson
@@ -0,0 +1,14 @@
+{
+ "errors": [{
+ "code": 1, "msg": "ASX0047: Invalid value for parameter \"format\": foo" }
+ ],
+ "status": "fatal",
+ "metrics": {
+ "elapsedTime": "R{.*}",
+ "executionTime": "R{.*}",
+ "resultCount": 0,
+ "resultSize": 0,
+ "processedObjects": 0,
+ "errorCount": 1
+ }
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.001.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.001.json
new file mode 100644
index 0000000..83ce118
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.001.json
@@ -0,0 +1 @@
+{"v":1}{"v":2}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.002.csv b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.002.csv
new file mode 100644
index 0000000..7a754f4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.002.csv
@@ -0,0 +1,2 @@
+1
+2
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.003.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.003.json
new file mode 100644
index 0000000..83ce118
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.003.json
@@ -0,0 +1 @@
+{"v":1}{"v":2}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.004.csv b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.004.csv
new file mode 100644
index 0000000..7a754f4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.004.csv
@@ -0,0 +1,2 @@
+1
+2
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.005.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.005.adm
new file mode 100644
index 0000000..cb88308
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.005.adm
@@ -0,0 +1,2 @@
+{ "v": 1 }
+{ "v": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.006.csv b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.006.csv
new file mode 100644
index 0000000..7a754f4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.006.csv
@@ -0,0 +1,2 @@
+1
+2
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.007.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.007.json
new file mode 100644
index 0000000..32c4637
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.007.json
@@ -0,0 +1 @@
+{"v":{"int64":1}}{"v":{"int64":2}}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.008.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.008.json
new file mode 100644
index 0000000..83ce118
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.008.json
@@ -0,0 +1 @@
+{"v":1}{"v":2}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.009.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.009.adm
new file mode 100644
index 0000000..cb88308
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.009.adm
@@ -0,0 +1,2 @@
+{ "v": 1 }
+{ "v": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/full-scan-2/full-scan-2.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/full-scan-2/full-scan-2.3.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/full-scan-2/full-scan-2.3.adm
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/full-scan-3/full-scan-3.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/full-scan-3/full-scan-3.3.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/full-scan-3/full-scan-3.3.adm
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 0f82c9e..7deee6f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -42,6 +42,72 @@
<expected-error>ASX0044: DELETE statement is prohibited by this request</expected-error>
</compilation-unit>
</test-case>
+ <test-case FilePath="api">
+ <compilation-unit name="request-param-validation">
+ <output-dir compare="Text">request-param-validation</output-dir>
+ <source-location>false</source-location>
+ <expected-error>Invalid value for parameter "format": foo</expected-error>
+ <expected-error>Invalid value for parameter "pretty": bar</expected-error>
+ <expected-error>Invalid value for parameter "plan-format": blah</expected-error>
+ <expected-error>Invalid value for parameter "max-result-reads": foo</expected-error>
+ <expected-error>Invalid value for parameter "max-result-reads": 9999999999999999999999999999999999999999</expected-error>
+ <expected-error>Invalid value for parameter "max-warnings": baz</expected-error>
+ <expected-error>Invalid value for parameter "max-warnings": 1.5</expected-error>
+ <expected-error>Invalid value for parameter "mode": asyn</expected-error>
+ <expected-error>Invalid value for parameter "timeout": 12</expected-error>
+ <expected-error>Invalid value for parameter "args": 12</expected-error>
+ <expected-error>Unable to process JSON content in request</expected-error>
+ <expected-error>Unable to process JSON content in request</expected-error>
+ <expected-error>Invalid value for parameter "format": foo</expected-error>
+ <expected-error>Invalid value for parameter "pretty": bar</expected-error>
+ <expected-error>Invalid value for parameter "plan-format": blah</expected-error>
+ <expected-error>Invalid value for parameter "max-result-reads": foo</expected-error>
+ <expected-error>Invalid value for parameter "max-warnings": baz</expected-error>
+ <expected-error>Invalid value for parameter "mode": asyn</expected-error>
+ <expected-error>Invalid value for parameter "args": 12</expected-error>
+ <expected-error>Unable to process JSON content in request</expected-error>
+ <expected-error>Unable to process JSON content in request</expected-error>
+ <expected-error>Invalid value for parameter "profile": true</expected-error>
+ <expected-error>Invalid value for parameter "profile": true</expected-error>
+ <expected-error>Invalid value for parameter "profile": foo</expected-error>
+ <expected-error>Invalid value for parameter "profile": foo</expected-error>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="api">
+ <compilation-unit name="request-param-validation-400-BAD">
+ <output-dir compare="Text">request-param-validation-400-BAD</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="api">
+ <compilation-unit name="request-param">
+ <output-dir compare="Text">request-param</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="api">
+ <compilation-unit name="format-param-in-accept-01">
+ <output-dir compare="Text">format-param-in-accept-01</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="api">
+ <compilation-unit name="format-param-in-accept-02">
+ <output-dir compare="Clean-JSON">format-param-in-accept-02</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="api">
+ <compilation-unit name="format-param-in-accept-03">
+ <output-dir compare="Lossless-JSON">format-param-in-accept-03</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="api">
+ <compilation-unit name="format-param-in-accept-04">
+ <output-dir compare="Text">format-param-in-accept-04</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="api">
+ <compilation-unit name="format-param-in-accept-05">
+ <output-dir compare="AST">format-param-in-accept-05</output-dir>
+ </compilation-unit>
+ </test-case>
</test-group>
<test-group name="flwor">
<test-case FilePath="flwor">
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 e718ca5..da1c4e7 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
@@ -79,6 +79,8 @@
public static final int PROHIBITED_STATEMENT_CATEGORY = 44;
public static final int INTEGER_VALUE_EXPECTED_FUNCTION = 45;
public static final int INVALID_LIKE_PATTERN = 46;
+ public static final int INVALID_REQ_PARAM_VAL = 47;
+ public static final int INVALID_REQ_JSON_VAL = 48;
public static final int UNSUPPORTED_JRE = 100;
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 f8d7a89..457206d 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -81,6 +81,8 @@
44 = %1$s statement is prohibited by this request
45 = Invalid value: function %1$s expects its %2$s input parameter to be an integer value, got %3$s
46 = Invalid pattern \"%1$s\" for LIKE
+47 = Invalid value for parameter \"%1$s\": %2$s
+48 = Unable to process JSON content in request
100 = Unsupported JRE: %1$s
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java
index 0f857bd..591cf8c 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java
@@ -69,7 +69,8 @@
public static final String APPLICATION_JSON = "application/json";
public static final String JSON = "json";
public static final String APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";
- public static final String CSV = "text/csv";
+ public static final String CSV = "csv";
+ public static final String TEXT_CSV = "text/csv";
public static final String IMG_PNG = "image/png";
public static final String TEXT_HTML = "text/html";
public static final String TEXT_PLAIN = "text/plain";