Remove support for indices with multiple types

Indices discovery actively ignores indices with more than one type.
However queries made such indices throw an exception (assuming the user
by mistake or not, selects such an index).

Original commit: elastic/x-pack-elasticsearch@16855c7b8f
This commit is contained in:
Costin Leau 2017-08-02 17:03:49 +03:00
parent 38ea150f17
commit 0675d08f25
46 changed files with 1786 additions and 2142 deletions

View File

@ -5,43 +5,46 @@
*/ */
package org.elasticsearch.xpack.sql.cli; package org.elasticsearch.xpack.sql.cli;
import org.apache.lucene.util.LuceneTestCase.AwaitsFix;
import java.io.IOException; import java.io.IOException;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.Matchers.startsWith;
@AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/2074")
public class ExplainIT extends CliIntegrationTestCase { public class ExplainIT extends CliIntegrationTestCase {
public void testExplainBasic() throws IOException { public void testExplainBasic() throws IOException {
index("test", body -> body.field("test_field", "test_value")); index("test", body -> body.field("test_field", "test_value"));
command("EXPLAIN (PLAN PARSED) SELECT * FROM test.doc"); command("EXPLAIN (PLAN PARSED) SELECT * FROM test");
assertThat(in.readLine(), containsString("plan")); assertThat(in.readLine(), containsString("plan"));
assertThat(in.readLine(), startsWith("----------")); assertThat(in.readLine(), startsWith("----------"));
assertThat(in.readLine(), startsWith("With[{}]")); assertThat(in.readLine(), startsWith("With[{}]"));
assertThat(in.readLine(), startsWith("\\_Project[[?*]]")); assertThat(in.readLine(), startsWith("\\_Project[[?*]]"));
assertThat(in.readLine(), startsWith(" \\_UnresolvedRelation[[index=test, type=doc],null]")); assertThat(in.readLine(), startsWith(" \\_UnresolvedRelation[[test],null]"));
assertEquals("", in.readLine()); assertEquals("", in.readLine());
command("EXPLAIN " + (randomBoolean() ? "" : "(PLAN ANALYZED) ") + "SELECT * FROM test.doc"); command("EXPLAIN " + (randomBoolean() ? "" : "(PLAN ANALYZED) ") + "SELECT * FROM test");
assertThat(in.readLine(), containsString("plan")); assertThat(in.readLine(), containsString("plan"));
assertThat(in.readLine(), startsWith("----------")); assertThat(in.readLine(), startsWith("----------"));
assertThat(in.readLine(), startsWith("Project[[test_field{r}#")); assertThat(in.readLine(), startsWith("Project[[test_field{r}#"));
assertThat(in.readLine(), startsWith("\\_SubQueryAlias[doc]")); assertThat(in.readLine(), startsWith("\\_SubQueryAlias[doc]"));
assertThat(in.readLine(), startsWith(" \\_CatalogTable[index=test,type=doc][test_field{r}#")); assertThat(in.readLine(), startsWith(" \\_CatalogTable[test][test_field{r}#"));
assertEquals("", in.readLine()); assertEquals("", in.readLine());
command("EXPLAIN (PLAN OPTIMIZED) SELECT * FROM test.doc"); command("EXPLAIN (PLAN OPTIMIZED) SELECT * FROM test");
assertThat(in.readLine(), containsString("plan")); assertThat(in.readLine(), containsString("plan"));
assertThat(in.readLine(), startsWith("----------")); assertThat(in.readLine(), startsWith("----------"));
assertThat(in.readLine(), startsWith("Project[[test_field{r}#")); assertThat(in.readLine(), startsWith("Project[[test_field{r}#"));
assertThat(in.readLine(), startsWith("\\_CatalogTable[index=test,type=doc][test_field{r}#")); assertThat(in.readLine(), startsWith("\\_CatalogTable[test][test_field{r}#"));
assertEquals("", in.readLine()); assertEquals("", in.readLine());
// TODO in this case we should probably remove the source filtering entirely. Right? It costs but we don't need it. // TODO in this case we should probably remove the source filtering entirely. Right? It costs but we don't need it.
command("EXPLAIN (PLAN EXECUTABLE) SELECT * FROM test.doc"); command("EXPLAIN (PLAN EXECUTABLE) SELECT * FROM test");
assertThat(in.readLine(), containsString("plan")); assertThat(in.readLine(), containsString("plan"));
assertThat(in.readLine(), startsWith("----------")); assertThat(in.readLine(), startsWith("----------"));
assertThat(in.readLine(), startsWith("EsQueryExec[test/doc,{")); assertThat(in.readLine(), startsWith("EsQueryExec[test,{"));
assertThat(in.readLine(), startsWith(" \"_source\" : {")); assertThat(in.readLine(), startsWith(" \"_source\" : {"));
assertThat(in.readLine(), startsWith(" \"includes\" : [")); assertThat(in.readLine(), startsWith(" \"includes\" : ["));
assertThat(in.readLine(), startsWith(" \"test_field\"")); assertThat(in.readLine(), startsWith(" \"test_field\""));
@ -56,36 +59,36 @@ public class ExplainIT extends CliIntegrationTestCase {
index("test", body -> body.field("test_field", "test_value1").field("i", 1)); index("test", body -> body.field("test_field", "test_value1").field("i", 1));
index("test", body -> body.field("test_field", "test_value2").field("i", 2)); index("test", body -> body.field("test_field", "test_value2").field("i", 2));
command("EXPLAIN (PLAN PARSED) SELECT * FROM test.doc WHERE i = 2"); command("EXPLAIN (PLAN PARSED) SELECT * FROM test WHERE i = 2");
assertThat(in.readLine(), containsString("plan")); assertThat(in.readLine(), containsString("plan"));
assertThat(in.readLine(), startsWith("----------")); assertThat(in.readLine(), startsWith("----------"));
assertThat(in.readLine(), startsWith("With[{}]")); assertThat(in.readLine(), startsWith("With[{}]"));
assertThat(in.readLine(), startsWith("\\_Project[[?*]]")); assertThat(in.readLine(), startsWith("\\_Project[[?*]]"));
assertThat(in.readLine(), startsWith(" \\_Filter[?i = 2]")); assertThat(in.readLine(), startsWith(" \\_Filter[?i = 2]"));
assertThat(in.readLine(), startsWith(" \\_UnresolvedRelation[[index=test, type=doc],null]")); assertThat(in.readLine(), startsWith(" \\_UnresolvedRelation[[type],null]"));
assertEquals("", in.readLine()); assertEquals("", in.readLine());
command("EXPLAIN " + (randomBoolean() ? "" : "(PLAN ANALYZED) ") + "SELECT * FROM test.doc WHERE i = 2"); command("EXPLAIN " + (randomBoolean() ? "" : "(PLAN ANALYZED) ") + "SELECT * FROM test WHERE i = 2");
assertThat(in.readLine(), containsString("plan")); assertThat(in.readLine(), containsString("plan"));
assertThat(in.readLine(), startsWith("----------")); assertThat(in.readLine(), startsWith("----------"));
assertThat(in.readLine(), startsWith("Project[[i{r}#")); assertThat(in.readLine(), startsWith("Project[[i{r}#"));
assertThat(in.readLine(), startsWith("\\_Filter[i{r}#")); assertThat(in.readLine(), startsWith("\\_Filter[i{r}#"));
assertThat(in.readLine(), startsWith(" \\_SubQueryAlias[doc]")); assertThat(in.readLine(), startsWith(" \\_SubQueryAlias[doc]"));
assertThat(in.readLine(), startsWith(" \\_CatalogTable[index=test,type=doc][i{r}#")); assertThat(in.readLine(), startsWith(" \\_CatalogTable[test][i{r}#"));
assertEquals("", in.readLine()); assertEquals("", in.readLine());
command("EXPLAIN (PLAN OPTIMIZED) SELECT * FROM test.doc WHERE i = 2"); command("EXPLAIN (PLAN OPTIMIZED) SELECT * FROM test WHERE i = 2");
assertThat(in.readLine(), containsString("plan")); assertThat(in.readLine(), containsString("plan"));
assertThat(in.readLine(), startsWith("----------")); assertThat(in.readLine(), startsWith("----------"));
assertThat(in.readLine(), startsWith("Project[[i{r}#")); assertThat(in.readLine(), startsWith("Project[[i{r}#"));
assertThat(in.readLine(), startsWith("\\_Filter[i{r}#")); assertThat(in.readLine(), startsWith("\\_Filter[i{r}#"));
assertThat(in.readLine(), startsWith(" \\_CatalogTable[index=test,type=doc][i{r}#")); assertThat(in.readLine(), startsWith(" \\_CatalogTable[test][i{r}#"));
assertEquals("", in.readLine()); assertEquals("", in.readLine());
command("EXPLAIN (PLAN EXECUTABLE) SELECT * FROM test.doc WHERE i = 2"); command("EXPLAIN (PLAN EXECUTABLE) SELECT * FROM test WHERE i = 2");
assertThat(in.readLine(), containsString("plan")); assertThat(in.readLine(), containsString("plan"));
assertThat(in.readLine(), startsWith("----------")); assertThat(in.readLine(), startsWith("----------"));
assertThat(in.readLine(), startsWith("EsQueryExec[test/doc,{")); assertThat(in.readLine(), startsWith("EsQueryExec[test,{"));
assertThat(in.readLine(), startsWith(" \"query\" : {")); assertThat(in.readLine(), startsWith(" \"query\" : {"));
assertThat(in.readLine(), startsWith(" \"term\" : {")); assertThat(in.readLine(), startsWith(" \"term\" : {"));
assertThat(in.readLine(), startsWith(" \"i\" : {")); assertThat(in.readLine(), startsWith(" \"i\" : {"));
@ -112,33 +115,33 @@ public class ExplainIT extends CliIntegrationTestCase {
index("test", body -> body.field("test_field", "test_value1").field("i", 1)); index("test", body -> body.field("test_field", "test_value1").field("i", 1));
index("test", body -> body.field("test_field", "test_value2").field("i", 2)); index("test", body -> body.field("test_field", "test_value2").field("i", 2));
command("EXPLAIN (PLAN PARSED) SELECT COUNT(*) FROM test.doc"); command("EXPLAIN (PLAN PARSED) SELECT COUNT(*) FROM test");
assertThat(in.readLine(), containsString("plan")); assertThat(in.readLine(), containsString("plan"));
assertThat(in.readLine(), startsWith("----------")); assertThat(in.readLine(), startsWith("----------"));
assertThat(in.readLine(), startsWith("With[{}]")); assertThat(in.readLine(), startsWith("With[{}]"));
assertThat(in.readLine(), startsWith("\\_Project[[?COUNT(?*)]]")); assertThat(in.readLine(), startsWith("\\_Project[[?COUNT(?*)]]"));
assertThat(in.readLine(), startsWith(" \\_UnresolvedRelation[[index=test, type=doc],null]")); assertThat(in.readLine(), startsWith(" \\_UnresolvedRelation[[test],null]"));
assertEquals("", in.readLine()); assertEquals("", in.readLine());
command("EXPLAIN " + (randomBoolean() ? "" : "(PLAN ANALYZED) ") + "SELECT COUNT(*) FROM test.doc"); command("EXPLAIN " + (randomBoolean() ? "" : "(PLAN ANALYZED) ") + "SELECT COUNT(*) FROM test");
assertThat(in.readLine(), containsString("plan")); assertThat(in.readLine(), containsString("plan"));
assertThat(in.readLine(), startsWith("----------")); assertThat(in.readLine(), startsWith("----------"));
assertThat(in.readLine(), startsWith("Aggregate[[],[COUNT(1)#")); assertThat(in.readLine(), startsWith("Aggregate[[],[COUNT(1)#"));
assertThat(in.readLine(), startsWith("\\_SubQueryAlias[doc]")); assertThat(in.readLine(), startsWith("\\_SubQueryAlias[doc]"));
assertThat(in.readLine(), startsWith(" \\_CatalogTable[index=test,type=doc][i{r}#")); assertThat(in.readLine(), startsWith(" \\_CatalogTable[test][i{r}#"));
assertEquals("", in.readLine()); assertEquals("", in.readLine());
command("EXPLAIN (PLAN OPTIMIZED) SELECT COUNT(*) FROM test.doc"); command("EXPLAIN (PLAN OPTIMIZED) SELECT COUNT(*) FROM test");
assertThat(in.readLine(), containsString("plan")); assertThat(in.readLine(), containsString("plan"));
assertThat(in.readLine(), startsWith("----------")); assertThat(in.readLine(), startsWith("----------"));
assertThat(in.readLine(), startsWith("Aggregate[[],[COUNT(1)#")); assertThat(in.readLine(), startsWith("Aggregate[[],[COUNT(1)#"));
assertThat(in.readLine(), startsWith("\\_CatalogTable[index=test,type=doc][i{r}#")); assertThat(in.readLine(), startsWith("\\_CatalogTable[test][i{r}#"));
assertEquals("", in.readLine()); assertEquals("", in.readLine());
command("EXPLAIN (PLAN EXECUTABLE) SELECT COUNT(*) FROM test.doc"); command("EXPLAIN (PLAN EXECUTABLE) SELECT COUNT(*) FROM test");
assertThat(in.readLine(), containsString("plan")); assertThat(in.readLine(), containsString("plan"));
assertThat(in.readLine(), startsWith("----------")); assertThat(in.readLine(), startsWith("----------"));
assertThat(in.readLine(), startsWith("EsQueryExec[test/doc,{")); assertThat(in.readLine(), startsWith("EsQueryExec[test,{"));
assertThat(in.readLine(), startsWith(" \"size\" : 0,")); assertThat(in.readLine(), startsWith(" \"size\" : 0,"));
assertThat(in.readLine(), startsWith(" \"_source\" : false,")); assertThat(in.readLine(), startsWith(" \"_source\" : false,"));
assertThat(in.readLine(), startsWith(" \"stored_fields\" : \"_none_\"")); assertThat(in.readLine(), startsWith(" \"stored_fields\" : \"_none_\""));

View File

@ -134,9 +134,9 @@ public class JdbcHttpClient implements Closeable {
ExceptionResponse ex = (ExceptionResponse) response; ExceptionResponse ex = (ExceptionResponse) response;
throw ex.asException(); throw ex.asException();
} }
if (response.responseType() == ResponseType.EXCEPTION) { if (response.responseType() == ResponseType.ERROR) {
ErrorResponse error = (ErrorResponse) response; ErrorResponse error = (ErrorResponse) response;
throw new JdbcException("%s", error.stack); throw new JdbcException("Server returned error: %s", error.stack);
} }
return response; return response;
} }

View File

@ -43,8 +43,6 @@ public class CsvSpecIT extends SpecBaseIntegrationTestCase {
assertMatchesCsv(testCase.query, testName, testCase.expectedResults); assertMatchesCsv(testCase.query, testName, testCase.expectedResults);
} catch (AssertionError ae) { } catch (AssertionError ae) {
throw reworkException(new AssertionError(errorMessage(ae), ae.getCause())); throw reworkException(new AssertionError(errorMessage(ae), ae.getCause()));
} catch (Throwable th) {
throw reworkException(th);
} }
} }
@ -93,4 +91,4 @@ public class CsvSpecIT extends SpecBaseIntegrationTestCase {
String query; String query;
String expectedResults; String expectedResults;
} }
} }

View File

@ -9,24 +9,28 @@ import org.elasticsearch.xpack.sql.jdbc.framework.JdbcIntegrationTestCase;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Locale;
/** /**
* Tests for error messages. * Tests for error messages.
*/ */
public class ErrorsIT extends JdbcIntegrationTestCase { public class ErrorsIT extends JdbcIntegrationTestCase {
String message(String index) {
return String.format(Locale.ROOT, "line 1:15: Cannot resolve index %s (does not exist or has multiple types)", index);
}
public void testSelectFromMissingTable() throws Exception { public void testSelectFromMissingTable() throws Exception {
try (Connection c = esJdbc()) { try (Connection c = esJdbc()) {
SQLException e = expectThrows(SQLException.class, () -> c.prepareStatement("SELECT * from test.doc").executeQuery()); SQLException e = expectThrows(SQLException.class, () -> c.prepareStatement("SELECT * from test").executeQuery());
assertEquals("line 1:15: Cannot resolve index test", e.getMessage()); assertEquals(message("test"), e.getMessage());
} }
} }
public void testSelectFromMissingType() throws Exception { public void testMultiTypeIndex() throws Exception {
index("test", builder -> builder.field("name", "bob"));
try (Connection c = esJdbc()) { try (Connection c = esJdbc()) {
SQLException e = expectThrows(SQLException.class, () -> c.prepareStatement("SELECT * from test.notdoc").executeQuery()); SQLException e = expectThrows(SQLException.class, () -> c.prepareStatement("SELECT * from multi_type").executeQuery());
assertEquals("line 1:15: Cannot resolve type notdoc in index test", e.getMessage()); assertEquals(message("multi_type"), e.getMessage());
} }
} }
} }

View File

@ -37,6 +37,10 @@ public class SqlSpecIT extends SpecBaseIntegrationTestCase {
@ParametersFactory(shuffle = false, argumentFormatting = PARAM_FORMATTNG) @ParametersFactory(shuffle = false, argumentFormatting = PARAM_FORMATTNG)
public static List<Object[]> readScriptSpec() throws Exception { public static List<Object[]> readScriptSpec() throws Exception {
// example for enabling logging
//JdbcTestUtils.sqlLogging();
SqlSpecParser parser = new SqlSpecParser(); SqlSpecParser parser = new SqlSpecParser();
return CollectionUtils.combine( return CollectionUtils.combine(
readScriptSpec("/select.sql-spec", parser), readScriptSpec("/select.sql-spec", parser),
@ -45,7 +49,7 @@ public class SqlSpecIT extends SpecBaseIntegrationTestCase {
readScriptSpec("/math.sql-spec", parser), readScriptSpec("/math.sql-spec", parser),
readScriptSpec("/agg.sql-spec", parser)); readScriptSpec("/agg.sql-spec", parser));
} }
private static class SqlSpecParser implements Parser { private static class SqlSpecParser implements Parser {
@Override @Override
public Object parse(String line) { public Object parse(String line) {
@ -70,14 +74,14 @@ public class SqlSpecIT extends SpecBaseIntegrationTestCase {
} catch (AssertionError ae) { } catch (AssertionError ae) {
throw reworkException(new AssertionError(errorMessage(ae), ae.getCause())); throw reworkException(new AssertionError(errorMessage(ae), ae.getCause()));
} }
} catch (Throwable th) {
throw reworkException(th);
} }
} }
private ResultSet executeQuery(Connection con) throws SQLException { private ResultSet executeQuery(Connection con) throws SQLException {
Statement statement = con.createStatement(); Statement statement = con.createStatement();
statement.setFetchSize(randomInt(10)); //statement.setFetchSize(randomInt(10));
// NOCOMMIT: hook up pagination
statement.setFetchSize(1000);
return statement.executeQuery(query); return statement.executeQuery(query);
} }

View File

@ -11,6 +11,7 @@ import org.elasticsearch.client.http.entity.ContentType;
import org.elasticsearch.client.http.entity.StringEntity; import org.elasticsearch.client.http.entity.StringEntity;
import org.elasticsearch.common.CheckedBiConsumer; import org.elasticsearch.common.CheckedBiConsumer;
import org.elasticsearch.common.io.PathUtils; import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.xpack.sql.jdbc.SqlSpecIT; import org.elasticsearch.xpack.sql.jdbc.SqlSpecIT;
@ -26,8 +27,10 @@ import static java.util.Collections.singletonMap;
public class DataLoader { public class DataLoader {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
RestClient client = RestClient.builder(new HttpHost("localhost", 9200)).build(); try (RestClient client = RestClient.builder(new HttpHost("localhost", 9200)).build()) {
loadDatasetIntoEs(client); loadDatasetIntoEs(client);
Loggers.getLogger(DataLoader.class).info("Data loaded");
}
} }
protected static void loadDatasetIntoEs(RestClient client) throws Exception { protected static void loadDatasetIntoEs(RestClient client) throws Exception {
@ -70,6 +73,7 @@ public class DataLoader {
bulk.append("}\n"); bulk.append("}\n");
}); });
client.performRequest("POST", "/test_emp/emp/_bulk", singletonMap("refresh", "true"), new StringEntity(bulk.toString(), ContentType.APPLICATION_JSON)); client.performRequest("POST", "/test_emp/emp/_bulk", singletonMap("refresh", "true"), new StringEntity(bulk.toString(), ContentType.APPLICATION_JSON));
} }
private static void csvToLines(String name, CheckedBiConsumer<List<String>, List<String>, Exception> consumeLine) throws Exception { private static void csvToLines(String name, CheckedBiConsumer<List<String>, List<String>, Exception> consumeLine) throws Exception {

View File

@ -0,0 +1,31 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.sql.jdbc.framework;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.xpack.sql.util.CollectionUtils;
import java.util.Map;
import java.util.Map.Entry;
public abstract class JdbcTestUtils {
public static void sqlLogging() {
String t = "TRACE";
String d = "DEBUG";
Map<String, String> of = CollectionUtils.of("org.elasticsearch.xpack.sql.parser", t,
"org.elasticsearch.xpack.sql.analysis.analyzer", t,
"org.elasticsearch.xpack.sql.optimizer", t,
"org.elasticsearch.xpack.sql.rule", t,
"org.elasticsearch.xpack.sql.planner", t,
"org.elasticsearch.xpack.sql.execution.search", t);
for (Entry<String, String> entry : of.entrySet()) {
Loggers.setLevel(Loggers.getLogger(entry.getKey()), entry.getValue());
}
}
}

View File

@ -5,14 +5,11 @@
*/ */
package org.elasticsearch.xpack.sql.jdbc.framework; package org.elasticsearch.xpack.sql.jdbc.framework;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.common.Booleans; import org.elasticsearch.common.Booleans;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.PathUtils; import org.elasticsearch.common.io.PathUtils;
import org.junit.AfterClass;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
@ -46,21 +43,9 @@ public abstract class SpecBaseIntegrationTestCase extends JdbcIntegrationTestCas
loadDatasetIntoEs(); loadDatasetIntoEs();
} }
@AfterClass
public static void cleanupTestData() throws IOException {
try {
client().performRequest("DELETE", "/*");
} catch (ResponseException e) {
if (e.getResponse().getStatusLine().getStatusCode() != 404) {
// 404 means no indices which shouldn't cause a failure
throw e;
}
}
}
@Override @Override
protected boolean preserveIndicesUponCompletion() { protected boolean preserveIndicesUponCompletion() {
return true; return !SETUP_DATA;
} }
public SpecBaseIntegrationTestCase(String groupName, String testName, Integer lineNumber, Path source) { public SpecBaseIntegrationTestCase(String groupName, String testName, Integer lineNumber, Path source) {
@ -125,7 +110,7 @@ public abstract class SpecBaseIntegrationTestCase extends JdbcIntegrationTestCas
return pairs; return pairs;
} }
public interface Parser { public interface Parser {
Object parse(String line); Object parse(String line);
} }

View File

@ -3,33 +3,33 @@
// //
groupByOnText groupByOnText
SELECT gender g FROM "test_emp.emp" GROUP BY gender; SELECT gender g FROM "test_emp" GROUP BY gender;
groupByOnTextWithWhereClause groupByOnTextWithWhereClause
SELECT gender g FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY gender; SELECT gender g FROM "test_emp" WHERE emp_no < 10020 GROUP BY gender;
groupByOnTextWithWhereAndLimit groupByOnTextWithWhereAndLimit
SELECT gender g FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY gender LIMIT 1; SELECT gender g FROM "test_emp" WHERE emp_no < 10020 GROUP BY gender LIMIT 1;
groupByOnTextOnAlias groupByOnTextOnAlias
SELECT gender g FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY g; SELECT gender g FROM "test_emp" WHERE emp_no < 10020 GROUP BY g;
groupByOnTextOnAliasOrderDesc groupByOnTextOnAliasOrderDesc
SELECT gender g FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY g ORDER BY g DESC; SELECT gender g FROM "test_emp" WHERE emp_no < 10020 GROUP BY g ORDER BY g DESC;
groupByOnDate groupByOnDate
SELECT birth_date b FROM "test_emp.emp" GROUP BY birth_date ORDER BY birth_date DESC; SELECT birth_date b FROM "test_emp" GROUP BY birth_date ORDER BY birth_date DESC;
groupByOnDateWithWhereClause groupByOnDateWithWhereClause
SELECT birth_date b FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY birth_date ORDER BY birth_date DESC; SELECT birth_date b FROM "test_emp" WHERE emp_no < 10020 GROUP BY birth_date ORDER BY birth_date DESC;
groupByOnDateWithWhereAndLimit groupByOnDateWithWhereAndLimit
SELECT birth_date b FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY birth_date ORDER BY birth_date DESC LIMIT 1; SELECT birth_date b FROM "test_emp" WHERE emp_no < 10020 GROUP BY birth_date ORDER BY birth_date DESC LIMIT 1;
groupByOnDateOnAlias groupByOnDateOnAlias
SELECT birth_date b FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY b ORDER BY birth_date DESC; SELECT birth_date b FROM "test_emp" WHERE emp_no < 10020 GROUP BY b ORDER BY birth_date DESC;
groupByOnNumber groupByOnNumber
SELECT emp_no e FROM "test_emp.emp" GROUP BY emp_no ORDER BY emp_no DESC; SELECT emp_no e FROM "test_emp" GROUP BY emp_no ORDER BY emp_no DESC;
groupByOnNumberWithWhereClause groupByOnNumberWithWhereClause
SELECT emp_no e FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY emp_no ORDER BY emp_no DESC; SELECT emp_no e FROM "test_emp" WHERE emp_no < 10020 GROUP BY emp_no ORDER BY emp_no DESC;
groupByOnNumberWithWhereAndLimit groupByOnNumberWithWhereAndLimit
SELECT emp_no e FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY emp_no ORDER BY emp_no DESC LIMIT 1; SELECT emp_no e FROM "test_emp" WHERE emp_no < 10020 GROUP BY emp_no ORDER BY emp_no DESC LIMIT 1;
groupByOnNumberOnAlias groupByOnNumberOnAlias
SELECT emp_no e FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY e ORDER BY emp_no DESC; SELECT emp_no e FROM "test_emp" WHERE emp_no < 10020 GROUP BY e ORDER BY emp_no DESC;
// //
// Aggregate Functions // Aggregate Functions
@ -37,160 +37,160 @@ SELECT emp_no e FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY e ORDER BY emp
// COUNT // COUNT
aggCountImplicit aggCountImplicit
SELECT COUNT(*) c FROM "test_emp.emp"; SELECT COUNT(*) c FROM "test_emp";
aggCountImplicitWithCast aggCountImplicitWithCast
SELECT CAST(COUNT(*) AS INT) c FROM "test_emp.emp"; SELECT CAST(COUNT(*) AS INT) c FROM "test_emp";
aggCountImplicitWithConstant aggCountImplicitWithConstant
SELECT COUNT(1) FROM "test_emp.emp"; SELECT COUNT(1) FROM "test_emp";
aggCountImplicitWithConstantAndFilter aggCountImplicitWithConstantAndFilter
SELECT COUNT(1) FROM "test_emp.emp" WHERE emp_no < 10010; SELECT COUNT(1) FROM "test_emp" WHERE emp_no < 10010;
aggCountAliasAndWhereClause aggCountAliasAndWhereClause
SELECT gender g, COUNT(*) c FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY gender; SELECT gender g, COUNT(*) c FROM "test_emp" WHERE emp_no < 10020 GROUP BY gender;
aggCountAliasAndWhereClauseAndLimit aggCountAliasAndWhereClauseAndLimit
SELECT gender g, COUNT(*) c FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY gender LIMIT 1; SELECT gender g, COUNT(*) c FROM "test_emp" WHERE emp_no < 10020 GROUP BY gender LIMIT 1;
aggCountAliasWithCastAndFilter aggCountAliasWithCastAndFilter
SELECT gender g, CAST(COUNT(*) AS INT) c FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY gender; SELECT gender g, CAST(COUNT(*) AS INT) c FROM "test_emp" WHERE emp_no < 10020 GROUP BY gender;
aggCountWithAlias aggCountWithAlias
SELECT gender g, COUNT(*) c FROM "test_emp.emp" GROUP BY g; SELECT gender g, COUNT(*) c FROM "test_emp" GROUP BY g;
// Conditional COUNT // Conditional COUNT
aggCountAndHaving aggCountAndHaving
SELECT gender g, COUNT(*) c FROM "test_emp.emp" GROUP BY g HAVING COUNT(*) > 10; SELECT gender g, COUNT(*) c FROM "test_emp" GROUP BY g HAVING COUNT(*) > 10;
aggCountOnColumnAndHaving aggCountOnColumnAndHaving
SELECT gender g, COUNT(gender) c FROM "test_emp.emp" GROUP BY g HAVING COUNT(gender) > 10; SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING COUNT(gender) > 10;
// NOT supported yet since Having introduces a new agg // NOT supported yet since Having introduces a new agg
//aggCountOnColumnAndWildcardAndHaving //aggCountOnColumnAndWildcardAndHaving
//SELECT gender g, COUNT(*) c FROM "test_emp.emp" GROUP BY g HAVING COUNT(gender) > 10; //SELECT gender g, COUNT(*) c FROM "test_emp" GROUP BY g HAVING COUNT(gender) > 10;
aggCountAndHavingOnAlias aggCountAndHavingOnAlias
SELECT gender g, COUNT(*) c FROM "test_emp.emp" GROUP BY g HAVING c > 10; SELECT gender g, COUNT(*) c FROM "test_emp" GROUP BY g HAVING c > 10;
aggCountOnColumnAndHavingOnAlias aggCountOnColumnAndHavingOnAlias
SELECT gender g, COUNT(gender) c FROM "test_emp.emp" GROUP BY g HAVING c > 10; SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING c > 10;
aggCountOnColumnAndMultipleHaving aggCountOnColumnAndMultipleHaving
SELECT gender g, COUNT(gender) c FROM "test_emp.emp" GROUP BY g HAVING c > 10 AND c < 70; SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING c > 10 AND c < 70;
aggCountOnColumnAndMultipleHavingWithLimit aggCountOnColumnAndMultipleHavingWithLimit
SELECT gender g, COUNT(gender) c FROM "test_emp.emp" GROUP BY g HAVING c > 10 AND c < 70 LIMIT 1; SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING c > 10 AND c < 70 LIMIT 1;
aggCountOnColumnAndHavingOnAliasAndFunction aggCountOnColumnAndHavingOnAliasAndFunction
SELECT gender g, COUNT(gender) c FROM "test_emp.emp" GROUP BY g HAVING c > 10 AND COUNT(gender) < 70; SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING c > 10 AND COUNT(gender) < 70;
// NOT supported yet since Having introduces a new agg // NOT supported yet since Having introduces a new agg
//aggCountOnColumnAndHavingOnAliasAndFunctionWildcard -> COUNT(*/1) vs COUNT(gender) //aggCountOnColumnAndHavingOnAliasAndFunctionWildcard -> COUNT(*/1) vs COUNT(gender)
//SELECT gender g, COUNT(gender) c FROM "test_emp.emp" GROUP BY g HAVING c > 10 AND COUNT(*) < 70; //SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING c > 10 AND COUNT(*) < 70;
//aggCountOnColumnAndHavingOnAliasAndFunctionConstant //aggCountOnColumnAndHavingOnAliasAndFunctionConstant
//SELECT gender g, COUNT(gender) c FROM "test_emp.emp" GROUP BY g HAVING c > 10 AND COUNT(1) < 70; //SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING c > 10 AND COUNT(1) < 70;
// MIN // MIN
aggMinImplicit aggMinImplicit
SELECT MIN(emp_no) m FROM "test_emp.emp"; SELECT MIN(emp_no) m FROM "test_emp";
aggMinImplicitWithCast aggMinImplicitWithCast
SELECT CAST(MIN(emp_no) AS SMALLINT) m FROM "test_emp.emp"; SELECT CAST(MIN(emp_no) AS SMALLINT) m FROM "test_emp";
aggMin aggMin
SELECT gender g, MIN(emp_no) m FROM "test_emp.emp" GROUP BY gender; SELECT gender g, MIN(emp_no) m FROM "test_emp" GROUP BY gender;
aggMinWithCast aggMinWithCast
SELECT CAST(MIN(emp_no) AS SMALLINT) m FROM "test_emp.emp" GROUP BY gender; SELECT CAST(MIN(emp_no) AS SMALLINT) m FROM "test_emp" GROUP BY gender;
aggMinAndCount aggMinAndCount
SELECT MIN(emp_no) m, COUNT(1) c FROM "test_emp.emp" GROUP BY gender; SELECT MIN(emp_no) m, COUNT(1) c FROM "test_emp" GROUP BY gender;
aggMinAndCountWithFilter aggMinAndCountWithFilter
SELECT MIN(emp_no) m, COUNT(1) c FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY gender ; SELECT MIN(emp_no) m, COUNT(1) c FROM "test_emp" WHERE emp_no < 10020 GROUP BY gender ;
aggMinAndCountWithFilterAndLimit aggMinAndCountWithFilterAndLimit
SELECT MIN(emp_no) m, COUNT(1) c FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY gender LIMIT 1; SELECT MIN(emp_no) m, COUNT(1) c FROM "test_emp" WHERE emp_no < 10020 GROUP BY gender LIMIT 1;
aggMinWithCastAndFilter aggMinWithCastAndFilter
SELECT gender g, CAST(MIN(emp_no) AS SMALLINT) m, COUNT(1) c FROM "test_emp.emp" WHERE emp_no < 10020 GROUP BY gender; SELECT gender g, CAST(MIN(emp_no) AS SMALLINT) m, COUNT(1) c FROM "test_emp" WHERE emp_no < 10020 GROUP BY gender;
aggMinWithAlias aggMinWithAlias
SELECT gender g, MIN(emp_no) m FROM "test_emp.emp" GROUP BY g; SELECT gender g, MIN(emp_no) m FROM "test_emp" GROUP BY g;
// Conditional MIN // Conditional MIN
aggMinWithHaving aggMinWithHaving
SELECT gender g, MIN(emp_no) m FROM "test_emp.emp" GROUP BY g HAVING MIN(emp_no) > 10; SELECT gender g, MIN(emp_no) m FROM "test_emp" GROUP BY g HAVING MIN(emp_no) > 10;
aggMinWithHavingOnAlias aggMinWithHavingOnAlias
SELECT gender g, MIN(emp_no) m FROM "test_emp.emp" GROUP BY g HAVING m > 10; SELECT gender g, MIN(emp_no) m FROM "test_emp" GROUP BY g HAVING m > 10;
aggMinWithMultipleHaving aggMinWithMultipleHaving
SELECT gender g, MIN(emp_no) m FROM "test_emp.emp" GROUP BY g HAVING m > 10 AND m < 99999; SELECT gender g, MIN(emp_no) m FROM "test_emp" GROUP BY g HAVING m > 10 AND m < 99999;
aggMinWithMultipleHavingWithLimit aggMinWithMultipleHavingWithLimit
SELECT gender g, MIN(emp_no) m FROM "test_emp.emp" GROUP BY g HAVING m > 10 AND m < 99999 LIMIT 1; SELECT gender g, MIN(emp_no) m FROM "test_emp" GROUP BY g HAVING m > 10 AND m < 99999 LIMIT 1;
aggMinWithMultipleHavingOnAliasAndFunction aggMinWithMultipleHavingOnAliasAndFunction
SELECT gender g, MIN(emp_no) m FROM "test_emp.emp" GROUP BY g HAVING m > 10 AND MIN(emp_no) < 99999; SELECT gender g, MIN(emp_no) m FROM "test_emp" GROUP BY g HAVING m > 10 AND MIN(emp_no) < 99999;
// MAX // MAX
aggMaxImplicit aggMaxImplicit
SELECT MAX(emp_no) c FROM "test_emp.emp"; SELECT MAX(emp_no) c FROM "test_emp";
aggMaxImplicitWithCast aggMaxImplicitWithCast
SELECT CAST(MAX(emp_no) AS SMALLINT) c FROM "test_emp.emp"; SELECT CAST(MAX(emp_no) AS SMALLINT) c FROM "test_emp";
aggMax aggMax
SELECT gender g, MAX(emp_no) m FROM "test_emp.emp" GROUP BY gender ; SELECT gender g, MAX(emp_no) m FROM "test_emp" GROUP BY gender ;
aggMaxWithCast aggMaxWithCast
SELECT gender g, CAST(MAX(emp_no) AS SMALLINT) m FROM "test_emp.emp" GROUP BY gender ; SELECT gender g, CAST(MAX(emp_no) AS SMALLINT) m FROM "test_emp" GROUP BY gender ;
aggMaxAndCount aggMaxAndCount
SELECT MAX(emp_no) m, COUNT(1) c FROM "test_emp.emp" GROUP BY gender; SELECT MAX(emp_no) m, COUNT(1) c FROM "test_emp" GROUP BY gender;
aggMaxAndCountWithFilter aggMaxAndCountWithFilter
SELECT gender g, MAX(emp_no) m, COUNT(1) c FROM "test_emp.emp" WHERE emp_no > 10000 GROUP BY gender; SELECT gender g, MAX(emp_no) m, COUNT(1) c FROM "test_emp" WHERE emp_no > 10000 GROUP BY gender;
aggMaxAndCountWithFilterAndLimit aggMaxAndCountWithFilterAndLimit
SELECT gender g, MAX(emp_no) m, COUNT(1) c FROM "test_emp.emp" WHERE emp_no > 10000 GROUP BY gender LIMIT 1; SELECT gender g, MAX(emp_no) m, COUNT(1) c FROM "test_emp" WHERE emp_no > 10000 GROUP BY gender LIMIT 1;
aggMaxWithAlias aggMaxWithAlias
SELECT gender g, MAX(emp_no) m FROM "test_emp.emp" GROUP BY g; SELECT gender g, MAX(emp_no) m FROM "test_emp" GROUP BY g;
// Conditional MAX // Conditional MAX
aggMaxWithHaving aggMaxWithHaving
SELECT gender g, MAX(emp_no) m FROM "test_emp.emp" GROUP BY g HAVING MAX(emp_no) > 10; SELECT gender g, MAX(emp_no) m FROM "test_emp" GROUP BY g HAVING MAX(emp_no) > 10;
aggMaxWithHavingOnAlias aggMaxWithHavingOnAlias
SELECT gender g, MAX(emp_no) m FROM "test_emp.emp" GROUP BY g HAVING m > 10; SELECT gender g, MAX(emp_no) m FROM "test_emp" GROUP BY g HAVING m > 10;
aggMaxWithMultipleHaving aggMaxWithMultipleHaving
SELECT gender g, MAX(emp_no) m FROM "test_emp.emp" GROUP BY g HAVING m > 10 AND m < 99999; SELECT gender g, MAX(emp_no) m FROM "test_emp" GROUP BY g HAVING m > 10 AND m < 99999;
aggMaxWithMultipleHavingWithLimit aggMaxWithMultipleHavingWithLimit
SELECT gender g, MAX(emp_no) m FROM "test_emp.emp" GROUP BY g HAVING m > 10 AND m < 99999 LIMIT 1; SELECT gender g, MAX(emp_no) m FROM "test_emp" GROUP BY g HAVING m > 10 AND m < 99999 LIMIT 1;
aggMaxWithMultipleHavingOnAliasAndFunction aggMaxWithMultipleHavingOnAliasAndFunction
SELECT gender g, MAX(emp_no) m FROM "test_emp.emp" GROUP BY g HAVING m > 10 AND MAX(emp_no) < 99999; SELECT gender g, MAX(emp_no) m FROM "test_emp" GROUP BY g HAVING m > 10 AND MAX(emp_no) < 99999;
// SUM // SUM
aggSumImplicitWithCast aggSumImplicitWithCast
SELECT CAST(SUM(emp_no) AS BIGINT) s FROM "test_emp.emp"; SELECT CAST(SUM(emp_no) AS BIGINT) s FROM "test_emp";
aggSumWithCast aggSumWithCast
SELECT gender g, CAST(SUM(emp_no) AS BIGINT) s FROM "test_emp.emp" GROUP BY gender; SELECT gender g, CAST(SUM(emp_no) AS BIGINT) s FROM "test_emp" GROUP BY gender;
aggSumWithCastAndCount aggSumWithCastAndCount
SELECT gender g, CAST(SUM(emp_no) AS BIGINT) s, COUNT(1) c FROM "test_emp.emp" GROUP BY gender; SELECT gender g, CAST(SUM(emp_no) AS BIGINT) s, COUNT(1) c FROM "test_emp" GROUP BY gender;
aggSumWithCastAndCountWithFilter aggSumWithCastAndCountWithFilter
SELECT gender g, CAST(SUM(emp_no) AS BIGINT) s, COUNT(1) c FROM "test_emp.emp" WHERE emp_no > 10000 GROUP BY gender; SELECT gender g, CAST(SUM(emp_no) AS BIGINT) s, COUNT(1) c FROM "test_emp" WHERE emp_no > 10000 GROUP BY gender;
aggSumWithCastAndCountWithFilterAndLimit aggSumWithCastAndCountWithFilterAndLimit
SELECT gender g, CAST(SUM(emp_no) AS BIGINT) s, COUNT(1) c FROM "test_emp.emp" WHERE emp_no > 10000 GROUP BY gender LIMIT 1; SELECT gender g, CAST(SUM(emp_no) AS BIGINT) s, COUNT(1) c FROM "test_emp" WHERE emp_no > 10000 GROUP BY gender LIMIT 1;
aggSumWithAlias aggSumWithAlias
SELECT gender g, CAST(SUM(emp_no) AS BIGINT) s FROM "test_emp.emp" GROUP BY g; SELECT gender g, CAST(SUM(emp_no) AS BIGINT) s FROM "test_emp" GROUP BY g;
// Conditional SUM // Conditional SUM
aggSumWithHaving aggSumWithHaving
SELECT gender g, CAST(SUM(emp_no) AS INT) s FROM "test_emp.emp" GROUP BY g HAVING SUM(emp_no) > 10; SELECT gender g, CAST(SUM(emp_no) AS INT) s FROM "test_emp" GROUP BY g HAVING SUM(emp_no) > 10;
aggSumWithHavingOnAlias aggSumWithHavingOnAlias
SELECT gender g, CAST(SUM(emp_no) AS INT) s FROM "test_emp.emp" GROUP BY g HAVING s > 10; SELECT gender g, CAST(SUM(emp_no) AS INT) s FROM "test_emp" GROUP BY g HAVING s > 10;
aggSumWithMultipleHaving aggSumWithMultipleHaving
SELECT gender g, CAST(SUM(emp_no) AS INT) s FROM "test_emp.emp" GROUP BY g HAVING s > 10 AND s < 10000000; SELECT gender g, CAST(SUM(emp_no) AS INT) s FROM "test_emp" GROUP BY g HAVING s > 10 AND s < 10000000;
aggSumWithMultipleHavingWithLimit aggSumWithMultipleHavingWithLimit
SELECT gender g, CAST(SUM(emp_no) AS INT) s FROM "test_emp.emp" GROUP BY g HAVING s > 10 AND s < 10000000 LIMIT 1; SELECT gender g, CAST(SUM(emp_no) AS INT) s FROM "test_emp" GROUP BY g HAVING s > 10 AND s < 10000000 LIMIT 1;
aggSumWithMultipleHavingOnAliasAndFunction aggSumWithMultipleHavingOnAliasAndFunction
SELECT gender g, CAST(SUM(emp_no) AS INT) s FROM "test_emp.emp" GROUP BY g HAVING s > 10 AND SUM(emp_no) > 10000000; SELECT gender g, CAST(SUM(emp_no) AS INT) s FROM "test_emp" GROUP BY g HAVING s > 10 AND SUM(emp_no) > 10000000;
// AVG // AVG
aggAvgImplicitWithCast aggAvgImplicitWithCast
SELECT CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp.emp"; SELECT CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp";
aggAvgWithCastToFloat aggAvgWithCastToFloat
SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp.emp" GROUP BY gender; SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp" GROUP BY gender;
// casting to an exact type - varchar, bigint, etc... will likely fail due to rounding error // casting to an exact type - varchar, bigint, etc... will likely fail due to rounding error
aggAvgWithCastToDouble aggAvgWithCastToDouble
SELECT gender g, CAST(AVG(emp_no) AS DOUBLE) a FROM "test_emp.emp" GROUP BY gender; SELECT gender g, CAST(AVG(emp_no) AS DOUBLE) a FROM "test_emp" GROUP BY gender;
aggAvgWithCastAndCount aggAvgWithCastAndCount
SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a, COUNT(1) c FROM "test_emp.emp" GROUP BY gender; SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a, COUNT(1) c FROM "test_emp" GROUP BY gender;
aggAvgWithCastAndCountWithFilter aggAvgWithCastAndCountWithFilter
SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a, COUNT(1) c FROM "test_emp.emp" WHERE emp_no > 10000 GROUP BY gender ; SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a, COUNT(1) c FROM "test_emp" WHERE emp_no > 10000 GROUP BY gender ;
aggAvgWithCastAndCountWithFilterAndLimit aggAvgWithCastAndCountWithFilterAndLimit
SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a, COUNT(1) c FROM "test_emp.emp" WHERE emp_no > 10000 GROUP BY gender LIMIT 1; SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a, COUNT(1) c FROM "test_emp" WHERE emp_no > 10000 GROUP BY gender LIMIT 1;
aggAvgWithAlias aggAvgWithAlias
SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp.emp" GROUP BY g; SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp" GROUP BY g;
// Conditional AVG // Conditional AVG
aggAvgWithHaving aggAvgWithHaving
SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp.emp" GROUP BY g HAVING AVG(emp_no) > 10; SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp" GROUP BY g HAVING AVG(emp_no) > 10;
aggAvgWithHavingOnAlias aggAvgWithHavingOnAlias
SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp.emp" GROUP BY g HAVING a > 10; SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp" GROUP BY g HAVING a > 10;
aggAvgWithMultipleHaving aggAvgWithMultipleHaving
SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp.emp" GROUP BY g HAVING a > 10 AND a < 10000000; SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp" GROUP BY g HAVING a > 10 AND a < 10000000;
aggAvgWithMultipleHavingWithLimit aggAvgWithMultipleHavingWithLimit
SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp.emp" GROUP BY g HAVING a > 10 AND a < 10000000 LIMIT 1; SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp" GROUP BY g HAVING a > 10 AND a < 10000000 LIMIT 1;
aggAvgWithMultipleHavingOnAliasAndFunction aggAvgWithMultipleHavingOnAliasAndFunction
SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp.emp" GROUP BY g HAVING a > 10 AND AVG(emp_no) > 10000000; SELECT gender g, CAST(AVG(emp_no) AS FLOAT) a FROM "test_emp" GROUP BY g HAVING a > 10 AND AVG(emp_no) > 10000000;

View File

@ -108,7 +108,7 @@ test_emp |emp
// DESCRIBE // DESCRIBE
describe describe
DESCRIBE "test_emp.emp"; DESCRIBE "test_emp";
column | type column | type
birth_date |TIMESTAMP birth_date |TIMESTAMP

View File

@ -6,11 +6,11 @@
// Time // Time
// //
dateTimeSecond dateTimeSecond
SELECT SECOND(birth_date) d, last_name l FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT SECOND(birth_date) d, last_name l FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
dateTimeMinute dateTimeMinute
SELECT MINUTE(birth_date) d, last_name l FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT MINUTE(birth_date) d, last_name l FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
dateTimeHour dateTimeHour
SELECT HOUR(birth_date) d, last_name l FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT HOUR(birth_date) d, last_name l FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
// //
@ -18,17 +18,17 @@ SELECT HOUR(birth_date) d, last_name l FROM "test_emp.emp" WHERE emp_no < 10010
// //
dateTimeDay dateTimeDay
SELECT DAY(birth_date) d, last_name l FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT DAY(birth_date) d, last_name l FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
dateTimeDayOfMonth dateTimeDayOfMonth
SELECT DAY_OF_MONTH(birth_date) d, last_name l FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT DAY_OF_MONTH(birth_date) d, last_name l FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
// dateTimeDayOfWeek - disable since it starts at 0 not 1 // dateTimeDayOfWeek - disable since it starts at 0 not 1
// SELECT DAY_OF_WEEK(birth_date) d, last_name l FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; // SELECT DAY_OF_WEEK(birth_date) d, last_name l FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
dateTimeDayOfYear dateTimeDayOfYear
SELECT DAY_OF_YEAR(birth_date) d, last_name l FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT DAY_OF_YEAR(birth_date) d, last_name l FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
dateTimeMonth dateTimeMonth
SELECT MONTH(birth_date) d, last_name l FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT MONTH(birth_date) d, last_name l FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
dateTimeYear dateTimeYear
SELECT YEAR(birth_date) d, last_name l FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT YEAR(birth_date) d, last_name l FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
// NOCOMMIT figure out a way to test the aliases that are unsupported by h2 but are supported by us because they are like PostgreSQL // NOCOMMIT figure out a way to test the aliases that are unsupported by h2 but are supported by us because they are like PostgreSQL
@ -37,19 +37,19 @@ SELECT YEAR(birth_date) d, last_name l FROM "test_emp.emp" WHERE emp_no < 10010
// Filter // Filter
// //
dateTimeFilterDayOfMonth dateTimeFilterDayOfMonth
SELECT DAY_OF_MONTH(birth_date) AS d, last_name l FROM "test_emp.emp" WHERE DAY_OF_MONTH(birth_date) <= 10 ORDER BY emp_no LIMIT 5; SELECT DAY_OF_MONTH(birth_date) AS d, last_name l FROM "test_emp" WHERE DAY_OF_MONTH(birth_date) <= 10 ORDER BY emp_no LIMIT 5;
dateTimeFilterMonth dateTimeFilterMonth
SELECT MONTH(birth_date) AS d, last_name l FROM "test_emp.emp" WHERE MONTH(birth_date) <= 5 ORDER BY emp_no LIMIT 5; SELECT MONTH(birth_date) AS d, last_name l FROM "test_emp" WHERE MONTH(birth_date) <= 5 ORDER BY emp_no LIMIT 5;
dateTimeFilterYear dateTimeFilterYear
SELECT YEAR(birth_date) AS d, last_name l FROM "test_emp.emp" WHERE YEAR(birth_date) <= 1960 ORDER BY emp_no LIMIT 5; SELECT YEAR(birth_date) AS d, last_name l FROM "test_emp" WHERE YEAR(birth_date) <= 1960 ORDER BY emp_no LIMIT 5;
// //
// Aggregate // Aggregate
// //
dateTimeAggByYear dateTimeAggByYear
SELECT YEAR(birth_date) AS d, CAST(SUM(emp_no) AS INT) s FROM "test_emp.emp" GROUP BY YEAR(birth_date) ORDER BY YEAR(birth_date) LIMIT 5; SELECT YEAR(birth_date) AS d, CAST(SUM(emp_no) AS INT) s FROM "test_emp" GROUP BY YEAR(birth_date) ORDER BY YEAR(birth_date) LIMIT 5;
// NOCOMMIT Elasticsearch doesn't line up // NOCOMMIT Elasticsearch doesn't line up
// dateTimeAggByMonth // dateTimeAggByMonth
// SELECT MONTH(birth_date) AS d, CAST(SUM(emp_no) AS INT) s FROM "test_emp.emp" GROUP BY MONTH(birth_date) ORDER BY MONTH(birth_date) LIMIT 5; // SELECT MONTH(birth_date) AS d, CAST(SUM(emp_no) AS INT) s FROM "test_emp" GROUP BY MONTH(birth_date) ORDER BY MONTH(birth_date) LIMIT 5;
// dateTimeAggByDayOfMonth // dateTimeAggByDayOfMonth
// SELECT DAY_OF_MONTH(birth_date) AS d, CAST(SUM(emp_no) AS INT) s FROM "test_emp.emp" GROUP BY DAY_OF_MONTH(birth_date) ORDER BY DAY_OF_MONTH(birth_date) DESC; // SELECT DAY_OF_MONTH(birth_date) AS d, CAST(SUM(emp_no) AS INT) s FROM "test_emp" GROUP BY DAY_OF_MONTH(birth_date) ORDER BY DAY_OF_MONTH(birth_date) DESC;

View File

@ -4,7 +4,7 @@
name name
// ES SQL query // ES SQL query
SELECT COUNT(*) FROM "emp.emp"; SELECT COUNT(*) FROM "emp";
// //
// expected result in CSV format // expected result in CSV format

View File

@ -3,6 +3,6 @@
// name of the test - translated into 'testName' // name of the test - translated into 'testName'
name name
// SQL query to be executed against H2 and ES // SQL query to be executed against H2 and ES
SELECT COUNT(*) FROM "emp.emp"; SELECT COUNT(*) FROM "emp";
// repeat the above // repeat the above

View File

@ -3,18 +3,18 @@
// //
whereFieldQuality whereFieldQuality
SELECT last_name l FROM "test_emp.emp" WHERE emp_no = 10000 LIMIT 5; SELECT last_name l FROM "test_emp" WHERE emp_no = 10000 LIMIT 5;
whereFieldLessThan whereFieldLessThan
SELECT last_name l FROM "test_emp.emp" WHERE emp_no < 10003 ORDER BY emp_no LIMIT 5; SELECT last_name l FROM "test_emp" WHERE emp_no < 10003 ORDER BY emp_no LIMIT 5;
whereFieldAndComparison whereFieldAndComparison
SELECT last_name l FROM "test_emp.emp" WHERE emp_no > 10000 AND emp_no < 10005 ORDER BY emp_no LIMIT 5; SELECT last_name l FROM "test_emp" WHERE emp_no > 10000 AND emp_no < 10005 ORDER BY emp_no LIMIT 5;
whereFieldOrComparison whereFieldOrComparison
SELECT last_name l FROM "test_emp.emp" WHERE emp_no < 10003 OR emp_no = 10005 ORDER BY emp_no LIMIT 5; SELECT last_name l FROM "test_emp" WHERE emp_no < 10003 OR emp_no = 10005 ORDER BY emp_no LIMIT 5;
whereFieldWithOrder whereFieldWithOrder
SELECT last_name l FROM "test_emp.emp" WHERE emp_no < 10003 ORDER BY emp_no; SELECT last_name l FROM "test_emp" WHERE emp_no < 10003 ORDER BY emp_no;
whereFieldWithExactMatchOnString whereFieldWithExactMatchOnString
SELECT last_name l FROM "test_emp.emp" WHERE emp_no < 10003 AND gender = 'M'; SELECT last_name l FROM "test_emp" WHERE emp_no < 10003 AND gender = 'M';
whereFieldWithLikeMatch whereFieldWithLikeMatch
SELECT last_name l FROM "test_emp.emp" WHERE emp_no < 10003 AND last_name LIKE 'K%'; SELECT last_name l FROM "test_emp" WHERE emp_no < 10003 AND last_name LIKE 'K%';
whereFieldOnMatchWithAndAndOr whereFieldOnMatchWithAndAndOr
SELECT last_name l FROM "test_emp.emp" WHERE emp_no < 10003 AND (gender = 'M' AND NOT FALSE OR last_name LIKE 'K%') ORDER BY emp_no; SELECT last_name l FROM "test_emp" WHERE emp_no < 10003 AND (gender = 'M' AND NOT FALSE OR last_name LIKE 'K%') ORDER BY emp_no;

View File

@ -3,28 +3,28 @@
// //
simpleQueryAllFields simpleQueryAllFields
SELECT emp_no, first_name, gender, last_name FROM test_emp.emp WHERE QUERY('Baek fox') LIMIT 3; SELECT emp_no, first_name, gender, last_name FROM test_emp WHERE QUERY('Baek fox') LIMIT 3;
emp_no | first_name | gender | last_name emp_no | first_name | gender | last_name
10080 |Premal |M |Baek 10080 |Premal |M |Baek
; ;
simpleQueryDedicatedField simpleQueryDedicatedField
SELECT emp_no, first_name, gender, last_name FROM test_emp.emp WHERE QUERY('Man*', 'fields=last_name') LIMIT 5; SELECT emp_no, first_name, gender, last_name FROM test_emp WHERE QUERY('Man*', 'fields=last_name') LIMIT 5;
emp_no | first_name | gender | last_name emp_no | first_name | gender | last_name
10096 |Jayson |M |Mandell 10096 |Jayson |M |Mandell
; ;
matchQuery matchQuery
SELECT emp_no, first_name, gender, last_name FROM test_emp.emp WHERE MATCH(first_name, 'Erez'); SELECT emp_no, first_name, gender, last_name FROM test_emp WHERE MATCH(first_name, 'Erez');
emp_no | first_name | gender | last_name emp_no | first_name | gender | last_name
10076 |Erez |F |Ritzmann 10076 |Erez |F |Ritzmann
; ;
multiMatchQuery multiMatchQuery
SELECT emp_no, first_name, gender, last_name FROM test_emp.emp WHERE MATCH('first_name,last_name', 'Morton', 'type=best_fields;default_operator=OR'); SELECT emp_no, first_name, gender, last_name FROM test_emp WHERE MATCH('first_name,last_name', 'Morton', 'type=best_fields;default_operator=OR');
emp_no | first_name | gender | last_name emp_no | first_name | gender | last_name
10095 |Hilari |M |Morton 10095 |Hilari |M |Morton

View File

@ -3,73 +3,73 @@
// //
mathAbs mathAbs
SELECT ABS(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT ABS(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathACos mathACos
SELECT ACOS(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT ACOS(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathASin mathASin
SELECT ASIN(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT ASIN(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathATan mathATan
SELECT ATAN(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT ATAN(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
//mathCbrt //mathCbrt
//SELECT CBRT(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; //SELECT CBRT(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathCeil mathCeil
SELECT CEIL(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT CEIL(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathCos mathCos
SELECT COS(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT COS(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathCosh mathCosh
SELECT COSH(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT COSH(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathDegrees mathDegrees
SELECT DEGREES(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT DEGREES(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathFloor mathFloor
SELECT CAST(FLOOR(emp_no) AS INT) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT CAST(FLOOR(emp_no) AS INT) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathLog mathLog
SELECT LOG(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT LOG(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathLog10 mathLog10
SELECT LOG10(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT LOG10(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathRadians mathRadians
SELECT RADIANS(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT RADIANS(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathRound mathRound
SELECT CAST(ROUND(emp_no) AS INT) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT CAST(ROUND(emp_no) AS INT) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathSin mathSin
SELECT SIN(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT SIN(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathSinH mathSinH
SELECT SINH(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT SINH(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathSqrt mathSqrt
SELECT SQRT(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT SQRT(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathTan mathTan
SELECT TAN(emp_no) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT TAN(emp_no) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
// //
// Combined methods // Combined methods
// //
mathAbsOfSin mathAbsOfSin
SELECT ABS(SIN(emp_no)) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT ABS(SIN(emp_no)) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathAbsOfCeilOfSin mathAbsOfCeilOfSin
SELECT EXP(ABS(CEIL(SIN(DEGREES(emp_no))))) m, first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; SELECT EXP(ABS(CEIL(SIN(DEGREES(emp_no))))) m, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
mathAbsOfCeilOfSinWithFilter mathAbsOfCeilOfSinWithFilter
SELECT EXP(ABS(CEIL(SIN(DEGREES(emp_no))))) m, first_name FROM "test_emp.emp" WHERE EXP(ABS(CEIL(SIN(DEGREES(emp_no))))) < 10 ORDER BY emp_no; SELECT EXP(ABS(CEIL(SIN(DEGREES(emp_no))))) m, first_name FROM "test_emp" WHERE EXP(ABS(CEIL(SIN(DEGREES(emp_no))))) < 10 ORDER BY emp_no;
// //
// Filter by Scalar // Filter by Scalar
// //
mathAbsFilterAndOrder mathAbsFilterAndOrder
SELECT emp_no, ABS(emp_no) m, first_name FROM "test_emp.emp" WHERE ABS(emp_no) < 10010 ORDER BY ABS(emp_no); SELECT emp_no, ABS(emp_no) m, first_name FROM "test_emp" WHERE ABS(emp_no) < 10010 ORDER BY ABS(emp_no);
mathACosFilterAndOrder mathACosFilterAndOrder
SELECT emp_no, ACOS(emp_no) m, first_name FROM "test_emp.emp" WHERE ACOS(emp_no) < 10010 ORDER BY ACOS(emp_no); SELECT emp_no, ACOS(emp_no) m, first_name FROM "test_emp" WHERE ACOS(emp_no) < 10010 ORDER BY ACOS(emp_no);
mathASinFilterAndOrder mathASinFilterAndOrder
SELECT emp_no, ASIN(emp_no) m, first_name FROM "test_emp.emp" WHERE ASIN(emp_no) < 10010 ORDER BY ASIN(emp_no); SELECT emp_no, ASIN(emp_no) m, first_name FROM "test_emp" WHERE ASIN(emp_no) < 10010 ORDER BY ASIN(emp_no);
//mathATanFilterAndOrder //mathATanFilterAndOrder
//SELECT emp_no, ATAN(emp_no) m, first_name FROM "test_emp.emp" WHERE ATAN(emp_no) < 10010 ORDER BY ATAN(emp_no); //SELECT emp_no, ATAN(emp_no) m, first_name FROM "test_emp" WHERE ATAN(emp_no) < 10010 ORDER BY ATAN(emp_no);
mathCeilFilterAndOrder mathCeilFilterAndOrder
SELECT emp_no, CEIL(emp_no) m, first_name FROM "test_emp.emp" WHERE CEIL(emp_no) < 10010 ORDER BY CEIL(emp_no); SELECT emp_no, CEIL(emp_no) m, first_name FROM "test_emp" WHERE CEIL(emp_no) < 10010 ORDER BY CEIL(emp_no);
//mathCosFilterAndOrder //mathCosFilterAndOrder
//SELECT emp_no, COS(emp_no) m, first_name FROM "test_emp.emp" WHERE COS(emp_no) < 10010 ORDER BY COS(emp_no); //SELECT emp_no, COS(emp_no) m, first_name FROM "test_emp" WHERE COS(emp_no) < 10010 ORDER BY COS(emp_no);
//mathCoshFilterAndOrder //mathCoshFilterAndOrder
//SELECT emp_no, COSH(emp_no) m, first_name FROM "test_emp.emp" WHERE COSH(emp_no) < 10010 ORDER BY COSH(emp_no); //SELECT emp_no, COSH(emp_no) m, first_name FROM "test_emp" WHERE COSH(emp_no) < 10010 ORDER BY COSH(emp_no);
// //
// constants - added when folding will be supported // constants - added when folding will be supported
// //
//mathConstantPI //mathConstantPI
//SELECT ABS(emp_no) m, PI(), first_name FROM "test_emp.emp" WHERE emp_no < 10010 ORDER BY emp_no; //SELECT ABS(emp_no) m, PI(), first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;

View File

@ -3,36 +3,36 @@
// //
wildcardWithOrder wildcardWithOrder
SELECT * FROM "test_emp.emp" ORDER BY emp_no; SELECT * FROM "test_emp" ORDER BY emp_no;
column column
SELECT last_name FROM "test_emp.emp" ORDER BY emp_no; SELECT last_name FROM "test_emp" ORDER BY emp_no;
columnWithAlias columnWithAlias
SELECT last_name AS l FROM "test_emp.emp" ORDER BY emp_no; SELECT last_name AS l FROM "test_emp" ORDER BY emp_no;
columnWithAliasNoAs columnWithAliasNoAs
SELECT last_name l FROM "test_emp.emp" ORDER BY emp_no; SELECT last_name l FROM "test_emp" ORDER BY emp_no;
multipleColumnsNoAlias multipleColumnsNoAlias
SELECT first_name, last_name FROM "test_emp.emp" ORDER BY emp_no; SELECT first_name, last_name FROM "test_emp" ORDER BY emp_no;
multipleColumnWithAliasWithAndWithoutAs multipleColumnWithAliasWithAndWithoutAs
SELECT first_name f, last_name AS l FROM "test_emp.emp" ORDER BY emp_no; SELECT first_name f, last_name AS l FROM "test_emp" ORDER BY emp_no;
// //
// SELECT with LIMIT // SELECT with LIMIT
// //
wildcardWithLimit wildcardWithLimit
SELECT * FROM "test_emp.emp" ORDER BY emp_no LIMIT 5; SELECT * FROM "test_emp" ORDER BY emp_no LIMIT 5;
wildcardWithOrderWithLimit wildcardWithOrderWithLimit
SELECT * FROM "test_emp.emp" ORDER BY emp_no LIMIT 5; SELECT * FROM "test_emp" ORDER BY emp_no LIMIT 5;
columnWithLimit columnWithLimit
SELECT last_name FROM "test_emp.emp" ORDER BY emp_no LIMIT 5; SELECT last_name FROM "test_emp" ORDER BY emp_no LIMIT 5;
columnWithAliasWithLimit columnWithAliasWithLimit
SELECT last_name AS l FROM "test_emp.emp" ORDER BY emp_no LIMIT 5; SELECT last_name AS l FROM "test_emp" ORDER BY emp_no LIMIT 5;
columnWithAliasNoAsWithLimit columnWithAliasNoAsWithLimit
SELECT last_name l FROM "test_emp.emp" ORDER BY emp_no LIMIT 5; SELECT last_name l FROM "test_emp" ORDER BY emp_no LIMIT 5;
multipleColumnsNoAliasWithLimit multipleColumnsNoAliasWithLimit
SELECT first_name, last_name FROM "test_emp.emp" ORDER BY emp_no LIMIT 5; SELECT first_name, last_name FROM "test_emp" ORDER BY emp_no LIMIT 5;
multipleColumnWithAliasWithAndWithoutAsWithLimit multipleColumnWithAliasWithAndWithoutAsWithLimit
SELECT first_name f, last_name AS l FROM "test_emp.emp" ORDER BY emp_no LIMIT 5; SELECT first_name f, last_name AS l FROM "test_emp" ORDER BY emp_no LIMIT 5;
// //
@ -41,16 +41,16 @@ SELECT first_name f, last_name AS l FROM "test_emp.emp" ORDER BY emp_no LIMIT 5;
//castWithLiteralToInt //castWithLiteralToInt
//SELECT CAST(1 AS INT); //SELECT CAST(1 AS INT);
castOnColumnNumberToVarchar castOnColumnNumberToVarchar
SELECT CAST(emp_no AS VARCHAR) AS emp_no_cast FROM "test_emp.emp" ORDER BY emp_no LIMIT 5; SELECT CAST(emp_no AS VARCHAR) AS emp_no_cast FROM "test_emp" ORDER BY emp_no LIMIT 5;
castOnColumnNumberToLong castOnColumnNumberToLong
SELECT CAST(emp_no AS BIGINT) AS emp_no_cast FROM "test_emp.emp" ORDER BY emp_no LIMIT 5; SELECT CAST(emp_no AS BIGINT) AS emp_no_cast FROM "test_emp" ORDER BY emp_no LIMIT 5;
castOnColumnNumberToSmallint castOnColumnNumberToSmallint
SELECT CAST(emp_no AS SMALLINT) AS emp_no_cast FROM "test_emp.emp" ORDER BY emp_no LIMIT 5; SELECT CAST(emp_no AS SMALLINT) AS emp_no_cast FROM "test_emp" ORDER BY emp_no LIMIT 5;
castOnColumnNumberWithAliasToInt castOnColumnNumberWithAliasToInt
SELECT CAST(emp_no AS INT) AS emp_no_cast FROM "test_emp.emp" ORDER BY emp_no LIMIT 5; SELECT CAST(emp_no AS INT) AS emp_no_cast FROM "test_emp" ORDER BY emp_no LIMIT 5;
castOnColumnNumberToReal castOnColumnNumberToReal
SELECT CAST(emp_no AS REAL) AS emp_no_cast FROM "test_emp.emp" ORDER BY emp_no LIMIT 5; SELECT CAST(emp_no AS REAL) AS emp_no_cast FROM "test_emp" ORDER BY emp_no LIMIT 5;
castOnColumnNumberToDouble castOnColumnNumberToDouble
SELECT CAST(emp_no AS DOUBLE) AS emp_no_cast FROM "test_emp.emp" ORDER BY emp_no LIMIT 5; SELECT CAST(emp_no AS DOUBLE) AS emp_no_cast FROM "test_emp" ORDER BY emp_no LIMIT 5;
castOnColumnNumberToBoolean castOnColumnNumberToBoolean
SELECT CAST(emp_no AS BOOL) AS emp_no_cast FROM "test_emp.emp" ORDER BY emp_no LIMIT 5; SELECT CAST(emp_no AS BOOL) AS emp_no_cast FROM "test_emp" ORDER BY emp_no LIMIT 5;

View File

@ -1,5 +1,5 @@
DROP TABLE IF EXISTS "test_emp.emp"; DROP TABLE IF EXISTS "test_emp";
CREATE TABLE "test_emp.emp" ("birth_date" TIMESTAMP, CREATE TABLE "test_emp" ("birth_date" TIMESTAMP,
"emp_no" INT, "emp_no" INT,
"first_name" VARCHAR(50), "first_name" VARCHAR(50),
"gender" VARCHAR(1), "gender" VARCHAR(1),

View File

@ -51,7 +51,7 @@ statement
)* )*
')')? ')')?
statement #debug statement #debug
| SHOW TABLES ((FROM | IN) index=identifier)? (LIKE? pattern=STRING)? #showTables | SHOW TABLES (LIKE? pattern=STRING)? #showTables
| SHOW COLUMNS (FROM | IN) tableIdentifier #showColumns | SHOW COLUMNS (FROM | IN) tableIdentifier #showColumns
| (DESCRIBE | DESC) tableIdentifier #showColumns | (DESCRIBE | DESC) tableIdentifier #showColumns
| SHOW FUNCTIONS (LIKE? pattern=STRING)? #showFunctions | SHOW FUNCTIONS (LIKE? pattern=STRING)? #showFunctions
@ -232,8 +232,7 @@ qualifiedName
; ;
tableIdentifier tableIdentifier
: index=identifier ('.' type=identifier)? : index=identifier
| '"' uindex=unquoteIdentifier ('.' utype=unquoteIdentifier)? '"'
; ;
identifier identifier

View File

@ -2,204 +2,202 @@ T__0=1
T__1=2 T__1=2
T__2=3 T__2=3
T__3=4 T__3=4
T__4=5 SELECT=5
SELECT=6 FROM=6
FROM=7 AS=7
AS=8 ALL=8
ALL=9 WHEN=9
WHEN=10 THEN=10
THEN=11 ANY=11
ANY=12 DISTINCT=12
DISTINCT=13 WHERE=13
WHERE=14 GROUP=14
GROUP=15 BY=15
BY=16 GROUPING=16
GROUPING=17 SETS=17
SETS=18 ORDER=18
ORDER=19 HAVING=19
HAVING=20 LIMIT=20
LIMIT=21 OR=21
OR=22 AND=22
AND=23 IN=23
IN=24 NOT=24
NOT=25 NO=25
NO=26 EXISTS=26
EXISTS=27 BETWEEN=27
BETWEEN=28 LIKE=28
LIKE=29 RLIKE=29
RLIKE=30 IS=30
IS=31 NULL=31
NULL=32 TRUE=32
TRUE=33 FALSE=33
FALSE=34 LAST=34
LAST=35 ASC=35
ASC=36 DESC=36
DESC=37 FOR=37
FOR=38 INTEGER=38
INTEGER=39 JOIN=39
JOIN=40 CROSS=40
CROSS=41 OUTER=41
OUTER=42 INNER=42
INNER=43 LEFT=43
LEFT=44 RIGHT=44
RIGHT=45 FULL=45
FULL=46 NATURAL=46
NATURAL=47 USING=47
USING=48 ON=48
ON=49 WITH=49
WITH=50 TABLE=50
TABLE=51 INTO=51
INTO=52 DESCRIBE=52
DESCRIBE=53 OPTION=53
OPTION=54 EXPLAIN=54
EXPLAIN=55 ANALYZE=55
ANALYZE=56 FORMAT=56
FORMAT=57 TYPE=57
TYPE=58 TEXT=58
TEXT=59 VERIFY=59
VERIFY=60 GRAPHVIZ=60
GRAPHVIZ=61 LOGICAL=61
LOGICAL=62 PHYSICAL=62
PHYSICAL=63 SHOW=63
SHOW=64 TABLES=64
TABLES=65 COLUMNS=65
COLUMNS=66 COLUMN=66
COLUMN=67 FUNCTIONS=67
FUNCTIONS=68 TO=68
TO=69 DEBUG=69
DEBUG=70 PLAN=70
PLAN=71 PARSED=71
PARSED=72 ANALYZED=72
ANALYZED=73 OPTIMIZED=73
OPTIMIZED=74 MAPPED=74
MAPPED=75 EXECUTABLE=75
EXECUTABLE=76 USE=76
USE=77 SET=77
SET=78 RESET=78
RESET=79 SESSION=79
SESSION=80 SCHEMAS=80
SCHEMAS=81 EXTRACT=81
EXTRACT=82 QUERY=82
QUERY=83 MATCH=83
MATCH=84 CAST=84
CAST=85 EQ=85
EQ=86 NEQ=86
NEQ=87 LT=87
LT=88 LTE=88
LTE=89 GT=89
GT=90 GTE=90
GTE=91 PLUS=91
PLUS=92 MINUS=92
MINUS=93 ASTERISK=93
ASTERISK=94 SLASH=94
SLASH=95 PERCENT=95
PERCENT=96 CONCAT=96
CONCAT=97 STRING=97
STRING=98 INTEGER_VALUE=98
INTEGER_VALUE=99 DECIMAL_VALUE=99
DECIMAL_VALUE=100 IDENTIFIER=100
IDENTIFIER=101 DIGIT_IDENTIFIER=101
DIGIT_IDENTIFIER=102 QUOTED_IDENTIFIER=102
QUOTED_IDENTIFIER=103 BACKQUOTED_IDENTIFIER=103
BACKQUOTED_IDENTIFIER=104 SIMPLE_COMMENT=104
SIMPLE_COMMENT=105 BRACKETED_COMMENT=105
BRACKETED_COMMENT=106 WS=106
WS=107 UNRECOGNIZED=107
UNRECOGNIZED=108 DELIMITER=108
DELIMITER=109
'('=1 '('=1
')'=2 ')'=2
','=3 ','=3
'.'=4 '.'=4
'"'=5 'SELECT'=5
'SELECT'=6 'FROM'=6
'FROM'=7 'AS'=7
'AS'=8 'ALL'=8
'ALL'=9 'WHEN'=9
'WHEN'=10 'THEN'=10
'THEN'=11 'ANY'=11
'ANY'=12 'DISTINCT'=12
'DISTINCT'=13 'WHERE'=13
'WHERE'=14 'GROUP'=14
'GROUP'=15 'BY'=15
'BY'=16 'GROUPING'=16
'GROUPING'=17 'SETS'=17
'SETS'=18 'ORDER'=18
'ORDER'=19 'HAVING'=19
'HAVING'=20 'LIMIT'=20
'LIMIT'=21 'OR'=21
'OR'=22 'AND'=22
'AND'=23 'IN'=23
'IN'=24 'NOT'=24
'NOT'=25 'NO'=25
'NO'=26 'EXISTS'=26
'EXISTS'=27 'BETWEEN'=27
'BETWEEN'=28 'LIKE'=28
'LIKE'=29 'RLIKE'=29
'RLIKE'=30 'IS'=30
'IS'=31 'NULL'=31
'NULL'=32 'TRUE'=32
'TRUE'=33 'FALSE'=33
'FALSE'=34 'LAST'=34
'LAST'=35 'ASC'=35
'ASC'=36 'DESC'=36
'DESC'=37 'FOR'=37
'FOR'=38 'INTEGER'=38
'INTEGER'=39 'JOIN'=39
'JOIN'=40 'CROSS'=40
'CROSS'=41 'OUTER'=41
'OUTER'=42 'INNER'=42
'INNER'=43 'LEFT'=43
'LEFT'=44 'RIGHT'=44
'RIGHT'=45 'FULL'=45
'FULL'=46 'NATURAL'=46
'NATURAL'=47 'USING'=47
'USING'=48 'ON'=48
'ON'=49 'WITH'=49
'WITH'=50 'TABLE'=50
'TABLE'=51 'INTO'=51
'INTO'=52 'DESCRIBE'=52
'DESCRIBE'=53 'OPTION'=53
'OPTION'=54 'EXPLAIN'=54
'EXPLAIN'=55 'ANALYZE'=55
'ANALYZE'=56 'FORMAT'=56
'FORMAT'=57 'TYPE'=57
'TYPE'=58 'TEXT'=58
'TEXT'=59 'VERIFY'=59
'VERIFY'=60 'GRAPHVIZ'=60
'GRAPHVIZ'=61 'LOGICAL'=61
'LOGICAL'=62 'PHYSICAL'=62
'PHYSICAL'=63 'SHOW'=63
'SHOW'=64 'TABLES'=64
'TABLES'=65 'COLUMNS'=65
'COLUMNS'=66 'COLUMN'=66
'COLUMN'=67 'FUNCTIONS'=67
'FUNCTIONS'=68 'TO'=68
'TO'=69 'DEBUG'=69
'DEBUG'=70 'PLAN'=70
'PLAN'=71 'PARSED'=71
'PARSED'=72 'ANALYZED'=72
'ANALYZED'=73 'OPTIMIZED'=73
'OPTIMIZED'=74 'MAPPED'=74
'MAPPED'=75 'EXECUTABLE'=75
'EXECUTABLE'=76 'USE'=76
'USE'=77 'SET'=77
'SET'=78 'RESET'=78
'RESET'=79 'SESSION'=79
'SESSION'=80 'SCHEMAS'=80
'SCHEMAS'=81 'EXTRACT'=81
'EXTRACT'=82 'QUERY'=82
'QUERY'=83 'MATCH'=83
'MATCH'=84 'CAST'=84
'CAST'=85 '='=85
'='=86 '<'=87
'<'=88 '<='=88
'<='=89 '>'=89
'>'=90 '>='=90
'>='=91 '+'=91
'+'=92 '-'=92
'-'=93 '*'=93
'*'=94 '/'=94
'/'=95 '%'=95
'%'=96 '||'=96
'||'=97

View File

@ -2,203 +2,201 @@ T__0=1
T__1=2 T__1=2
T__2=3 T__2=3
T__3=4 T__3=4
T__4=5 SELECT=5
SELECT=6 FROM=6
FROM=7 AS=7
AS=8 ALL=8
ALL=9 WHEN=9
WHEN=10 THEN=10
THEN=11 ANY=11
ANY=12 DISTINCT=12
DISTINCT=13 WHERE=13
WHERE=14 GROUP=14
GROUP=15 BY=15
BY=16 GROUPING=16
GROUPING=17 SETS=17
SETS=18 ORDER=18
ORDER=19 HAVING=19
HAVING=20 LIMIT=20
LIMIT=21 OR=21
OR=22 AND=22
AND=23 IN=23
IN=24 NOT=24
NOT=25 NO=25
NO=26 EXISTS=26
EXISTS=27 BETWEEN=27
BETWEEN=28 LIKE=28
LIKE=29 RLIKE=29
RLIKE=30 IS=30
IS=31 NULL=31
NULL=32 TRUE=32
TRUE=33 FALSE=33
FALSE=34 LAST=34
LAST=35 ASC=35
ASC=36 DESC=36
DESC=37 FOR=37
FOR=38 INTEGER=38
INTEGER=39 JOIN=39
JOIN=40 CROSS=40
CROSS=41 OUTER=41
OUTER=42 INNER=42
INNER=43 LEFT=43
LEFT=44 RIGHT=44
RIGHT=45 FULL=45
FULL=46 NATURAL=46
NATURAL=47 USING=47
USING=48 ON=48
ON=49 WITH=49
WITH=50 TABLE=50
TABLE=51 INTO=51
INTO=52 DESCRIBE=52
DESCRIBE=53 OPTION=53
OPTION=54 EXPLAIN=54
EXPLAIN=55 ANALYZE=55
ANALYZE=56 FORMAT=56
FORMAT=57 TYPE=57
TYPE=58 TEXT=58
TEXT=59 VERIFY=59
VERIFY=60 GRAPHVIZ=60
GRAPHVIZ=61 LOGICAL=61
LOGICAL=62 PHYSICAL=62
PHYSICAL=63 SHOW=63
SHOW=64 TABLES=64
TABLES=65 COLUMNS=65
COLUMNS=66 COLUMN=66
COLUMN=67 FUNCTIONS=67
FUNCTIONS=68 TO=68
TO=69 DEBUG=69
DEBUG=70 PLAN=70
PLAN=71 PARSED=71
PARSED=72 ANALYZED=72
ANALYZED=73 OPTIMIZED=73
OPTIMIZED=74 MAPPED=74
MAPPED=75 EXECUTABLE=75
EXECUTABLE=76 USE=76
USE=77 SET=77
SET=78 RESET=78
RESET=79 SESSION=79
SESSION=80 SCHEMAS=80
SCHEMAS=81 EXTRACT=81
EXTRACT=82 QUERY=82
QUERY=83 MATCH=83
MATCH=84 CAST=84
CAST=85 EQ=85
EQ=86 NEQ=86
NEQ=87 LT=87
LT=88 LTE=88
LTE=89 GT=89
GT=90 GTE=90
GTE=91 PLUS=91
PLUS=92 MINUS=92
MINUS=93 ASTERISK=93
ASTERISK=94 SLASH=94
SLASH=95 PERCENT=95
PERCENT=96 CONCAT=96
CONCAT=97 STRING=97
STRING=98 INTEGER_VALUE=98
INTEGER_VALUE=99 DECIMAL_VALUE=99
DECIMAL_VALUE=100 IDENTIFIER=100
IDENTIFIER=101 DIGIT_IDENTIFIER=101
DIGIT_IDENTIFIER=102 QUOTED_IDENTIFIER=102
QUOTED_IDENTIFIER=103 BACKQUOTED_IDENTIFIER=103
BACKQUOTED_IDENTIFIER=104 SIMPLE_COMMENT=104
SIMPLE_COMMENT=105 BRACKETED_COMMENT=105
BRACKETED_COMMENT=106 WS=106
WS=107 UNRECOGNIZED=107
UNRECOGNIZED=108
'('=1 '('=1
')'=2 ')'=2
','=3 ','=3
'.'=4 '.'=4
'"'=5 'SELECT'=5
'SELECT'=6 'FROM'=6
'FROM'=7 'AS'=7
'AS'=8 'ALL'=8
'ALL'=9 'WHEN'=9
'WHEN'=10 'THEN'=10
'THEN'=11 'ANY'=11
'ANY'=12 'DISTINCT'=12
'DISTINCT'=13 'WHERE'=13
'WHERE'=14 'GROUP'=14
'GROUP'=15 'BY'=15
'BY'=16 'GROUPING'=16
'GROUPING'=17 'SETS'=17
'SETS'=18 'ORDER'=18
'ORDER'=19 'HAVING'=19
'HAVING'=20 'LIMIT'=20
'LIMIT'=21 'OR'=21
'OR'=22 'AND'=22
'AND'=23 'IN'=23
'IN'=24 'NOT'=24
'NOT'=25 'NO'=25
'NO'=26 'EXISTS'=26
'EXISTS'=27 'BETWEEN'=27
'BETWEEN'=28 'LIKE'=28
'LIKE'=29 'RLIKE'=29
'RLIKE'=30 'IS'=30
'IS'=31 'NULL'=31
'NULL'=32 'TRUE'=32
'TRUE'=33 'FALSE'=33
'FALSE'=34 'LAST'=34
'LAST'=35 'ASC'=35
'ASC'=36 'DESC'=36
'DESC'=37 'FOR'=37
'FOR'=38 'INTEGER'=38
'INTEGER'=39 'JOIN'=39
'JOIN'=40 'CROSS'=40
'CROSS'=41 'OUTER'=41
'OUTER'=42 'INNER'=42
'INNER'=43 'LEFT'=43
'LEFT'=44 'RIGHT'=44
'RIGHT'=45 'FULL'=45
'FULL'=46 'NATURAL'=46
'NATURAL'=47 'USING'=47
'USING'=48 'ON'=48
'ON'=49 'WITH'=49
'WITH'=50 'TABLE'=50
'TABLE'=51 'INTO'=51
'INTO'=52 'DESCRIBE'=52
'DESCRIBE'=53 'OPTION'=53
'OPTION'=54 'EXPLAIN'=54
'EXPLAIN'=55 'ANALYZE'=55
'ANALYZE'=56 'FORMAT'=56
'FORMAT'=57 'TYPE'=57
'TYPE'=58 'TEXT'=58
'TEXT'=59 'VERIFY'=59
'VERIFY'=60 'GRAPHVIZ'=60
'GRAPHVIZ'=61 'LOGICAL'=61
'LOGICAL'=62 'PHYSICAL'=62
'PHYSICAL'=63 'SHOW'=63
'SHOW'=64 'TABLES'=64
'TABLES'=65 'COLUMNS'=65
'COLUMNS'=66 'COLUMN'=66
'COLUMN'=67 'FUNCTIONS'=67
'FUNCTIONS'=68 'TO'=68
'TO'=69 'DEBUG'=69
'DEBUG'=70 'PLAN'=70
'PLAN'=71 'PARSED'=71
'PARSED'=72 'ANALYZED'=72
'ANALYZED'=73 'OPTIMIZED'=73
'OPTIMIZED'=74 'MAPPED'=74
'MAPPED'=75 'EXECUTABLE'=75
'EXECUTABLE'=76 'USE'=76
'USE'=77 'SET'=77
'SET'=78 'RESET'=78
'RESET'=79 'SESSION'=79
'SESSION'=80 'SCHEMAS'=80
'SCHEMAS'=81 'EXTRACT'=81
'EXTRACT'=82 'QUERY'=82
'QUERY'=83 'MATCH'=83
'MATCH'=84 'CAST'=84
'CAST'=85 '='=85
'='=86 '<'=87
'<'=88 '<='=88
'<='=89 '>'=89
'>'=90 '>='=90
'>='=91 '+'=91
'+'=92 '-'=92
'-'=93 '*'=93
'*'=94 '/'=94
'/'=95 '%'=95
'%'=96 '||'=96
'||'=97

View File

@ -7,9 +7,9 @@ package org.elasticsearch.xpack.sql.analysis;
import org.elasticsearch.xpack.sql.tree.Node; import org.elasticsearch.xpack.sql.tree.Node;
public class UnknownTypeException extends AnalysisException { public class InvalidIndexException extends AnalysisException {
public UnknownTypeException(String index, String type, Node<?> source) { public InvalidIndexException(String index, Node<?> source) {
super(source, "Cannot resolve type %s in index %s", type, index); super(source, "Invalid index %s; contains more than one type", index);
} }
} }

View File

@ -6,9 +6,9 @@
package org.elasticsearch.xpack.sql.analysis.analyzer; package org.elasticsearch.xpack.sql.analysis.analyzer;
import org.elasticsearch.xpack.sql.analysis.AnalysisException; import org.elasticsearch.xpack.sql.analysis.AnalysisException;
import org.elasticsearch.xpack.sql.analysis.InvalidIndexException;
import org.elasticsearch.xpack.sql.analysis.UnknownFunctionException; import org.elasticsearch.xpack.sql.analysis.UnknownFunctionException;
import org.elasticsearch.xpack.sql.analysis.UnknownIndexException; import org.elasticsearch.xpack.sql.analysis.UnknownIndexException;
import org.elasticsearch.xpack.sql.analysis.UnknownTypeException;
import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier.Failure; import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier.Failure;
import org.elasticsearch.xpack.sql.analysis.catalog.Catalog; import org.elasticsearch.xpack.sql.analysis.catalog.Catalog;
import org.elasticsearch.xpack.sql.capabilities.Resolvables; import org.elasticsearch.xpack.sql.capabilities.Resolvables;
@ -217,7 +217,7 @@ public class Analyzer extends RuleExecutor<LogicalPlan> {
private LogicalPlan substituteCTE(LogicalPlan p, Map<String, SubQueryAlias> subQueries) { private LogicalPlan substituteCTE(LogicalPlan p, Map<String, SubQueryAlias> subQueries) {
if (p instanceof UnresolvedRelation) { if (p instanceof UnresolvedRelation) {
UnresolvedRelation ur = (UnresolvedRelation) p; UnresolvedRelation ur = (UnresolvedRelation) p;
SubQueryAlias subQueryAlias = subQueries.get(ur.table().type()); SubQueryAlias subQueryAlias = subQueries.get(ur.table().index());
if (subQueryAlias != null) { if (subQueryAlias != null) {
if (ur.alias() != null) { if (ur.alias() != null) {
return new SubQueryAlias(ur.location(), subQueryAlias, ur.alias()); return new SubQueryAlias(ur.location(), subQueryAlias, ur.alias());
@ -245,14 +245,13 @@ public class Analyzer extends RuleExecutor<LogicalPlan> {
if (!catalog.indexExists(index)) { if (!catalog.indexExists(index)) {
throw new UnknownIndexException(index, plan); throw new UnknownIndexException(index, plan);
} }
String type = table.type(); if (!catalog.indexIsValid(index)) {
if (!catalog.typeExists(index, type)) { throw new InvalidIndexException(index, plan);
throw new UnknownTypeException(index, type, plan);
} }
LogicalPlan catalogTable = new CatalogTable(plan.location(), catalog.getType(index, type)); LogicalPlan catalogTable = new CatalogTable(plan.location(), catalog.getIndex(index));
SubQueryAlias sa = new SubQueryAlias(plan.location(), catalogTable, type); SubQueryAlias sa = new SubQueryAlias(plan.location(), catalogTable, index);
if (plan.alias() != null) { if (plan.alias() != null) {
sa = new SubQueryAlias(plan.location(), sa, plan.alias()); sa = new SubQueryAlias(plan.location(), sa, plan.alias());

View File

@ -9,21 +9,14 @@ import java.util.List;
public interface Catalog { public interface Catalog {
// NOCOMMIT make sure we need all of these methods....
EsIndex getIndex(String index);
boolean indexExists(String index); boolean indexExists(String index);
boolean indexIsValid(String index);
EsIndex getIndex(String index);
List<EsIndex> listIndices(); List<EsIndex> listIndices();
List<EsIndex> listIndices(String pattern); List<EsIndex> listIndices(String pattern);
EsType getType(String index, String type);
boolean typeExists(String index, String type);
List<EsType> listTypes(String index);
List<EsType> listTypes(String index, String pattern);
} }

View File

@ -9,9 +9,7 @@ import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.Strings;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
@ -20,8 +18,6 @@ import java.util.function.Supplier;
public class EsCatalog implements Catalog { public class EsCatalog implements Catalog {
private static final String WILDCARD = "*";
private final Supplier<ClusterState> clusterState; private final Supplier<ClusterState> clusterState;
private IndexNameExpressionResolver indexNameExpressionResolver; private IndexNameExpressionResolver indexNameExpressionResolver;
@ -48,8 +44,14 @@ public class EsCatalog implements Catalog {
@Override @Override
public boolean indexExists(String index) { public boolean indexExists(String index) {
MetaData meta = metadata(); IndexMetaData idx = metadata().index(index);
return meta.hasIndex(index); return idx != null;
}
@Override
public boolean indexIsValid(String index) {
IndexMetaData idx = metadata().index(index);
return idx != null && indexHasOnlyOneType(idx);
} }
@Override @Override
@ -68,62 +70,27 @@ public class EsCatalog implements Catalog {
String[] indexNames = resolveIndex(pattern); String[] indexNames = resolveIndex(pattern);
List<IndexMetaData> indices = new ArrayList<>(indexNames.length); List<IndexMetaData> indices = new ArrayList<>(indexNames.length);
for (String indexName : indexNames) { for (String indexName : indexNames) {
indices.add(md.index(indexName)); indices.add(md.index(indexName));
} }
indexMetadata = indices.iterator(); indexMetadata = indices.iterator();
} }
return EsIndex.build(indexMetadata); List<EsIndex> list = new ArrayList<>();
} // filter unsupported (indices with more than one type) indices
while (indexMetadata.hasNext()) {
@Override IndexMetaData imd = indexMetadata.next();
public EsType getType(String index, String type) { if (indexHasOnlyOneType(imd)) {
if (!indexExists(index)) { list.add(EsIndex.build(imd));
return EsType.NOT_FOUND;
}
// NOCOMMIT verify that this works if the index isn't on the node
MappingMetaData mapping = metadata().index(index).mapping(type);
if (mapping == null) {
return EsType.NOT_FOUND;
}
return EsType.build(index, type, mapping);
}
@Override
public boolean typeExists(String index, String type) {
return indexExists(index) && metadata().index(index).getMappings().containsKey(type);
}
@Override
public List<EsType> listTypes(String index) {
return listTypes(index, null);
}
@Override
public List<EsType> listTypes(String indexPattern, String pattern) {
if (!Strings.hasText(indexPattern)) {
indexPattern = WILDCARD;
}
String[] iName = indexNameExpressionResolver.concreteIndexNames(clusterState.get(), IndicesOptions.strictExpandOpenAndForbidClosed(), indexPattern);
List<EsType> types = new ArrayList<>();
for (String cIndex : iName) {
IndexMetaData imd = metadata().index(cIndex);
if (Strings.hasText(pattern)) {
types.add(EsType.build(cIndex, pattern, imd.mapping(pattern)));
}
else {
types.addAll(EsType.build(cIndex, imd.getMappings()));
} }
} }
return types; return list;
} }
private boolean indexHasOnlyOneType(IndexMetaData index) {
return index.getMappings().size() <= 1;
}
private String[] resolveIndex(String pattern) { private String[] resolveIndex(String pattern) {
return indexNameExpressionResolver.concreteIndexNames(clusterState.get(), IndicesOptions.strictExpandOpenAndForbidClosed(), pattern); return indexNameExpressionResolver.concreteIndexNames(clusterState.get(), IndicesOptions.strictExpandOpenAndForbidClosed(), pattern);
} }

View File

@ -5,29 +5,36 @@
*/ */
package org.elasticsearch.xpack.sql.analysis.catalog; package org.elasticsearch.xpack.sql.analysis.catalog;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.collect.ImmutableOpenMap;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
import org.elasticsearch.xpack.sql.type.DataType;
import org.elasticsearch.xpack.sql.type.Types;
import org.elasticsearch.xpack.sql.util.StringUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.settings.Settings;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
public class EsIndex { public class EsIndex {
public static final EsIndex NOT_FOUND = new EsIndex("", emptyList(), emptyList(), Settings.EMPTY); public static final EsIndex NOT_FOUND = new EsIndex(StringUtils.EMPTY, emptyMap(), emptyList(), Settings.EMPTY);
private final String name; private final String name;
private final List<String> types; private final Map<String, DataType> mapping;
private final List<String> aliases; private final List<String> aliases;
private final Settings settings; private final Settings settings;
public EsIndex(String name, List<String> types, List<String> aliases, Settings settings) { public EsIndex(String name, Map<String, DataType> mapping, List<String> aliases, Settings settings) {
this.name = name; this.name = name;
this.types = types; this.mapping = mapping;
this.aliases = aliases; this.aliases = aliases;
this.settings = settings; this.settings = settings;
} }
@ -36,17 +43,14 @@ public class EsIndex {
return name; return name;
} }
public Map<String, DataType> mapping() {
public List<String> types() { return mapping;
return types;
} }
public List<String> aliases() { public List<String> aliases() {
return aliases; return aliases;
} }
public Settings settings() { public Settings settings() {
return settings; return settings;
} }
@ -57,14 +61,25 @@ public class EsIndex {
} }
List<EsIndex> list = new ArrayList<>(); List<EsIndex> list = new ArrayList<>();
while (metadata.hasNext()) { while (metadata.hasNext()) {
list.add(build(metadata.next())); build(metadata.next());
} }
return list; return list;
} }
static EsIndex build(IndexMetaData metadata) { static EsIndex build(IndexMetaData metadata) {
List<String> types = Arrays.asList(metadata.getMappings().keys().toArray(String.class)); ImmutableOpenMap<String, MappingMetaData> mappings = metadata.getMappings();
if (mappings.size() > 1) {
throw new SqlIllegalArgumentException("Cannot use index [%s] as it contains multiple types %s", metadata.getIndex().getName(), Arrays.toString(mappings.keys().toArray()));
}
MappingMetaData mm = mappings.isEmpty() ? null : mappings.valuesIt().next();
Map<String, DataType> mapping = mm != null ? Types.fromEs(mm.sourceAsMap()) : emptyMap();
List<String> aliases = Arrays.asList(metadata.getAliases().keys().toArray(String.class)); List<String> aliases = Arrays.asList(metadata.getAliases().keys().toArray(String.class));
return new EsIndex(metadata.getIndex().getName(), types, aliases, metadata.getSettings()); return new EsIndex(metadata.getIndex().getName(), mapping, aliases, metadata.getSettings());
}
@Override
public String toString() {
return name;
} }
} }

View File

@ -1,73 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.sql.analysis.catalog;
import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.collect.ImmutableOpenMap;
import org.elasticsearch.xpack.sql.type.DataType;
import org.elasticsearch.xpack.sql.type.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class EsType {
public static final EsType NOT_FOUND = new EsType("", "", Collections.emptyMap());
private final String index;
private final String name;
private final Map<String, DataType> mapping;
public EsType(String index, String name, Map<String, DataType> mapping) {
this.index = index;
this.name = name;
this.mapping = mapping;
}
public String index() {
return index;
}
public String name() {
return name;
}
public Map<String, DataType> mapping() {
return mapping;
}
static EsType build(String index, String type, MappingMetaData metaData) {
Map<String, Object> asMap = metaData.sourceAsMap();
Map<String, DataType> mapping = Types.fromEs(asMap);
return new EsType(index, type, mapping);
}
static Collection<EsType> build(String index, ImmutableOpenMap<String, MappingMetaData> mapping) {
List<EsType> tps = new ArrayList<>();
for (ObjectObjectCursor<String, MappingMetaData> entry : mapping) {
tps.add(build(index, entry.key, entry.value));
}
return tps;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("index=");
sb.append(index);
sb.append(",type=");
sb.append(name);
return sb.toString();
}
}

View File

@ -1,108 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.sql.analysis.catalog;
import org.elasticsearch.xpack.sql.util.StringUtils;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toList;
public abstract class InMemoryCatalog implements Catalog {
protected final Map<String, EsIndex> indices = new LinkedHashMap<>();
protected final Map<String, Map<String, EsType>> types = new LinkedHashMap<>();
{
List<EsIndex> idxs = indices();
for (EsIndex esIndex : idxs) {
indices.put(esIndex.name(), esIndex);
types.put(esIndex.name(), new LinkedHashMap<>());
}
List<EsType> tps = types();
for (EsType esType : tps) {
Map<String, EsType> idxTypes = types.get(esType.index());
idxTypes.put(esType.name(), esType);
}
}
@Override
public EsIndex getIndex(String index) {
EsIndex idx = indices.get(index);
return (idx == null ? EsIndex.NOT_FOUND : idx);
}
@Override
public boolean indexExists(String index) {
return indices.containsKey(index);
}
@Override
public List<EsIndex> listIndices() {
return new ArrayList<>(indices.values());
}
@Override
public List<EsIndex> listIndices(String pattern) {
Pattern p = StringUtils.likeRegex(pattern);
return indices.entrySet().stream()
.filter(e -> p.matcher(e.getKey()).matches())
.map(Map.Entry::getValue)
.collect(Collectors.toList());
}
@Override
public EsType getType(String index, String type) {
Map<String, EsType> typs = types.get(index);
if (typs == null) {
return EsType.NOT_FOUND;
}
EsType esType = typs.get(type);
return (esType == null ? EsType.NOT_FOUND : esType);
}
@Override
public boolean typeExists(String index, String type) {
Map<String, EsType> typs = types.get(index);
return (typs != null && typs.containsKey(type));
}
@Override
public List<EsType> listTypes(String index) {
Map<String, EsType> typs = types.get(index);
return typs != null ? new ArrayList<>(typs.values()) : emptyList();
}
@Override
public List<EsType> listTypes(String index, String pattern) {
Map<String, EsType> typs = types.get(index);
if (typs == null) {
return emptyList();
}
Pattern p = StringUtils.likeRegex(pattern);
return typs.entrySet().stream()
.filter(e -> p.matcher(e.getKey()).matches())
.map(Map.Entry::getValue)
.collect(toList());
}
public void clear() {
indices.clear();
types.clear();
}
protected abstract List<EsIndex> indices();
protected abstract List<EsType> types();
}

View File

@ -64,13 +64,13 @@ public class Scroller {
this.size = size; this.size = size;
} }
public void scroll(Schema schema, QueryContainer query, String index, String type, ActionListener<RowSetCursor> listener) { public void scroll(Schema schema, QueryContainer query, String index, ActionListener<RowSetCursor> listener) {
// prepare the request // prepare the request
SearchSourceBuilder sourceBuilder = SourceGenerator.sourceBuilder(query); SearchSourceBuilder sourceBuilder = SourceGenerator.sourceBuilder(query);
log.trace("About to execute query {}", sourceBuilder); log.trace("About to execute query {} on {}", sourceBuilder, index);
SearchRequest search = client.prepareSearch(index).setTypes(type).setSource(sourceBuilder).request(); SearchRequest search = client.prepareSearch(index).setSource(sourceBuilder).request();
search.scroll(keepAlive).source().timeout(timeout); search.scroll(keepAlive).source().timeout(timeout);
// set the size only if it hasn't been specified (aggs only queries set the size to 0) // set the size only if it hasn't been specified (aggs only queries set the size to 0)
@ -280,7 +280,7 @@ public class Scroller {
// is all the content already retrieved? // is all the content already retrieved?
if (Boolean.TRUE.equals(response.isTerminatedEarly()) || response.getHits().getTotalHits() == hits.length if (Boolean.TRUE.equals(response.isTerminatedEarly()) || response.getHits().getTotalHits() == hits.length
// or maybe the limit has been reached // or maybe the limit has been reached
|| docsRead >= limit) { || (docsRead >= limit && limit > -1)) {
// if so, clear the scroll // if so, clear the scroll
clearScroll(scrollId); clearScroll(scrollId);
// and remove it to indicate no more data is expected // and remove it to indicate no more data is expected

View File

@ -155,7 +155,7 @@ abstract class AbstractFunctionRegistry implements FunctionRegistry {
if (timezoneAware) { if (timezoneAware) {
args.add(settings.timeZone()); args.add(settings.timeZone());
} }
} }
return (Function) info.ctr.newInstance(args.toArray()); return (Function) info.ctr.newInstance(args.toArray());
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
throw new SqlIllegalArgumentException(ex, "Cannot create instance of function %s", ur.name()); throw new SqlIllegalArgumentException(ex, "Cannot create instance of function %s", ur.name());

View File

@ -108,7 +108,7 @@ abstract class CommandBuilder extends LogicalPlanBuilder {
@Override @Override
public Object visitShowTables(ShowTablesContext ctx) { public Object visitShowTables(ShowTablesContext ctx) {
return new ShowTables(source(ctx), visitIdentifier(ctx.index), text(ctx.pattern)); return new ShowTables(source(ctx), text(ctx.pattern));
} }
@Override @Override
@ -120,10 +120,7 @@ abstract class CommandBuilder extends LogicalPlanBuilder {
@Override @Override
public Object visitShowColumns(ShowColumnsContext ctx) { public Object visitShowColumns(ShowColumnsContext ctx) {
TableIdentifier identifier = visitTableIdentifier(ctx.tableIdentifier()); TableIdentifier identifier = visitTableIdentifier(ctx.tableIdentifier());
if (!identifier.hasType()) { return new ShowColumns(source(ctx), identifier.index());
throw new ParsingException(identifier.location(), "Target type needs to be specified");
}
return new ShowColumns(source(ctx), identifier.index(), identifier.type());
} }
@Override @Override

View File

@ -133,7 +133,7 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
} }
else if (ctx.table != null) { else if (ctx.table != null) {
TableIdentifier table = visitTableIdentifier(ctx.table); TableIdentifier table = visitTableIdentifier(ctx.table);
qualifier = table.index() + "." + table.type(); qualifier = table.index();
} }
return new UnresolvedAttribute(source(ctx), visitIdentifier(ctx.name), qualifier); return new UnresolvedAttribute(source(ctx), visitIdentifier(ctx.name), qualifier);
} }

View File

@ -5,8 +5,6 @@
*/ */
package org.elasticsearch.xpack.sql.parser; package org.elasticsearch.xpack.sql.parser;
import java.util.Locale;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.xpack.sql.parser.SqlBaseParser.IdentifierContext; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.IdentifierContext;
import org.elasticsearch.xpack.sql.parser.SqlBaseParser.QualifiedNameContext; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.QualifiedNameContext;
@ -14,28 +12,20 @@ import org.elasticsearch.xpack.sql.parser.SqlBaseParser.TableIdentifierContext;
import org.elasticsearch.xpack.sql.plan.TableIdentifier; import org.elasticsearch.xpack.sql.plan.TableIdentifier;
import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.Location;
import java.util.Locale;
import static java.lang.String.format; import static java.lang.String.format;
abstract class IdentifierBuilder extends AbstractBuilder { abstract class IdentifierBuilder extends AbstractBuilder {
@Override @Override
public TableIdentifier visitTableIdentifier(TableIdentifierContext ctx) { public TableIdentifier visitTableIdentifier(TableIdentifierContext ctx) {
String index = null; String index = text(ctx.index);
String type = null;
index = text(ctx.uindex);
type = text(ctx.utype);
if (index == null) {
index = text(ctx.index);
type = text(ctx.type);
}
Location source = source(ctx); Location source = source(ctx);
validateIndex(index, source); validateIndex(index, source);
validateType(type, source);
return new TableIdentifier(source, index, type); return new TableIdentifier(source, index);
} }
// see https://github.com/elastic/elasticsearch/issues/6736 // see https://github.com/elastic/elasticsearch/issues/6736
@ -51,10 +41,6 @@ abstract class IdentifierBuilder extends AbstractBuilder {
} }
} }
private static void validateType(String type, Location source) {
// no-op
}
@Override @Override
public String visitIdentifier(IdentifierContext ctx) { public String visitIdentifier(IdentifierContext ctx) {
return ctx == null ? null : ctx.quoteIdentifier() != null ? text(ctx.quoteIdentifier()) : text(ctx.unquoteIdentifier()); return ctx == null ? null : ctx.quoteIdentifier() != null ? text(ctx.quoteIdentifier()) : text(ctx.unquoteIdentifier());

View File

@ -195,9 +195,6 @@ abstract class LogicalPlanBuilder extends ExpressionBuilder {
public LogicalPlan visitTableName(TableNameContext ctx) { public LogicalPlan visitTableName(TableNameContext ctx) {
String alias = visitQualifiedName(ctx.qualifiedName()); String alias = visitQualifiedName(ctx.qualifiedName());
TableIdentifier tableIdentifier = visitTableIdentifier(ctx.tableIdentifier()); TableIdentifier tableIdentifier = visitTableIdentifier(ctx.tableIdentifier());
if (!tableIdentifier.hasType()) {
throw new ParsingException(source(ctx), "Index type is required");
}
return new UnresolvedRelation(source(ctx), tableIdentifier, alias); return new UnresolvedRelation(source(ctx), tableIdentifier, alias);
} }
} }

View File

@ -22,30 +22,30 @@ class SqlBaseLexer extends Lexer {
protected static final PredictionContextCache _sharedContextCache = protected static final PredictionContextCache _sharedContextCache =
new PredictionContextCache(); new PredictionContextCache();
public static final int public static final int
T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, SELECT=6, FROM=7, AS=8, ALL=9, T__0=1, T__1=2, T__2=3, T__3=4, SELECT=5, FROM=6, AS=7, ALL=8, WHEN=9,
WHEN=10, THEN=11, ANY=12, DISTINCT=13, WHERE=14, GROUP=15, BY=16, GROUPING=17, THEN=10, ANY=11, DISTINCT=12, WHERE=13, GROUP=14, BY=15, GROUPING=16,
SETS=18, ORDER=19, HAVING=20, LIMIT=21, OR=22, AND=23, IN=24, NOT=25, SETS=17, ORDER=18, HAVING=19, LIMIT=20, OR=21, AND=22, IN=23, NOT=24,
NO=26, EXISTS=27, BETWEEN=28, LIKE=29, RLIKE=30, IS=31, NULL=32, TRUE=33, NO=25, EXISTS=26, BETWEEN=27, LIKE=28, RLIKE=29, IS=30, NULL=31, TRUE=32,
FALSE=34, LAST=35, ASC=36, DESC=37, FOR=38, INTEGER=39, JOIN=40, CROSS=41, FALSE=33, LAST=34, ASC=35, DESC=36, FOR=37, INTEGER=38, JOIN=39, CROSS=40,
OUTER=42, INNER=43, LEFT=44, RIGHT=45, FULL=46, NATURAL=47, USING=48, OUTER=41, INNER=42, LEFT=43, RIGHT=44, FULL=45, NATURAL=46, USING=47,
ON=49, WITH=50, TABLE=51, INTO=52, DESCRIBE=53, OPTION=54, EXPLAIN=55, ON=48, WITH=49, TABLE=50, INTO=51, DESCRIBE=52, OPTION=53, EXPLAIN=54,
ANALYZE=56, FORMAT=57, TYPE=58, TEXT=59, VERIFY=60, GRAPHVIZ=61, LOGICAL=62, ANALYZE=55, FORMAT=56, TYPE=57, TEXT=58, VERIFY=59, GRAPHVIZ=60, LOGICAL=61,
PHYSICAL=63, SHOW=64, TABLES=65, COLUMNS=66, COLUMN=67, FUNCTIONS=68, PHYSICAL=62, SHOW=63, TABLES=64, COLUMNS=65, COLUMN=66, FUNCTIONS=67,
TO=69, DEBUG=70, PLAN=71, PARSED=72, ANALYZED=73, OPTIMIZED=74, MAPPED=75, TO=68, DEBUG=69, PLAN=70, PARSED=71, ANALYZED=72, OPTIMIZED=73, MAPPED=74,
EXECUTABLE=76, USE=77, SET=78, RESET=79, SESSION=80, SCHEMAS=81, EXTRACT=82, EXECUTABLE=75, USE=76, SET=77, RESET=78, SESSION=79, SCHEMAS=80, EXTRACT=81,
QUERY=83, MATCH=84, CAST=85, EQ=86, NEQ=87, LT=88, LTE=89, GT=90, GTE=91, QUERY=82, MATCH=83, CAST=84, EQ=85, NEQ=86, LT=87, LTE=88, GT=89, GTE=90,
PLUS=92, MINUS=93, ASTERISK=94, SLASH=95, PERCENT=96, CONCAT=97, STRING=98, PLUS=91, MINUS=92, ASTERISK=93, SLASH=94, PERCENT=95, CONCAT=96, STRING=97,
INTEGER_VALUE=99, DECIMAL_VALUE=100, IDENTIFIER=101, DIGIT_IDENTIFIER=102, INTEGER_VALUE=98, DECIMAL_VALUE=99, IDENTIFIER=100, DIGIT_IDENTIFIER=101,
QUOTED_IDENTIFIER=103, BACKQUOTED_IDENTIFIER=104, SIMPLE_COMMENT=105, QUOTED_IDENTIFIER=102, BACKQUOTED_IDENTIFIER=103, SIMPLE_COMMENT=104,
BRACKETED_COMMENT=106, WS=107, UNRECOGNIZED=108; BRACKETED_COMMENT=105, WS=106, UNRECOGNIZED=107;
public static String[] modeNames = { public static String[] modeNames = {
"DEFAULT_MODE" "DEFAULT_MODE"
}; };
public static final String[] ruleNames = { public static final String[] ruleNames = {
"T__0", "T__1", "T__2", "T__3", "T__4", "SELECT", "FROM", "AS", "ALL", "T__0", "T__1", "T__2", "T__3", "SELECT", "FROM", "AS", "ALL", "WHEN",
"WHEN", "THEN", "ANY", "DISTINCT", "WHERE", "GROUP", "BY", "GROUPING", "THEN", "ANY", "DISTINCT", "WHERE", "GROUP", "BY", "GROUPING", "SETS",
"SETS", "ORDER", "HAVING", "LIMIT", "OR", "AND", "IN", "NOT", "NO", "EXISTS", "ORDER", "HAVING", "LIMIT", "OR", "AND", "IN", "NOT", "NO", "EXISTS",
"BETWEEN", "LIKE", "RLIKE", "IS", "NULL", "TRUE", "FALSE", "LAST", "ASC", "BETWEEN", "LIKE", "RLIKE", "IS", "NULL", "TRUE", "FALSE", "LAST", "ASC",
"DESC", "FOR", "INTEGER", "JOIN", "CROSS", "OUTER", "INNER", "LEFT", "RIGHT", "DESC", "FOR", "INTEGER", "JOIN", "CROSS", "OUTER", "INNER", "LEFT", "RIGHT",
"FULL", "NATURAL", "USING", "ON", "WITH", "TABLE", "INTO", "DESCRIBE", "FULL", "NATURAL", "USING", "ON", "WITH", "TABLE", "INTO", "DESCRIBE",
@ -61,10 +61,10 @@ class SqlBaseLexer extends Lexer {
}; };
private static final String[] _LITERAL_NAMES = { private static final String[] _LITERAL_NAMES = {
null, "'('", "')'", "','", "'.'", "'\"'", "'SELECT'", "'FROM'", "'AS'", null, "'('", "')'", "','", "'.'", "'SELECT'", "'FROM'", "'AS'", "'ALL'",
"'ALL'", "'WHEN'", "'THEN'", "'ANY'", "'DISTINCT'", "'WHERE'", "'GROUP'", "'WHEN'", "'THEN'", "'ANY'", "'DISTINCT'", "'WHERE'", "'GROUP'", "'BY'",
"'BY'", "'GROUPING'", "'SETS'", "'ORDER'", "'HAVING'", "'LIMIT'", "'OR'", "'GROUPING'", "'SETS'", "'ORDER'", "'HAVING'", "'LIMIT'", "'OR'", "'AND'",
"'AND'", "'IN'", "'NOT'", "'NO'", "'EXISTS'", "'BETWEEN'", "'LIKE'", "'RLIKE'", "'IN'", "'NOT'", "'NO'", "'EXISTS'", "'BETWEEN'", "'LIKE'", "'RLIKE'",
"'IS'", "'NULL'", "'TRUE'", "'FALSE'", "'LAST'", "'ASC'", "'DESC'", "'FOR'", "'IS'", "'NULL'", "'TRUE'", "'FALSE'", "'LAST'", "'ASC'", "'DESC'", "'FOR'",
"'INTEGER'", "'JOIN'", "'CROSS'", "'OUTER'", "'INNER'", "'LEFT'", "'RIGHT'", "'INTEGER'", "'JOIN'", "'CROSS'", "'OUTER'", "'INNER'", "'LEFT'", "'RIGHT'",
"'FULL'", "'NATURAL'", "'USING'", "'ON'", "'WITH'", "'TABLE'", "'INTO'", "'FULL'", "'NATURAL'", "'USING'", "'ON'", "'WITH'", "'TABLE'", "'INTO'",
@ -77,11 +77,11 @@ class SqlBaseLexer extends Lexer {
"'-'", "'*'", "'/'", "'%'", "'||'" "'-'", "'*'", "'/'", "'%'", "'||'"
}; };
private static final String[] _SYMBOLIC_NAMES = { private static final String[] _SYMBOLIC_NAMES = {
null, null, null, null, null, null, "SELECT", "FROM", "AS", "ALL", "WHEN", null, null, null, null, null, "SELECT", "FROM", "AS", "ALL", "WHEN", "THEN",
"THEN", "ANY", "DISTINCT", "WHERE", "GROUP", "BY", "GROUPING", "SETS", "ANY", "DISTINCT", "WHERE", "GROUP", "BY", "GROUPING", "SETS", "ORDER",
"ORDER", "HAVING", "LIMIT", "OR", "AND", "IN", "NOT", "NO", "EXISTS", "HAVING", "LIMIT", "OR", "AND", "IN", "NOT", "NO", "EXISTS", "BETWEEN",
"BETWEEN", "LIKE", "RLIKE", "IS", "NULL", "TRUE", "FALSE", "LAST", "ASC", "LIKE", "RLIKE", "IS", "NULL", "TRUE", "FALSE", "LAST", "ASC", "DESC",
"DESC", "FOR", "INTEGER", "JOIN", "CROSS", "OUTER", "INNER", "LEFT", "RIGHT", "FOR", "INTEGER", "JOIN", "CROSS", "OUTER", "INNER", "LEFT", "RIGHT",
"FULL", "NATURAL", "USING", "ON", "WITH", "TABLE", "INTO", "DESCRIBE", "FULL", "NATURAL", "USING", "ON", "WITH", "TABLE", "INTO", "DESCRIBE",
"OPTION", "EXPLAIN", "ANALYZE", "FORMAT", "TYPE", "TEXT", "VERIFY", "GRAPHVIZ", "OPTION", "EXPLAIN", "ANALYZE", "FORMAT", "TYPE", "TEXT", "VERIFY", "GRAPHVIZ",
"LOGICAL", "PHYSICAL", "SHOW", "TABLES", "COLUMNS", "COLUMN", "FUNCTIONS", "LOGICAL", "PHYSICAL", "SHOW", "TABLES", "COLUMNS", "COLUMN", "FUNCTIONS",
@ -147,7 +147,7 @@ class SqlBaseLexer extends Lexer {
public ATN getATN() { return _ATN; } public ATN getATN() { return _ATN; }
public static final String _serializedATN = public static final String _serializedATN =
"\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2n\u038a\b\1\4\2\t"+ "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2m\u0386\b\1\4\2\t"+
"\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
@ -159,298 +159,297 @@ class SqlBaseLexer extends Lexer {
"\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\tT"+ "\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\tT"+
"\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_\4"+ "\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_\4"+
"`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4h\th\4i\ti\4j\tj\4k\t"+ "`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4h\th\4i\ti\4j\tj\4k\t"+
"k\4l\tl\4m\tm\4n\tn\4o\to\4p\tp\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3"+ "k\4l\tl\4m\tm\4n\tn\4o\to\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\6"+
"\6\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\n\3\n"+ "\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\n\3"+
"\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r"+ "\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3"+
"\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17"+ "\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3"+
"\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\22\3\22\3\22\3\22"+ "\17\3\17\3\17\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3"+
"\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24"+ "\21\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3"+
"\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26"+ "\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3"+
"\3\26\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3\31\3\31\3\31\3\32\3\32\3\32"+ "\27\3\27\3\27\3\27\3\30\3\30\3\30\3\31\3\31\3\31\3\31\3\32\3\32\3\32\3"+
"\3\32\3\33\3\33\3\33\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\35\3\35\3\35"+ "\33\3\33\3\33\3\33\3\33\3\33\3\33\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3"+
"\3\35\3\35\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\37\3\37\3\37\3\37"+ "\34\3\35\3\35\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\36\3\37\3\37\3"+
"\3\37\3\37\3 \3 \3 \3!\3!\3!\3!\3!\3\"\3\"\3\"\3\"\3\"\3#\3#\3#\3#\3#"+ "\37\3 \3 \3 \3 \3 \3!\3!\3!\3!\3!\3\"\3\"\3\"\3\"\3\"\3\"\3#\3#\3#\3#"+
"\3#\3$\3$\3$\3$\3$\3%\3%\3%\3%\3&\3&\3&\3&\3&\3\'\3\'\3\'\3\'\3(\3(\3"+ "\3#\3$\3$\3$\3$\3%\3%\3%\3%\3%\3&\3&\3&\3&\3\'\3\'\3\'\3\'\3\'\3\'\3\'"+
"(\3(\3(\3(\3(\3(\3)\3)\3)\3)\3)\3*\3*\3*\3*\3*\3*\3+\3+\3+\3+\3+\3+\3"+ "\3\'\3(\3(\3(\3(\3(\3)\3)\3)\3)\3)\3)\3*\3*\3*\3*\3*\3*\3+\3+\3+\3+\3"+
",\3,\3,\3,\3,\3,\3-\3-\3-\3-\3-\3.\3.\3.\3.\3.\3.\3/\3/\3/\3/\3/\3\60"+ "+\3+\3,\3,\3,\3,\3,\3-\3-\3-\3-\3-\3-\3.\3.\3.\3.\3.\3/\3/\3/\3/\3/\3"+
"\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\61\3\61\3\61\3\61\3\61\3\61\3\62"+ "/\3/\3/\3\60\3\60\3\60\3\60\3\60\3\60\3\61\3\61\3\61\3\62\3\62\3\62\3"+
"\3\62\3\62\3\63\3\63\3\63\3\63\3\63\3\64\3\64\3\64\3\64\3\64\3\64\3\65"+ "\62\3\62\3\63\3\63\3\63\3\63\3\63\3\63\3\64\3\64\3\64\3\64\3\64\3\65\3"+
"\3\65\3\65\3\65\3\65\3\66\3\66\3\66\3\66\3\66\3\66\3\66\3\66\3\66\3\67"+ "\65\3\65\3\65\3\65\3\65\3\65\3\65\3\65\3\66\3\66\3\66\3\66\3\66\3\66\3"+
"\3\67\3\67\3\67\3\67\3\67\3\67\38\38\38\38\38\38\38\38\39\39\39\39\39"+ "\66\3\67\3\67\3\67\3\67\3\67\3\67\3\67\3\67\38\38\38\38\38\38\38\38\3"+
"\39\39\39\3:\3:\3:\3:\3:\3:\3:\3;\3;\3;\3;\3;\3<\3<\3<\3<\3<\3=\3=\3="+ "9\39\39\39\39\39\39\3:\3:\3:\3:\3:\3;\3;\3;\3;\3;\3<\3<\3<\3<\3<\3<\3"+
"\3=\3=\3=\3=\3>\3>\3>\3>\3>\3>\3>\3>\3>\3?\3?\3?\3?\3?\3?\3?\3?\3@\3@"+ "<\3=\3=\3=\3=\3=\3=\3=\3=\3=\3>\3>\3>\3>\3>\3>\3>\3>\3?\3?\3?\3?\3?\3"+
"\3@\3@\3@\3@\3@\3@\3@\3A\3A\3A\3A\3A\3B\3B\3B\3B\3B\3B\3B\3C\3C\3C\3C"+ "?\3?\3?\3?\3@\3@\3@\3@\3@\3A\3A\3A\3A\3A\3A\3A\3B\3B\3B\3B\3B\3B\3B\3"+
"\3C\3C\3C\3C\3D\3D\3D\3D\3D\3D\3D\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3F\3F"+ "B\3C\3C\3C\3C\3C\3C\3C\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3E\3E\3E\3F\3F\3"+
"\3F\3G\3G\3G\3G\3G\3G\3H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3I\3I\3J\3J\3J\3J"+ "F\3F\3F\3F\3G\3G\3G\3G\3G\3H\3H\3H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3I\3I\3"+
"\3J\3J\3J\3J\3J\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3L\3L\3L\3L\3L\3L\3L\3M"+ "I\3I\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3K\3K\3K\3K\3K\3K\3K\3L\3L\3L\3L\3"+
"\3M\3M\3M\3M\3M\3M\3M\3M\3M\3M\3N\3N\3N\3N\3O\3O\3O\3O\3P\3P\3P\3P\3P"+ "L\3L\3L\3L\3L\3L\3L\3M\3M\3M\3M\3N\3N\3N\3N\3O\3O\3O\3O\3O\3O\3P\3P\3"+
"\3P\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3R\3R\3R\3R\3R\3R\3R\3R\3S\3S\3S\3S\3S\3S"+ "P\3P\3P\3P\3P\3P\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3R\3R\3R\3R\3R\3R\3R\3R\3S\3"+
"\3S\3S\3T\3T\3T\3T\3T\3T\3U\3U\3U\3U\3U\3U\3V\3V\3V\3V\3V\3W\3W\3X\3X"+ "S\3S\3S\3S\3S\3T\3T\3T\3T\3T\3T\3U\3U\3U\3U\3U\3V\3V\3W\3W\3W\3W\3W\3"+
"\3X\3X\3X\3X\3X\5X\u02d7\nX\3Y\3Y\3Z\3Z\3Z\3[\3[\3\\\3\\\3\\\3]\3]\3^"+ "W\3W\5W\u02d3\nW\3X\3X\3Y\3Y\3Y\3Z\3Z\3[\3[\3[\3\\\3\\\3]\3]\3^\3^\3_"+
"\3^\3_\3_\3`\3`\3a\3a\3b\3b\3b\3c\3c\3c\3c\7c\u02f4\nc\fc\16c\u02f7\13"+ "\3_\3`\3`\3a\3a\3a\3b\3b\3b\3b\7b\u02f0\nb\fb\16b\u02f3\13b\3b\3b\3c\6"+
"c\3c\3c\3d\6d\u02fc\nd\rd\16d\u02fd\3e\6e\u0301\ne\re\16e\u0302\3e\3e"+ "c\u02f8\nc\rc\16c\u02f9\3d\6d\u02fd\nd\rd\16d\u02fe\3d\3d\7d\u0303\nd"+
"\7e\u0307\ne\fe\16e\u030a\13e\3e\3e\6e\u030e\ne\re\16e\u030f\3e\6e\u0313"+ "\fd\16d\u0306\13d\3d\3d\6d\u030a\nd\rd\16d\u030b\3d\6d\u030f\nd\rd\16"+
"\ne\re\16e\u0314\3e\3e\7e\u0319\ne\fe\16e\u031c\13e\5e\u031e\ne\3e\3e"+ "d\u0310\3d\3d\7d\u0315\nd\fd\16d\u0318\13d\5d\u031a\nd\3d\3d\3d\3d\6d"+
"\3e\3e\6e\u0324\ne\re\16e\u0325\3e\3e\5e\u032a\ne\3f\3f\5f\u032e\nf\3"+ "\u0320\nd\rd\16d\u0321\3d\3d\5d\u0326\nd\3e\3e\5e\u032a\ne\3e\3e\3e\7"+
"f\3f\3f\7f\u0333\nf\ff\16f\u0336\13f\3g\3g\3g\3g\6g\u033c\ng\rg\16g\u033d"+ "e\u032f\ne\fe\16e\u0332\13e\3f\3f\3f\3f\6f\u0338\nf\rf\16f\u0339\3g\3"+
"\3h\3h\3h\7h\u0343\nh\fh\16h\u0346\13h\3h\3h\3i\3i\3i\3i\7i\u034e\ni\f"+ "g\3g\7g\u033f\ng\fg\16g\u0342\13g\3g\3g\3h\3h\3h\3h\7h\u034a\nh\fh\16"+
"i\16i\u0351\13i\3i\3i\3j\3j\5j\u0357\nj\3j\6j\u035a\nj\rj\16j\u035b\3"+ "h\u034d\13h\3h\3h\3i\3i\5i\u0353\ni\3i\6i\u0356\ni\ri\16i\u0357\3j\3j"+
"k\3k\3l\3l\3m\3m\3m\3m\7m\u0366\nm\fm\16m\u0369\13m\3m\5m\u036c\nm\3m"+ "\3k\3k\3l\3l\3l\3l\7l\u0362\nl\fl\16l\u0365\13l\3l\5l\u0368\nl\3l\5l\u036b"+
"\5m\u036f\nm\3m\3m\3n\3n\3n\3n\3n\7n\u0378\nn\fn\16n\u037b\13n\3n\3n\3"+ "\nl\3l\3l\3m\3m\3m\3m\3m\7m\u0374\nm\fm\16m\u0377\13m\3m\3m\3m\3m\3m\3"+
"n\3n\3n\3o\6o\u0383\no\ro\16o\u0384\3o\3o\3p\3p\3\u0379\2q\3\3\5\4\7\5"+ "n\6n\u037f\nn\rn\16n\u0380\3n\3n\3o\3o\3\u0375\2p\3\3\5\4\7\5\t\6\13\7"+
"\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23"+ "\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25"+
"%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G"+ ")\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O"+
"%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{"+ ")Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081"+
"?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091"+ "B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095"+
"J\u0093K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5"+ "L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9"+
"T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9"+ "V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9^\u00bb_\u00bd"+
"^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5d\u00c7e\u00c9f\u00cbg\u00cd"+ "`\u00bfa\u00c1b\u00c3c\u00c5d\u00c7e\u00c9f\u00cbg\u00cdh\u00cfi\u00d1"+
"h\u00cfi\u00d1j\u00d3\2\u00d5\2\u00d7\2\u00d9k\u00dbl\u00ddm\u00dfn\3"+ "\2\u00d3\2\u00d5\2\u00d7j\u00d9k\u00dbl\u00ddm\3\2\13\3\2))\5\2<<BBaa"+
"\2\13\3\2))\5\2<<BBaa\6\2$$))\60\60~~\6\2))\60\60bb~~\4\2--//\3\2\62;"+ "\6\2$$))\60\60~~\6\2))\60\60bb~~\4\2--//\3\2\62;\3\2C\\\4\2\f\f\17\17"+
"\3\2C\\\4\2\f\f\17\17\5\2\13\f\17\17\"\"\u03a8\2\3\3\2\2\2\2\5\3\2\2\2"+ "\5\2\13\f\17\17\"\"\u03a4\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2"+
"\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3"+ "\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2"+
"\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2"+ "\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3"+
"\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2"+ "\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2"+
"\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2"+ "\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67"+
"\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2"+ "\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2"+
"\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2"+ "\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2"+
"\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y"+ "\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]"+
"\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2"+ "\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2"+
"\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2"+ "\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2"+
"\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177"+ "\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2"+
"\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2"+ "\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2"+
"\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2\2\u0091"+ "\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093"+
"\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099\3\2\2"+ "\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099\3\2\2\2\2\u009b\3\2\2"+
"\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2\2\2\u00a3"+ "\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2\2\2\u00a3\3\2\2\2\2\u00a5"+
"\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab\3\2\2"+ "\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2"+
"\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2\2\2\u00b5"+ "\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2\2\2\u00b5\3\2\2\2\2\u00b7"+
"\3\2\2\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb\3\2\2\2\2\u00bd\3\2\2"+ "\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb\3\2\2\2\2\u00bd\3\2\2\2\2\u00bf\3\2\2"+
"\2\2\u00bf\3\2\2\2\2\u00c1\3\2\2\2\2\u00c3\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7"+ "\2\2\u00c1\3\2\2\2\2\u00c3\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9"+
"\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2\2\2\u00cf\3\2\2"+ "\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2\2\2\u00cf\3\2\2\2\2\u00d7\3\2\2"+
"\2\2\u00d1\3\2\2\2\2\u00d9\3\2\2\2\2\u00db\3\2\2\2\2\u00dd\3\2\2\2\2\u00df"+ "\2\2\u00d9\3\2\2\2\2\u00db\3\2\2\2\2\u00dd\3\2\2\2\3\u00df\3\2\2\2\5\u00e1"+
"\3\2\2\2\3\u00e1\3\2\2\2\5\u00e3\3\2\2\2\7\u00e5\3\2\2\2\t\u00e7\3\2\2"+ "\3\2\2\2\7\u00e3\3\2\2\2\t\u00e5\3\2\2\2\13\u00e7\3\2\2\2\r\u00ee\3\2"+
"\2\13\u00e9\3\2\2\2\r\u00eb\3\2\2\2\17\u00f2\3\2\2\2\21\u00f7\3\2\2\2"+ "\2\2\17\u00f3\3\2\2\2\21\u00f6\3\2\2\2\23\u00fa\3\2\2\2\25\u00ff\3\2\2"+
"\23\u00fa\3\2\2\2\25\u00fe\3\2\2\2\27\u0103\3\2\2\2\31\u0108\3\2\2\2\33"+ "\2\27\u0104\3\2\2\2\31\u0108\3\2\2\2\33\u0111\3\2\2\2\35\u0117\3\2\2\2"+
"\u010c\3\2\2\2\35\u0115\3\2\2\2\37\u011b\3\2\2\2!\u0121\3\2\2\2#\u0124"+ "\37\u011d\3\2\2\2!\u0120\3\2\2\2#\u0129\3\2\2\2%\u012e\3\2\2\2\'\u0134"+
"\3\2\2\2%\u012d\3\2\2\2\'\u0132\3\2\2\2)\u0138\3\2\2\2+\u013f\3\2\2\2"+ "\3\2\2\2)\u013b\3\2\2\2+\u0141\3\2\2\2-\u0144\3\2\2\2/\u0148\3\2\2\2\61"+
"-\u0145\3\2\2\2/\u0148\3\2\2\2\61\u014c\3\2\2\2\63\u014f\3\2\2\2\65\u0153"+ "\u014b\3\2\2\2\63\u014f\3\2\2\2\65\u0152\3\2\2\2\67\u0159\3\2\2\29\u0161"+
"\3\2\2\2\67\u0156\3\2\2\29\u015d\3\2\2\2;\u0165\3\2\2\2=\u016a\3\2\2\2"+ "\3\2\2\2;\u0166\3\2\2\2=\u016c\3\2\2\2?\u016f\3\2\2\2A\u0174\3\2\2\2C"+
"?\u0170\3\2\2\2A\u0173\3\2\2\2C\u0178\3\2\2\2E\u017d\3\2\2\2G\u0183\3"+ "\u0179\3\2\2\2E\u017f\3\2\2\2G\u0184\3\2\2\2I\u0188\3\2\2\2K\u018d\3\2"+
"\2\2\2I\u0188\3\2\2\2K\u018c\3\2\2\2M\u0191\3\2\2\2O\u0195\3\2\2\2Q\u019d"+ "\2\2M\u0191\3\2\2\2O\u0199\3\2\2\2Q\u019e\3\2\2\2S\u01a4\3\2\2\2U\u01aa"+
"\3\2\2\2S\u01a2\3\2\2\2U\u01a8\3\2\2\2W\u01ae\3\2\2\2Y\u01b4\3\2\2\2["+ "\3\2\2\2W\u01b0\3\2\2\2Y\u01b5\3\2\2\2[\u01bb\3\2\2\2]\u01c0\3\2\2\2_"+
"\u01b9\3\2\2\2]\u01bf\3\2\2\2_\u01c4\3\2\2\2a\u01cc\3\2\2\2c\u01d2\3\2"+ "\u01c8\3\2\2\2a\u01ce\3\2\2\2c\u01d1\3\2\2\2e\u01d6\3\2\2\2g\u01dc\3\2"+
"\2\2e\u01d5\3\2\2\2g\u01da\3\2\2\2i\u01e0\3\2\2\2k\u01e5\3\2\2\2m\u01ee"+ "\2\2i\u01e1\3\2\2\2k\u01ea\3\2\2\2m\u01f1\3\2\2\2o\u01f9\3\2\2\2q\u0201"+
"\3\2\2\2o\u01f5\3\2\2\2q\u01fd\3\2\2\2s\u0205\3\2\2\2u\u020c\3\2\2\2w"+ "\3\2\2\2s\u0208\3\2\2\2u\u020d\3\2\2\2w\u0212\3\2\2\2y\u0219\3\2\2\2{"+
"\u0211\3\2\2\2y\u0216\3\2\2\2{\u021d\3\2\2\2}\u0226\3\2\2\2\177\u022e"+ "\u0222\3\2\2\2}\u022a\3\2\2\2\177\u0233\3\2\2\2\u0081\u0238\3\2\2\2\u0083"+
"\3\2\2\2\u0081\u0237\3\2\2\2\u0083\u023c\3\2\2\2\u0085\u0243\3\2\2\2\u0087"+ "\u023f\3\2\2\2\u0085\u0247\3\2\2\2\u0087\u024e\3\2\2\2\u0089\u0258\3\2"+
"\u024b\3\2\2\2\u0089\u0252\3\2\2\2\u008b\u025c\3\2\2\2\u008d\u025f\3\2"+ "\2\2\u008b\u025b\3\2\2\2\u008d\u0261\3\2\2\2\u008f\u0266\3\2\2\2\u0091"+
"\2\2\u008f\u0265\3\2\2\2\u0091\u026a\3\2\2\2\u0093\u0271\3\2\2\2\u0095"+ "\u026d\3\2\2\2\u0093\u0276\3\2\2\2\u0095\u0280\3\2\2\2\u0097\u0287\3\2"+
"\u027a\3\2\2\2\u0097\u0284\3\2\2\2\u0099\u028b\3\2\2\2\u009b\u0296\3\2"+ "\2\2\u0099\u0292\3\2\2\2\u009b\u0296\3\2\2\2\u009d\u029a\3\2\2\2\u009f"+
"\2\2\u009d\u029a\3\2\2\2\u009f\u029e\3\2\2\2\u00a1\u02a4\3\2\2\2\u00a3"+ "\u02a0\3\2\2\2\u00a1\u02a8\3\2\2\2\u00a3\u02b0\3\2\2\2\u00a5\u02b8\3\2"+
"\u02ac\3\2\2\2\u00a5\u02b4\3\2\2\2\u00a7\u02bc\3\2\2\2\u00a9\u02c2\3\2"+ "\2\2\u00a7\u02be\3\2\2\2\u00a9\u02c4\3\2\2\2\u00ab\u02c9\3\2\2\2\u00ad"+
"\2\2\u00ab\u02c8\3\2\2\2\u00ad\u02cd\3\2\2\2\u00af\u02d6\3\2\2\2\u00b1"+ "\u02d2\3\2\2\2\u00af\u02d4\3\2\2\2\u00b1\u02d6\3\2\2\2\u00b3\u02d9\3\2"+
"\u02d8\3\2\2\2\u00b3\u02da\3\2\2\2\u00b5\u02dd\3\2\2\2\u00b7\u02df\3\2"+ "\2\2\u00b5\u02db\3\2\2\2\u00b7\u02de\3\2\2\2\u00b9\u02e0\3\2\2\2\u00bb"+
"\2\2\u00b9\u02e2\3\2\2\2\u00bb\u02e4\3\2\2\2\u00bd\u02e6\3\2\2\2\u00bf"+ "\u02e2\3\2\2\2\u00bd\u02e4\3\2\2\2\u00bf\u02e6\3\2\2\2\u00c1\u02e8\3\2"+
"\u02e8\3\2\2\2\u00c1\u02ea\3\2\2\2\u00c3\u02ec\3\2\2\2\u00c5\u02ef\3\2"+ "\2\2\u00c3\u02eb\3\2\2\2\u00c5\u02f7\3\2\2\2\u00c7\u0325\3\2\2\2\u00c9"+
"\2\2\u00c7\u02fb\3\2\2\2\u00c9\u0329\3\2\2\2\u00cb\u032d\3\2\2\2\u00cd"+ "\u0329\3\2\2\2\u00cb\u0333\3\2\2\2\u00cd\u033b\3\2\2\2\u00cf\u0345\3\2"+
"\u0337\3\2\2\2\u00cf\u033f\3\2\2\2\u00d1\u0349\3\2\2\2\u00d3\u0354\3\2"+ "\2\2\u00d1\u0350\3\2\2\2\u00d3\u0359\3\2\2\2\u00d5\u035b\3\2\2\2\u00d7"+
"\2\2\u00d5\u035d\3\2\2\2\u00d7\u035f\3\2\2\2\u00d9\u0361\3\2\2\2\u00db"+ "\u035d\3\2\2\2\u00d9\u036e\3\2\2\2\u00db\u037e\3\2\2\2\u00dd\u0384\3\2"+
"\u0372\3\2\2\2\u00dd\u0382\3\2\2\2\u00df\u0388\3\2\2\2\u00e1\u00e2\7*"+ "\2\2\u00df\u00e0\7*\2\2\u00e0\4\3\2\2\2\u00e1\u00e2\7+\2\2\u00e2\6\3\2"+
"\2\2\u00e2\4\3\2\2\2\u00e3\u00e4\7+\2\2\u00e4\6\3\2\2\2\u00e5\u00e6\7"+ "\2\2\u00e3\u00e4\7.\2\2\u00e4\b\3\2\2\2\u00e5\u00e6\7\60\2\2\u00e6\n\3"+
".\2\2\u00e6\b\3\2\2\2\u00e7\u00e8\7\60\2\2\u00e8\n\3\2\2\2\u00e9\u00ea"+ "\2\2\2\u00e7\u00e8\7U\2\2\u00e8\u00e9\7G\2\2\u00e9\u00ea\7N\2\2\u00ea"+
"\7$\2\2\u00ea\f\3\2\2\2\u00eb\u00ec\7U\2\2\u00ec\u00ed\7G\2\2\u00ed\u00ee"+ "\u00eb\7G\2\2\u00eb\u00ec\7E\2\2\u00ec\u00ed\7V\2\2\u00ed\f\3\2\2\2\u00ee"+
"\7N\2\2\u00ee\u00ef\7G\2\2\u00ef\u00f0\7E\2\2\u00f0\u00f1\7V\2\2\u00f1"+ "\u00ef\7H\2\2\u00ef\u00f0\7T\2\2\u00f0\u00f1\7Q\2\2\u00f1\u00f2\7O\2\2"+
"\16\3\2\2\2\u00f2\u00f3\7H\2\2\u00f3\u00f4\7T\2\2\u00f4\u00f5\7Q\2\2\u00f5"+ "\u00f2\16\3\2\2\2\u00f3\u00f4\7C\2\2\u00f4\u00f5\7U\2\2\u00f5\20\3\2\2"+
"\u00f6\7O\2\2\u00f6\20\3\2\2\2\u00f7\u00f8\7C\2\2\u00f8\u00f9\7U\2\2\u00f9"+ "\2\u00f6\u00f7\7C\2\2\u00f7\u00f8\7N\2\2\u00f8\u00f9\7N\2\2\u00f9\22\3"+
"\22\3\2\2\2\u00fa\u00fb\7C\2\2\u00fb\u00fc\7N\2\2\u00fc\u00fd\7N\2\2\u00fd"+ "\2\2\2\u00fa\u00fb\7Y\2\2\u00fb\u00fc\7J\2\2\u00fc\u00fd\7G\2\2\u00fd"+
"\24\3\2\2\2\u00fe\u00ff\7Y\2\2\u00ff\u0100\7J\2\2\u0100\u0101\7G\2\2\u0101"+ "\u00fe\7P\2\2\u00fe\24\3\2\2\2\u00ff\u0100\7V\2\2\u0100\u0101\7J\2\2\u0101"+
"\u0102\7P\2\2\u0102\26\3\2\2\2\u0103\u0104\7V\2\2\u0104\u0105\7J\2\2\u0105"+ "\u0102\7G\2\2\u0102\u0103\7P\2\2\u0103\26\3\2\2\2\u0104\u0105\7C\2\2\u0105"+
"\u0106\7G\2\2\u0106\u0107\7P\2\2\u0107\30\3\2\2\2\u0108\u0109\7C\2\2\u0109"+ "\u0106\7P\2\2\u0106\u0107\7[\2\2\u0107\30\3\2\2\2\u0108\u0109\7F\2\2\u0109"+
"\u010a\7P\2\2\u010a\u010b\7[\2\2\u010b\32\3\2\2\2\u010c\u010d\7F\2\2\u010d"+ "\u010a\7K\2\2\u010a\u010b\7U\2\2\u010b\u010c\7V\2\2\u010c\u010d\7K\2\2"+
"\u010e\7K\2\2\u010e\u010f\7U\2\2\u010f\u0110\7V\2\2\u0110\u0111\7K\2\2"+ "\u010d\u010e\7P\2\2\u010e\u010f\7E\2\2\u010f\u0110\7V\2\2\u0110\32\3\2"+
"\u0111\u0112\7P\2\2\u0112\u0113\7E\2\2\u0113\u0114\7V\2\2\u0114\34\3\2"+ "\2\2\u0111\u0112\7Y\2\2\u0112\u0113\7J\2\2\u0113\u0114\7G\2\2\u0114\u0115"+
"\2\2\u0115\u0116\7Y\2\2\u0116\u0117\7J\2\2\u0117\u0118\7G\2\2\u0118\u0119"+ "\7T\2\2\u0115\u0116\7G\2\2\u0116\34\3\2\2\2\u0117\u0118\7I\2\2\u0118\u0119"+
"\7T\2\2\u0119\u011a\7G\2\2\u011a\36\3\2\2\2\u011b\u011c\7I\2\2\u011c\u011d"+ "\7T\2\2\u0119\u011a\7Q\2\2\u011a\u011b\7W\2\2\u011b\u011c\7R\2\2\u011c"+
"\7T\2\2\u011d\u011e\7Q\2\2\u011e\u011f\7W\2\2\u011f\u0120\7R\2\2\u0120"+ "\36\3\2\2\2\u011d\u011e\7D\2\2\u011e\u011f\7[\2\2\u011f \3\2\2\2\u0120"+
" \3\2\2\2\u0121\u0122\7D\2\2\u0122\u0123\7[\2\2\u0123\"\3\2\2\2\u0124"+ "\u0121\7I\2\2\u0121\u0122\7T\2\2\u0122\u0123\7Q\2\2\u0123\u0124\7W\2\2"+
"\u0125\7I\2\2\u0125\u0126\7T\2\2\u0126\u0127\7Q\2\2\u0127\u0128\7W\2\2"+ "\u0124\u0125\7R\2\2\u0125\u0126\7K\2\2\u0126\u0127\7P\2\2\u0127\u0128"+
"\u0128\u0129\7R\2\2\u0129\u012a\7K\2\2\u012a\u012b\7P\2\2\u012b\u012c"+ "\7I\2\2\u0128\"\3\2\2\2\u0129\u012a\7U\2\2\u012a\u012b\7G\2\2\u012b\u012c"+
"\7I\2\2\u012c$\3\2\2\2\u012d\u012e\7U\2\2\u012e\u012f\7G\2\2\u012f\u0130"+ "\7V\2\2\u012c\u012d\7U\2\2\u012d$\3\2\2\2\u012e\u012f\7Q\2\2\u012f\u0130"+
"\7V\2\2\u0130\u0131\7U\2\2\u0131&\3\2\2\2\u0132\u0133\7Q\2\2\u0133\u0134"+ "\7T\2\2\u0130\u0131\7F\2\2\u0131\u0132\7G\2\2\u0132\u0133\7T\2\2\u0133"+
"\7T\2\2\u0134\u0135\7F\2\2\u0135\u0136\7G\2\2\u0136\u0137\7T\2\2\u0137"+ "&\3\2\2\2\u0134\u0135\7J\2\2\u0135\u0136\7C\2\2\u0136\u0137\7X\2\2\u0137"+
"(\3\2\2\2\u0138\u0139\7J\2\2\u0139\u013a\7C\2\2\u013a\u013b\7X\2\2\u013b"+ "\u0138\7K\2\2\u0138\u0139\7P\2\2\u0139\u013a\7I\2\2\u013a(\3\2\2\2\u013b"+
"\u013c\7K\2\2\u013c\u013d\7P\2\2\u013d\u013e\7I\2\2\u013e*\3\2\2\2\u013f"+ "\u013c\7N\2\2\u013c\u013d\7K\2\2\u013d\u013e\7O\2\2\u013e\u013f\7K\2\2"+
"\u0140\7N\2\2\u0140\u0141\7K\2\2\u0141\u0142\7O\2\2\u0142\u0143\7K\2\2"+ "\u013f\u0140\7V\2\2\u0140*\3\2\2\2\u0141\u0142\7Q\2\2\u0142\u0143\7T\2"+
"\u0143\u0144\7V\2\2\u0144,\3\2\2\2\u0145\u0146\7Q\2\2\u0146\u0147\7T\2"+ "\2\u0143,\3\2\2\2\u0144\u0145\7C\2\2\u0145\u0146\7P\2\2\u0146\u0147\7"+
"\2\u0147.\3\2\2\2\u0148\u0149\7C\2\2\u0149\u014a\7P\2\2\u014a\u014b\7"+ "F\2\2\u0147.\3\2\2\2\u0148\u0149\7K\2\2\u0149\u014a\7P\2\2\u014a\60\3"+
"F\2\2\u014b\60\3\2\2\2\u014c\u014d\7K\2\2\u014d\u014e\7P\2\2\u014e\62"+ "\2\2\2\u014b\u014c\7P\2\2\u014c\u014d\7Q\2\2\u014d\u014e\7V\2\2\u014e"+
"\3\2\2\2\u014f\u0150\7P\2\2\u0150\u0151\7Q\2\2\u0151\u0152\7V\2\2\u0152"+ "\62\3\2\2\2\u014f\u0150\7P\2\2\u0150\u0151\7Q\2\2\u0151\64\3\2\2\2\u0152"+
"\64\3\2\2\2\u0153\u0154\7P\2\2\u0154\u0155\7Q\2\2\u0155\66\3\2\2\2\u0156"+ "\u0153\7G\2\2\u0153\u0154\7Z\2\2\u0154\u0155\7K\2\2\u0155\u0156\7U\2\2"+
"\u0157\7G\2\2\u0157\u0158\7Z\2\2\u0158\u0159\7K\2\2\u0159\u015a\7U\2\2"+ "\u0156\u0157\7V\2\2\u0157\u0158\7U\2\2\u0158\66\3\2\2\2\u0159\u015a\7"+
"\u015a\u015b\7V\2\2\u015b\u015c\7U\2\2\u015c8\3\2\2\2\u015d\u015e\7D\2"+ "D\2\2\u015a\u015b\7G\2\2\u015b\u015c\7V\2\2\u015c\u015d\7Y\2\2\u015d\u015e"+
"\2\u015e\u015f\7G\2\2\u015f\u0160\7V\2\2\u0160\u0161\7Y\2\2\u0161\u0162"+ "\7G\2\2\u015e\u015f\7G\2\2\u015f\u0160\7P\2\2\u01608\3\2\2\2\u0161\u0162"+
"\7G\2\2\u0162\u0163\7G\2\2\u0163\u0164\7P\2\2\u0164:\3\2\2\2\u0165\u0166"+ "\7N\2\2\u0162\u0163\7K\2\2\u0163\u0164\7M\2\2\u0164\u0165\7G\2\2\u0165"+
"\7N\2\2\u0166\u0167\7K\2\2\u0167\u0168\7M\2\2\u0168\u0169\7G\2\2\u0169"+ ":\3\2\2\2\u0166\u0167\7T\2\2\u0167\u0168\7N\2\2\u0168\u0169\7K\2\2\u0169"+
"<\3\2\2\2\u016a\u016b\7T\2\2\u016b\u016c\7N\2\2\u016c\u016d\7K\2\2\u016d"+ "\u016a\7M\2\2\u016a\u016b\7G\2\2\u016b<\3\2\2\2\u016c\u016d\7K\2\2\u016d"+
"\u016e\7M\2\2\u016e\u016f\7G\2\2\u016f>\3\2\2\2\u0170\u0171\7K\2\2\u0171"+ "\u016e\7U\2\2\u016e>\3\2\2\2\u016f\u0170\7P\2\2\u0170\u0171\7W\2\2\u0171"+
"\u0172\7U\2\2\u0172@\3\2\2\2\u0173\u0174\7P\2\2\u0174\u0175\7W\2\2\u0175"+ "\u0172\7N\2\2\u0172\u0173\7N\2\2\u0173@\3\2\2\2\u0174\u0175\7V\2\2\u0175"+
"\u0176\7N\2\2\u0176\u0177\7N\2\2\u0177B\3\2\2\2\u0178\u0179\7V\2\2\u0179"+ "\u0176\7T\2\2\u0176\u0177\7W\2\2\u0177\u0178\7G\2\2\u0178B\3\2\2\2\u0179"+
"\u017a\7T\2\2\u017a\u017b\7W\2\2\u017b\u017c\7G\2\2\u017cD\3\2\2\2\u017d"+ "\u017a\7H\2\2\u017a\u017b\7C\2\2\u017b\u017c\7N\2\2\u017c\u017d\7U\2\2"+
"\u017e\7H\2\2\u017e\u017f\7C\2\2\u017f\u0180\7N\2\2\u0180\u0181\7U\2\2"+ "\u017d\u017e\7G\2\2\u017eD\3\2\2\2\u017f\u0180\7N\2\2\u0180\u0181\7C\2"+
"\u0181\u0182\7G\2\2\u0182F\3\2\2\2\u0183\u0184\7N\2\2\u0184\u0185\7C\2"+ "\2\u0181\u0182\7U\2\2\u0182\u0183\7V\2\2\u0183F\3\2\2\2\u0184\u0185\7"+
"\2\u0185\u0186\7U\2\2\u0186\u0187\7V\2\2\u0187H\3\2\2\2\u0188\u0189\7"+ "C\2\2\u0185\u0186\7U\2\2\u0186\u0187\7E\2\2\u0187H\3\2\2\2\u0188\u0189"+
"C\2\2\u0189\u018a\7U\2\2\u018a\u018b\7E\2\2\u018bJ\3\2\2\2\u018c\u018d"+ "\7F\2\2\u0189\u018a\7G\2\2\u018a\u018b\7U\2\2\u018b\u018c\7E\2\2\u018c"+
"\7F\2\2\u018d\u018e\7G\2\2\u018e\u018f\7U\2\2\u018f\u0190\7E\2\2\u0190"+ "J\3\2\2\2\u018d\u018e\7H\2\2\u018e\u018f\7Q\2\2\u018f\u0190\7T\2\2\u0190"+
"L\3\2\2\2\u0191\u0192\7H\2\2\u0192\u0193\7Q\2\2\u0193\u0194\7T\2\2\u0194"+ "L\3\2\2\2\u0191\u0192\7K\2\2\u0192\u0193\7P\2\2\u0193\u0194\7V\2\2\u0194"+
"N\3\2\2\2\u0195\u0196\7K\2\2\u0196\u0197\7P\2\2\u0197\u0198\7V\2\2\u0198"+ "\u0195\7G\2\2\u0195\u0196\7I\2\2\u0196\u0197\7G\2\2\u0197\u0198\7T\2\2"+
"\u0199\7G\2\2\u0199\u019a\7I\2\2\u019a\u019b\7G\2\2\u019b\u019c\7T\2\2"+ "\u0198N\3\2\2\2\u0199\u019a\7L\2\2\u019a\u019b\7Q\2\2\u019b\u019c\7K\2"+
"\u019cP\3\2\2\2\u019d\u019e\7L\2\2\u019e\u019f\7Q\2\2\u019f\u01a0\7K\2"+ "\2\u019c\u019d\7P\2\2\u019dP\3\2\2\2\u019e\u019f\7E\2\2\u019f\u01a0\7"+
"\2\u01a0\u01a1\7P\2\2\u01a1R\3\2\2\2\u01a2\u01a3\7E\2\2\u01a3\u01a4\7"+ "T\2\2\u01a0\u01a1\7Q\2\2\u01a1\u01a2\7U\2\2\u01a2\u01a3\7U\2\2\u01a3R"+
"T\2\2\u01a4\u01a5\7Q\2\2\u01a5\u01a6\7U\2\2\u01a6\u01a7\7U\2\2\u01a7T"+ "\3\2\2\2\u01a4\u01a5\7Q\2\2\u01a5\u01a6\7W\2\2\u01a6\u01a7\7V\2\2\u01a7"+
"\3\2\2\2\u01a8\u01a9\7Q\2\2\u01a9\u01aa\7W\2\2\u01aa\u01ab\7V\2\2\u01ab"+ "\u01a8\7G\2\2\u01a8\u01a9\7T\2\2\u01a9T\3\2\2\2\u01aa\u01ab\7K\2\2\u01ab"+
"\u01ac\7G\2\2\u01ac\u01ad\7T\2\2\u01adV\3\2\2\2\u01ae\u01af\7K\2\2\u01af"+ "\u01ac\7P\2\2\u01ac\u01ad\7P\2\2\u01ad\u01ae\7G\2\2\u01ae\u01af\7T\2\2"+
"\u01b0\7P\2\2\u01b0\u01b1\7P\2\2\u01b1\u01b2\7G\2\2\u01b2\u01b3\7T\2\2"+ "\u01afV\3\2\2\2\u01b0\u01b1\7N\2\2\u01b1\u01b2\7G\2\2\u01b2\u01b3\7H\2"+
"\u01b3X\3\2\2\2\u01b4\u01b5\7N\2\2\u01b5\u01b6\7G\2\2\u01b6\u01b7\7H\2"+ "\2\u01b3\u01b4\7V\2\2\u01b4X\3\2\2\2\u01b5\u01b6\7T\2\2\u01b6\u01b7\7"+
"\2\u01b7\u01b8\7V\2\2\u01b8Z\3\2\2\2\u01b9\u01ba\7T\2\2\u01ba\u01bb\7"+ "K\2\2\u01b7\u01b8\7I\2\2\u01b8\u01b9\7J\2\2\u01b9\u01ba\7V\2\2\u01baZ"+
"K\2\2\u01bb\u01bc\7I\2\2\u01bc\u01bd\7J\2\2\u01bd\u01be\7V\2\2\u01be\\"+ "\3\2\2\2\u01bb\u01bc\7H\2\2\u01bc\u01bd\7W\2\2\u01bd\u01be\7N\2\2\u01be"+
"\3\2\2\2\u01bf\u01c0\7H\2\2\u01c0\u01c1\7W\2\2\u01c1\u01c2\7N\2\2\u01c2"+ "\u01bf\7N\2\2\u01bf\\\3\2\2\2\u01c0\u01c1\7P\2\2\u01c1\u01c2\7C\2\2\u01c2"+
"\u01c3\7N\2\2\u01c3^\3\2\2\2\u01c4\u01c5\7P\2\2\u01c5\u01c6\7C\2\2\u01c6"+ "\u01c3\7V\2\2\u01c3\u01c4\7W\2\2\u01c4\u01c5\7T\2\2\u01c5\u01c6\7C\2\2"+
"\u01c7\7V\2\2\u01c7\u01c8\7W\2\2\u01c8\u01c9\7T\2\2\u01c9\u01ca\7C\2\2"+ "\u01c6\u01c7\7N\2\2\u01c7^\3\2\2\2\u01c8\u01c9\7W\2\2\u01c9\u01ca\7U\2"+
"\u01ca\u01cb\7N\2\2\u01cb`\3\2\2\2\u01cc\u01cd\7W\2\2\u01cd\u01ce\7U\2"+ "\2\u01ca\u01cb\7K\2\2\u01cb\u01cc\7P\2\2\u01cc\u01cd\7I\2\2\u01cd`\3\2"+
"\2\u01ce\u01cf\7K\2\2\u01cf\u01d0\7P\2\2\u01d0\u01d1\7I\2\2\u01d1b\3\2"+ "\2\2\u01ce\u01cf\7Q\2\2\u01cf\u01d0\7P\2\2\u01d0b\3\2\2\2\u01d1\u01d2"+
"\2\2\u01d2\u01d3\7Q\2\2\u01d3\u01d4\7P\2\2\u01d4d\3\2\2\2\u01d5\u01d6"+ "\7Y\2\2\u01d2\u01d3\7K\2\2\u01d3\u01d4\7V\2\2\u01d4\u01d5\7J\2\2\u01d5"+
"\7Y\2\2\u01d6\u01d7\7K\2\2\u01d7\u01d8\7V\2\2\u01d8\u01d9\7J\2\2\u01d9"+ "d\3\2\2\2\u01d6\u01d7\7V\2\2\u01d7\u01d8\7C\2\2\u01d8\u01d9\7D\2\2\u01d9"+
"f\3\2\2\2\u01da\u01db\7V\2\2\u01db\u01dc\7C\2\2\u01dc\u01dd\7D\2\2\u01dd"+ "\u01da\7N\2\2\u01da\u01db\7G\2\2\u01dbf\3\2\2\2\u01dc\u01dd\7K\2\2\u01dd"+
"\u01de\7N\2\2\u01de\u01df\7G\2\2\u01dfh\3\2\2\2\u01e0\u01e1\7K\2\2\u01e1"+ "\u01de\7P\2\2\u01de\u01df\7V\2\2\u01df\u01e0\7Q\2\2\u01e0h\3\2\2\2\u01e1"+
"\u01e2\7P\2\2\u01e2\u01e3\7V\2\2\u01e3\u01e4\7Q\2\2\u01e4j\3\2\2\2\u01e5"+ "\u01e2\7F\2\2\u01e2\u01e3\7G\2\2\u01e3\u01e4\7U\2\2\u01e4\u01e5\7E\2\2"+
"\u01e6\7F\2\2\u01e6\u01e7\7G\2\2\u01e7\u01e8\7U\2\2\u01e8\u01e9\7E\2\2"+ "\u01e5\u01e6\7T\2\2\u01e6\u01e7\7K\2\2\u01e7\u01e8\7D\2\2\u01e8\u01e9"+
"\u01e9\u01ea\7T\2\2\u01ea\u01eb\7K\2\2\u01eb\u01ec\7D\2\2\u01ec\u01ed"+ "\7G\2\2\u01e9j\3\2\2\2\u01ea\u01eb\7Q\2\2\u01eb\u01ec\7R\2\2\u01ec\u01ed"+
"\7G\2\2\u01edl\3\2\2\2\u01ee\u01ef\7Q\2\2\u01ef\u01f0\7R\2\2\u01f0\u01f1"+ "\7V\2\2\u01ed\u01ee\7K\2\2\u01ee\u01ef\7Q\2\2\u01ef\u01f0\7P\2\2\u01f0"+
"\7V\2\2\u01f1\u01f2\7K\2\2\u01f2\u01f3\7Q\2\2\u01f3\u01f4\7P\2\2\u01f4"+ "l\3\2\2\2\u01f1\u01f2\7G\2\2\u01f2\u01f3\7Z\2\2\u01f3\u01f4\7R\2\2\u01f4"+
"n\3\2\2\2\u01f5\u01f6\7G\2\2\u01f6\u01f7\7Z\2\2\u01f7\u01f8\7R\2\2\u01f8"+ "\u01f5\7N\2\2\u01f5\u01f6\7C\2\2\u01f6\u01f7\7K\2\2\u01f7\u01f8\7P\2\2"+
"\u01f9\7N\2\2\u01f9\u01fa\7C\2\2\u01fa\u01fb\7K\2\2\u01fb\u01fc\7P\2\2"+ "\u01f8n\3\2\2\2\u01f9\u01fa\7C\2\2\u01fa\u01fb\7P\2\2\u01fb\u01fc\7C\2"+
"\u01fcp\3\2\2\2\u01fd\u01fe\7C\2\2\u01fe\u01ff\7P\2\2\u01ff\u0200\7C\2"+ "\2\u01fc\u01fd\7N\2\2\u01fd\u01fe\7[\2\2\u01fe\u01ff\7\\\2\2\u01ff\u0200"+
"\2\u0200\u0201\7N\2\2\u0201\u0202\7[\2\2\u0202\u0203\7\\\2\2\u0203\u0204"+ "\7G\2\2\u0200p\3\2\2\2\u0201\u0202\7H\2\2\u0202\u0203\7Q\2\2\u0203\u0204"+
"\7G\2\2\u0204r\3\2\2\2\u0205\u0206\7H\2\2\u0206\u0207\7Q\2\2\u0207\u0208"+ "\7T\2\2\u0204\u0205\7O\2\2\u0205\u0206\7C\2\2\u0206\u0207\7V\2\2\u0207"+
"\7T\2\2\u0208\u0209\7O\2\2\u0209\u020a\7C\2\2\u020a\u020b\7V\2\2\u020b"+ "r\3\2\2\2\u0208\u0209\7V\2\2\u0209\u020a\7[\2\2\u020a\u020b\7R\2\2\u020b"+
"t\3\2\2\2\u020c\u020d\7V\2\2\u020d\u020e\7[\2\2\u020e\u020f\7R\2\2\u020f"+ "\u020c\7G\2\2\u020ct\3\2\2\2\u020d\u020e\7V\2\2\u020e\u020f\7G\2\2\u020f"+
"\u0210\7G\2\2\u0210v\3\2\2\2\u0211\u0212\7V\2\2\u0212\u0213\7G\2\2\u0213"+ "\u0210\7Z\2\2\u0210\u0211\7V\2\2\u0211v\3\2\2\2\u0212\u0213\7X\2\2\u0213"+
"\u0214\7Z\2\2\u0214\u0215\7V\2\2\u0215x\3\2\2\2\u0216\u0217\7X\2\2\u0217"+ "\u0214\7G\2\2\u0214\u0215\7T\2\2\u0215\u0216\7K\2\2\u0216\u0217\7H\2\2"+
"\u0218\7G\2\2\u0218\u0219\7T\2\2\u0219\u021a\7K\2\2\u021a\u021b\7H\2\2"+ "\u0217\u0218\7[\2\2\u0218x\3\2\2\2\u0219\u021a\7I\2\2\u021a\u021b\7T\2"+
"\u021b\u021c\7[\2\2\u021cz\3\2\2\2\u021d\u021e\7I\2\2\u021e\u021f\7T\2"+ "\2\u021b\u021c\7C\2\2\u021c\u021d\7R\2\2\u021d\u021e\7J\2\2\u021e\u021f"+
"\2\u021f\u0220\7C\2\2\u0220\u0221\7R\2\2\u0221\u0222\7J\2\2\u0222\u0223"+ "\7X\2\2\u021f\u0220\7K\2\2\u0220\u0221\7\\\2\2\u0221z\3\2\2\2\u0222\u0223"+
"\7X\2\2\u0223\u0224\7K\2\2\u0224\u0225\7\\\2\2\u0225|\3\2\2\2\u0226\u0227"+ "\7N\2\2\u0223\u0224\7Q\2\2\u0224\u0225\7I\2\2\u0225\u0226\7K\2\2\u0226"+
"\7N\2\2\u0227\u0228\7Q\2\2\u0228\u0229\7I\2\2\u0229\u022a\7K\2\2\u022a"+ "\u0227\7E\2\2\u0227\u0228\7C\2\2\u0228\u0229\7N\2\2\u0229|\3\2\2\2\u022a"+
"\u022b\7E\2\2\u022b\u022c\7C\2\2\u022c\u022d\7N\2\2\u022d~\3\2\2\2\u022e"+ "\u022b\7R\2\2\u022b\u022c\7J\2\2\u022c\u022d\7[\2\2\u022d\u022e\7U\2\2"+
"\u022f\7R\2\2\u022f\u0230\7J\2\2\u0230\u0231\7[\2\2\u0231\u0232\7U\2\2"+ "\u022e\u022f\7K\2\2\u022f\u0230\7E\2\2\u0230\u0231\7C\2\2\u0231\u0232"+
"\u0232\u0233\7K\2\2\u0233\u0234\7E\2\2\u0234\u0235\7C\2\2\u0235\u0236"+ "\7N\2\2\u0232~\3\2\2\2\u0233\u0234\7U\2\2\u0234\u0235\7J\2\2\u0235\u0236"+
"\7N\2\2\u0236\u0080\3\2\2\2\u0237\u0238\7U\2\2\u0238\u0239\7J\2\2\u0239"+ "\7Q\2\2\u0236\u0237\7Y\2\2\u0237\u0080\3\2\2\2\u0238\u0239\7V\2\2\u0239"+
"\u023a\7Q\2\2\u023a\u023b\7Y\2\2\u023b\u0082\3\2\2\2\u023c\u023d\7V\2"+ "\u023a\7C\2\2\u023a\u023b\7D\2\2\u023b\u023c\7N\2\2\u023c\u023d\7G\2\2"+
"\2\u023d\u023e\7C\2\2\u023e\u023f\7D\2\2\u023f\u0240\7N\2\2\u0240\u0241"+ "\u023d\u023e\7U\2\2\u023e\u0082\3\2\2\2\u023f\u0240\7E\2\2\u0240\u0241"+
"\7G\2\2\u0241\u0242\7U\2\2\u0242\u0084\3\2\2\2\u0243\u0244\7E\2\2\u0244"+ "\7Q\2\2\u0241\u0242\7N\2\2\u0242\u0243\7W\2\2\u0243\u0244\7O\2\2\u0244"+
"\u0245\7Q\2\2\u0245\u0246\7N\2\2\u0246\u0247\7W\2\2\u0247\u0248\7O\2\2"+ "\u0245\7P\2\2\u0245\u0246\7U\2\2\u0246\u0084\3\2\2\2\u0247\u0248\7E\2"+
"\u0248\u0249\7P\2\2\u0249\u024a\7U\2\2\u024a\u0086\3\2\2\2\u024b\u024c"+ "\2\u0248\u0249\7Q\2\2\u0249\u024a\7N\2\2\u024a\u024b\7W\2\2\u024b\u024c"+
"\7E\2\2\u024c\u024d\7Q\2\2\u024d\u024e\7N\2\2\u024e\u024f\7W\2\2\u024f"+ "\7O\2\2\u024c\u024d\7P\2\2\u024d\u0086\3\2\2\2\u024e\u024f\7H\2\2\u024f"+
"\u0250\7O\2\2\u0250\u0251\7P\2\2\u0251\u0088\3\2\2\2\u0252\u0253\7H\2"+ "\u0250\7W\2\2\u0250\u0251\7P\2\2\u0251\u0252\7E\2\2\u0252\u0253\7V\2\2"+
"\2\u0253\u0254\7W\2\2\u0254\u0255\7P\2\2\u0255\u0256\7E\2\2\u0256\u0257"+ "\u0253\u0254\7K\2\2\u0254\u0255\7Q\2\2\u0255\u0256\7P\2\2\u0256\u0257"+
"\7V\2\2\u0257\u0258\7K\2\2\u0258\u0259\7Q\2\2\u0259\u025a\7P\2\2\u025a"+ "\7U\2\2\u0257\u0088\3\2\2\2\u0258\u0259\7V\2\2\u0259\u025a\7Q\2\2\u025a"+
"\u025b\7U\2\2\u025b\u008a\3\2\2\2\u025c\u025d\7V\2\2\u025d\u025e\7Q\2"+ "\u008a\3\2\2\2\u025b\u025c\7F\2\2\u025c\u025d\7G\2\2\u025d\u025e\7D\2"+
"\2\u025e\u008c\3\2\2\2\u025f\u0260\7F\2\2\u0260\u0261\7G\2\2\u0261\u0262"+ "\2\u025e\u025f\7W\2\2\u025f\u0260\7I\2\2\u0260\u008c\3\2\2\2\u0261\u0262"+
"\7D\2\2\u0262\u0263\7W\2\2\u0263\u0264\7I\2\2\u0264\u008e\3\2\2\2\u0265"+ "\7R\2\2\u0262\u0263\7N\2\2\u0263\u0264\7C\2\2\u0264\u0265\7P\2\2\u0265"+
"\u0266\7R\2\2\u0266\u0267\7N\2\2\u0267\u0268\7C\2\2\u0268\u0269\7P\2\2"+ "\u008e\3\2\2\2\u0266\u0267\7R\2\2\u0267\u0268\7C\2\2\u0268\u0269\7T\2"+
"\u0269\u0090\3\2\2\2\u026a\u026b\7R\2\2\u026b\u026c\7C\2\2\u026c\u026d"+ "\2\u0269\u026a\7U\2\2\u026a\u026b\7G\2\2\u026b\u026c\7F\2\2\u026c\u0090"+
"\7T\2\2\u026d\u026e\7U\2\2\u026e\u026f\7G\2\2\u026f\u0270\7F\2\2\u0270"+ "\3\2\2\2\u026d\u026e\7C\2\2\u026e\u026f\7P\2\2\u026f\u0270\7C\2\2\u0270"+
"\u0092\3\2\2\2\u0271\u0272\7C\2\2\u0272\u0273\7P\2\2\u0273\u0274\7C\2"+ "\u0271\7N\2\2\u0271\u0272\7[\2\2\u0272\u0273\7\\\2\2\u0273\u0274\7G\2"+
"\2\u0274\u0275\7N\2\2\u0275\u0276\7[\2\2\u0276\u0277\7\\\2\2\u0277\u0278"+ "\2\u0274\u0275\7F\2\2\u0275\u0092\3\2\2\2\u0276\u0277\7Q\2\2\u0277\u0278"+
"\7G\2\2\u0278\u0279\7F\2\2\u0279\u0094\3\2\2\2\u027a\u027b\7Q\2\2\u027b"+ "\7R\2\2\u0278\u0279\7V\2\2\u0279\u027a\7K\2\2\u027a\u027b\7O\2\2\u027b"+
"\u027c\7R\2\2\u027c\u027d\7V\2\2\u027d\u027e\7K\2\2\u027e\u027f\7O\2\2"+ "\u027c\7K\2\2\u027c\u027d\7\\\2\2\u027d\u027e\7G\2\2\u027e\u027f\7F\2"+
"\u027f\u0280\7K\2\2\u0280\u0281\7\\\2\2\u0281\u0282\7G\2\2\u0282\u0283"+ "\2\u027f\u0094\3\2\2\2\u0280\u0281\7O\2\2\u0281\u0282\7C\2\2\u0282\u0283"+
"\7F\2\2\u0283\u0096\3\2\2\2\u0284\u0285\7O\2\2\u0285\u0286\7C\2\2\u0286"+ "\7R\2\2\u0283\u0284\7R\2\2\u0284\u0285\7G\2\2\u0285\u0286\7F\2\2\u0286"+
"\u0287\7R\2\2\u0287\u0288\7R\2\2\u0288\u0289\7G\2\2\u0289\u028a\7F\2\2"+ "\u0096\3\2\2\2\u0287\u0288\7G\2\2\u0288\u0289\7Z\2\2\u0289\u028a\7G\2"+
"\u028a\u0098\3\2\2\2\u028b\u028c\7G\2\2\u028c\u028d\7Z\2\2\u028d\u028e"+ "\2\u028a\u028b\7E\2\2\u028b\u028c\7W\2\2\u028c\u028d\7V\2\2\u028d\u028e"+
"\7G\2\2\u028e\u028f\7E\2\2\u028f\u0290\7W\2\2\u0290\u0291\7V\2\2\u0291"+ "\7C\2\2\u028e\u028f\7D\2\2\u028f\u0290\7N\2\2\u0290\u0291\7G\2\2\u0291"+
"\u0292\7C\2\2\u0292\u0293\7D\2\2\u0293\u0294\7N\2\2\u0294\u0295\7G\2\2"+ "\u0098\3\2\2\2\u0292\u0293\7W\2\2\u0293\u0294\7U\2\2\u0294\u0295\7G\2"+
"\u0295\u009a\3\2\2\2\u0296\u0297\7W\2\2\u0297\u0298\7U\2\2\u0298\u0299"+ "\2\u0295\u009a\3\2\2\2\u0296\u0297\7U\2\2\u0297\u0298\7G\2\2\u0298\u0299"+
"\7G\2\2\u0299\u009c\3\2\2\2\u029a\u029b\7U\2\2\u029b\u029c\7G\2\2\u029c"+ "\7V\2\2\u0299\u009c\3\2\2\2\u029a\u029b\7T\2\2\u029b\u029c\7G\2\2\u029c"+
"\u029d\7V\2\2\u029d\u009e\3\2\2\2\u029e\u029f\7T\2\2\u029f\u02a0\7G\2"+ "\u029d\7U\2\2\u029d\u029e\7G\2\2\u029e\u029f\7V\2\2\u029f\u009e\3\2\2"+
"\2\u02a0\u02a1\7U\2\2\u02a1\u02a2\7G\2\2\u02a2\u02a3\7V\2\2\u02a3\u00a0"+ "\2\u02a0\u02a1\7U\2\2\u02a1\u02a2\7G\2\2\u02a2\u02a3\7U\2\2\u02a3\u02a4"+
"\3\2\2\2\u02a4\u02a5\7U\2\2\u02a5\u02a6\7G\2\2\u02a6\u02a7\7U\2\2\u02a7"+ "\7U\2\2\u02a4\u02a5\7K\2\2\u02a5\u02a6\7Q\2\2\u02a6\u02a7\7P\2\2\u02a7"+
"\u02a8\7U\2\2\u02a8\u02a9\7K\2\2\u02a9\u02aa\7Q\2\2\u02aa\u02ab\7P\2\2"+ "\u00a0\3\2\2\2\u02a8\u02a9\7U\2\2\u02a9\u02aa\7E\2\2\u02aa\u02ab\7J\2"+
"\u02ab\u00a2\3\2\2\2\u02ac\u02ad\7U\2\2\u02ad\u02ae\7E\2\2\u02ae\u02af"+ "\2\u02ab\u02ac\7G\2\2\u02ac\u02ad\7O\2\2\u02ad\u02ae\7C\2\2\u02ae\u02af"+
"\7J\2\2\u02af\u02b0\7G\2\2\u02b0\u02b1\7O\2\2\u02b1\u02b2\7C\2\2\u02b2"+ "\7U\2\2\u02af\u00a2\3\2\2\2\u02b0\u02b1\7G\2\2\u02b1\u02b2\7Z\2\2\u02b2"+
"\u02b3\7U\2\2\u02b3\u00a4\3\2\2\2\u02b4\u02b5\7G\2\2\u02b5\u02b6\7Z\2"+ "\u02b3\7V\2\2\u02b3\u02b4\7T\2\2\u02b4\u02b5\7C\2\2\u02b5\u02b6\7E\2\2"+
"\2\u02b6\u02b7\7V\2\2\u02b7\u02b8\7T\2\2\u02b8\u02b9\7C\2\2\u02b9\u02ba"+ "\u02b6\u02b7\7V\2\2\u02b7\u00a4\3\2\2\2\u02b8\u02b9\7S\2\2\u02b9\u02ba"+
"\7E\2\2\u02ba\u02bb\7V\2\2\u02bb\u00a6\3\2\2\2\u02bc\u02bd\7S\2\2\u02bd"+ "\7W\2\2\u02ba\u02bb\7G\2\2\u02bb\u02bc\7T\2\2\u02bc\u02bd\7[\2\2\u02bd"+
"\u02be\7W\2\2\u02be\u02bf\7G\2\2\u02bf\u02c0\7T\2\2\u02c0\u02c1\7[\2\2"+ "\u00a6\3\2\2\2\u02be\u02bf\7O\2\2\u02bf\u02c0\7C\2\2\u02c0\u02c1\7V\2"+
"\u02c1\u00a8\3\2\2\2\u02c2\u02c3\7O\2\2\u02c3\u02c4\7C\2\2\u02c4\u02c5"+ "\2\u02c1\u02c2\7E\2\2\u02c2\u02c3\7J\2\2\u02c3\u00a8\3\2\2\2\u02c4\u02c5"+
"\7V\2\2\u02c5\u02c6\7E\2\2\u02c6\u02c7\7J\2\2\u02c7\u00aa\3\2\2\2\u02c8"+ "\7E\2\2\u02c5\u02c6\7C\2\2\u02c6\u02c7\7U\2\2\u02c7\u02c8\7V\2\2\u02c8"+
"\u02c9\7E\2\2\u02c9\u02ca\7C\2\2\u02ca\u02cb\7U\2\2\u02cb\u02cc\7V\2\2"+ "\u00aa\3\2\2\2\u02c9\u02ca\7?\2\2\u02ca\u00ac\3\2\2\2\u02cb\u02cc\7>\2"+
"\u02cc\u00ac\3\2\2\2\u02cd\u02ce\7?\2\2\u02ce\u00ae\3\2\2\2\u02cf\u02d0"+ "\2\u02cc\u02d3\7@\2\2\u02cd\u02ce\7#\2\2\u02ce\u02d3\7?\2\2\u02cf\u02d0"+
"\7>\2\2\u02d0\u02d7\7@\2\2\u02d1\u02d2\7#\2\2\u02d2\u02d7\7?\2\2\u02d3"+ "\7>\2\2\u02d0\u02d1\7?\2\2\u02d1\u02d3\7@\2\2\u02d2\u02cb\3\2\2\2\u02d2"+
"\u02d4\7>\2\2\u02d4\u02d5\7?\2\2\u02d5\u02d7\7@\2\2\u02d6\u02cf\3\2\2"+ "\u02cd\3\2\2\2\u02d2\u02cf\3\2\2\2\u02d3\u00ae\3\2\2\2\u02d4\u02d5\7>"+
"\2\u02d6\u02d1\3\2\2\2\u02d6\u02d3\3\2\2\2\u02d7\u00b0\3\2\2\2\u02d8\u02d9"+ "\2\2\u02d5\u00b0\3\2\2\2\u02d6\u02d7\7>\2\2\u02d7\u02d8\7?\2\2\u02d8\u00b2"+
"\7>\2\2\u02d9\u00b2\3\2\2\2\u02da\u02db\7>\2\2\u02db\u02dc\7?\2\2\u02dc"+ "\3\2\2\2\u02d9\u02da\7@\2\2\u02da\u00b4\3\2\2\2\u02db\u02dc\7@\2\2\u02dc"+
"\u00b4\3\2\2\2\u02dd\u02de\7@\2\2\u02de\u00b6\3\2\2\2\u02df\u02e0\7@\2"+ "\u02dd\7?\2\2\u02dd\u00b6\3\2\2\2\u02de\u02df\7-\2\2\u02df\u00b8\3\2\2"+
"\2\u02e0\u02e1\7?\2\2\u02e1\u00b8\3\2\2\2\u02e2\u02e3\7-\2\2\u02e3\u00ba"+ "\2\u02e0\u02e1\7/\2\2\u02e1\u00ba\3\2\2\2\u02e2\u02e3\7,\2\2\u02e3\u00bc"+
"\3\2\2\2\u02e4\u02e5\7/\2\2\u02e5\u00bc\3\2\2\2\u02e6\u02e7\7,\2\2\u02e7"+ "\3\2\2\2\u02e4\u02e5\7\61\2\2\u02e5\u00be\3\2\2\2\u02e6\u02e7\7\'\2\2"+
"\u00be\3\2\2\2\u02e8\u02e9\7\61\2\2\u02e9\u00c0\3\2\2\2\u02ea\u02eb\7"+ "\u02e7\u00c0\3\2\2\2\u02e8\u02e9\7~\2\2\u02e9\u02ea\7~\2\2\u02ea\u00c2"+
"\'\2\2\u02eb\u00c2\3\2\2\2\u02ec\u02ed\7~\2\2\u02ed\u02ee\7~\2\2\u02ee"+ "\3\2\2\2\u02eb\u02f1\7)\2\2\u02ec\u02f0\n\2\2\2\u02ed\u02ee\7)\2\2\u02ee"+
"\u00c4\3\2\2\2\u02ef\u02f5\7)\2\2\u02f0\u02f4\n\2\2\2\u02f1\u02f2\7)\2"+ "\u02f0\7)\2\2\u02ef\u02ec\3\2\2\2\u02ef\u02ed\3\2\2\2\u02f0\u02f3\3\2"+
"\2\u02f2\u02f4\7)\2\2\u02f3\u02f0\3\2\2\2\u02f3\u02f1\3\2\2\2\u02f4\u02f7"+ "\2\2\u02f1\u02ef\3\2\2\2\u02f1\u02f2\3\2\2\2\u02f2\u02f4\3\2\2\2\u02f3"+
"\3\2\2\2\u02f5\u02f3\3\2\2\2\u02f5\u02f6\3\2\2\2\u02f6\u02f8\3\2\2\2\u02f7"+ "\u02f1\3\2\2\2\u02f4\u02f5\7)\2\2\u02f5\u00c4\3\2\2\2\u02f6\u02f8\5\u00d3"+
"\u02f5\3\2\2\2\u02f8\u02f9\7)\2\2\u02f9\u00c6\3\2\2\2\u02fa\u02fc\5\u00d5"+ "j\2\u02f7\u02f6\3\2\2\2\u02f8\u02f9\3\2\2\2\u02f9\u02f7\3\2\2\2\u02f9"+
"k\2\u02fb\u02fa\3\2\2\2\u02fc\u02fd\3\2\2\2\u02fd\u02fb\3\2\2\2\u02fd"+ "\u02fa\3\2\2\2\u02fa\u00c6\3\2\2\2\u02fb\u02fd\5\u00d3j\2\u02fc\u02fb"+
"\u02fe\3\2\2\2\u02fe\u00c8\3\2\2\2\u02ff\u0301\5\u00d5k\2\u0300\u02ff"+ "\3\2\2\2\u02fd\u02fe\3\2\2\2\u02fe\u02fc\3\2\2\2\u02fe\u02ff\3\2\2\2\u02ff"+
"\3\2\2\2\u0301\u0302\3\2\2\2\u0302\u0300\3\2\2\2\u0302\u0303\3\2\2\2\u0303"+ "\u0300\3\2\2\2\u0300\u0304\7\60\2\2\u0301\u0303\5\u00d3j\2\u0302\u0301"+
"\u0304\3\2\2\2\u0304\u0308\7\60\2\2\u0305\u0307\5\u00d5k\2\u0306\u0305"+ "\3\2\2\2\u0303\u0306\3\2\2\2\u0304\u0302\3\2\2\2\u0304\u0305\3\2\2\2\u0305"+
"\3\2\2\2\u0307\u030a\3\2\2\2\u0308\u0306\3\2\2\2\u0308\u0309\3\2\2\2\u0309"+ "\u0326\3\2\2\2\u0306\u0304\3\2\2\2\u0307\u0309\7\60\2\2\u0308\u030a\5"+
"\u032a\3\2\2\2\u030a\u0308\3\2\2\2\u030b\u030d\7\60\2\2\u030c\u030e\5"+ "\u00d3j\2\u0309\u0308\3\2\2\2\u030a\u030b\3\2\2\2\u030b\u0309\3\2\2\2"+
"\u00d5k\2\u030d\u030c\3\2\2\2\u030e\u030f\3\2\2\2\u030f\u030d\3\2\2\2"+ "\u030b\u030c\3\2\2\2\u030c\u0326\3\2\2\2\u030d\u030f\5\u00d3j\2\u030e"+
"\u030f\u0310\3\2\2\2\u0310\u032a\3\2\2\2\u0311\u0313\5\u00d5k\2\u0312"+ "\u030d\3\2\2\2\u030f\u0310\3\2\2\2\u0310\u030e\3\2\2\2\u0310\u0311\3\2"+
"\u0311\3\2\2\2\u0313\u0314\3\2\2\2\u0314\u0312\3\2\2\2\u0314\u0315\3\2"+ "\2\2\u0311\u0319\3\2\2\2\u0312\u0316\7\60\2\2\u0313\u0315\5\u00d3j\2\u0314"+
"\2\2\u0315\u031d\3\2\2\2\u0316\u031a\7\60\2\2\u0317\u0319\5\u00d5k\2\u0318"+ "\u0313\3\2\2\2\u0315\u0318\3\2\2\2\u0316\u0314\3\2\2\2\u0316\u0317\3\2"+
"\u0317\3\2\2\2\u0319\u031c\3\2\2\2\u031a\u0318\3\2\2\2\u031a\u031b\3\2"+ "\2\2\u0317\u031a\3\2\2\2\u0318\u0316\3\2\2\2\u0319\u0312\3\2\2\2\u0319"+
"\2\2\u031b\u031e\3\2\2\2\u031c\u031a\3\2\2\2\u031d\u0316\3\2\2\2\u031d"+ "\u031a\3\2\2\2\u031a\u031b\3\2\2\2\u031b\u031c\5\u00d1i\2\u031c\u0326"+
"\u031e\3\2\2\2\u031e\u031f\3\2\2\2\u031f\u0320\5\u00d3j\2\u0320\u032a"+ "\3\2\2\2\u031d\u031f\7\60\2\2\u031e\u0320\5\u00d3j\2\u031f\u031e\3\2\2"+
"\3\2\2\2\u0321\u0323\7\60\2\2\u0322\u0324\5\u00d5k\2\u0323\u0322\3\2\2"+ "\2\u0320\u0321\3\2\2\2\u0321\u031f\3\2\2\2\u0321\u0322\3\2\2\2\u0322\u0323"+
"\2\u0324\u0325\3\2\2\2\u0325\u0323\3\2\2\2\u0325\u0326\3\2\2\2\u0326\u0327"+ "\3\2\2\2\u0323\u0324\5\u00d1i\2\u0324\u0326\3\2\2\2\u0325\u02fc\3\2\2"+
"\3\2\2\2\u0327\u0328\5\u00d3j\2\u0328\u032a\3\2\2\2\u0329\u0300\3\2\2"+ "\2\u0325\u0307\3\2\2\2\u0325\u030e\3\2\2\2\u0325\u031d\3\2\2\2\u0326\u00c8"+
"\2\u0329\u030b\3\2\2\2\u0329\u0312\3\2\2\2\u0329\u0321\3\2\2\2\u032a\u00ca"+ "\3\2\2\2\u0327\u032a\5\u00d5k\2\u0328\u032a\7a\2\2\u0329\u0327\3\2\2\2"+
"\3\2\2\2\u032b\u032e\5\u00d7l\2\u032c\u032e\7a\2\2\u032d\u032b\3\2\2\2"+ "\u0329\u0328\3\2\2\2\u032a\u0330\3\2\2\2\u032b\u032f\5\u00d5k\2\u032c"+
"\u032d\u032c\3\2\2\2\u032e\u0334\3\2\2\2\u032f\u0333\5\u00d7l\2\u0330"+ "\u032f\5\u00d3j\2\u032d\u032f\t\3\2\2\u032e\u032b\3\2\2\2\u032e\u032c"+
"\u0333\5\u00d5k\2\u0331\u0333\t\3\2\2\u0332\u032f\3\2\2\2\u0332\u0330"+ "\3\2\2\2\u032e\u032d\3\2\2\2\u032f\u0332\3\2\2\2\u0330\u032e\3\2\2\2\u0330"+
"\3\2\2\2\u0332\u0331\3\2\2\2\u0333\u0336\3\2\2\2\u0334\u0332\3\2\2\2\u0334"+ "\u0331\3\2\2\2\u0331\u00ca\3\2\2\2\u0332\u0330\3\2\2\2\u0333\u0337\5\u00d3"+
"\u0335\3\2\2\2\u0335\u00cc\3\2\2\2\u0336\u0334\3\2\2\2\u0337\u033b\5\u00d5"+ "j\2\u0334\u0338\5\u00d5k\2\u0335\u0338\5\u00d3j\2\u0336\u0338\t\3\2\2"+
"k\2\u0338\u033c\5\u00d7l\2\u0339\u033c\5\u00d5k\2\u033a\u033c\t\3\2\2"+ "\u0337\u0334\3\2\2\2\u0337\u0335\3\2\2\2\u0337\u0336\3\2\2\2\u0338\u0339"+
"\u033b\u0338\3\2\2\2\u033b\u0339\3\2\2\2\u033b\u033a\3\2\2\2\u033c\u033d"+ "\3\2\2\2\u0339\u0337\3\2\2\2\u0339\u033a\3\2\2\2\u033a\u00cc\3\2\2\2\u033b"+
"\3\2\2\2\u033d\u033b\3\2\2\2\u033d\u033e\3\2\2\2\u033e\u00ce\3\2\2\2\u033f"+ "\u0340\7$\2\2\u033c\u033f\n\4\2\2\u033d\u033f\7$\2\2\u033e\u033c\3\2\2"+
"\u0344\7$\2\2\u0340\u0343\n\4\2\2\u0341\u0343\7$\2\2\u0342\u0340\3\2\2"+ "\2\u033e\u033d\3\2\2\2\u033f\u0342\3\2\2\2\u0340\u033e\3\2\2\2\u0340\u0341"+
"\2\u0342\u0341\3\2\2\2\u0343\u0346\3\2\2\2\u0344\u0342\3\2\2\2\u0344\u0345"+ "\3\2\2\2\u0341\u0343\3\2\2\2\u0342\u0340\3\2\2\2\u0343\u0344\7$\2\2\u0344"+
"\3\2\2\2\u0345\u0347\3\2\2\2\u0346\u0344\3\2\2\2\u0347\u0348\7$\2\2\u0348"+ "\u00ce\3\2\2\2\u0345\u034b\7b\2\2\u0346\u034a\n\5\2\2\u0347\u0348\7b\2"+
"\u00d0\3\2\2\2\u0349\u034f\7b\2\2\u034a\u034e\n\5\2\2\u034b\u034c\7b\2"+ "\2\u0348\u034a\7b\2\2\u0349\u0346\3\2\2\2\u0349\u0347\3\2\2\2\u034a\u034d"+
"\2\u034c\u034e\7b\2\2\u034d\u034a\3\2\2\2\u034d\u034b\3\2\2\2\u034e\u0351"+ "\3\2\2\2\u034b\u0349\3\2\2\2\u034b\u034c\3\2\2\2\u034c\u034e\3\2\2\2\u034d"+
"\3\2\2\2\u034f\u034d\3\2\2\2\u034f\u0350\3\2\2\2\u0350\u0352\3\2\2\2\u0351"+ "\u034b\3\2\2\2\u034e\u034f\7b\2\2\u034f\u00d0\3\2\2\2\u0350\u0352\7G\2"+
"\u034f\3\2\2\2\u0352\u0353\7b\2\2\u0353\u00d2\3\2\2\2\u0354\u0356\7G\2"+ "\2\u0351\u0353\t\6\2\2\u0352\u0351\3\2\2\2\u0352\u0353\3\2\2\2\u0353\u0355"+
"\2\u0355\u0357\t\6\2\2\u0356\u0355\3\2\2\2\u0356\u0357\3\2\2\2\u0357\u0359"+ "\3\2\2\2\u0354\u0356\5\u00d3j\2\u0355\u0354\3\2\2\2\u0356\u0357\3\2\2"+
"\3\2\2\2\u0358\u035a\5\u00d5k\2\u0359\u0358\3\2\2\2\u035a\u035b\3\2\2"+ "\2\u0357\u0355\3\2\2\2\u0357\u0358\3\2\2\2\u0358\u00d2\3\2\2\2\u0359\u035a"+
"\2\u035b\u0359\3\2\2\2\u035b\u035c\3\2\2\2\u035c\u00d4\3\2\2\2\u035d\u035e"+ "\t\7\2\2\u035a\u00d4\3\2\2\2\u035b\u035c\t\b\2\2\u035c\u00d6\3\2\2\2\u035d"+
"\t\7\2\2\u035e\u00d6\3\2\2\2\u035f\u0360\t\b\2\2\u0360\u00d8\3\2\2\2\u0361"+ "\u035e\7/\2\2\u035e\u035f\7/\2\2\u035f\u0363\3\2\2\2\u0360\u0362\n\t\2"+
"\u0362\7/\2\2\u0362\u0363\7/\2\2\u0363\u0367\3\2\2\2\u0364\u0366\n\t\2"+ "\2\u0361\u0360\3\2\2\2\u0362\u0365\3\2\2\2\u0363\u0361\3\2\2\2\u0363\u0364"+
"\2\u0365\u0364\3\2\2\2\u0366\u0369\3\2\2\2\u0367\u0365\3\2\2\2\u0367\u0368"+ "\3\2\2\2\u0364\u0367\3\2\2\2\u0365\u0363\3\2\2\2\u0366\u0368\7\17\2\2"+
"\3\2\2\2\u0368\u036b\3\2\2\2\u0369\u0367\3\2\2\2\u036a\u036c\7\17\2\2"+ "\u0367\u0366\3\2\2\2\u0367\u0368\3\2\2\2\u0368\u036a\3\2\2\2\u0369\u036b"+
"\u036b\u036a\3\2\2\2\u036b\u036c\3\2\2\2\u036c\u036e\3\2\2\2\u036d\u036f"+ "\7\f\2\2\u036a\u0369\3\2\2\2\u036a\u036b\3\2\2\2\u036b\u036c\3\2\2\2\u036c"+
"\7\f\2\2\u036e\u036d\3\2\2\2\u036e\u036f\3\2\2\2\u036f\u0370\3\2\2\2\u0370"+ "\u036d\bl\2\2\u036d\u00d8\3\2\2\2\u036e\u036f\7\61\2\2\u036f\u0370\7,"+
"\u0371\bm\2\2\u0371\u00da\3\2\2\2\u0372\u0373\7\61\2\2\u0373\u0374\7,"+ "\2\2\u0370\u0375\3\2\2\2\u0371\u0374\5\u00d9m\2\u0372\u0374\13\2\2\2\u0373"+
"\2\2\u0374\u0379\3\2\2\2\u0375\u0378\5\u00dbn\2\u0376\u0378\13\2\2\2\u0377"+ "\u0371\3\2\2\2\u0373\u0372\3\2\2\2\u0374\u0377\3\2\2\2\u0375\u0376\3\2"+
"\u0375\3\2\2\2\u0377\u0376\3\2\2\2\u0378\u037b\3\2\2\2\u0379\u037a\3\2"+ "\2\2\u0375\u0373\3\2\2\2\u0376\u0378\3\2\2\2\u0377\u0375\3\2\2\2\u0378"+
"\2\2\u0379\u0377\3\2\2\2\u037a\u037c\3\2\2\2\u037b\u0379\3\2\2\2\u037c"+ "\u0379\7,\2\2\u0379\u037a\7\61\2\2\u037a\u037b\3\2\2\2\u037b\u037c\bm"+
"\u037d\7,\2\2\u037d\u037e\7\61\2\2\u037e\u037f\3\2\2\2\u037f\u0380\bn"+ "\2\2\u037c\u00da\3\2\2\2\u037d\u037f\t\n\2\2\u037e\u037d\3\2\2\2\u037f"+
"\2\2\u0380\u00dc\3\2\2\2\u0381\u0383\t\n\2\2\u0382\u0381\3\2\2\2\u0383"+ "\u0380\3\2\2\2\u0380\u037e\3\2\2\2\u0380\u0381\3\2\2\2\u0381\u0382\3\2"+
"\u0384\3\2\2\2\u0384\u0382\3\2\2\2\u0384\u0385\3\2\2\2\u0385\u0386\3\2"+ "\2\2\u0382\u0383\bn\2\2\u0383\u00dc\3\2\2\2\u0384\u0385\13\2\2\2\u0385"+
"\2\2\u0386\u0387\bo\2\2\u0387\u00de\3\2\2\2\u0388\u0389\13\2\2\2\u0389"+ "\u00de\3\2\2\2 \2\u02d2\u02ef\u02f1\u02f9\u02fe\u0304\u030b\u0310\u0316"+
"\u00e0\3\2\2\2 \2\u02d6\u02f3\u02f5\u02fd\u0302\u0308\u030f\u0314\u031a"+ "\u0319\u0321\u0325\u0329\u032e\u0330\u0337\u0339\u033e\u0340\u0349\u034b"+
"\u031d\u0325\u0329\u032d\u0332\u0334\u033b\u033d\u0342\u0344\u034d\u034f"+ "\u0352\u0357\u0363\u0367\u036a\u0373\u0375\u0380\3\2\3\2";
"\u0356\u035b\u0367\u036b\u036e\u0377\u0379\u0384\3\2\3\2";
public static final ATN _ATN = public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray()); new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static { static {

View File

@ -5,37 +5,27 @@
*/ */
package org.elasticsearch.xpack.sql.plan; package org.elasticsearch.xpack.sql.plan;
import java.util.Objects;
import org.elasticsearch.common.Strings;
import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.Location;
import java.util.Objects;
public class TableIdentifier { public class TableIdentifier {
private final String index, type; private final String index;
private final Location location; private final Location location;
public TableIdentifier(Location location, String index, String type) { public TableIdentifier(Location location, String index) {
this.location = location; this.location = location;
this.index = index; this.index = index;
this.type = type;
} }
public String index() { public String index() {
return index; return index;
} }
public String type() {
return type;
}
public boolean hasType() {
return Strings.hasText(type);
}
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(index, type); return Objects.hash(index);
} }
@Override @Override
@ -49,8 +39,7 @@ public class TableIdentifier {
} }
TableIdentifier other = (TableIdentifier) obj; TableIdentifier other = (TableIdentifier) obj;
return Objects.equals(index, other.index) return Objects.equals(index, other.index);
&& Objects.equals(type, other.type);
} }
public Location location() { public Location location() {
@ -62,8 +51,6 @@ public class TableIdentifier {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("[index="); builder.append("[index=");
builder.append(index); builder.append(index);
builder.append(", type=");
builder.append(type);
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
} }

View File

@ -5,13 +5,8 @@
*/ */
package org.elasticsearch.xpack.sql.plan.logical; package org.elasticsearch.xpack.sql.plan.logical;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
import org.elasticsearch.xpack.sql.analysis.catalog.EsType; import org.elasticsearch.xpack.sql.analysis.catalog.EsIndex;
import org.elasticsearch.xpack.sql.expression.Attribute; import org.elasticsearch.xpack.sql.expression.Attribute;
import org.elasticsearch.xpack.sql.expression.NestedFieldAttribute; import org.elasticsearch.xpack.sql.expression.NestedFieldAttribute;
import org.elasticsearch.xpack.sql.expression.RootFieldAttribute; import org.elasticsearch.xpack.sql.expression.RootFieldAttribute;
@ -21,20 +16,24 @@ import org.elasticsearch.xpack.sql.type.NestedType;
import org.elasticsearch.xpack.sql.type.StringType; import org.elasticsearch.xpack.sql.type.StringType;
import org.elasticsearch.xpack.sql.util.StringUtils; import org.elasticsearch.xpack.sql.util.StringUtils;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import static org.elasticsearch.xpack.sql.util.CollectionUtils.combine; import static org.elasticsearch.xpack.sql.util.CollectionUtils.combine;
public class CatalogTable extends LeafPlan { public class CatalogTable extends LeafPlan {
private final EsType type; private final EsIndex index;
private final List<Attribute> attrs; private final List<Attribute> attrs;
public CatalogTable(Location location, EsType type) { public CatalogTable(Location location, EsIndex index) {
super(location); super(location);
this.type = type; this.index = index;
attrs = flatten(location, type.mapping()).collect(toList()); attrs = flatten(location, index.mapping()).collect(toList());
} }
private static Stream<Attribute> flatten(Location location, Map<String, DataType> mapping) { private static Stream<Attribute> flatten(Location location, Map<String, DataType> mapping) {
@ -62,8 +61,8 @@ public class CatalogTable extends LeafPlan {
}); });
} }
public EsType type() { public EsIndex index() {
return type; return index;
} }
@Override @Override
@ -78,7 +77,7 @@ public class CatalogTable extends LeafPlan {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(type); return Objects.hash(index);
} }
@Override @Override
@ -92,11 +91,11 @@ public class CatalogTable extends LeafPlan {
} }
CatalogTable other = (CatalogTable) obj; CatalogTable other = (CatalogTable) obj;
return Objects.equals(type, other.type); return Objects.equals(index, other.index);
} }
@Override @Override
public String nodeString() { public String nodeString() {
return nodeName() + "[" + type + "]" + StringUtils.limitedToString(attrs); return nodeName() + "[" + index + "]" + StringUtils.limitedToString(attrs);
} }
} }

View File

@ -5,11 +5,6 @@
*/ */
package org.elasticsearch.xpack.sql.plan.logical.command; package org.elasticsearch.xpack.sql.plan.logical.command;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.elasticsearch.xpack.sql.analysis.catalog.Catalog; import org.elasticsearch.xpack.sql.analysis.catalog.Catalog;
import org.elasticsearch.xpack.sql.expression.Attribute; import org.elasticsearch.xpack.sql.expression.Attribute;
import org.elasticsearch.xpack.sql.expression.RootFieldAttribute; import org.elasticsearch.xpack.sql.expression.RootFieldAttribute;
@ -21,28 +16,27 @@ import org.elasticsearch.xpack.sql.type.CompoundDataType;
import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.type.DataType;
import org.elasticsearch.xpack.sql.type.DataTypes; import org.elasticsearch.xpack.sql.type.DataTypes;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects; import java.util.Objects;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
public class ShowColumns extends Command { public class ShowColumns extends Command {
private final String index, type; private final String index;
public ShowColumns(Location location, String index, String type) { public ShowColumns(Location location, String index) {
super(location); super(location);
this.index = index; this.index = index;
this.type = type;
} }
public String index() { public String index() {
return index; return index;
} }
public String type() {
return type;
}
@Override @Override
public List<Attribute> output() { public List<Attribute> output() {
return asList(new RootFieldAttribute(location(), "column", DataTypes.KEYWORD), return asList(new RootFieldAttribute(location(), "column", DataTypes.KEYWORD),
@ -52,7 +46,7 @@ public class ShowColumns extends Command {
@Override @Override
protected RowSetCursor execute(SqlSession session) { protected RowSetCursor execute(SqlSession session) {
Catalog catalog = session.catalog(); Catalog catalog = session.catalog();
Map<String, DataType> mapping = catalog.getType(index, type).mapping(); Map<String, DataType> mapping = catalog.getIndex(index).mapping();
List<List<?>> rows = new ArrayList<>(); List<List<?>> rows = new ArrayList<>();
fillInRows(mapping, null, rows); fillInRows(mapping, null, rows);
@ -75,7 +69,7 @@ public class ShowColumns extends Command {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(index, type); return Objects.hash(index);
} }
@Override @Override
@ -89,7 +83,6 @@ public class ShowColumns extends Command {
} }
ShowColumns other = (ShowColumns) obj; ShowColumns other = (ShowColumns) obj;
return Objects.equals(index, other.index) return Objects.equals(index, other.index);
&& Objects.equals(type, other.type);
} }
} }

View File

@ -5,7 +5,7 @@
*/ */
package org.elasticsearch.xpack.sql.plan.logical.command; package org.elasticsearch.xpack.sql.plan.logical.command;
import org.elasticsearch.xpack.sql.analysis.catalog.EsType; import org.elasticsearch.xpack.sql.analysis.catalog.EsIndex;
import org.elasticsearch.xpack.sql.expression.Attribute; import org.elasticsearch.xpack.sql.expression.Attribute;
import org.elasticsearch.xpack.sql.expression.RootFieldAttribute; import org.elasticsearch.xpack.sql.expression.RootFieldAttribute;
import org.elasticsearch.xpack.sql.session.RowSetCursor; import org.elasticsearch.xpack.sql.session.RowSetCursor;
@ -19,47 +19,42 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static java.util.Comparator.comparing; import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
public class ShowTables extends Command { public class ShowTables extends Command {
private final String index, pattern; private final String pattern;
public ShowTables(Location location, String index, String pattern) { public ShowTables(Location location, String pattern) {
super(location); super(location);
this.index = index;
this.pattern = pattern; this.pattern = pattern;
} }
public String index() {
return index;
}
public String pattern() { public String pattern() {
return pattern; return pattern;
} }
@Override @Override
public List<Attribute> output() { public List<Attribute> output() {
return asList(new RootFieldAttribute(location(), "index", DataTypes.KEYWORD), return asList(new RootFieldAttribute(location(), "table", DataTypes.KEYWORD));
new RootFieldAttribute(location(), "type", DataTypes.KEYWORD));
} }
@Override @Override
protected RowSetCursor execute(SqlSession session) { protected RowSetCursor execute(SqlSession session) {
List<EsType> types = session.catalog().listTypes(index, pattern); List<EsIndex> indices = session.catalog().listIndices(pattern);
// Consistent sorting is nice both for testing and humans // Consistent sorting is nice both for testing and humans
Collections.sort(types, comparing(EsType::index).thenComparing(EsType::name)); Collections.sort(indices, comparing(EsIndex::name));
return Rows.of(output(), types.stream() return Rows.of(output(), indices.stream()
.map(t -> asList(t.index(), t.name())) .map(t -> singletonList(t.name()))
.collect(toList())); .collect(toList()));
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(index, pattern); return Objects.hash(pattern);
} }
@Override @Override
@ -73,7 +68,6 @@ public class ShowTables extends Command {
} }
ShowTables other = (ShowTables) obj; ShowTables other = (ShowTables) obj;
return Objects.equals(index, other.index) return Objects.equals(pattern, other.pattern);
&& Objects.equals(pattern, other.pattern);
} }
} }

View File

@ -19,30 +19,25 @@ import java.util.Objects;
public class EsQueryExec extends LeafExec { public class EsQueryExec extends LeafExec {
private final String index, type; private final String index;
private final List<Attribute> output; private final List<Attribute> output;
private final QueryContainer queryContainer; private final QueryContainer queryContainer;
public EsQueryExec(Location location, String index, String type, List<Attribute> output, QueryContainer queryContainer) { public EsQueryExec(Location location, String index, List<Attribute> output, QueryContainer queryContainer) {
super(location); super(location);
this.index = index; this.index = index;
this.type = type;
this.output = output; this.output = output;
this.queryContainer = queryContainer; this.queryContainer = queryContainer;
} }
public EsQueryExec with(QueryContainer queryContainer) { public EsQueryExec with(QueryContainer queryContainer) {
return new EsQueryExec(location(), index, type, output, queryContainer); return new EsQueryExec(location(), index, output, queryContainer);
} }
public String index() { public String index() {
return index; return index;
} }
public String type() {
return type;
}
public QueryContainer queryContainer() { public QueryContainer queryContainer() {
return queryContainer; return queryContainer;
@ -56,12 +51,12 @@ public class EsQueryExec extends LeafExec {
@Override @Override
public void execute(SqlSession session, ActionListener<RowSetCursor> listener) { public void execute(SqlSession session, ActionListener<RowSetCursor> listener) {
Scroller scroller = new Scroller(session.client(), session.settings()); Scroller scroller = new Scroller(session.client(), session.settings());
scroller.scroll(Rows.schema(output), queryContainer, index, type, listener); scroller.scroll(Rows.schema(output), queryContainer, index, listener);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(index, type, queryContainer, output); return Objects.hash(index, queryContainer, output);
} }
@Override @Override
@ -76,13 +71,12 @@ public class EsQueryExec extends LeafExec {
EsQueryExec other = (EsQueryExec) obj; EsQueryExec other = (EsQueryExec) obj;
return Objects.equals(index, other.index) return Objects.equals(index, other.index)
&& Objects.equals(type, other.type)
&& Objects.equals(queryContainer, other.queryContainer) && Objects.equals(queryContainer, other.queryContainer)
&& Objects.equals(output, other.output); && Objects.equals(output, other.output);
} }
@Override @Override
public String nodeString() { public String nodeString() {
return nodeName() + "[" + index + "/" + type + "," + queryContainer + "]"; return nodeName() + "[" + index + "," + queryContainer + "]";
} }
} }

View File

@ -5,9 +5,6 @@
*/ */
package org.elasticsearch.xpack.sql.planner; package org.elasticsearch.xpack.sql.planner;
import java.util.Arrays;
import java.util.List;
import org.elasticsearch.xpack.sql.expression.Attribute; import org.elasticsearch.xpack.sql.expression.Attribute;
import org.elasticsearch.xpack.sql.plan.logical.Aggregate; import org.elasticsearch.xpack.sql.plan.logical.Aggregate;
import org.elasticsearch.xpack.sql.plan.logical.CatalogTable; import org.elasticsearch.xpack.sql.plan.logical.CatalogTable;
@ -35,6 +32,9 @@ import org.elasticsearch.xpack.sql.rule.Rule;
import org.elasticsearch.xpack.sql.rule.RuleExecutor; import org.elasticsearch.xpack.sql.rule.RuleExecutor;
import org.elasticsearch.xpack.sql.util.ReflectionUtils; import org.elasticsearch.xpack.sql.util.ReflectionUtils;
import java.util.Arrays;
import java.util.List;
class Mapper extends RuleExecutor<PhysicalPlan> { class Mapper extends RuleExecutor<PhysicalPlan> {
public PhysicalPlan map(LogicalPlan plan) { public PhysicalPlan map(LogicalPlan plan) {
@ -91,7 +91,7 @@ class Mapper extends RuleExecutor<PhysicalPlan> {
if (p instanceof CatalogTable) { if (p instanceof CatalogTable) {
CatalogTable c = (CatalogTable) p; CatalogTable c = (CatalogTable) p;
List<Attribute> output = c.output(); List<Attribute> output = c.output();
return new EsQueryExec(c.location(), c.type().index(), c.type().name(), output, new QueryContainer()); return new EsQueryExec(c.location(), c.index().name(), output, new QueryContainer());
} }
if (p instanceof Limit) { if (p instanceof Limit) {

View File

@ -118,7 +118,7 @@ class QueryFolder extends RuleExecutor<PhysicalPlan> {
} }
QueryContainer clone = new QueryContainer(queryC.query(), queryC.aggs(), queryC.refs(), aliases, processors, queryC.pseudoFunctions(), queryC.sort(), queryC.limit()); QueryContainer clone = new QueryContainer(queryC.query(), queryC.aggs(), queryC.refs(), aliases, processors, queryC.pseudoFunctions(), queryC.sort(), queryC.limit());
return new EsQueryExec(exec.location(), exec.index(), exec.type(), project.output(), clone); return new EsQueryExec(exec.location(), exec.index(), project.output(), clone);
} }
return project; return project;
} }
@ -323,7 +323,7 @@ class QueryFolder extends RuleExecutor<PhysicalPlan> {
if (!aliases.isEmpty()) { if (!aliases.isEmpty()) {
queryC = queryC.withAliases(combine(queryC.aliases(), aliases)); queryC = queryC.withAliases(combine(queryC.aliases(), aliases));
} }
return new EsQueryExec(exec.location(), exec.index(), exec.type(), a.output(), queryC); return new EsQueryExec(exec.location(), exec.index(), a.output(), queryC);
} }
return a; return a;
} }

View File

@ -10,7 +10,7 @@ import org.elasticsearch.Version;
import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionListener;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.sql.analysis.catalog.EsType; import org.elasticsearch.xpack.sql.analysis.catalog.EsIndex;
import org.elasticsearch.xpack.sql.execution.PlanExecutor; import org.elasticsearch.xpack.sql.execution.PlanExecutor;
import org.elasticsearch.xpack.sql.execution.search.SearchHitRowSetCursor; import org.elasticsearch.xpack.sql.execution.search.SearchHitRowSetCursor;
import org.elasticsearch.xpack.sql.jdbc.net.protocol.ColumnInfo; import org.elasticsearch.xpack.sql.jdbc.net.protocol.ColumnInfo;
@ -45,9 +45,7 @@ import java.util.regex.Pattern;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import static org.elasticsearch.action.ActionListener.wrap; import static org.elasticsearch.action.ActionListener.wrap;
import static org.elasticsearch.common.Strings.coalesceToEmpty;
import static org.elasticsearch.common.Strings.hasText; import static org.elasticsearch.common.Strings.hasText;
import static org.elasticsearch.common.Strings.tokenizeToStringArray;
import static org.elasticsearch.xpack.sql.util.StringUtils.EMPTY; import static org.elasticsearch.xpack.sql.util.StringUtils.EMPTY;
public class JdbcServer extends AbstractSqlServer { public class JdbcServer extends AbstractSqlServer {
@ -100,35 +98,29 @@ public class JdbcServer extends AbstractSqlServer {
} }
public MetaTableResponse metaTable(MetaTableRequest req) { public MetaTableResponse metaTable(MetaTableRequest req) {
String[] split = splitToIndexAndType(req.pattern()); String indexPattern = hasText(req.pattern()) ? StringUtils.jdbcToEsPattern(req.pattern()) : "*";
String index = split[0];
String type = split[1];
String indexPattern = hasText(index) ? StringUtils.jdbcToEsPattern(index) : "*";
Collection<EsType> types = executor.catalog().listTypes(indexPattern, type); Collection<EsIndex> indices = executor.catalog().listIndices(indexPattern);
return new MetaTableResponse(types.stream() return new MetaTableResponse(indices.stream()
.map(t -> t.index() + "." + t.name()) .map(EsIndex::name)
.collect(toList())); .collect(toList()));
} }
public MetaColumnResponse metaColumn(MetaColumnRequest req) { public MetaColumnResponse metaColumn(MetaColumnRequest req) {
String[] split = splitToIndexAndType(req.tablePattern()); String pattern = Strings.hasText(req.tablePattern()) ? StringUtils.jdbcToEsPattern(req.tablePattern()) : "*";
String index = split[0];
String type = split[1];
String indexPattern = Strings.hasText(index) ? StringUtils.jdbcToEsPattern(index) : "*";
Collection<EsType> types = executor.catalog().listTypes(indexPattern, type); Collection<EsIndex> indices = executor.catalog().listIndices(pattern);
Pattern columnMatcher = hasText(req.columnPattern()) ? StringUtils.likeRegex(req.columnPattern()) : null; Pattern columnMatcher = hasText(req.columnPattern()) ? StringUtils.likeRegex(req.columnPattern()) : null;
List<MetaColumnInfo> resp = new ArrayList<>(); List<MetaColumnInfo> resp = new ArrayList<>();
for (EsType esType : types) { for (EsIndex esIndex : indices) {
int pos = 0; int pos = 0;
for (Entry<String, DataType> entry : esType.mapping().entrySet()) { for (Entry<String, DataType> entry : esIndex.mapping().entrySet()) {
pos++; pos++;
if (columnMatcher == null || columnMatcher.matcher(entry.getKey()).matches()) { if (columnMatcher == null || columnMatcher.matcher(entry.getKey()).matches()) {
String name = entry.getKey(); String name = entry.getKey();
String table = esType.index() + "." + esType.name(); String table = esIndex.name();
JDBCType tp = entry.getValue().sqlType(); JDBCType tp = entry.getValue().sqlType();
int size = entry.getValue().precision(); int size = entry.getValue().precision();
resp.add(new MetaColumnInfo(table, name, tp, size, pos)); resp.add(new MetaColumnInfo(table, name, tp, size, pos));
@ -149,6 +141,7 @@ public class JdbcServer extends AbstractSqlServer {
.build() .build()
); );
//NOCOMMIT: this should be pushed down to the TransportSqlAction to hook up pagination
executor.sql(sqlCfg, req.query, wrap(c -> { executor.sql(sqlCfg, req.query, wrap(c -> {
long stop = System.currentTimeMillis(); long stop = System.currentTimeMillis();
String requestId = EMPTY; String requestId = EMPTY;
@ -167,17 +160,4 @@ public class JdbcServer extends AbstractSqlServer {
public void queryPage(QueryPageRequest req, ActionListener<Response> listener) { public void queryPage(QueryPageRequest req, ActionListener<Response> listener) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
static String[] splitToIndexAndType(String pattern) {
String[] tokens = tokenizeToStringArray(pattern, ".");
if (tokens.length == 2) {
return tokens;
}
if (tokens.length != 1) {
throw new IllegalArgumentException("bad pattern: [" + pattern + "]");
}
return new String[] {coalesceToEmpty(pattern), ""};
}
} }

View File

@ -60,10 +60,6 @@ public class TransportSqlAction extends HandledTransportAction<SqlRequest, SqlRe
String sessionId = request.sessionId(); String sessionId = request.sessionId();
String query = request.query(); String query = request.query();
// NOCOMMIT this should be linked up
// SqlSettings sqlCfg = new SqlSettings(Settings.builder()
// // .put(SqlSettings.PAGE_SIZE, req.fetchSize)
// .put(SqlSettings.TIMEZONE_ID, request.timeZone().getID()).build());
try { try {
if (sessionId == null) { if (sessionId == null) {
if (!Strings.hasText(query)) { if (!Strings.hasText(query)) {
@ -71,6 +67,11 @@ public class TransportSqlAction extends HandledTransportAction<SqlRequest, SqlRe
return; return;
} }
// NOCOMMIT this should be linked up
// SqlSettings sqlCfg = new SqlSettings(Settings.builder()
// .put(SqlSettings.PAGE_SIZE, req.fetchSize)
// .put(SqlSettings.TIMEZONE_ID, request.timeZone().getID()).build());
planExecutor.sql(query, chain(listener, c -> { planExecutor.sql(query, chain(listener, c -> {
String id = generateId(); String id = generateId();
SESSIONS.put(id, c); SESSIONS.put(id, c);

View File

@ -39,7 +39,7 @@ public class SqlSettings {
} }
public DateTimeZone timeZone() { public DateTimeZone timeZone() {
return DateTimeZone.forID(TIMEZONE_ID); return DateTimeZone.forID(timeZoneId());
} }
public int pageSize() { public int pageSize() {