SQL: Use declared source for error messages (#37161)

Improve error messages by returning the original SQL statement
declaration instead of trying to reproduce it as the casing and
whitespaces are not preserved accurately leading to small 
differences.

Close #37161
This commit is contained in:
Costin Leau 2019-01-13 01:40:22 +02:00 committed by GitHub
parent 03be4dbaca
commit a4339ec7e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 458 additions and 500 deletions

View File

@ -108,7 +108,7 @@ public class RestSqlMultinodeIT extends ESRestTestCase {
private void assertCount(RestClient client, int count) throws IOException {
Map<String, Object> expected = new HashMap<>();
String mode = randomMode();
expected.put("columns", singletonList(columnInfo(mode, "COUNT(1)", "long", JDBCType.BIGINT, 20)));
expected.put("columns", singletonList(columnInfo(mode, "COUNT(*)", "long", JDBCType.BIGINT, 20)));
expected.put("rows", singletonList(singletonList(count)));
Request request = new Request("POST", "/_sql");

View File

@ -60,7 +60,7 @@ public class UserFunctionIT extends ESRestTestCase {
@Before
private void setUpUsers() throws IOException {
int usersCount = name.getMethodName().startsWith("testSingle") ? 1 : randomIntBetween(5, 15);
users = new ArrayList<String>(usersCount);
users = new ArrayList<>(usersCount);
users.addAll(randomUnique(() -> randomAlphaOfLengthBetween(1, 15), usersCount));
for (String user : users) {
createUser(user, MINIMAL_ACCESS_ROLE);
@ -80,7 +80,7 @@ public class UserFunctionIT extends ESRestTestCase {
Map<String, Object> expected = new HashMap<>();
expected.put("columns", Arrays.asList(
columnInfo(mode, "USER", "keyword", JDBCType.VARCHAR, 0)));
columnInfo(mode, "USER()", "keyword", JDBCType.VARCHAR, 0)));
expected.put("rows", Arrays.asList(Arrays.asList(randomUserName)));
Map<String, Object> actual = runSql(randomUserName, mode, SQL);
@ -96,7 +96,7 @@ public class UserFunctionIT extends ESRestTestCase {
Map<String, Object> expected = new HashMap<>();
expected.put("columns", Arrays.asList(
columnInfo(mode, "USER", "keyword", JDBCType.VARCHAR, 0)));
columnInfo(mode, "USER()", "keyword", JDBCType.VARCHAR, 0)));
expected.put("rows", Arrays.asList(Arrays.asList(randomUserName),
Arrays.asList(randomUserName),
Arrays.asList(randomUserName)));
@ -114,7 +114,7 @@ public class UserFunctionIT extends ESRestTestCase {
Map<String, Object> expected = new HashMap<>();
expected.put("columns", Arrays.asList(
columnInfo(mode, "USER", "keyword", JDBCType.VARCHAR, 0)));
columnInfo(mode, "USER()", "keyword", JDBCType.VARCHAR, 0)));
expected.put("rows", Collections.<ArrayList<String>>emptyList());
String anotherRandomUserName = randomValueOtherThan(randomUserName, () -> randomAlphaOfLengthBetween(1, 15));
Map<String, Object> actual = runSql(randomUserName, mode, SQL + " FROM test WHERE USER()='" + anotherRandomUserName + "' LIMIT 3");
@ -129,7 +129,7 @@ public class UserFunctionIT extends ESRestTestCase {
Map<String, Object> expected = new HashMap<>();
expected.put("columns", Arrays.asList(
columnInfo(mode, "USER", "keyword", JDBCType.VARCHAR, 0)));
columnInfo(mode, "USER()", "keyword", JDBCType.VARCHAR, 0)));
expected.put("rows", Arrays.asList(Arrays.asList(randomlyPickedUsername)));
Map<String, Object> actual = runSql(randomlyPickedUsername, mode, SQL);
@ -147,7 +147,7 @@ public class UserFunctionIT extends ESRestTestCase {
Map<String, Object> expected = new HashMap<>();
expected.put("columns", Arrays.asList(
columnInfo(mode, "USER", "keyword", JDBCType.VARCHAR, 0)));
columnInfo(mode, "USER()", "keyword", JDBCType.VARCHAR, 0)));
expected.put("rows", Arrays.asList(Arrays.asList(randomUserName),
Arrays.asList(randomUserName),
Arrays.asList(randomUserName)));

View File

@ -64,7 +64,7 @@ public class CliExplainIT extends CliIntegrationTestCase {
assertThat(readLine(), startsWith("----------"));
assertThat(readLine(), startsWith("With[{}]"));
assertThat(readLine(), startsWith("\\_Project[[?*]]"));
assertThat(readLine(), startsWith(" \\_Filter[?i == 2]"));
assertThat(readLine(), startsWith(" \\_Filter[i = 2#"));
assertThat(readLine(), startsWith(" \\_UnresolvedRelation[[][index=test],null,Unknown index [test]]"));
assertEquals("", readLine());
@ -72,14 +72,14 @@ public class CliExplainIT extends CliIntegrationTestCase {
containsString("plan"));
assertThat(readLine(), startsWith("----------"));
assertThat(readLine(), startsWith("Project[[i{f}#"));
assertThat(readLine(), startsWith("\\_Filter[i{f}#"));
assertThat(readLine(), startsWith("\\_Filter[i = 2#"));
assertThat(readLine(), startsWith(" \\_EsRelation[test][i{f}#"));
assertEquals("", readLine());
assertThat(command("EXPLAIN (PLAN OPTIMIZED) SELECT * FROM test WHERE i = 2"), containsString("plan"));
assertThat(readLine(), startsWith("----------"));
assertThat(readLine(), startsWith("Project[[i{f}#"));
assertThat(readLine(), startsWith("\\_Filter[i{f}#"));
assertThat(readLine(), startsWith("\\_Filter[i = 2#"));
assertThat(readLine(), startsWith(" \\_EsRelation[test][i{f}#"));
assertEquals("", readLine());
@ -124,20 +124,20 @@ public class CliExplainIT extends CliIntegrationTestCase {
assertThat(command("EXPLAIN (PLAN PARSED) SELECT COUNT(*) FROM test"), containsString("plan"));
assertThat(readLine(), startsWith("----------"));
assertThat(readLine(), startsWith("With[{}]"));
assertThat(readLine(), startsWith("\\_Project[[?COUNT(?*)]]"));
assertThat(readLine(), startsWith("\\_Project[[?COUNT(*)]]"));
assertThat(readLine(), startsWith(" \\_UnresolvedRelation[[][index=test],null,Unknown index [test]]"));
assertEquals("", readLine());
assertThat(command("EXPLAIN " + (randomBoolean() ? "" : "(PLAN ANALYZED) ") + "SELECT COUNT(*) FROM test"),
containsString("plan"));
assertThat(readLine(), startsWith("----------"));
assertThat(readLine(), startsWith("Aggregate[[],[COUNT(1)#"));
assertThat(readLine(), startsWith("Aggregate[[],[COUNT(*)#"));
assertThat(readLine(), startsWith("\\_EsRelation[test][i{f}#"));
assertEquals("", readLine());
assertThat(command("EXPLAIN (PLAN OPTIMIZED) SELECT COUNT(*) FROM test"), containsString("plan"));
assertThat(readLine(), startsWith("----------"));
assertThat(readLine(), startsWith("Aggregate[[],[COUNT(1)#"));
assertThat(readLine(), startsWith("Aggregate[[],[COUNT(*)#"));
assertThat(readLine(), startsWith("\\_EsRelation[test][i{f}#"));
assertEquals("", readLine());

View File

@ -20,7 +20,7 @@ import static org.elasticsearch.xpack.sql.qa.jdbc.CsvTestUtils.csvConnection;
import static org.elasticsearch.xpack.sql.qa.jdbc.CsvTestUtils.executeCsvQuery;
import static org.elasticsearch.xpack.sql.qa.jdbc.CsvTestUtils.specParser;
@TestLogging(JdbcTestUtils.SQL_TRACE)
@TestLogging("org.elasticsearch.xpack.sql:TRACE")
public abstract class DebugCsvSpec extends SpecBaseIntegrationTestCase {
private final CsvTestCase testCase;

View File

@ -169,7 +169,7 @@ FROM "test_emp" GROUP BY "TEMP" ORDER BY "TEMP" LIMIT 20;
aggAndOrderByCastedValue
SELECT CHAR_LENGTH(SPACE(CAST(languages AS SMALLINT))), COUNT(*) FROM test_emp GROUP BY 1 ORDER BY 1 DESC;
CHAR_LENGTH(SPACE(CAST(languages AS SMALLINT))):i| COUNT(1):l
CHAR_LENGTH(SPACE(CAST(languages AS SMALLINT))):i| COUNT(*):l
-------------------------------------------------+---------------
5 |21
4 |18
@ -180,9 +180,9 @@ null |10
;
aggAndOrderByCastedFunctionValue
SELECT ROUND(SQRT(CAST(EXP(languages) AS SMALLINT)), 2), COUNT(*) FROM test_emp GROUP BY 1 ORDER BY 1 DESC;
SELECT ROUND(SQRT(CAST(EXP(languages) AS SMALLINT)),2), COUNT(*) FROM test_emp GROUP BY 1 ORDER BY 1 DESC;
ROUND(SQRT(CAST(EXP(languages) AS SMALLINT)),2):d| COUNT(1):l
ROUND(SQRT(CAST(EXP(languages) AS SMALLINT)),2):d| COUNT(*):l
-------------------------------------------------+---------------
12.17 |21
7.42 |18

View File

@ -1124,8 +1124,8 @@ stringAscii
// tag::stringAscii
SELECT ASCII('Elastic');
ASCII(Elastic)
---------------
ASCII('Elastic')
----------------
69
// end::stringAscii
;
@ -1134,8 +1134,8 @@ stringBitLength
// tag::stringBitLength
SELECT BIT_LENGTH('Elastic');
BIT_LENGTH(Elastic)
-------------------
BIT_LENGTH('Elastic')
---------------------
56
// end::stringBitLength
;
@ -1154,8 +1154,8 @@ stringCharLength
// tag::stringCharLength
SELECT CHAR_LENGTH('Elastic');
CHAR_LENGTH(Elastic)
--------------------
CHAR_LENGTH('Elastic')
----------------------
7
// end::stringCharLength
;
@ -1164,8 +1164,8 @@ stringConcat
// tag::stringConcat
SELECT CONCAT('Elasticsearch', ' SQL');
CONCAT(Elasticsearch, SQL)
--------------------------
CONCAT('Elasticsearch', ' SQL')
-------------------------------
Elasticsearch SQL
// end::stringConcat
;
@ -1174,8 +1174,8 @@ stringInsert
// tag::stringInsert
SELECT INSERT('Elastic ', 8, 1, 'search');
INSERT(Elastic ,8,1,search)
---------------------------
INSERT('Elastic ', 8, 1, 'search')
----------------------------------
Elasticsearch
// end::stringInsert
;
@ -1184,8 +1184,8 @@ stringLCase
// tag::stringLCase
SELECT LCASE('Elastic');
LCASE(Elastic)
---------------
LCASE('Elastic')
----------------
elastic
// end::stringLCase
;
@ -1194,8 +1194,8 @@ stringLeft
// tag::stringLeft
SELECT LEFT('Elastic',3);
LEFT(Elastic,3)
---------------
LEFT('Elastic',3)
-----------------
Ela
// end::stringLeft
;
@ -1204,8 +1204,8 @@ stringLength
// tag::stringLength
SELECT LENGTH('Elastic ');
LENGTH(Elastic )
------------------
LENGTH('Elastic ')
--------------------
7
// end::stringLength
;
@ -1214,8 +1214,8 @@ stringLocateWoStart
// tag::stringLocateWoStart
SELECT LOCATE('a', 'Elasticsearch');
LOCATE(a,Elasticsearch)
-----------------------
LOCATE('a', 'Elasticsearch')
----------------------------
3
// end::stringLocateWoStart
;
@ -1224,8 +1224,8 @@ stringLocateWithStart
// tag::stringLocateWithStart
SELECT LOCATE('a', 'Elasticsearch', 5);
LOCATE(a,Elasticsearch,5)
-------------------------
LOCATE('a', 'Elasticsearch', 5)
-------------------------------
10
// end::stringLocateWithStart
;
@ -1234,8 +1234,8 @@ stringLTrim
// tag::stringLTrim
SELECT LTRIM(' Elastic');
LTRIM( Elastic)
-----------------
LTRIM(' Elastic')
-------------------
Elastic
// end::stringLTrim
;
@ -1244,8 +1244,8 @@ stringOctetLength
// tag::stringOctetLength
SELECT OCTET_LENGTH('Elastic');
OCTET_LENGTH(Elastic)
-------------------
OCTET_LENGTH('Elastic')
-----------------------
7
// end::stringOctetLength
;
@ -1254,8 +1254,8 @@ stringPosition
// tag::stringPosition
SELECT POSITION('Elastic', 'Elasticsearch');
POSITION(Elastic,Elasticsearch)
-------------------------------
POSITION('Elastic', 'Elasticsearch')
------------------------------------
1
// end::stringPosition
;
@ -1264,8 +1264,8 @@ stringRepeat
// tag::stringRepeat
SELECT REPEAT('La', 3);
REPEAT(La,3)
---------------
REPEAT('La', 3)
----------------
LaLaLa
// end::stringRepeat
;
@ -1274,8 +1274,8 @@ stringReplace
// tag::stringReplace
SELECT REPLACE('Elastic','El','Fant');
REPLACE(Elastic,El,Fant)
-----------------------------
REPLACE('Elastic','El','Fant')
------------------------------
Fantastic
// end::stringReplace
;
@ -1284,8 +1284,8 @@ stringRight
// tag::stringRight
SELECT RIGHT('Elastic',3);
RIGHT(Elastic,3)
----------------
RIGHT('Elastic',3)
------------------
tic
// end::stringRight
;
@ -1294,8 +1294,8 @@ stringRTrim
// tag::stringRTrim
SELECT RTRIM('Elastic ');
RTRIM(Elastic )
-----------------
RTRIM('Elastic ')
-------------------
Elastic
// end::stringRTrim
;
@ -1316,8 +1316,8 @@ stringSubString
// tag::stringSubString
SELECT SUBSTRING('Elasticsearch', 0, 7);
SUBSTRING(Elasticsearch,0,7)
----------------------------
SUBSTRING('Elasticsearch', 0, 7)
--------------------------------
Elastic
// end::stringSubString
;
@ -1326,8 +1326,8 @@ stringUCase
// tag::stringUCase
SELECT UCASE('Elastic');
UCASE(Elastic)
---------------
UCASE('Elastic')
----------------
ELASTIC
// end::stringUCase
;
@ -1417,7 +1417,7 @@ mathInlineAcos
// tag::mathInlineAcos
SELECT ACOS(COS(PI())), PI();
ACOS(COS(PI)) | PI
ACOS(COS(PI())) | PI()
-----------------+-----------------
3.141592653589793|3.141592653589793
// end::mathInlineAcos
@ -1467,8 +1467,8 @@ mathInlineCeiling
// tag::mathInlineCeiling
SELECT CEIL(125.01), CEILING(-125.99);
CEIL(125.01) | CEIL(-125.99)
---------------+---------------
CEIL(125.01) |CEILING(-125.99)
---------------+----------------
126 |-125
// end::mathInlineCeiling
;
@ -1507,7 +1507,7 @@ mathInlineDegrees
// tag::mathInlineDegrees
SELECT DEGREES(PI() * 2), DEGREES(PI());
DEGREES((PI) * 2)| DEGREES(PI)
DEGREES(PI() * 2)| DEGREES(PI())
-----------------+---------------
360.0 |180.0
// end::mathInlineDegrees
@ -1517,7 +1517,7 @@ mathEulersNumber
// tag::mathEulersNumber
SELECT E(), CEIL(E());
E | CEIL(E)
E() | CEIL(E())
-----------------+---------------
2.718281828459045|3
// end::mathEulersNumber
@ -1527,7 +1527,7 @@ mathExpInline
// tag::mathExpInline
SELECT EXP(1), E(), EXP(2), E() * E();
EXP(1) | E | EXP(2) | (E) * (E)
EXP(1) | E() | EXP(2) | E() * E()
-----------------+-----------------+----------------+------------------
2.718281828459045|2.718281828459045|7.38905609893065|7.3890560989306495
// end::mathExpInline
@ -1537,7 +1537,7 @@ mathExpm1Inline
// tag::mathExpm1Inline
SELECT E(), EXP(2), EXPM1(2);
E | EXP(2) | EXPM1(2)
E() | EXP(2) | EXPM1(2)
-----------------+----------------+----------------
2.718281828459045|7.38905609893065|6.38905609893065
// end::mathExpm1Inline
@ -1567,8 +1567,8 @@ mathInlineLog10
// tag::mathInlineLog10
SELECT LOG10(5), LOG(5)/LOG(10);
LOG10(5) |(LOG(5)) / (LOG(10))
------------------+--------------------
LOG10(5) | LOG(5)/LOG(10)
------------------+-----------------------
0.6989700043360189|0.6989700043360187
// end::mathInlineLog10
;
@ -1577,7 +1577,7 @@ mathPINumber
// tag::mathPINumber
SELECT PI();
PI
PI()
-----------------
3.141592653589793
// end::mathPINumber
@ -1587,7 +1587,7 @@ mathInlinePowerPositive
// tag::mathInlinePowerPositive
SELECT POWER(3, 2), POWER(3, 3);
POWER(3,2) | POWER(3,3)
POWER(3, 2) | POWER(3, 3)
---------------+---------------
9.0 |27.0
// end::mathInlinePowerPositive
@ -1597,7 +1597,7 @@ mathInlinePowerNegative
// tag::mathInlinePowerNegative
SELECT POWER(5, -1), POWER(5, -2);
POWER(5,-1) | POWER(5,-2)
POWER(5, -1) | POWER(5, -2)
---------------+---------------
0.2 |0.04
// end::mathInlinePowerNegative
@ -1607,7 +1607,7 @@ mathInlineRadians
// tag::mathInlineRadians
SELECT RADIANS(90), PI()/2;
RADIANS(90) | (PI) / 2
RADIANS(90) | PI()/2
------------------+------------------
1.5707963267948966|1.5707963267948966
// end::mathInlineRadians
@ -1677,7 +1677,7 @@ mathInlineSqrt
// tag::mathInlineSqrt
SELECT SQRT(EXP(2)), E(), SQRT(25);
SQRT(EXP(2)) | E | SQRT(25)
SQRT(EXP(2)) | E() | SQRT(25)
-----------------+-----------------+---------------
2.718281828459045|2.718281828459045|5.0
// end::mathInlineSqrt

View File

@ -263,18 +263,18 @@ SELECT POSITION('x',LCASE("first_name")) pos, "first_name" FROM "test_emp" WHERE
;
selectPositionWithLcaseAndConditionWithGroupByAndOrderBy
SELECT POSITION('m',LCASE("first_name")), COUNT(*) pos FROM "test_emp"
SELECT POSITION('m',LCASE("first_name")) AS pos, COUNT(*) c FROM "test_emp"
WHERE POSITION('m',LCASE("first_name")) != 0
GROUP BY POSITION('m',LCASE("first_name")) ORDER BY POSITION('m',LCASE("first_name")) DESC;
POSITION(m,LCASE(first_name)):i| pos:l
-------------------------------+---------------
9 |1
7 |1
4 |2
3 |6
2 |1
1 |9
pos:i| c:l
-----+-----
9 |1
7 |1
4 |2
3 |6
2 |1
1 |9
;
selectInsertWithPositionAndCondition
@ -299,8 +299,8 @@ ReMzi |3
selectLocateAndInsertWithLocateWithConditionAndThreeParameters
SELECT LOCATE('a',"first_name",7) pos, INSERT("first_name",LOCATE('a',"first_name",7),1,'AAA') FROM "test_emp" WHERE LOCATE('a',"first_name",7) > 0;
pos:i |INSERT(first_name,LOCATE(a,first_name,7),1,AAA):s
---------------+-----------------------------------------------
pos:i |INSERT("first_name",LOCATE('a',"first_name",7),1,'AAA'):s
---------------+---------------------------------------------------------
8 |ChirstiAAAn
7 |DuangkAAAew
8 |PrasadrAAAm
@ -317,8 +317,8 @@ SELECT LOCATE('a',"first_name",7) pos, INSERT("first_name",LOCATE('a',"first_nam
selectLocateAndInsertWithLocateWithConditionAndTwoParameters
SELECT LOCATE('a',"first_name") pos, INSERT("first_name",LOCATE('a',"first_name"),1,'AAA') FROM "test_emp" WHERE LOCATE('a',"first_name") > 0 ORDER BY "first_name" LIMIT 10;
pos:i |INSERT(first_name,LOCATE(a,first_name),1,AAA):s
---------------+---------------------------------------------
pos:i |INSERT("first_name",LOCATE('a',"first_name"),1,'AAA'):s
---------------+-------------------------------------------------------
5 |AlejAAAndro
3 |AmAAAbile
7 |ArumugAAAm
@ -455,23 +455,23 @@ AlejandRo |1
checkColumnNameWithNestedArithmeticFunctionCallsOnTableColumn
SELECT CHAR(emp_no % 10000) FROM "test_emp" WHERE emp_no > 10064 ORDER BY emp_no LIMIT 1;
SELECT CHAR(emp_no % 10000) AS c FROM "test_emp" WHERE emp_no > 10064 ORDER BY emp_no LIMIT 1;
CHAR((emp_no) % 10000):s
c:s
A
;
checkColumnNameWithComplexNestedArithmeticFunctionCallsOnTableColumn1
SELECT CHAR(emp_no % (7000 + 3000)) FROM "test_emp" WHERE emp_no > 10065 ORDER BY emp_no LIMIT 1;
SELECT CHAR(emp_no % (7000 + 3000)) AS c FROM "test_emp" WHERE emp_no > 10065 ORDER BY emp_no LIMIT 1;
CHAR((emp_no) % (7000 + 3000)):s
c:s
B
;
checkColumnNameWithComplexNestedArithmeticFunctionCallsOnTableColumn2
SELECT CHAR((emp_no % (emp_no - 1 + 1)) + 67) FROM "test_emp" WHERE emp_no > 10066 ORDER BY emp_no LIMIT 1;
SELECT CHAR((emp_no % (emp_no - 1 + 1)) + 67) AS c FROM "test_emp" WHERE emp_no > 10066 ORDER BY emp_no LIMIT 1;
CHAR(((emp_no) % (((emp_no) - 1) + 1)) + 67):s
c:s
C
;

View File

@ -2,27 +2,27 @@
truncateWithAsciiHavingAndOrderBy
SELECT TRUNCATE(ASCII(LEFT(first_name, 1)), 1), COUNT(*) count FROM test_emp GROUP BY ASCII(LEFT(first_name, 1)) HAVING COUNT(*) > 5 ORDER BY TRUNCATE(ASCII(LEFT(first_name, 1)), 1) DESC;
TRUNCATE(ASCII(LEFT(first_name,1)),1):i| count:l
---------------------------------------+---------------
null |10
66 |7
72 |6
75 |7
77 |9
83 |11
TRUNCATE(ASCII(LEFT(first_name, 1)), 1):i| count:l
-----------------------------------------+---------------
null |10
66 |7
72 |6
75 |7
77 |9
83 |11
;
truncateWithNoSecondParameterWithAsciiHavingAndOrderBy
SELECT TRUNCATE(ASCII(LEFT(first_name, 1))), COUNT(*) count FROM test_emp GROUP BY ASCII(LEFT(first_name, 1)) HAVING COUNT(*) > 5 ORDER BY TRUNCATE(ASCII(LEFT(first_name, 1))) DESC;
TRUNCATE(ASCII(LEFT(first_name,1)),0):i| count:l
---------------------------------------+---------------
null |10
66 |7
72 |6
75 |7
77 |9
83 |11
TRUNCATE(ASCII(LEFT(first_name, 1))):i| count:l
--------------------------------------+---------------
null |10
66 |7
72 |6
75 |7
77 |9
83 |11
;
roundWithGroupByAndOrderBy
@ -97,21 +97,21 @@ SELECT MIN(salary) mi, MAX(salary) ma, COUNT(*) c, TRUNCATE(AVG(salary)) tr FROM
minMaxTruncateAndRoundOfAverageWithHavingRoundAndTruncate
SELECT MIN(salary) mi, MAX(salary) ma, YEAR(hire_date) year, ROUND(AVG(languages), 1), TRUNCATE(AVG(languages), 1), COUNT(*) FROM test_emp GROUP BY YEAR(hire_date) HAVING ROUND(AVG(languages), 1) > 2.5 AND TRUNCATE(AVG(languages), 1) <= 3.0 ORDER BY YEAR(hire_date);
mi:i | ma:i | year:i |ROUND(AVG(languages),1):d|TRUNCATE(AVG(languages),1):d| COUNT(1):l
---------------+---------------+---------------+-------------------------+----------------------------+---------------
25324 |70011 |1986 |3.0 |3.0 |15
25945 |73578 |1987 |2.9 |2.8 |9
25976 |74970 |1988 |3.0 |3.0 |13
31120 |71165 |1989 |3.1 |3.0 |12
30404 |58715 |1992 |3.0 |3.0 |3
35742 |67492 |1993 |2.8 |2.7 |4
45656 |45656 |1995 |3.0 |3.0 |1
mi:i | ma:i | year:i |ROUND(AVG(languages), 1):d|TRUNCATE(AVG(languages), 1):d| COUNT(*):l
---------------+---------------+---------------+--------------------------+-----------------------------+---------------
25324 |70011 |1986 |3.0 |3.0 |15
25945 |73578 |1987 |2.9 |2.8 |9
25976 |74970 |1988 |3.0 |3.0 |13
31120 |71165 |1989 |3.1 |3.0 |12
30404 |58715 |1992 |3.0 |3.0 |3
35742 |67492 |1993 |2.8 |2.7 |4
45656 |45656 |1995 |3.0 |3.0 |1
;
minMaxRoundWithHavingRound
SELECT MIN(salary) mi, MAX(salary) ma, YEAR(hire_date) year, ROUND(AVG(languages), 1), COUNT(*) FROM test_emp GROUP BY YEAR(hire_date) HAVING ROUND(AVG(languages), 1) > 2.5 ORDER BY YEAR(hire_date);
SELECT MIN(salary) mi, MAX(salary) ma, YEAR(hire_date) year, ROUND(AVG(languages),1), COUNT(*) FROM test_emp GROUP BY YEAR(hire_date) HAVING ROUND(AVG(languages), 1) > 2.5 ORDER BY YEAR(hire_date);
mi:i | ma:i | year:i |ROUND(AVG(languages),1):d| COUNT(1):l
mi:i | ma:i | year:i |ROUND(AVG(languages),1):d| COUNT(*):l
---------------+---------------+---------------+-------------------------+---------------
26436 |74999 |1984 |3.1 |11
31897 |61805 |1985 |3.5 |11
@ -127,9 +127,9 @@ SELECT MIN(salary) mi, MAX(salary) ma, YEAR(hire_date) year, ROUND(AVG(languages
;
groupByAndOrderByTruncateWithPositiveParameter
SELECT TRUNCATE(AVG(salary), 2), AVG(salary), COUNT(*) FROM test_emp GROUP BY TRUNCATE(salary, 2) ORDER BY TRUNCATE(salary, 2) DESC LIMIT 10;
SELECT TRUNCATE(AVG(salary),2), AVG(salary), COUNT(*) FROM test_emp GROUP BY TRUNCATE(salary, 2) ORDER BY TRUNCATE(salary, 2) DESC LIMIT 10;
TRUNCATE(AVG(salary),2):d| AVG(salary):d | COUNT(1):l
TRUNCATE(AVG(salary),2):d| AVG(salary):d | COUNT(*):l
-------------------------+---------------+---------------
74999.0 |74999.0 |1
74970.0 |74970.0 |1
@ -144,9 +144,9 @@ TRUNCATE(AVG(salary),2):d| AVG(salary):d | COUNT(1):l
;
groupByAndOrderByRoundWithPositiveParameter
SELECT ROUND(AVG(salary), 2), AVG(salary), COUNT(*) FROM test_emp GROUP BY ROUND(salary, 2) ORDER BY ROUND(salary, 2) DESC LIMIT 10;
SELECT ROUND(AVG(salary),2), AVG(salary), COUNT(*) FROM test_emp GROUP BY ROUND(salary, 2) ORDER BY ROUND(salary, 2) DESC LIMIT 10;
ROUND(AVG(salary),2):d| AVG(salary):d | COUNT(1):l
ROUND(AVG(salary),2):d| AVG(salary):d | COUNT(*):l
----------------------+---------------+---------------
74999.0 |74999.0 |1
74970.0 |74970.0 |1
@ -163,16 +163,16 @@ ROUND(AVG(salary),2):d| AVG(salary):d | COUNT(1):l
groupByAndOrderByRoundWithNoSecondParameter
SELECT ROUND(AVG(salary)), ROUND(salary) rounded, AVG(salary), COUNT(*) FROM test_emp GROUP BY rounded ORDER BY rounded DESC LIMIT 10;
ROUND(AVG(salary),0):d| rounded:i | AVG(salary):d | COUNT(1):l
----------------------+---------------+---------------+---------------
74999.0 |74999 |74999.0 |1
74970.0 |74970 |74970.0 |1
74572.0 |74572 |74572.0 |1
73851.0 |73851 |73851.0 |1
73717.0 |73717 |73717.0 |1
73578.0 |73578 |73578.0 |1
71165.0 |71165 |71165.0 |1
70011.0 |70011 |70011.0 |1
69904.0 |69904 |69904.0 |1
68547.0 |68547 |68547.0 |1
ROUND(AVG(salary)):d| rounded:i | AVG(salary):d | COUNT(*):l
--------------------+---------------+---------------+---------------
74999.0 |74999 |74999.0 |1
74970.0 |74970 |74970.0 |1
74572.0 |74572 |74572.0 |1
73851.0 |73851 |73851.0 |1
73717.0 |73717 |73717.0 |1
73578.0 |73578 |73578.0 |1
71165.0 |71165 |71165.0 |1
70011.0 |70011 |70011.0 |1
69904.0 |69904 |69904.0 |1
68547.0 |68547 |68547.0 |1
;

View File

@ -5,39 +5,39 @@
equalsSelectClause
SELECT CAST(4 = 4 AS STRING), CAST(NOT 4 = 4 AS STRING), CAST(3 = 4 AS STRING), CAST(NOT 3 = 4 AS STRING), CAST(1 = null AS STRING), CAST(NOT null = 1 AS STRING);
CAST(4 == 4 AS VARCHAR):s | CAST(NOT(4 == 4) AS VARCHAR):s | CAST(3 == 4 AS VARCHAR):s | CAST(NOT(3 == 4) AS VARCHAR):s | CAST(1 == null AS VARCHAR):s | CAST(NOT(null == 1) AS VARCHAR):s
----------------------------+---------------------------------+----------------------------+---------------------------------+-------------------------------+-----------------------------------
true |false |false |true |null |null
CAST(4 = 4 AS STRING):s|CAST(NOT 4 = 4 AS STRING):s|CAST(3 = 4 AS STRING):s|CAST(NOT 3 = 4 AS STRING):s|CAST(1 = null AS STRING):s|CAST(NOT null = 1 AS STRING):s
-----------------------+---------------------------+-----------------------+---------------------------+--------------------------+----------------------------
true |false |false |true |null |null
;
notEqualsSelectClause
SELECT CAST(4 != 4 AS STRING), CAST(NOT 4 != 4 AS STRING), CAST(3 != 4 AS STRING), CAST(NOT 3 != 4 AS STRING), CAST(1 != null AS STRING), CAST(NOT 1 != null AS STRING);
CAST(4 != 4 AS VARCHAR):s | CAST(NOT(4 != 4) AS VARCHAR):s | CAST(3 != 4 AS VARCHAR):s | CAST(NOT(3 != 4) AS VARCHAR):s | CAST(1 != null AS VARCHAR):s | CAST(NOT(1 != null) AS VARCHAR):s
----------------------------+---------------------------------+----------------------------+---------------------------------+-------------------------------+-----------------------------------
false |true |true |false |null |null
CAST(4 != 4 AS STRING):s|CAST(NOT 4 != 4 AS STRING):s|CAST(3 != 4 AS STRING):s|CAST(NOT 3 != 4 AS STRING):s|CAST(1 != null AS STRING):s|CAST(NOT 1 != null AS STRING):s
------------------------+----------------------------+------------------------+----------------------------+---------------------------+-------------------------------
false |true |true |false |null |null
;
equalSelectClauseWithTableColumns
SELECT CAST(languages = 2 AS STRING), CAST(NOT languages = 2 AS STRING), CAST(languages = null AS STRING), CAST(NOT languages = null AS STRING)
FROM "test_emp" WHERE emp_no IN(10018, 10019, 10020) ORDER BY emp_no;
CAST((languages) == 2 AS VARCHAR):s | CAST(NOT((languages) == 2) AS VARCHAR):s | CAST((languages) == null AS VARCHAR):s | CAST(NOT((languages) == null) AS VARCHAR):s
--------------------------------------+-------------------------------------------+-----------------------------------------+---------------------------------------------
true |false |null |null
false |true |null |null
null |null |null |null
CAST(languages = 2 AS STRING):s|CAST(NOT languages = 2 AS STRING):s|CAST(languages = null AS STRING):s|CAST(NOT languages = null AS STRING):s
-------------------------------+-----------------------------------+----------------------------------+--------------------------------------
true |false |null |null
false |true |null |null
null |null |null |null
;
notEqualsAndNotEqualsSelectClauseWithTableColumns
SELECT CAST(languages != 2 AS STRING), CAST(NOT languages != 2 AS STRING), CAST(languages != null AS STRING), CAST(NOT languages != null AS STRING)
FROM "test_emp" WHERE emp_no IN(10018, 10019, 10020) ORDER BY emp_no;
CAST((languages) != 2 AS VARCHAR):s | CAST(NOT((languages) != 2) AS VARCHAR):s | CAST((languages) != null AS VARCHAR):s | CAST(NOT((languages) != null) AS VARCHAR):s
--------------------------------------+-------------------------------------------+-----------------------------------------+---------------------------------------------
false |true |null |null
true |false |null |null
null |null |null |null
CAST(languages != 2 AS STRING):s|CAST(NOT languages != 2 AS STRING):s|CAST(languages != null AS STRING):s|CAST(NOT languages != null AS STRING):s
--------------------------------+------------------------------------+-----------------------------------+---------------------------------------
false |true |null |null
true |false |null |null
null |null |null |null
;
@ -48,27 +48,27 @@ null |null
selectWithOrAndNullHandling
SELECT CAST(true OR null AS STRING), CAST(null OR true AS STRING), CAST(false OR null AS STRING), CAST(null OR false AS STRING), CAST(null OR null AS STRING);
CAST(true OR null AS VARCHAR):s | CAST(null OR true AS VARCHAR):s | CAST(false OR null AS VARCHAR):s | CAST(null OR false AS VARCHAR):s | CAST(null OR null AS VARCHAR):s
----------------------------------+----------------------------------+-----------------------------------+-----------------------------------+---------------------------------
true |true |null |null |null
CAST(true OR null AS STRING):s|CAST(null OR true AS STRING):s|CAST(false OR null AS STRING):s|CAST(null OR false AS STRING):s|CAST(null OR null AS STRING):s
------------------------------+------------------------------+-------------------------------+-------------------------------+----------------------------
true |true |null |null |null
;
selectWithAndAndNullHandling
SELECT CAST(true AND null AS STRING), CAST(null AND true AS STRING), CAST(false AND null AS STRING), CAST(null AND false AS STRING), CAST(null AND null AS STRING);
CAST(true AND null AS VARCHAR):s | CAST(null AND true AS VARCHAR):s | CAST(false AND null AS VARCHAR):s | CAST(null AND false AS VARCHAR):s | CAST(null AND null AS VARCHAR):s
-----------------------------------+-----------------------------------+------------------------------------+------------------------------------+----------------------------------
null |null |false |false |null
CAST(true AND null AS STRING):s|CAST(null AND true AS STRING):s|CAST(false AND null AS STRING):s|CAST(null AND false AS STRING):s|CAST(null AND null AS STRING):s
-------------------------------+-------------------------------+--------------------------------+--------------------------------+-----------------------------
null |null |false |false |null
;
selectWithOrAndAndAndNullHandling_WithTableColumns
SELECT CAST(languages = 2 OR null AS STRING), CAST(languages = 2 AND null AS STRING) FROM test_emp WHERE emp_no BETWEEN 10018 AND 10020 ORDER BY emp_no;
CAST(((languages) == 2) OR null AS VARCHAR):s | CAST(((languages) == 2) AND null AS VARCHAR):s
-----------------------------------------------+------------------------------------------------
true |null
null |false
null |null
CAST(languages = 2 OR null AS STRING):s|CAST(languages = 2 AND null AS STRING):s
---------------------------------------+----------------------------------------
true |null
null |false
null |null
;
@ -76,45 +76,45 @@ null |null
// SELECT with IN
//
inWithLiterals
SELECT 1 IN (1, 2, 3), 1 IN (2, 3);
SELECT 1 IN (1,2, 3), 1 IN (2, 3);
1 IN (1, 2, 3):b | 1 IN (2, 3):b
-------------------+-------------
true |false
1 IN (1,2, 3) | 1 IN (2, 3)
---------------+---------------
true |false
;
inWithLiteralsAndFunctions
SELECT 1 IN (2 - 1, 2, 3), abs(-1) IN (2, 3, abs(4 - 5));
1 IN (2 - 1, 2, 3) | ABS(-1) IN (2, 3, ABS(4 - 5))
---------------------+------------------------------
true |true
1 IN (2 - 1, 2, 3)|abs(-1) IN (2, 3, abs(4 - 5))
------------------+-----------------------------
true |true
;
inWithLiteralsAndNegation
SELECT 1 NOT IN (1, 1 + 1, 3), 1 NOT IN (2, 3);
NOT(1 IN (1, 1 + 1, 3)) | NOT(1 IN (2, 3))
--------------------------+-----------------
false |true
1 NOT IN (1, 1 + 1, 3)|1 NOT IN (2, 3)
----------------------+---------------
false |true
;
// Need to CAST as STRING since for boolean types the jdbc CSV translates null -> false
inWithNullHandling
SELECT CAST(2 IN (1, null, 3) AS STRING), CAST(3 IN (1, null, 3) AS STRING), CAST(null IN (1, null, 3) AS STRING), CAST(null IN (1, 2, 3) AS STRING);
CAST(2 IN (1, null, 3) AS VARCHAR):s | CAST(3 IN (1, null, 3) AS VARCHAR):s | CAST(null IN (1, null, 3) AS VARCHAR):s | CAST(null IN (1, 2, 3) AS VARCHAR):s
---------------------------------------+--------------------------------------+------------------------------------------+--------------------------------------
null |true |null |null
CAST(2 IN (1, null, 3) AS STRING):s|CAST(3 IN (1, null, 3) AS STRING):s|CAST(null IN (1, null, 3) AS STRING):s|CAST(null IN (1, 2, 3) AS STRING):s
-----------------------------------+-----------------------------------+--------------------------------------+-----------------------------------
null |true |null |null
;
inWithNullHandlingAndNegation
SELECT CAST(NOT 2 IN (1, null, 3) AS STRING), CAST(3 NOT IN (1, null, 3) AS STRING), CAST(NOT null IN (1, null, 3) AS STRING), CAST(null NOT IN (1, 2, 3) AS STRING);
CAST(NOT(2 IN (1, null, 3)) AS VARCHAR):s | CAST(NOT(3 IN (1, null, 3)) AS VARCHAR):s | CAST(NOT(null IN (1, null, 3)) AS VARCHAR):s | CAST(NOT(null IN (1, 2, 3)) AS VARCHAR):s
--------------------------------------------+--------------------------------------------+-----------------------------------------------+-------------------------------------------
null |false |null |null
CAST(NOT 2 IN (1, null, 3) AS STRING):s|CAST(3 NOT IN (1, null, 3) AS STRING):s|CAST(NOT null IN (1, null, 3) AS STRING):s|CAST(null NOT IN (1, 2, 3) AS STRING):s
---------------------------------------+---------------------------------------+------------------------------------------+---------------------------------------
null |false |null |null
;
//
@ -134,34 +134,34 @@ false
inWithTableColumnAndFunction
SELECT emp_no IN (10000, 10000 + 1, abs(-10000 - 2)) FROM test_emp WHERE emp_no BETWEEN 10001 AND 10004 ORDER BY emp_no;
emp_no IN (10000, 10000 + 1, ABS(-10000 - 2)):b
------------------------------------------------
true
true
false
false
emp_no IN (10000, 10000 + 1, abs(-10000 - 2))
---------------------------------------------
true
true
false
false
;
inWithTableColumnAndNegation
SELECT emp_no NOT IN (10000, 10000 + 1, 10002) FROM test_emp WHERE emp_no BETWEEN 10001 AND 10004 ORDER BY emp_no;
NOT(emp_no IN (10000, 10000 + 1, 10002)):b
-------------------------------------------
false
false
true
true
emp_no NOT IN (10000, 10000 + 1, 10002)
---------------------------------------
false
false
true
true
;
inWithTableColumnAndComplexFunctions
SELECT emp_no IN (1, abs(1 - 10002), 3) OR emp_no NOT IN (10000, 10000 + 2, 10003) FROM test_emp WHERE emp_no BETWEEN 10001 AND 10004 ORDER BY emp_no;
(emp_no IN (1, ABS(1 - 10002), 3)) OR (NOT(emp_no IN (10000, 10000 + 2, 10003))):b
----------------------------------------------------------------------------------
true
false
false
true
emp_no IN (1, abs(1 - 10002), 3) OR emp_no NOT IN (10000, 10000 + 2, 10003)
---------------------------------------------------------------------------
true
false
false
true
;
@ -169,19 +169,19 @@ true
inWithTableColumnAndNullHandling
SELECT emp_no, CAST(languages IN (2, 3) AS STRING), CAST(languages IN (2, null, 3) AS STRING) FROM test_emp WHERE emp_no BETWEEN 10018 AND 10020 ORDER BY emp_no;
emp_no:i | CAST(languages IN (2, 3) AS VARCHAR):s | CAST(languages IN (2, null, 3) AS VARCHAR):s
----------+-----------------------------------------+----------------------------------------------
10018 |true |true
10019 |false |null
10020 |null |null
emp_no:i |CAST(languages IN (2, 3) AS STRING):s|CAST(languages IN (2, null, 3) AS STRING):s
---------------+-------------------------------------+-------------------------------------------
10018 |true |true
10019 |false |null
10020 |null |null
;
inWithTableColumnAndNullHandlingAndNegation
SELECT emp_no, CAST(languages NOT IN (2, 3) AS STRING), CAST(NOT languages IN (2, null, 3) AS STRING) FROM test_emp WHERE emp_no BETWEEN 10018 AND 10020 ORDER BY emp_no;
emp_no:i | CAST(NOT(languages IN (2, 3)) AS VARCHAR):s | CAST(NOT(languages IN (2, null, 3)) AS VARCHAR):s
----------+----------------------------------------------+---------------------------------------------------
10018 |false |false
10019 |true |null
10020 |null |null
emp_no:i |CAST(languages NOT IN (2, 3) AS STRING):s|CAST(NOT languages IN (2, null, 3) AS STRING):s
---------------+-----------------------------------------+-----------------------------------------------
10018 |false |false
10019 |true |null
10020 |null |null
;

View File

@ -772,7 +772,7 @@ public class Analyzer extends RuleExecutor<LogicalPlan> {
for (Function seenFunction : list) {
if (seenFunction != f && f.arguments().equals(seenFunction.arguments())) {
// Special check for COUNT: an already seen COUNT function will be returned only if its DISTINCT property
// matches the one from the unresolved function to be checked.
// matches the one from the unresolved function to be checked.
if (seenFunction instanceof Count) {
if (seenFunction.equals(f)){
return seenFunction;
@ -818,7 +818,7 @@ public class Analyzer extends RuleExecutor<LogicalPlan> {
for (Function seenFunction : list) {
if (uf.arguments().equals(seenFunction.arguments())) {
// Special check for COUNT: an already seen COUNT function will be returned only if its DISTINCT property
// matches the one from the unresolved function to be checked.
// matches the one from the unresolved function to be checked.
if (seenFunction instanceof Count) {
if (uf.sameAs((Count) seenFunction)) {
return seenFunction;
@ -899,8 +899,7 @@ public class Analyzer extends RuleExecutor<LogicalPlan> {
return new Alias(c.source(), ((NamedExpression) c.field()).name(), c);
}
}
//TODO: maybe add something closer to SQL
return new Alias(child.source(), child.toString(), child);
return new Alias(child.source(), child.sourceText(), child);
}, UnresolvedAlias.class);
newExpr.add(expr.equals(transformed) ? expr : transformed);
}
@ -1031,7 +1030,7 @@ public class Analyzer extends RuleExecutor<LogicalPlan> {
}
private boolean functionsEquals(Function f, Function seenFunction) {
return f.name().equals(seenFunction.name()) && f.arguments().equals(seenFunction.arguments());
return f.sourceText().equals(seenFunction.sourceText()) && f.arguments().equals(seenFunction.arguments());
}
}

View File

@ -36,7 +36,7 @@ public class Literal extends NamedExpression {
}
public Literal(Source source, String name, Object value, DataType dataType) {
super(source, name == null ? String.valueOf(value) : name, emptyList(), null);
super(source, name == null ? source.text() : name, emptyList(), null);
this.dataType = dataType;
this.value = DataTypeConversion.convert(value, dataType);
}

View File

@ -14,7 +14,6 @@ import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.util.StringUtils;
import java.util.List;
import java.util.StringJoiner;
/**
* Any SQL expression with parentheses, like {@code MAX()}, or {@code ABS()}. A
@ -33,7 +32,7 @@ public abstract class Function extends NamedExpression {
// cannot detect name yet so override the name
super(source, null, children, id, synthetic);
functionName = StringUtils.camelCaseToUnderscore(getClass().getSimpleName());
name = functionName() + functionArgs();
name = source.text();
}
public final List<Expression> arguments() {
@ -52,7 +51,7 @@ public abstract class Function extends NamedExpression {
@Override
public String toString() {
return name() + "#" + id();
return sourceText() + "#" + id();
}
public String functionName() {
@ -64,16 +63,7 @@ public abstract class Function extends NamedExpression {
return id().toString();
}
protected String functionArgs() {
StringJoiner sj = new StringJoiner(",", "(", ")");
for (Expression child : children()) {
String val = child instanceof NamedExpression && child.resolved() ? Expressions.name(child) : child.toString();
sj.add(val);
}
return sj.toString();
}
public boolean functionEquals(Function f) {
return f != null && getClass() == f.getClass() && arguments().equals(f.arguments());
}
}
}

View File

@ -166,7 +166,7 @@ public class UnresolvedFunction extends Function implements Unresolvable {
@Override
public String toString() {
return UNRESOLVED_PREFIX + functionName() + functionArgs();
return UNRESOLVED_PREFIX + sourceText();
}
@Override

View File

@ -8,8 +8,8 @@ package org.elasticsearch.xpack.sql.expression.function.aggregate;
import org.elasticsearch.xpack.sql.expression.Expression;
import org.elasticsearch.xpack.sql.expression.Expressions;
import org.elasticsearch.xpack.sql.expression.Expressions.ParamOrdinal;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataType;
import java.util.List;
@ -45,6 +45,6 @@ public class Max extends NumericAggregate implements EnclosedAgg {
@Override
protected TypeResolution resolveType() {
return Expressions.typeMustBeNumericOrDate(field(), functionName(), ParamOrdinal.DEFAULT);
return Expressions.typeMustBeNumericOrDate(field(), sourceText(), ParamOrdinal.DEFAULT);
}
}
}

View File

@ -8,8 +8,8 @@ package org.elasticsearch.xpack.sql.expression.function.aggregate;
import org.elasticsearch.xpack.sql.expression.Expression;
import org.elasticsearch.xpack.sql.expression.Expressions;
import org.elasticsearch.xpack.sql.expression.Expressions.ParamOrdinal;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataType;
import java.util.List;
@ -48,6 +48,6 @@ public class Min extends NumericAggregate implements EnclosedAgg {
@Override
protected TypeResolution resolveType() {
return Expressions.typeMustBeNumericOrDate(field(), functionName(), ParamOrdinal.DEFAULT);
return Expressions.typeMustBeNumericOrDate(field(), sourceText(), ParamOrdinal.DEFAULT);
}
}

View File

@ -25,7 +25,7 @@ abstract class NumericAggregate extends AggregateFunction {
@Override
protected TypeResolution resolveType() {
return Expressions.typeMustBeNumeric(field(), functionName(), ParamOrdinal.DEFAULT);
return Expressions.typeMustBeNumeric(field(), sourceText(), ParamOrdinal.DEFAULT);
}
@Override

View File

@ -10,8 +10,8 @@ import org.elasticsearch.xpack.sql.expression.Expression;
import org.elasticsearch.xpack.sql.expression.Expressions;
import org.elasticsearch.xpack.sql.expression.Expressions.ParamOrdinal;
import org.elasticsearch.xpack.sql.expression.Foldables;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataType;
import java.util.List;
@ -52,7 +52,7 @@ public class Percentile extends NumericAggregate implements EnclosedAgg {
return resolution;
}
return Expressions.typeMustBeNumeric(percent, functionName(), ParamOrdinal.DEFAULT);
return Expressions.typeMustBeNumeric(percent, sourceText(), ParamOrdinal.DEFAULT);
}
public Expression percent() {

View File

@ -10,8 +10,8 @@ import org.elasticsearch.xpack.sql.expression.Expression;
import org.elasticsearch.xpack.sql.expression.Expressions;
import org.elasticsearch.xpack.sql.expression.Expressions.ParamOrdinal;
import org.elasticsearch.xpack.sql.expression.Foldables;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataType;
import java.util.List;
@ -52,7 +52,7 @@ public class PercentileRank extends AggregateFunction implements EnclosedAgg {
return resolution;
}
return Expressions.typeMustBeNumeric(value, functionName(), ParamOrdinal.DEFAULT);
return Expressions.typeMustBeNumeric(value, sourceText(), ParamOrdinal.DEFAULT);
}
public Expression value() {

View File

@ -111,16 +111,4 @@ public class Cast extends UnaryScalarFunction {
return Objects.equals(dataType, other.dataType())
&& Objects.equals(field(), other.field());
}
@Override
public String toString() {
return functionName() + "(" + field().toString() + " AS " + to().sqlName() + ")#" + id();
}
@Override
public String name() {
StringBuilder sb = new StringBuilder(super.name());
sb.insert(sb.length() - 1, " AS " + to().sqlName());
return sb.toString();
}
}

View File

@ -12,7 +12,6 @@ import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
import org.elasticsearch.xpack.sql.session.Configuration;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataType;
import org.elasticsearch.xpack.sql.util.StringUtils;
import java.util.List;
import java.util.Objects;
@ -55,11 +54,6 @@ public abstract class ConfigurationFunction extends ScalarFunction {
@Override
public abstract Object fold();
@Override
protected String functionArgs() {
return StringUtils.EMPTY;
}
@Override
public ScriptTemplate asScript() {
return asScript(this);

View File

@ -10,8 +10,8 @@ import org.elasticsearch.xpack.sql.expression.Expression;
import org.elasticsearch.xpack.sql.expression.Expressions;
import org.elasticsearch.xpack.sql.expression.Expressions.ParamOrdinal;
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
import org.elasticsearch.xpack.sql.tree.Source;
import java.time.ZoneId;
import java.time.ZonedDateTime;
@ -20,17 +20,10 @@ import java.util.Objects;
abstract class BaseDateTimeFunction extends UnaryScalarFunction {
private final ZoneId zoneId;
private final String name;
BaseDateTimeFunction(Source source, Expression field, ZoneId zoneId) {
super(source, field);
this.zoneId = zoneId;
StringBuilder sb = new StringBuilder(super.name());
// add timezone as last argument
sb.insert(sb.length() - 1, " [" + zoneId.getId() + "]");
this.name = sb.toString();
}
@Override
@ -42,17 +35,12 @@ abstract class BaseDateTimeFunction extends UnaryScalarFunction {
@Override
protected TypeResolution resolveType() {
return Expressions.typeMustBeDate(field(), functionName(), ParamOrdinal.DEFAULT);
return Expressions.typeMustBeDate(field(), sourceText(), ParamOrdinal.DEFAULT);
}
public ZoneId zoneId() {
return zoneId;
}
@Override
public String name() {
return name;
}
@Override
public boolean foldable() {

View File

@ -36,12 +36,12 @@ public abstract class BinaryNumericFunction extends BinaryScalarFunction {
return new TypeResolution("Unresolved children");
}
TypeResolution resolution = Expressions.typeMustBeNumeric(left(), functionName(), ParamOrdinal.FIRST);
TypeResolution resolution = Expressions.typeMustBeNumeric(left(), sourceText(), ParamOrdinal.FIRST);
if (resolution.unresolved()) {
return resolution;
}
return Expressions.typeMustBeNumeric(right(), functionName(), ParamOrdinal.SECOND);
return Expressions.typeMustBeNumeric(right(), sourceText(), ParamOrdinal.SECOND);
}
@Override

View File

@ -11,10 +11,9 @@ import org.elasticsearch.xpack.sql.expression.Literal;
import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation;
import org.elasticsearch.xpack.sql.expression.gen.script.Params;
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataType;
import org.elasticsearch.xpack.sql.util.StringUtils;
public class E extends MathFunction {
@ -39,11 +38,6 @@ public class E extends MathFunction {
return Math.E;
}
@Override
protected String functionArgs() {
return StringUtils.EMPTY;
}
@Override
public ScriptTemplate asScript() {
return TEMPLATE;

View File

@ -11,10 +11,9 @@ import org.elasticsearch.xpack.sql.expression.Literal;
import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation;
import org.elasticsearch.xpack.sql.expression.gen.script.Params;
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataType;
import org.elasticsearch.xpack.sql.util.StringUtils;
public class Pi extends MathFunction {
@ -39,11 +38,6 @@ public class Pi extends MathFunction {
return Math.PI;
}
@Override
protected String functionArgs() {
return StringUtils.EMPTY;
}
@Override
public ScriptTemplate asScript() {
return TEMPLATE;

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack.sql.expression.function.scalar.string;
import org.elasticsearch.xpack.sql.expression.Expression;
import org.elasticsearch.xpack.sql.expression.Expressions.ParamOrdinal;
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
import org.elasticsearch.xpack.sql.expression.function.scalar.BinaryScalarFunction;
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
@ -15,7 +16,6 @@ import java.util.Locale;
import java.util.Objects;
import java.util.function.BiFunction;
import static org.elasticsearch.xpack.sql.expression.Expressions.ParamOrdinal;
import static org.elasticsearch.xpack.sql.expression.Expressions.typeMustBeString;
import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.paramsBuilder;
@ -42,7 +42,7 @@ public abstract class BinaryStringFunction<T,R> extends BinaryScalarFunction {
return new TypeResolution("Unresolved children");
}
TypeResolution resolution = typeMustBeString(left(), functionName(), ParamOrdinal.FIRST);
TypeResolution resolution = typeMustBeString(left(), sourceText(), ParamOrdinal.FIRST);
if (resolution.unresolved()) {
return resolution;
}

View File

@ -26,7 +26,7 @@ public abstract class BinaryStringNumericFunction extends BinaryStringFunction<N
@Override
protected TypeResolution resolveSecondParameterInputType(Expression e) {
return Expressions.typeMustBeNumeric(e,functionName(), Expressions.ParamOrdinal.SECOND);
return Expressions.typeMustBeNumeric(e, sourceText(), Expressions.ParamOrdinal.SECOND);
}
@Override

View File

@ -21,7 +21,7 @@ public abstract class BinaryStringStringFunction extends BinaryStringFunction<St
@Override
protected TypeResolution resolveSecondParameterInputType(Expression e) {
return Expressions.typeMustBeString(e, functionName(), Expressions.ParamOrdinal.SECOND);
return Expressions.typeMustBeString(e, sourceText(), Expressions.ParamOrdinal.SECOND);
}
@Override

View File

@ -13,8 +13,8 @@ import org.elasticsearch.xpack.sql.expression.Nullability;
import org.elasticsearch.xpack.sql.expression.function.scalar.BinaryScalarFunction;
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataType;
import static org.elasticsearch.xpack.sql.expression.function.scalar.string.ConcatFunctionProcessor.process;
@ -37,12 +37,12 @@ public class Concat extends BinaryScalarFunction {
return new TypeResolution("Unresolved children");
}
TypeResolution sourceResolution = Expressions.typeMustBeString(left(), functionName(), ParamOrdinal.FIRST);
TypeResolution sourceResolution = Expressions.typeMustBeString(left(), sourceText(), ParamOrdinal.FIRST);
if (sourceResolution.unresolved()) {
return sourceResolution;
}
return Expressions.typeMustBeString(right(), functionName(), ParamOrdinal.SECOND);
return Expressions.typeMustBeString(right(), sourceText(), ParamOrdinal.SECOND);
}
@Override

View File

@ -46,22 +46,22 @@ public class Insert extends ScalarFunction {
return new TypeResolution("Unresolved children");
}
TypeResolution sourceResolution = Expressions.typeMustBeString(source, functionName(), ParamOrdinal.FIRST);
TypeResolution sourceResolution = Expressions.typeMustBeString(source, sourceText(), ParamOrdinal.FIRST);
if (sourceResolution.unresolved()) {
return sourceResolution;
}
TypeResolution startResolution = Expressions.typeMustBeNumeric(start, functionName(), ParamOrdinal.SECOND);
TypeResolution startResolution = Expressions.typeMustBeNumeric(start, sourceText(), ParamOrdinal.SECOND);
if (startResolution.unresolved()) {
return startResolution;
}
TypeResolution lengthResolution = Expressions.typeMustBeNumeric(length, functionName(), ParamOrdinal.THIRD);
TypeResolution lengthResolution = Expressions.typeMustBeNumeric(length, sourceText(), ParamOrdinal.THIRD);
if (lengthResolution.unresolved()) {
return lengthResolution;
}
return Expressions.typeMustBeString(replacement, functionName(), ParamOrdinal.FOURTH);
return Expressions.typeMustBeString(replacement, sourceText(), ParamOrdinal.FOURTH);
}
@Override

View File

@ -48,19 +48,19 @@ public class Locate extends ScalarFunction {
return new TypeResolution("Unresolved children");
}
TypeResolution patternResolution = Expressions.typeMustBeString(pattern, functionName(), ParamOrdinal.FIRST);
TypeResolution patternResolution = Expressions.typeMustBeString(pattern, sourceText(), ParamOrdinal.FIRST);
if (patternResolution.unresolved()) {
return patternResolution;
}
TypeResolution sourceResolution = Expressions.typeMustBeString(source, functionName(), ParamOrdinal.SECOND);
TypeResolution sourceResolution = Expressions.typeMustBeString(source, sourceText(), ParamOrdinal.SECOND);
if (sourceResolution.unresolved()) {
return sourceResolution;
}
return start == null ?
TypeResolution.TYPE_RESOLVED :
Expressions.typeMustBeNumeric(start, functionName(), ParamOrdinal.THIRD);
Expressions.typeMustBeNumeric(start, sourceText(), ParamOrdinal.THIRD);
}
@Override

View File

@ -44,17 +44,17 @@ public class Replace extends ScalarFunction {
return new TypeResolution("Unresolved children");
}
TypeResolution sourceResolution = Expressions.typeMustBeString(source, functionName(), ParamOrdinal.FIRST);
TypeResolution sourceResolution = Expressions.typeMustBeString(source, sourceText(), ParamOrdinal.FIRST);
if (sourceResolution.unresolved()) {
return sourceResolution;
}
TypeResolution patternResolution = Expressions.typeMustBeString(pattern, functionName(), ParamOrdinal.SECOND);
TypeResolution patternResolution = Expressions.typeMustBeString(pattern, sourceText(), ParamOrdinal.SECOND);
if (patternResolution.unresolved()) {
return patternResolution;
}
return Expressions.typeMustBeString(replacement, functionName(), ParamOrdinal.THIRD);
return Expressions.typeMustBeString(replacement, sourceText(), ParamOrdinal.THIRD);
}
@Override
@ -124,4 +124,4 @@ public class Replace extends ScalarFunction {
return new Replace(source(), newChildren.get(0), newChildren.get(1), newChildren.get(2));
}
}
}

View File

@ -45,17 +45,17 @@ public class Substring extends ScalarFunction {
return new TypeResolution("Unresolved children");
}
TypeResolution sourceResolution = Expressions.typeMustBeString(source, functionName(), ParamOrdinal.FIRST);
TypeResolution sourceResolution = Expressions.typeMustBeString(source, sourceText(), ParamOrdinal.FIRST);
if (sourceResolution.unresolved()) {
return sourceResolution;
}
TypeResolution startResolution = Expressions.typeMustBeNumeric(start, functionName(), ParamOrdinal.SECOND);
TypeResolution startResolution = Expressions.typeMustBeNumeric(start, sourceText(), ParamOrdinal.SECOND);
if (startResolution.unresolved()) {
return startResolution;
}
return Expressions.typeMustBeNumeric(length, functionName(), ParamOrdinal.THIRD);
return Expressions.typeMustBeNumeric(length, sourceText(), ParamOrdinal.THIRD);
}
@Override
@ -124,4 +124,4 @@ public class Substring extends ScalarFunction {
return new Substring(source(), newChildren.get(0), newChildren.get(1), newChildren.get(2));
}
}
}

View File

@ -6,8 +6,6 @@
package org.elasticsearch.xpack.sql.expression.predicate;
import org.elasticsearch.xpack.sql.expression.Expression;
import org.elasticsearch.xpack.sql.expression.Expressions;
import org.elasticsearch.xpack.sql.expression.Literal;
import org.elasticsearch.xpack.sql.expression.function.scalar.BinaryScalarFunction;
import org.elasticsearch.xpack.sql.tree.Source;
@ -21,12 +19,10 @@ import java.util.Objects;
*/
public abstract class BinaryPredicate<T, U, R, F extends PredicateBiFunction<T, U, R>> extends BinaryScalarFunction {
private final String name;
private final F function;
protected BinaryPredicate(Source source, Expression left, Expression right, F function) {
super(source, left, right);
this.name = name(left, right, function.symbol());
this.function = function;
}
@ -65,11 +61,6 @@ public abstract class BinaryPredicate<T, U, R, F extends PredicateBiFunction<T,
&& Objects.equals(right(), other.right());
}
@Override
public String name() {
return name;
}
public String symbol() {
return function.symbol();
}
@ -77,23 +68,4 @@ public abstract class BinaryPredicate<T, U, R, F extends PredicateBiFunction<T,
public F function() {
return function;
}
private static String name(Expression left, Expression right, String symbol) {
StringBuilder sb = new StringBuilder();
sb.append(Expressions.name(left));
if (!(left instanceof Literal)) {
sb.insert(0, "(");
sb.append(")");
}
sb.append(" ");
sb.append(symbol);
sb.append(" ");
int pos = sb.length();
sb.append(Expressions.name(right));
if (!(right instanceof Literal)) {
sb.insert(pos, "(");
sb.append(")");
}
return sb.toString();
}
}

View File

@ -18,8 +18,8 @@ import org.elasticsearch.xpack.sql.expression.predicate.logical.BinaryLogicProce
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparison;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparisonPipe;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparisonProcessor.BinaryComparisonOperation;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataType;
import java.util.List;
@ -33,7 +33,6 @@ import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.pa
// BETWEEN or range - is a mix of gt(e) AND lt(e)
public class Range extends ScalarFunction {
private final String name;
private final Expression value, lower, upper;
private final boolean includeLower, includeUpper;
@ -45,12 +44,6 @@ public class Range extends ScalarFunction {
this.upper = upper;
this.includeLower = includeLower;
this.includeUpper = includeUpper;
this.name = name(value, lower, upper, includeLower, includeUpper);
}
@Override
public String name() {
return name;
}
@Override
@ -212,9 +205,4 @@ public class Range extends ScalarFunction {
return sb.toString();
}
@Override
public String toString() {
return name();
}
}

View File

@ -27,7 +27,7 @@ public abstract class BinaryLogic extends BinaryOperator<Boolean, Boolean, Boole
@Override
protected TypeResolution resolveInputType(Expression e, Expressions.ParamOrdinal paramOrdinal) {
return Expressions.typeMustBeBoolean(e, functionName(), paramOrdinal);
return Expressions.typeMustBeBoolean(e, sourceText(), paramOrdinal);
}
@Override

View File

@ -12,8 +12,8 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunctio
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
import org.elasticsearch.xpack.sql.expression.gen.script.Scripts;
import org.elasticsearch.xpack.sql.expression.predicate.Negatable;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataType;
public class Not extends UnaryScalarFunction {
@ -37,7 +37,7 @@ public class Not extends UnaryScalarFunction {
if (DataType.BOOLEAN == field().dataType()) {
return TypeResolution.TYPE_RESOLVED;
}
return Expressions.typeMustBeBoolean(field(), functionName(), ParamOrdinal.DEFAULT);
return Expressions.typeMustBeBoolean(field(), sourceText(), ParamOrdinal.DEFAULT);
}
@Override

View File

@ -8,13 +8,12 @@ package org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic;
import org.elasticsearch.xpack.sql.expression.Expression;
import org.elasticsearch.xpack.sql.expression.Expressions;
import org.elasticsearch.xpack.sql.expression.Expressions.ParamOrdinal;
import org.elasticsearch.xpack.sql.expression.NamedExpression;
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
import org.elasticsearch.xpack.sql.expression.gen.script.Scripts;
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.UnaryArithmeticProcessor.UnaryArithmeticOperation;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataType;
/**
@ -38,7 +37,7 @@ public class Neg extends UnaryScalarFunction {
@Override
protected TypeResolution resolveType() {
return Expressions.typeMustBeNumeric(field(), functionName(), ParamOrdinal.DEFAULT);
return Expressions.typeMustBeNumeric(field(), sourceText(), ParamOrdinal.DEFAULT);
}
@Override
@ -51,11 +50,6 @@ public class Neg extends UnaryScalarFunction {
return field().dataType();
}
@Override
public String name() {
return "-" + (field() instanceof NamedExpression && field().resolved() ? Expressions.name(field()) : field().toString());
}
@Override
public String processScript(String script) {
return Scripts.formatTemplate(Scripts.SQL_SCRIPTS + ".neg(" + script + ")");

View File

@ -40,18 +40,7 @@ public abstract class BinaryComparison extends BinaryOperator<Object, Object, Bo
return new BinaryComparisonPipe(source(), this, Expressions.pipe(left()), Expressions.pipe(right()), function());
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(left());
sb.append(" ");
sb.append(symbol());
sb.append(" ");
sb.append(right());
return sb.toString();
}
public static Integer compare(Object left, Object right) {
return Comparisons.compare(left, right);
}
}
}

View File

@ -21,7 +21,6 @@ import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.stream.Collectors;
import static org.elasticsearch.common.logging.LoggerMessageFormat.format;
@ -85,13 +84,6 @@ public class In extends ScalarFunction {
return InProcessor.apply(value.fold(), Foldables.valuesOf(list, value.dataType()));
}
@Override
public String name() {
StringJoiner sj = new StringJoiner(", ", " IN (", ")");
list.forEach(e -> sj.add(Expressions.name(e)));
return Expressions.name(value) + sj.toString();
}
@Override
public ScriptTemplate asScript() {
ScriptTemplate leftScript = asScript(value);

View File

@ -92,6 +92,16 @@ abstract class AbstractBuilder extends SqlBaseBaseVisitor<Object> {
return new Source(new Location(token.getLine(), token.getCharPositionInLine()), text);
}
Source source(ParserRuleContext begin, ParserRuleContext end) {
Check.notNull(begin, "begin is null");
Check.notNull(end, "end is null");
Token start = begin.start;
Token stop = end.stop != null ? end.stop : begin.stop;
Interval interval = new Interval(start.getStartIndex(), stop.getStopIndex());
String text = start.getInputStream().getText(interval);
return new Source(new Location(start.getLine(), start.getCharPositionInLine()), text);
}
/**
* Retrieves the raw text of the node (without interpreting it as a string literal).
*/

View File

@ -11,6 +11,7 @@ import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.elasticsearch.common.Booleans;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
import org.elasticsearch.xpack.sql.expression.Alias;
import org.elasticsearch.xpack.sql.expression.Exists;
@ -215,7 +216,7 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
}
PredicateContext pCtx = ctx.predicate();
Source source = source(pCtx);
Source source = source(ctx.valueExpression(), ctx);
Expression e = null;
switch (pCtx.kind.getType()) {
@ -320,7 +321,7 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
if (value instanceof Literal) { // Minus already processed together with literal number
return value;
}
return new Neg(source(ctx.operator), value);
return new Neg(source(ctx), value);
default:
throw new ParsingException(source, "Unknown arithmetic {}", source.text());
}
@ -331,7 +332,7 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
Expression left = expression(ctx.left);
Expression right = expression(ctx.right);
Source source = source(ctx.operator);
Source source = source(ctx);
switch (ctx.operator.getType()) {
case SqlBaseParser.ASTERISK:
@ -611,7 +612,7 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
Interval<?> timeInterval = value instanceof Period ? new IntervalYearMonth((Period) value,
intervalType) : new IntervalDayTime((Duration) value, intervalType);
return new Literal(source(interval), text(interval), timeInterval, timeInterval.dataType());
return new Literal(source(interval), timeInterval, timeInterval.dataType());
}
private TemporalAmount of(NumberContext valueNumeric, TimeUnit unit) {
@ -689,23 +690,24 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
@Override
public Literal visitDecimalLiteral(DecimalLiteralContext ctx) {
String string = (hasMinusFromParent(ctx) ? "-" : "") + ctx.getText();
Tuple<Source, String> tuple = withMinus(ctx);
try {
return new Literal(source(ctx), Double.valueOf(StringUtils.parseDouble(string)), DataType.DOUBLE);
return new Literal(tuple.v1(), Double.valueOf(StringUtils.parseDouble(tuple.v2())), DataType.DOUBLE);
} catch (SqlIllegalArgumentException siae) {
throw new ParsingException(source(ctx), siae.getMessage());
throw new ParsingException(tuple.v1(), siae.getMessage());
}
}
@Override
public Literal visitIntegerLiteral(IntegerLiteralContext ctx) {
String string = (hasMinusFromParent(ctx) ? "-" : "") + ctx.getText();
Tuple<Source, String> tuple = withMinus(ctx);
long value;
try {
value = Long.valueOf(StringUtils.parseLong(string));
value = Long.valueOf(StringUtils.parseLong(tuple.v2()));
} catch (SqlIllegalArgumentException siae) {
throw new ParsingException(source(ctx), siae.getMessage());
throw new ParsingException(tuple.v1(), siae.getMessage());
}
Object val = Long.valueOf(value);
@ -715,7 +717,7 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
type = DataType.INTEGER;
val = Integer.valueOf((int) value);
}
return new Literal(source(ctx), val, type);
return new Literal(tuple.v1(), val, type);
}
@Override
@ -876,7 +878,30 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
return new Literal(source(ctx), string, DataType.KEYWORD);
}
private boolean hasMinusFromParent(SqlBaseParser.NumberContext ctx) {
/**
* Return the source and the value of the given number,
* taking into account MINUS (-) if needed.
*/
private static Tuple<Source, String> withMinus(NumberContext ctx) {
String string = ctx.getText();
Source source = minusAwareSource(ctx);
if (source != null) {
string = "-" + string;
} else {
source = source(ctx);
}
return new Tuple<>(source, string);
}
/**
* Checks the presence of MINUS (-) in the parent and if found,
* returns the parent source or null otherwise.
* Parsing of the value should not depend on the returned source
* as it might contain extra spaces.
*/
private static Source minusAwareSource(SqlBaseParser.NumberContext ctx) {
ParserRuleContext parentCtx = ctx.getParent();
if (parentCtx != null) {
if (parentCtx instanceof SqlBaseParser.NumericLiteralContext) {
@ -886,17 +911,23 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
if (parentCtx != null && parentCtx instanceof SqlBaseParser.ValueExpressionDefaultContext) {
parentCtx = parentCtx.getParent();
if (parentCtx != null && parentCtx instanceof SqlBaseParser.ArithmeticUnaryContext) {
return ((ArithmeticUnaryContext) parentCtx).MINUS() != null;
if (((ArithmeticUnaryContext) parentCtx).MINUS() != null) {
return source(parentCtx);
}
}
}
}
} else if (parentCtx instanceof SqlBaseParser.IntervalContext) {
IntervalContext ic = (IntervalContext) parentCtx;
return ic.sign != null && ic.sign.getType() == SqlBaseParser.MINUS;
if (ic.sign != null && ic.sign.getType() == SqlBaseParser.MINUS) {
return source(ic);
}
} else if (parentCtx instanceof SqlBaseParser.SysTypesContext) {
return ((SysTypesContext) parentCtx).MINUS() != null;
if (((SysTypesContext) parentCtx).MINUS() != null) {
return source(parentCtx);
}
}
}
return false;
return null;
}
}
}

View File

@ -239,7 +239,7 @@ public class VerifierErrorMessagesTests extends ESTestCase {
}
public void testGroupByOrderByScalarOverNonGrouped() {
assertEquals("1:50: Cannot order by non-grouped column [YEAR(date [Z])], expected [text]",
assertEquals("1:50: Cannot order by non-grouped column [YEAR(date)], expected [text]",
error("SELECT MAX(int) FROM test GROUP BY text ORDER BY YEAR(date)"));
}
@ -249,7 +249,7 @@ public class VerifierErrorMessagesTests extends ESTestCase {
}
public void testGroupByOrderByScalarOverNonGrouped_WithHaving() {
assertEquals("1:71: Cannot order by non-grouped column [YEAR(date [Z])], expected [text]",
assertEquals("1:71: Cannot order by non-grouped column [YEAR(date)], expected [text]",
error("SELECT MAX(int) FROM test GROUP BY text HAVING MAX(int) > 10 ORDER BY YEAR(date)"));
}
@ -373,12 +373,12 @@ public class VerifierErrorMessagesTests extends ESTestCase {
}
public void testNotSupportedAggregateOnDate() {
assertEquals("1:8: [AVG] argument must be [numeric], found value [date] type [date]",
assertEquals("1:8: [AVG(date)] argument must be [numeric], found value [date] type [date]",
error("SELECT AVG(date) FROM test"));
}
public void testNotSupportedAggregateOnString() {
assertEquals("1:8: [MAX] argument must be [numeric or date], found value [keyword] type [keyword]",
assertEquals("1:8: [MAX(keyword)] argument must be [numeric or date], found value [keyword] type [keyword]",
error("SELECT MAX(keyword) FROM test"));
}
@ -388,53 +388,53 @@ public class VerifierErrorMessagesTests extends ESTestCase {
}
public void testInvalidTypeForNumericFunction_WithOneArg() {
assertEquals("1:8: [COS] argument must be [numeric], found value [foo] type [keyword]",
assertEquals("1:8: [COS] argument must be [numeric], found value ['foo'] type [keyword]",
error("SELECT COS('foo')"));
}
public void testInvalidTypeForBooleanFunction_WithOneArg() {
assertEquals("1:8: [NOT] argument must be [boolean], found value [foo] type [keyword]",
assertEquals("1:8: [NOT 'foo'] argument must be [boolean], found value ['foo'] type [keyword]",
error("SELECT NOT 'foo'"));
}
public void testInvalidTypeForStringFunction_WithTwoArgs() {
assertEquals("1:8: [CONCAT] first argument must be [string], found value [1] type [integer]",
assertEquals("1:8: [CONCAT(1, 'bar')] first argument must be [string], found value [1] type [integer]",
error("SELECT CONCAT(1, 'bar')"));
assertEquals("1:8: [CONCAT] second argument must be [string], found value [2] type [integer]",
assertEquals("1:8: [CONCAT('foo', 2)] second argument must be [string], found value [2] type [integer]",
error("SELECT CONCAT('foo', 2)"));
}
public void testInvalidTypeForNumericFunction_WithTwoArgs() {
assertEquals("1:8: [TRUNCATE] first argument must be [numeric], found value [foo] type [keyword]",
assertEquals("1:8: [TRUNCATE('foo', 2)] first argument must be [numeric], found value ['foo'] type [keyword]",
error("SELECT TRUNCATE('foo', 2)"));
assertEquals("1:8: [TRUNCATE] second argument must be [numeric], found value [bar] type [keyword]",
assertEquals("1:8: [TRUNCATE(1.2, 'bar')] second argument must be [numeric], found value ['bar'] type [keyword]",
error("SELECT TRUNCATE(1.2, 'bar')"));
}
public void testInvalidTypeForBooleanFuntion_WithTwoArgs() {
assertEquals("1:8: [OR] first argument must be [boolean], found value [1] type [integer]",
assertEquals("1:8: [1 OR true] first argument must be [boolean], found value [1] type [integer]",
error("SELECT 1 OR true"));
assertEquals("1:8: [OR] second argument must be [boolean], found value [2] type [integer]",
assertEquals("1:8: [true OR 2] second argument must be [boolean], found value [2] type [integer]",
error("SELECT true OR 2"));
}
public void testInvalidTypeForFunction_WithThreeArgs() {
assertEquals("1:8: [REPLACE] first argument must be [string], found value [1] type [integer]",
assertEquals("1:8: [REPLACE(1, 'foo', 'bar')] first argument must be [string], found value [1] type [integer]",
error("SELECT REPLACE(1, 'foo', 'bar')"));
assertEquals("1:8: [REPLACE] second argument must be [string], found value [2] type [integer]",
assertEquals("1:8: [REPLACE('text', 2, 'bar')] second argument must be [string], found value [2] type [integer]",
error("SELECT REPLACE('text', 2, 'bar')"));
assertEquals("1:8: [REPLACE] third argument must be [string], found value [3] type [integer]",
assertEquals("1:8: [REPLACE('text', 'foo', 3)] third argument must be [string], found value [3] type [integer]",
error("SELECT REPLACE('text', 'foo', 3)"));
}
public void testInvalidTypeForFunction_WithFourArgs() {
assertEquals("1:8: [INSERT] first argument must be [string], found value [1] type [integer]",
assertEquals("1:8: [INSERT(1, 1, 2, 'new')] first argument must be [string], found value [1] type [integer]",
error("SELECT INSERT(1, 1, 2, 'new')"));
assertEquals("1:8: [INSERT] second argument must be [numeric], found value [foo] type [keyword]",
assertEquals("1:8: [INSERT('text', 'foo', 2, 'new')] second argument must be [numeric], found value ['foo'] type [keyword]",
error("SELECT INSERT('text', 'foo', 2, 'new')"));
assertEquals("1:8: [INSERT] third argument must be [numeric], found value [bar] type [keyword]",
assertEquals("1:8: [INSERT('text', 1, 'bar', 'new')] third argument must be [numeric], found value ['bar'] type [keyword]",
error("SELECT INSERT('text', 1, 'bar', 'new')"));
assertEquals("1:8: [INSERT] fourth argument must be [string], found value [3] type [integer]",
assertEquals("1:8: [INSERT('text', 1, 2, 3)] fourth argument must be [string], found value [3] type [integer]",
error("SELECT INSERT('text', 1, 2, 3)"));
}
@ -508,7 +508,7 @@ public class VerifierErrorMessagesTests extends ESTestCase {
}
public void testHistogramInFilter() {
assertEquals("1:63: Cannot filter on grouping function [HISTOGRAM(date)], use its argument instead",
assertEquals("1:63: Cannot filter on grouping function [HISTOGRAM(date, INTERVAL 1 MONTH)], use its argument instead",
error("SELECT HISTOGRAM(date, INTERVAL 1 MONTH) AS h FROM test WHERE "
+ "HISTOGRAM(date, INTERVAL 1 MONTH) > CAST('2000-01-01' AS DATE) GROUP BY h"));
}
@ -522,8 +522,8 @@ public class VerifierErrorMessagesTests extends ESTestCase {
public void testGroupByScalarOnTopOfGrouping() {
assertEquals(
"1:14: Cannot combine [HISTOGRAM(date)] grouping function inside GROUP BY, "
+ "found [MONTH_OF_YEAR(HISTOGRAM(date) [Z])]; consider moving the expression inside the histogram",
"1:14: Cannot combine [HISTOGRAM(date, INTERVAL 1 MONTH)] grouping function inside "
+ "GROUP BY, found [MONTH(HISTOGRAM(date, INTERVAL 1 MONTH))]; consider moving the expression inside the histogram",
error("SELECT MONTH(HISTOGRAM(date, INTERVAL 1 MONTH)) AS h FROM test GROUP BY h"));
}

View File

@ -14,6 +14,8 @@ import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Mod;
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Mul;
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Neg;
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Sub;
import org.elasticsearch.xpack.sql.tree.Location;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataType;
import org.elasticsearch.xpack.sql.type.EsField;
@ -23,29 +25,40 @@ import static org.elasticsearch.xpack.sql.tree.Source.EMPTY;
public class NamedExpressionTests extends ESTestCase {
public void testArithmeticFunctionName() {
Add add = new Add(EMPTY, l(5), l(2));
assertEquals("5 + 2", add.name());
String e = "5 + 2";
Add add = new Add(s(e), l(5), l(2));
assertEquals(e, add.sourceText());
Div div = new Div(EMPTY, l(5), l(2));
assertEquals("5 / 2", div.name());
e = "5 / 2";
Div div = new Div(s(e), l(5), l(2));
assertEquals(e, div.sourceText());
Mod mod = new Mod(EMPTY, l(5), l(2));
assertEquals("5 % 2", mod.name());
e = "5%2";
Mod mod = new Mod(s(e), l(5), l(2));
assertEquals(e, mod.sourceText());
Mul mul = new Mul(EMPTY, l(5), l(2));
assertEquals("5 * 2", mul.name());
e = "5 * 2";
Mul mul = new Mul(s(e), l(5), l(2));
assertEquals(e, mul.sourceText());
Sub sub = new Sub(EMPTY, l(5), l(2));
assertEquals("5 - 2", sub.name());
e = "5 -2";
Sub sub = new Sub(s(e), l(5), l(2));
assertEquals(e, sub.sourceText());
Neg neg = new Neg(EMPTY, l(5));
assertEquals("-5", neg.name());
e = " - 5";
Neg neg = new Neg(s(e), l(5));
assertEquals(e, neg.sourceText());
}
public void testNameForArithmeticFunctionAppliedOnTableColumn() {
FieldAttribute fa = new FieldAttribute(EMPTY, "myField", new EsField("myESField", DataType.INTEGER, emptyMap(), true));
Add add = new Add(EMPTY, fa, l(10));
assertEquals("(myField) + 10", add.name());
String e = "myField + 10";
Add add = new Add(s(e), fa, l(10));
assertEquals(e, add.sourceText());
}
private static Source s(String text) {
return new Source(Location.EMPTY, text);
}
private static Literal l(Object value) {

View File

@ -7,6 +7,7 @@ package org.elasticsearch.xpack.sql.expression.function.scalar.datetime;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.expression.Literal;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataType;
import java.time.ZoneId;
@ -27,6 +28,6 @@ public class DayOfYearTests extends ESTestCase {
}
private DayOfYear build(Object value, ZoneId zoneId) {
return new DayOfYear(null, new Literal(null, value, DataType.DATE), zoneId);
return new DayOfYear(Source.EMPTY, new Literal(Source.EMPTY, value, DataType.DATE), zoneId);
}
}

View File

@ -585,7 +585,7 @@ public class OptimizerTests extends ESTestCase {
BooleanLiteralsOnTheRight swapLiteralsToRight = new BooleanLiteralsOnTheRight();
BinaryComparisonSimplification bcSimpl = new BinaryComparisonSimplification();
FieldAttribute fa = getFieldAttribute();
Source source = new Source(1, 10, StringUtils.EMPTY);
Source source = new Source(1, 10, "IS_NULL(a)");
Expression e = bcSimpl.rule(swapLiteralsToRight.rule(new NullEquals(source, fa, NULL)));
assertEquals(IsNull.class, e.getClass());

View File

@ -80,12 +80,12 @@ public class EscapedFunctionsTests extends ESTestCase {
public void testFunctionNoArg() {
Function f = function("SCORE()");
assertEquals("SCORE", f.functionName());
assertEquals("{fn SCORE()}", f.sourceText());
}
public void testFunctionOneArg() {
Function f = function("ABS(foo)");
assertEquals("ABS", f.functionName());
assertEquals("{fn ABS(foo)}", f.sourceText());
assertEquals(1, f.arguments().size());
Expression arg = f.arguments().get(0);
assertThat(arg, instanceOf(UnresolvedAttribute.class));
@ -95,75 +95,77 @@ public class EscapedFunctionsTests extends ESTestCase {
public void testFunctionOneArgFunction() {
Function f = function("ABS({fn SCORE()})");
assertEquals("ABS", f.functionName());
assertEquals("{fn ABS({fn SCORE()})}", f.sourceText());
assertEquals(1, f.arguments().size());
Expression arg = f.arguments().get(0);
assertThat(arg, instanceOf(UnresolvedFunction.class));
UnresolvedFunction uf = (UnresolvedFunction) arg;
assertThat(uf.name(), is("SCORE"));
assertThat(uf.sourceText(), is("{fn SCORE()}"));
}
public void testFunctionFloorWithExtract() {
Function f = function("CAST({fn FLOOR({fn EXTRACT(YEAR FROM \"foo\")})} AS int)");
assertEquals("CAST", f.functionName());
String e = "CAST({fn FLOOR({fn EXTRACT(YEAR FROM \"foo\")})} AS int)";
Function f = function(e);
assertEquals(e, f.sourceText());
assertEquals(1, f.arguments().size());
Expression arg = f.arguments().get(0);
assertThat(arg, instanceOf(UnresolvedFunction.class));
f = (Function) arg;
assertEquals("FLOOR", f.functionName());
assertEquals("{fn FLOOR({fn EXTRACT(YEAR FROM \"foo\")})}", f.sourceText());
assertEquals(1, f.arguments().size());
arg = f.arguments().get(0);
assertThat(arg, instanceOf(UnresolvedFunction.class));
UnresolvedFunction uf = (UnresolvedFunction) arg;
assertThat(uf.name(), is("YEAR"));
assertThat(uf.sourceText(), is("EXTRACT(YEAR FROM \"foo\")"));
}
public void testFunctionWithFunctionWithArg() {
Function f = function("POWER(foo, {fn POWER({fn SCORE()}, {fN SCORE()})})");
assertEquals("POWER", f.functionName());
assertEquals("{fn POWER(foo, {fn POWER({fn SCORE()}, {fN SCORE()})})}", f.sourceText());
assertEquals(2, f.arguments().size());
Expression arg = f.arguments().get(1);
assertThat(arg, instanceOf(UnresolvedFunction.class));
UnresolvedFunction uf = (UnresolvedFunction) arg;
assertThat(uf.name(), is("POWER"));
assertThat(uf.sourceText(), is("{fn POWER({fn SCORE()}, {fN SCORE()})}"));
assertEquals(2, uf.arguments().size());
List<Expression> args = uf.arguments();
arg = args.get(0);
assertThat(arg, instanceOf(UnresolvedFunction.class));
uf = (UnresolvedFunction) arg;
assertThat(uf.name(), is("SCORE"));
assertThat(uf.sourceText(), is("{fn SCORE()}"));
arg = args.get(1);
assertThat(arg, instanceOf(UnresolvedFunction.class));
uf = (UnresolvedFunction) arg;
assertThat(uf.name(), is("SCORE"));
assertThat(uf.sourceText(), is("{fN SCORE()}"));
}
public void testFunctionWithFunctionWithArgAndParams() {
Function f = (Function) parser.createExpression("POWER(?, {fn POWER({fn ABS(?)}, {fN ABS(?)})})",
String e = "POWER(?, {fn POWER({fn ABS(?)}, {fN ABS(?)})})";
Function f = (Function) parser.createExpression(e,
asList(new SqlTypedParamValue(DataType.LONG.esType, 1),
new SqlTypedParamValue(DataType.LONG.esType, 1),
new SqlTypedParamValue(DataType.LONG.esType, 1)));
assertEquals("POWER", f.functionName());
assertEquals(e, f.sourceText());
assertEquals(2, f.arguments().size());
Expression arg = f.arguments().get(1);
assertThat(arg, instanceOf(UnresolvedFunction.class));
UnresolvedFunction uf = (UnresolvedFunction) arg;
assertThat(uf.name(), is("POWER"));
assertEquals("{fn POWER({fn ABS(?)}, {fN ABS(?)})}", uf.sourceText());
assertEquals(2, uf.arguments().size());
List<Expression> args = uf.arguments();
arg = args.get(0);
assertThat(arg, instanceOf(UnresolvedFunction.class));
uf = (UnresolvedFunction) arg;
assertThat(uf.name(), is("ABS"));
assertThat(uf.sourceText(), is("{fn ABS(?)}"));
arg = args.get(1);
assertThat(arg, instanceOf(UnresolvedFunction.class));
uf = (UnresolvedFunction) arg;
assertThat(uf.name(), is("ABS"));
assertThat(uf.sourceText(), is("{fN ABS(?)}"));
}
public void testDateLiteral() {

View File

@ -26,7 +26,6 @@ import java.time.temporal.TemporalAmount;
import java.util.Locale;
import static java.lang.String.format;
import static org.hamcrest.core.StringStartsWith.startsWith;
public class ExpressionTests extends ESTestCase {
@ -36,7 +35,7 @@ public class ExpressionTests extends ESTestCase {
Expression lt = parser.createExpression("LEFT()");
assertEquals(UnresolvedFunction.class, lt.getClass());
UnresolvedFunction uf = (UnresolvedFunction) lt;
assertEquals("LEFT", uf.functionName());
assertEquals("LEFT()", uf.sourceText());
}
public void testLiteralBoolean() {
@ -182,10 +181,10 @@ public class ExpressionTests extends ESTestCase {
}
public void testLiteralTimesLiteral() {
Expression expr = parser.createExpression("10*2");
Expression expr = parser.createExpression("10 *2");
assertEquals(Mul.class, expr.getClass());
Mul mul = (Mul) expr;
assertEquals("10 * 2", mul.name());
assertEquals("10 *2", mul.sourceText());
assertEquals(DataType.INTEGER, mul.dataType());
}
@ -193,39 +192,46 @@ public class ExpressionTests extends ESTestCase {
Expression expr = parser.createExpression("PI()*2");
assertEquals(Mul.class, expr.getClass());
Mul mul = (Mul) expr;
assertEquals("(PI) * 2", mul.name());
assertEquals("PI()*2", mul.sourceText());
}
public void testNegativeLiteral() {
Expression expr = parser.createExpression("- 6");
assertEquals(Literal.class, expr.getClass());
assertEquals("- 6", expr.sourceText());
}
public void testComplexArithmetic() {
Expression expr = parser.createExpression("-(((a-2)-(-3))+b)");
String sql = "-(((a-2)-(-3))+b)";
Expression expr = parser.createExpression(sql);
assertEquals(Neg.class, expr.getClass());
Neg neg = (Neg) expr;
assertThat(neg.name(), startsWith("-(((a) - 2) - -3) + (b)#"));
assertEquals(sql, neg.sourceText());
assertEquals(1, neg.children().size());
assertEquals(Add.class, neg.children().get(0).getClass());
Add add = (Add) neg.children().get(0);
assertEquals("(((a) - 2) - -3) + (b)", add.name());
assertEquals("((a-2)-(-3))+b", add.sourceText());
assertEquals(2, add.children().size());
assertEquals("?b", add.children().get(1).toString());
assertEquals(Sub.class, add.children().get(0).getClass());
Sub sub1 = (Sub) add.children().get(0);
assertEquals("((a) - 2) - -3", sub1.name());
assertEquals("(a-2)-(-3)", sub1.sourceText());
assertEquals(2, sub1.children().size());
assertEquals(Literal.class, sub1.children().get(1).getClass());
assertEquals("-3", ((Literal) sub1.children().get(1)).name());
assertEquals("-3", ((Literal) sub1.children().get(1)).sourceText());
assertEquals(Sub.class, sub1.children().get(0).getClass());
Sub sub2 = (Sub) sub1.children().get(0);
assertEquals(2, sub2.children().size());
assertEquals("?a", sub2.children().get(0).toString());
assertEquals(Literal.class, sub2.children().get(1).getClass());
assertEquals("2", ((Literal) sub2.children().get(1)).name());
assertEquals("2", ((Literal) sub2.children().get(1)).sourceText());
}
public void testEquals() {
Expression expr = parser.createExpression("a = 10");
assertEquals(Equals.class, expr.getClass());
Equals eq = (Equals) expr;
assertEquals("(a) == 10", eq.name());
assertEquals("a = 10", eq.sourceText());
assertEquals(2, eq.children().size());
}
@ -233,7 +239,7 @@ public class ExpressionTests extends ESTestCase {
Expression expr = parser.createExpression("a <=> 10");
assertEquals(NullEquals.class, expr.getClass());
NullEquals nullEquals = (NullEquals) expr;
assertEquals("(a) <=> 10", nullEquals.name());
assertEquals("a <=> 10", nullEquals.sourceText());
assertEquals(2, nullEquals.children().size());
}
@ -241,12 +247,12 @@ public class ExpressionTests extends ESTestCase {
Expression expr = parser.createExpression("a != 10");
assertEquals(NotEquals.class, expr.getClass());
NotEquals neq = (NotEquals) expr;
assertEquals("(a) != 10", neq.name());
assertEquals("a != 10", neq.sourceText());
assertEquals(2, neq.children().size());
}
public void testCastWithUnquotedDataType() {
Expression expr = parser.createExpression("CAST(10*2 AS long)");
Expression expr = parser.createExpression("CAST(10* 2 AS long)");
assertEquals(Cast.class, expr.getClass());
Cast cast = (Cast) expr;
assertEquals(DataType.INTEGER, cast.from());
@ -254,7 +260,7 @@ public class ExpressionTests extends ESTestCase {
assertEquals(DataType.LONG, cast.dataType());
assertEquals(Mul.class, cast.field().getClass());
Mul mul = (Mul) cast.field();
assertEquals("10 * 2", mul.name());
assertEquals("10* 2", mul.sourceText());
assertEquals(DataType.INTEGER, mul.dataType());
}
@ -267,7 +273,7 @@ public class ExpressionTests extends ESTestCase {
assertEquals(DataType.LONG, cast.dataType());
assertEquals(Mul.class, cast.field().getClass());
Mul mul = (Mul) cast.field();
assertEquals("10 * 2", mul.name());
assertEquals("10*2", mul.sourceText());
assertEquals(DataType.INTEGER, mul.dataType());
}
@ -285,20 +291,22 @@ public class ExpressionTests extends ESTestCase {
assertEquals(DataType.LONG, cast.dataType());
assertEquals(Mul.class, cast.field().getClass());
Mul mul = (Mul) cast.field();
assertEquals("10 * 2", mul.name());
assertEquals("10*2", mul.sourceText());
assertEquals(DataType.INTEGER, mul.dataType());
}
public void testConvertWithQuotedDataType() {
Expression expr = parser.createExpression("CONVERT(10*2, \"LonG\")");
String e = "CONVERT(10*2, \"LonG\")";
Expression expr = parser.createExpression(e);
assertEquals(Cast.class, expr.getClass());
Cast cast = (Cast) expr;
assertEquals(e, cast.sourceText());
assertEquals(DataType.INTEGER, cast.from());
assertEquals(DataType.LONG, cast.to());
assertEquals(DataType.LONG, cast.dataType());
assertEquals(Mul.class, cast.field().getClass());
Mul mul = (Mul) cast.field();
assertEquals("10 * 2", mul.name());
assertEquals("10*2", mul.sourceText());
assertEquals(DataType.INTEGER, mul.dataType());
}
@ -334,7 +342,7 @@ public class ExpressionTests extends ESTestCase {
Expression expr = parser.createExpression("CURRENT_TIMESTAMP");
assertEquals(UnresolvedFunction.class, expr.getClass());
UnresolvedFunction ur = (UnresolvedFunction) expr;
assertEquals("CURRENT_TIMESTAMP", ur.name());
assertEquals("CURRENT_TIMESTAMP", ur.sourceText());
assertEquals(0, ur.children().size());
}
@ -342,7 +350,7 @@ public class ExpressionTests extends ESTestCase {
Expression expr = parser.createExpression("CURRENT_TIMESTAMP(4)");
assertEquals(UnresolvedFunction.class, expr.getClass());
UnresolvedFunction ur = (UnresolvedFunction) expr;
assertEquals("CURRENT_TIMESTAMP", ur.name());
assertEquals("CURRENT_TIMESTAMP(4)", ur.sourceText());
assertEquals(1, ur.children().size());
Expression child = ur.children().get(0);
assertEquals(Literal.class, child.getClass());

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack.sql.parser;
import com.google.common.base.Joiner;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.expression.NamedExpression;
import org.elasticsearch.xpack.sql.expression.Order;
@ -15,6 +16,7 @@ import org.elasticsearch.xpack.sql.expression.function.UnresolvedFunction;
import org.elasticsearch.xpack.sql.expression.predicate.fulltext.MatchQueryPredicate;
import org.elasticsearch.xpack.sql.expression.predicate.fulltext.MultiMatchQueryPredicate;
import org.elasticsearch.xpack.sql.expression.predicate.fulltext.StringQueryPredicate;
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Add;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In;
import org.elasticsearch.xpack.sql.parser.SqlBaseParser.BooleanExpressionContext;
import org.elasticsearch.xpack.sql.parser.SqlBaseParser.QueryPrimaryDefaultContext;
@ -60,12 +62,17 @@ public class SqlParserTests extends ESTestCase {
public void testSelectScore() {
UnresolvedFunction f = singleProjection(project(parseStatement("SELECT SCORE() FROM foo")), UnresolvedFunction.class);
assertEquals("SCORE", f.functionName());
assertEquals("SCORE()", f.sourceText());
}
public void testSelectAddWithParanthesis() {
Add f = singleProjection(project(parseStatement("SELECT (1 + 2)")), Add.class);
assertEquals("1 + 2", f.sourceText());
}
public void testSelectRightFunction() {
UnresolvedFunction f = singleProjection(project(parseStatement("SELECT RIGHT()")), UnresolvedFunction.class);
assertEquals("RIGHT", f.functionName());
assertEquals("RIGHT()", f.sourceText());
}
public void testsSelectNonReservedKeywords() {
@ -102,13 +109,13 @@ public class SqlParserTests extends ESTestCase {
public void testOrderByScore() {
Order.OrderDirection dir = randomFrom(Order.OrderDirection.values());
OrderBy ob = orderBy(parseStatement("SELECT * FROM foo ORDER BY SCORE()" + stringForDirection(dir)));
OrderBy ob = orderBy(parseStatement("SELECT * FROM foo ORDER BY SCORE( )" + stringForDirection(dir)));
assertThat(ob.order(), hasSize(1));
Order o = ob.order().get(0);
assertEquals(dir, o.direction());
assertThat(o.child(), instanceOf(UnresolvedFunction.class));
UnresolvedFunction f = (UnresolvedFunction) o.child();
assertEquals("SCORE", f.functionName());
assertEquals("SCORE( )", f.sourceText());
}
public void testOrderByTwo() {
@ -299,7 +306,7 @@ public class SqlParserTests extends ESTestCase {
In in = (In) filter.condition();
assertEquals("?a", in.value().toString());
assertEquals(noChildren, in.list().size());
assertThat(in.list().get(0).toString(), startsWith("(a) + (b)#"));
assertThat(in.list().get(0).toString(), startsWith("a + b#"));
}
public void testDecrementOfDepthCounter() {

View File

@ -76,7 +76,7 @@ public class QueryFolderTests extends ESTestCase {
assertEquals(EmptyExecutable.class, le.executable().getClass());
EmptyExecutable ee = (EmptyExecutable) le.executable();
assertEquals(1, ee.output().size());
assertThat(ee.output().get(0).toString(), startsWith("E{c}#"));
assertThat(ee.output().get(0).toString(), startsWith("E(){c}#"));
}
public void testLocalExecWithPrunedFilterWithFunctionAndAggregation() {
@ -86,7 +86,7 @@ public class QueryFolderTests extends ESTestCase {
assertEquals(EmptyExecutable.class, le.executable().getClass());
EmptyExecutable ee = (EmptyExecutable) le.executable();
assertEquals(1, ee.output().size());
assertThat(ee.output().get(0).toString(), startsWith("E{c}#"));
assertThat(ee.output().get(0).toString(), startsWith("E(){c}#"));
}
public void testLocalExecWithoutFromClause() {
@ -96,9 +96,9 @@ public class QueryFolderTests extends ESTestCase {
assertEquals(SingletonExecutable.class, le.executable().getClass());
SingletonExecutable ee = (SingletonExecutable) le.executable();
assertEquals(3, ee.output().size());
assertThat(ee.output().get(0).toString(), startsWith("E{c}#"));
assertThat(ee.output().get(1).toString(), startsWith("foo{c}#"));
assertThat(ee.output().get(2).toString(), startsWith("ABS(10){c}#"));
assertThat(ee.output().get(0).toString(), startsWith("E(){c}#"));
assertThat(ee.output().get(1).toString(), startsWith("'foo'{c}#"));
assertThat(ee.output().get(2).toString(), startsWith("abs(10){c}#"));
}
public void testLocalExecWithoutFromClauseWithPrunedFilter() {
@ -108,7 +108,7 @@ public class QueryFolderTests extends ESTestCase {
assertEquals(EmptyExecutable.class, le.executable().getClass());
EmptyExecutable ee = (EmptyExecutable) le.executable();
assertEquals(1, ee.output().size());
assertThat(ee.output().get(0).toString(), startsWith("E{c}#"));
assertThat(ee.output().get(0).toString(), startsWith("E(){c}#"));
}
public void testFoldingOfIsNull() {
@ -137,7 +137,7 @@ public class QueryFolderTests extends ESTestCase {
EmptyExecutable ee = (EmptyExecutable) le.executable();
assertEquals(2, ee.output().size());
assertThat(ee.output().get(0).toString(), startsWith("keyword{f}#"));
assertThat(ee.output().get(1).toString(), startsWith("MAX(int){a->"));
assertThat(ee.output().get(1).toString(), startsWith("max(int){a->"));
}
public void testFoldingBooleanOrNull_WhereClause() {
@ -159,7 +159,7 @@ public class QueryFolderTests extends ESTestCase {
"\"lang\":\"painless\",\"params\":{\"v0\":10}},"));
assertEquals(2, ee.output().size());
assertThat(ee.output().get(0).toString(), startsWith("keyword{f}#"));
assertThat(ee.output().get(1).toString(), startsWith("MAX(int){a->"));
assertThat(ee.output().get(1).toString(), startsWith("max(int){a->"));
}
public void testFoldingOfIsNotNull() {
@ -208,7 +208,7 @@ public class QueryFolderTests extends ESTestCase {
EmptyExecutable ee = (EmptyExecutable) le.executable();
assertEquals(2, ee.output().size());
assertThat(ee.output().get(0).toString(), startsWith("keyword{f}#"));
assertThat(ee.output().get(1).toString(), startsWith("MAX(int){a->"));
assertThat(ee.output().get(1).toString(), startsWith("max(int){a->"));
}
public void testFoldingToLocalExecWithProjectWithGroupBy_WithHaving_WithOrderAndLimit() {
@ -219,7 +219,7 @@ public class QueryFolderTests extends ESTestCase {
EmptyExecutable ee = (EmptyExecutable) le.executable();
assertEquals(2, ee.output().size());
assertThat(ee.output().get(0).toString(), startsWith("keyword{f}#"));
assertThat(ee.output().get(1).toString(), startsWith("MAX(int){a->"));
assertThat(ee.output().get(1).toString(), startsWith("max(int){a->"));
}
public void testGroupKeyTypes_Boolean() {
@ -232,7 +232,7 @@ public class QueryFolderTests extends ESTestCase {
"\"lang\":\"painless\",\"params\":{\"v0\":\"int\",\"v1\":10}},\"missing_bucket\":true," +
"\"value_type\":\"boolean\",\"order\":\"asc\"}}}]}}}"));
assertEquals(2, ee.output().size());
assertThat(ee.output().get(0).toString(), startsWith("COUNT(1){a->"));
assertThat(ee.output().get(0).toString(), startsWith("count(*){a->"));
assertThat(ee.output().get(1).toString(), startsWith("a{s->"));
}
@ -246,7 +246,7 @@ public class QueryFolderTests extends ESTestCase {
"\"lang\":\"painless\",\"params\":{\"v0\":\"int\",\"v1\":10}},\"missing_bucket\":true," +
"\"value_type\":\"long\",\"order\":\"asc\"}}}]}}}"));
assertEquals(2, ee.output().size());
assertThat(ee.output().get(0).toString(), startsWith("COUNT(1){a->"));
assertThat(ee.output().get(0).toString(), startsWith("count(*){a->"));
assertThat(ee.output().get(1).toString(), startsWith("a{s->"));
}
@ -260,7 +260,7 @@ public class QueryFolderTests extends ESTestCase {
"\"lang\":\"painless\",\"params\":{\"v0\":\"int\"}},\"missing_bucket\":true," +
"\"value_type\":\"double\",\"order\":\"asc\"}}}]}}}"));
assertEquals(2, ee.output().size());
assertThat(ee.output().get(0).toString(), startsWith("COUNT(1){a->"));
assertThat(ee.output().get(0).toString(), startsWith("count(*){a->"));
assertThat(ee.output().get(1).toString(), startsWith("a{s->"));
}
@ -274,7 +274,7 @@ public class QueryFolderTests extends ESTestCase {
"\"lang\":\"painless\",\"params\":{\"v0\":\"keyword\"}},\"missing_bucket\":true," +
"\"value_type\":\"string\",\"order\":\"asc\"}}}]}}}"));
assertEquals(2, ee.output().size());
assertThat(ee.output().get(0).toString(), startsWith("COUNT(1){a->"));
assertThat(ee.output().get(0).toString(), startsWith("count(*){a->"));
assertThat(ee.output().get(1).toString(), startsWith("a{s->"));
}
@ -288,7 +288,7 @@ public class QueryFolderTests extends ESTestCase {
"\"lang\":\"painless\",\"params\":{\"v0\":\"keyword\",\"v1\":\"IP\"}}," +
"\"missing_bucket\":true,\"value_type\":\"ip\",\"order\":\"asc\"}}}]}}}"));
assertEquals(2, ee.output().size());
assertThat(ee.output().get(0).toString(), startsWith("COUNT(1){a->"));
assertThat(ee.output().get(0).toString(), startsWith("count(*){a->"));
assertThat(ee.output().get(1).toString(), startsWith("a{s->"));
}
@ -303,7 +303,7 @@ public class QueryFolderTests extends ESTestCase {
"\"v0\":\"date\",\"v1\":\"P1Y2M\",\"v2\":\"INTERVAL_YEAR_TO_MONTH\"}},\"missing_bucket\":true," +
"\"value_type\":\"date\",\"order\":\"asc\"}}}]}}}"));
assertEquals(2, ee.output().size());
assertThat(ee.output().get(0).toString(), startsWith("COUNT(1){a->"));
assertThat(ee.output().get(0).toString(), startsWith("count(*){a->"));
assertThat(ee.output().get(1).toString(), startsWith("a{s->"));
}

View File

@ -277,7 +277,7 @@ public class QueryTranslatorTests extends ESTestCase {
AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalSqlScriptUtils.nullSafeFilter(InternalSqlScriptUtils.isNull(params.a0))",
aggFilter.scriptTemplate().toString());
assertThat(aggFilter.scriptTemplate().params().toString(), startsWith("[{a=MAX(int){a->"));
assertThat(aggFilter.scriptTemplate().params().toString(), startsWith("[{a=max(int){a->"));
}
public void testTranslateIsNotNullExpression_HavingClause_Painless() {
@ -290,7 +290,7 @@ public class QueryTranslatorTests extends ESTestCase {
AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalSqlScriptUtils.nullSafeFilter(InternalSqlScriptUtils.isNotNull(params.a0))",
aggFilter.scriptTemplate().toString());
assertThat(aggFilter.scriptTemplate().params().toString(), startsWith("[{a=MAX(int){a->"));
assertThat(aggFilter.scriptTemplate().params().toString(), startsWith("[{a=max(int){a->"));
}
public void testTranslateInExpression_WhereClause() {
@ -328,8 +328,10 @@ public class QueryTranslatorTests extends ESTestCase {
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
SqlIllegalArgumentException ex = expectThrows(SqlIllegalArgumentException.class, () -> QueryTranslator.toQuery(condition, false));
assertEquals("Line 1:52: Comparisons against variables are not (currently) supported; " +
"offender [keyword] in [keyword IN (foo, bar, keyword)]", ex.getMessage());
assertEquals(
"Line 1:52: Comparisons against variables are not (currently) supported; "
+ "offender [keyword] in [keyword IN ('foo', 'bar', keyword)]",
ex.getMessage());
}
public void testTranslateInExpression_WhereClause_Painless() {
@ -358,7 +360,7 @@ public class QueryTranslatorTests extends ESTestCase {
AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalSqlScriptUtils.nullSafeFilter(InternalSqlScriptUtils.in(params.a0, params.v0))",
aggFilter.scriptTemplate().toString());
assertThat(aggFilter.scriptTemplate().params().toString(), startsWith("[{a=MAX(int){a->"));
assertThat(aggFilter.scriptTemplate().params().toString(), startsWith("[{a=max(int){a->"));
assertThat(aggFilter.scriptTemplate().params().toString(), endsWith(", {v=[10, 20]}]"));
}
@ -372,7 +374,7 @@ public class QueryTranslatorTests extends ESTestCase {
AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalSqlScriptUtils.nullSafeFilter(InternalSqlScriptUtils.in(params.a0, params.v0))",
aggFilter.scriptTemplate().toString());
assertThat(aggFilter.scriptTemplate().params().toString(), startsWith("[{a=MAX(int){a->"));
assertThat(aggFilter.scriptTemplate().params().toString(), startsWith("[{a=max(int){a->"));
assertThat(aggFilter.scriptTemplate().params().toString(), endsWith(", {v=[10]}]"));
}
@ -387,7 +389,7 @@ public class QueryTranslatorTests extends ESTestCase {
AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalSqlScriptUtils.nullSafeFilter(InternalSqlScriptUtils.in(params.a0, params.v0))",
aggFilter.scriptTemplate().toString());
assertThat(aggFilter.scriptTemplate().params().toString(), startsWith("[{a=MAX(int){a->"));
assertThat(aggFilter.scriptTemplate().params().toString(), startsWith("[{a=max(int){a->"));
assertThat(aggFilter.scriptTemplate().params().toString(), endsWith(", {v=[10, null, 20, 30]}]"));
}
@ -406,7 +408,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertEquals("InternalSqlScriptUtils.nullSafeFilter(InternalSqlScriptUtils.gt(InternalSqlScriptUtils." +
operation.name().toLowerCase(Locale.ROOT) + "(params.a0),params.v0))",
aggFilter.scriptTemplate().toString());
assertThat(aggFilter.scriptTemplate().params().toString(), startsWith("[{a=MAX(int){a->"));
assertThat(aggFilter.scriptTemplate().params().toString(), startsWith("[{a=max(int){a->"));
assertThat(aggFilter.scriptTemplate().params().toString(), endsWith(", {v=10}]"));
}

View File

@ -9,12 +9,13 @@ import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
import org.elasticsearch.xpack.sql.TestUtils;
import org.elasticsearch.xpack.sql.expression.Literal;
import org.elasticsearch.xpack.sql.tree.Location;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataTypeConversion.Conversion;
import java.time.ZonedDateTime;
import static org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeTestUtils.dateTime;
import static org.elasticsearch.xpack.sql.tree.Source.EMPTY;
import static org.elasticsearch.xpack.sql.type.DataType.BOOLEAN;
import static org.elasticsearch.xpack.sql.type.DataType.BYTE;
import static org.elasticsearch.xpack.sql.type.DataType.DATE;
@ -291,9 +292,10 @@ public class DataTypeConversionTests extends ESTestCase {
}
public void testIpToString() {
Source s = new Source(Location.EMPTY, "10.0.0.1");
Conversion ipToString = conversionFor(IP, KEYWORD);
assertEquals("10.0.0.1", ipToString.convert(new Literal(EMPTY, "10.0.0.1", IP)));
assertEquals("10.0.0.1", ipToString.convert(new Literal(s, "10.0.0.1", IP)));
Conversion stringToIp = conversionFor(KEYWORD, IP);
assertEquals("10.0.0.1", ipToString.convert(stringToIp.convert(Literal.of(EMPTY, "10.0.0.1"))));
assertEquals("10.0.0.1", ipToString.convert(stringToIp.convert(Literal.of(s, "10.0.0.1"))));
}
}