-
Notifications
You must be signed in to change notification settings - Fork 24.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SQL: add support for passing query parameters in REST API calls #51029
Conversation
Pinging @elastic/es-search (:Search/SQL) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
-------------------------------------------------- | ||
// TEST[setup:library] | ||
|
||
or it can be done by extracting the values in a separate list of parameters and using question mark placeholders (`?`) in the query string: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add a statement to mention that this is the recommended way of passing parameters to avoid hacking or SQL injection (which does not apply to us but nevertheless).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Left 2 comments
@@ -61,8 +61,8 @@ public SqlQueryRequest() { | |||
} | |||
|
|||
public SqlQueryRequest(String query, List<SqlTypedParamValue> params, QueryBuilder filter, ZoneId zoneId, | |||
int fetchSize, TimeValue requestTimeout, TimeValue pageTimeout, Boolean columnar, | |||
String cursor, RequestInfo requestInfo, boolean fieldMultiValueLeniency, boolean indexIncludeFrozen) { | |||
int fetchSize, TimeValue requestTimeout, TimeValue pageTimeout, Boolean columnar, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this formatting change is wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll change it.
return Objects.equals(value, that.value) && Objects.equals(type, that.type); | ||
return Objects.equals(value, that.value) | ||
&& Objects.equals(type, that.type) | ||
&& Objects.equals(hasExplicitType, that.hasExplicitType); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tokenLocation
shouldn't be part of equals and hashCode?
parser.declareString((request, zoneId) -> request.zoneId(ZoneId.of(zoneId)), TIME_ZONE); | ||
parser.declareInt(AbstractSqlQueryRequest::fetchSize, FETCH_SIZE); | ||
parser.declareString((request, timeout) -> request.requestTimeout(TimeValue.parseTimeValue(timeout, Protocol.REQUEST_TIMEOUT, | ||
"request_timeout")), REQUEST_TIMEOUT); | ||
"request_timeout")), REQUEST_TIMEOUT); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
was the extra space intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, to have a uniform formatting for the field parsers' declaration. See here the initial formatting.
// we are at the start of a value/type pair... hopefully | ||
SqlTypedParamValue s = SqlTypedParamValue.fromXContent(p); | ||
/* | ||
* Set the xcontentlocation for the first param just in case the first one doesn't meet the parsing rules |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was wondering if this was meant as ... for the first param that doesn't meet ...
, since an object could occur at any point in the array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I rephrased this section for, hopefully, better clarity.
if ((previousParam != null && previousParam.hasExplicitType() == false) || result.isEmpty()) { | ||
s.tokenLocation(loc); | ||
} | ||
result.add(s); | ||
previousParam = s; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code executes in both if/else branches, it might be worth considering taking it out.
Another nit: a switch
with all the top enums (object, string, number, bool, null) might also arguably simplify the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've extracted the common code, but I kept the if/else approach. I find it a bit more clear than a switch
.
@@ -75,11 +81,11 @@ public AbstractSqlQueryRequest(String query, List<SqlTypedParamValue> params, Qu | |||
parser.declareString(AbstractSqlQueryRequest::query, QUERY); | |||
parser.declareString((request, mode) -> request.mode(Mode.fromString(mode)), MODE); | |||
parser.declareString((request, clientId) -> request.clientId(clientId), CLIENT_ID); | |||
parser.declareObjectArray(AbstractSqlQueryRequest::params, (p, c) -> SqlTypedParamValue.fromXContent(p), PARAMS); | |||
parser.declareField(AbstractSqlQueryRequest::params, p -> AbstractSqlQueryRequest.parseParams(p), PARAMS, ValueType.VALUE_ARRAY); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could the second arg also be a method reference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, only left a few questions and suggestions.
the equality between TokenLocations is based on instance and not inner values.
…tic#51029) * REST PreparedStatement-like query parameters are now supported in the form of an array of non-object, non-array values where ES SQL parser will try to infer the data type of the value being passed as parameter. (cherry picked from commit 45b8bf6)
…tic#51029) * REST PreparedStatement-like query parameters are now supported in the form of an array of non-object, non-array values where ES SQL parser will try to infer the data type of the value being passed as parameter.
Add support for PreparedStatement-like of passing values to a sql query.
The query string will use question mark placeholders (
?
) for any values that will be passed in through a newparams
request parameter:Addresses #42916.