Skip to content
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

Adds runtime_mappings to EQL and SQL requests #71356

Merged
merged 5 commits into from
Apr 7, 2021

Conversation

astefan
Copy link
Contributor

@astefan astefan commented Apr 6, 2021

The runtime_mappings request element will allow EQL and SQL users to define search time runtime fields which can later be used in queries.
Addresses #68116.

define search time runtime fields which will be used in queries
@astefan astefan marked this pull request as ready for review April 6, 2021 16:48
@elasticmachine elasticmachine added the Team:QL (Deprecated) Meta label for query languages team label Apr 6, 2021
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-ql (Team:QL)

@astefan astefan requested review from matriv, costin and bpintea and removed request for matriv April 6, 2021 16:48
@astefan astefan changed the title Adds runtime_mappings to EQL and SQL requests allowing users to Adds runtime_mappings to EQL and SQL requests Apr 6, 2021
Copy link
Member

@costin costin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

The only minor observations that I have are:

  • use static imports for emptyList/emptyMap - same number of line changes but improves readability
  • if my understanding is correct, all integration tests moving forward will run with the new runtime field enable; maybe it wouldn't be too much effort to randomize this (though a separate PR). in ES this happens dynamically, it's H2 that we have to worry about (either by having two separate load files or ideally, manipulating the loaded data at runtime, similar to what ES does).

1961-09-23T00:00:00Z,10098,Sreekrishna,F,1985-05-13T00:00:00Z,4,Servieres,44817
1956-05-25T00:00:00Z,10099,Valter,F,1988-10-18T00:00:00Z,2,Sullins,73578
1953-04-21T00:00:00Z,10100,Hironobu,F,1987-09-21T00:00:00Z,4,Haraldson,68431
birth_date,birth_date_day_of_week,emp_no,first_name,gender,hire_date,languages,last_name,salary
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The extra column can be generated at runtime in H2 through the SELECT of CSVREAD function - instead of doing just SELECT * do a SELECT *, DAY_OF_THE_WEEK(birth_date)orSELECT birth_date, DAY_OF_THE_WEEK(birth_date) AS birth_date_dow, ...`
If that doesn't work do the insert as is followed by an update inside the sql script.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea I haven't thought of. I'll change the way data is loaded in H2.

Copy link
Contributor

@bpintea bpintea left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.
I take the docs would be updated subsequently?

String fieldName = entry.getKey();
if (entry.getValue() instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> propNode = new HashMap<>(((Map<String, Object>) entry.getValue()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is a new map instance necessary?
(and same in AbstractSqlQueryRequest.java)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@@ -532,3 +532,18 @@ SELECT GREATEST(null, null, birth_date + INTERVAL 25 YEARS, hire_date + INTERVAL
1986-02-28T00:00:00.000Z|1952-11-13T00:00:00.000Z|1986-02-26T00:00:00.000Z
1986-05-30T00:00:00.000Z|1961-05-30T00:00:00.000Z|1986-03-14T00:00:00.000Z
;

ifNullWithRuntimeField
SELECT COUNT(*) c, IFNULL(birth_date_day_of_week, 'Some day') AS day FROM test_emp GROUP BY day ORDER BY c;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'no day'? :-)

Copy link
Contributor

@matriv matriv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great stuff @astefan! Very nice testing!
Left some mostly minor comments.

@@ -129,7 +130,7 @@ public void execute(SqlSession session, ActionListener<Page> listener) {

// special case for '%' (translated to *)
if ("*".equals(idx)) {
session.indexResolver().resolveAsSeparateMappings(idx, regex, includeFrozen,
session.indexResolver().resolveAsSeparateMappings(idx, regex, includeFrozen, Collections.emptyMap(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: here and below you could use the static import.

@@ -116,6 +116,11 @@ public void query(List<Attribute> output, QueryContainer query, String index, Ac
sourceBuilder.timeout(timeout);
}

// set runtime mappings
if (this.cfg.runtimeMappings() != null && this.cfg.runtimeMappings().isEmpty() == false) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this check? is it possible to be set twice or more?

@@ -242,6 +259,9 @@ private static void toXContent(SqlQueryRequest request, XContentBuilder builder)
if (request.cursor() != null) {
builder.field(CURSOR_NAME, request.cursor());
}
if (request.runtimeMappings() != null && request.runtimeMappings().isEmpty() == false) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, why do we need to check if it's empty?
maybe an assertion that are empty could be better?

1953-09-02T00:00:00Z|10001 |Georgi |M |1986-06-26T00:00:00Z|2 |Facello |57305
birth_date |birth_date_day_of_week| emp_no | first_name | gender | hire_date | languages | last_name | salary
--------------------+----------------------+---------------+---------------+---------------+--------------------+---------------+---------------+---------------
1953-09-02T00:00:00Z|Wednesday |10001 |Georgi |M |1986-06-26T00:00:00Z|2 |Facello |57305
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: here and below, trailing whitespaces.

null |10044 |Mingsen |F |1994-05-21 00:00:00.0|Casley |39728 |null
1952-04-19 00:00:00.0|10009 |Sumant |F |1985-02-18 00:00:00.0|Peac |66174 |null
1953-01-07 00:00:00.0|10067 |Claudi |M |1987-03-04 00:00:00.0|Stavenow |null |52044
birth_date |birth_date_day_of_week| emp_no | first_name | gender | hire_date | last_name | 1 | 2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: trailing whitespaces, also below.

String fieldName = entry.getKey();
if (entry.getValue() instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> propNode = new HashMap<>(((Map<String, Object>) entry.getValue()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

1959-12-03T00:00:00.000Z|10003 |Parto |M |1986-08-28T00:00:00.000Z|4 |Bamford |61805
1954-05-01T00:00:00.000Z|10004 |Chirstian |M |1986-12-01T00:00:00.000Z|5 |Koblick |36174
1955-01-21T00:00:00.000Z|10005 |Kyoichi |M |1989-09-12T00:00:00.000Z|1 |Maliniak |63528
birth_date |birth_date_day_of_week| emp_no | first_name | gender | hire_date | languages | last_name | salary
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: trailing whitespaces.

@@ -225,3 +225,24 @@ SELECT TOP 3 count(*) AS cnt, emp_no % languages FROM test_emp GROUP BY 2 ORDER
24 |1
16 |2
;

runtimeFieldWithFunctions
SELECT CONCAT(CONCAT(SUBSTRING(birth_date_day_of_week, 0, LENGTH(birth_date_day_of_week) - 3), SPACE(11 - LENGTH(birth_date_day_of_week))), 'DAY') AS c, ISO_DAY_OF_WEEK(birth_date) AS iso FROM test_emp LIMIT 14;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe an ORDER BY, to avoid non-deterministic ordering.

return validationException;
}

private static ActionRequestValidationException validateRuntimeMappings(Map<String, Object> runtimeMappings,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to extract this in ql module?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately (and frustratingly), no. sql-action has almost no dependencies on other projects. Which is a good thing for the end user, but it brings some limitations in the code reusability and organization area.

@@ -498,6 +498,90 @@ public void testUseColumnarForTranslateRequest() throws IOException {
}, containsString("unknown field [columnar]"));
}

public void testValidateRuntimeMappingsInSqlQuery() throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we move the validation of the RuntimeMappings in QL maybe we can have a simpler unit tests for the validation itself (incorrect json)

@@ -117,7 +117,7 @@ public void query(List<Attribute> output, QueryContainer query, String index, Ac
}

// set runtime mappings
if (this.cfg.runtimeMappings() != null && this.cfg.runtimeMappings().isEmpty() == false) {
if (this.cfg.runtimeMappings() != null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not insisting, it's a "safety net": Since we initialise the runtimeMappings with an empty map, maybe we could also remove this check.

Copy link
Contributor

@matriv matriv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thx!

@astefan astefan merged commit b8266e5 into elastic:master Apr 7, 2021
@astefan astefan deleted the 68116_impl branch April 7, 2021 16:38
astefan added a commit to astefan/elasticsearch that referenced this pull request Apr 7, 2021
* Adds `runtime_mappings` to EQL and SQL requests allowing users to
define search time runtime fields which will be used in queries

(cherry picked from commit b8266e5)
astefan added a commit that referenced this pull request Apr 8, 2021
* Adds `runtime_mappings` to EQL and SQL requests allowing users to
define search time runtime fields which will be used in queries

(cherry picked from commit b8266e5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants