SQL: Add support for FROZEN indices (#41558)

Allow querying of FROZEN indices both through dedicated SQL grammar
extension:
> SELECT field FROM FROZEN index
and also through driver configuration parameter, namely:
> index.include.frozen: true/false

Fix #39390
Fix #39377

(cherry picked from commit 2445a933915f420c7f51e8505afa0a7978ce6b0f)
This commit is contained in:
Costin Leau 2019-05-10 00:26:56 +03:00 committed by Costin Leau
parent a142e8cfd8
commit d5f04d29c9
61 changed files with 2334 additions and 1929 deletions

View File

@ -57,10 +57,13 @@ public class JdbcConfiguration extends ConnectionConfiguration {
static final String FIELD_MULTI_VALUE_LENIENCY = "field.multi.value.leniency"; static final String FIELD_MULTI_VALUE_LENIENCY = "field.multi.value.leniency";
static final String FIELD_MULTI_VALUE_LENIENCY_DEFAULT = "true"; static final String FIELD_MULTI_VALUE_LENIENCY_DEFAULT = "true";
static final String INDEX_INCLUDE_FROZEN = "index.include.frozen";
static final String INDEX_INCLUDE_FROZEN_DEFAULT = "false";
// options that don't change at runtime // options that don't change at runtime
private static final Set<String> OPTION_NAMES = new LinkedHashSet<>( private static final Set<String> OPTION_NAMES = new LinkedHashSet<>(
Arrays.asList(TIME_ZONE, FIELD_MULTI_VALUE_LENIENCY, DEBUG, DEBUG_OUTPUT)); Arrays.asList(TIME_ZONE, FIELD_MULTI_VALUE_LENIENCY, INDEX_INCLUDE_FROZEN, DEBUG, DEBUG_OUTPUT));
static { static {
// trigger version initialization // trigger version initialization
@ -77,6 +80,7 @@ public class JdbcConfiguration extends ConnectionConfiguration {
// mutable ones // mutable ones
private ZoneId zoneId; private ZoneId zoneId;
private boolean fieldMultiValueLeniency; private boolean fieldMultiValueLeniency;
private boolean includeFrozen;
public static JdbcConfiguration create(String u, Properties props, int loginTimeoutSeconds) throws JdbcSQLException { public static JdbcConfiguration create(String u, Properties props, int loginTimeoutSeconds) throws JdbcSQLException {
URI uri = parseUrl(u); URI uri = parseUrl(u);
@ -159,6 +163,8 @@ public class JdbcConfiguration extends ConnectionConfiguration {
s -> TimeZone.getTimeZone(s).toZoneId().normalized()); s -> TimeZone.getTimeZone(s).toZoneId().normalized());
this.fieldMultiValueLeniency = parseValue(FIELD_MULTI_VALUE_LENIENCY, this.fieldMultiValueLeniency = parseValue(FIELD_MULTI_VALUE_LENIENCY,
props.getProperty(FIELD_MULTI_VALUE_LENIENCY, FIELD_MULTI_VALUE_LENIENCY_DEFAULT), Boolean::parseBoolean); props.getProperty(FIELD_MULTI_VALUE_LENIENCY, FIELD_MULTI_VALUE_LENIENCY_DEFAULT), Boolean::parseBoolean);
this.includeFrozen = parseValue(INDEX_INCLUDE_FROZEN, props.getProperty(INDEX_INCLUDE_FROZEN, INDEX_INCLUDE_FROZEN_DEFAULT),
Boolean::parseBoolean);
} }
@Override @Override
@ -186,6 +192,10 @@ public class JdbcConfiguration extends ConnectionConfiguration {
return fieldMultiValueLeniency; return fieldMultiValueLeniency;
} }
public boolean indexIncludeFrozen() {
return includeFrozen;
}
public static boolean canAccept(String url) { public static boolean canAccept(String url) {
return (StringUtils.hasText(url) && url.trim().startsWith(JdbcConfiguration.URL_PREFIX)); return (StringUtils.hasText(url) && url.trim().startsWith(JdbcConfiguration.URL_PREFIX));
} }

View File

@ -63,7 +63,8 @@ class JdbcHttpClient {
Boolean.FALSE, Boolean.FALSE,
null, null,
new RequestInfo(Mode.JDBC), new RequestInfo(Mode.JDBC),
conCfg.fieldMultiValueLeniency()); conCfg.fieldMultiValueLeniency(),
conCfg.indexIncludeFrozen());
SqlQueryResponse response = httpClient.query(sqlRequest); SqlQueryResponse response = httpClient.query(sqlRequest);
return new DefaultCursor(this, response.cursor(), toJdbcColumnInfo(response.columns()), response.rows(), meta); return new DefaultCursor(this, response.cursor(), toJdbcColumnInfo(response.columns()), response.rows(), meta);
} }

View File

@ -145,7 +145,8 @@ public class CliSecurityIT extends SqlSecurityTestCase {
String tablesOutput = cli.command("SHOW TABLES"); String tablesOutput = cli.command("SHOW TABLES");
assertThat(tablesOutput, containsString("name")); assertThat(tablesOutput, containsString("name"));
assertThat(tablesOutput, containsString("type")); assertThat(tablesOutput, containsString("type"));
assertEquals("---------------+---------------", cli.readLine()); assertThat(tablesOutput, containsString("kind"));
assertEquals("---------------+---------------+---------------", cli.readLine());
for (String table : tables) { for (String table : tables) {
String line = null; String line = null;
/* /*

View File

@ -122,6 +122,7 @@ public class RestSqlSecurityIT extends SqlSecurityTestCase {
List<Object> columns = new ArrayList<>(); List<Object> columns = new ArrayList<>();
columns.add(columnInfo(mode, "name", "keyword", JDBCType.VARCHAR, 32766)); columns.add(columnInfo(mode, "name", "keyword", JDBCType.VARCHAR, 32766));
columns.add(columnInfo(mode, "type", "keyword", JDBCType.VARCHAR, 32766)); columns.add(columnInfo(mode, "type", "keyword", JDBCType.VARCHAR, 32766));
columns.add(columnInfo(mode, "kind", "keyword", JDBCType.VARCHAR, 32766));
Map<String, Object> expected = new HashMap<>(); Map<String, Object> expected = new HashMap<>();
expected.put("columns", columns); expected.put("columns", columns);
List<List<String>> rows = new ArrayList<>(); List<List<String>> rows = new ArrayList<>();
@ -129,6 +130,7 @@ public class RestSqlSecurityIT extends SqlSecurityTestCase {
List<String> fields = new ArrayList<>(); List<String> fields = new ArrayList<>();
fields.add(table); fields.add(table);
fields.add("BASE TABLE"); fields.add("BASE TABLE");
fields.add("INDEX");
rows.add(fields); rows.add(fields);
} }
expected.put("rows", rows); expected.put("rows", rows);

View File

@ -17,12 +17,12 @@ import static org.elasticsearch.xpack.sql.qa.jdbc.CsvTestUtils.specParser;
public class JdbcCsvSpecIT extends CsvSpecTestCase { public class JdbcCsvSpecIT extends CsvSpecTestCase {
@ParametersFactory(argumentFormatting = PARAM_FORMATTING) @ParametersFactory(argumentFormatting = PARAM_FORMATTING)
public static List<Object[]> readScriptSpec() throws Exception { public static List<Object[]> readScriptSpec() throws Exception {
List<Object[]> list = new ArrayList<>(); List<Object[]> list = new ArrayList<>();
list.addAll(CsvSpecTestCase.readScriptSpec()); list.addAll(CsvSpecTestCase.readScriptSpec());
return readScriptSpec("/single-node-only/command-sys.csv-spec", specParser()); list.addAll(readScriptSpec("/single-node-only/command-sys.csv-spec", specParser()));
return list;
} }
public JdbcCsvSpecIT(String fileName, String groupName, String testName, Integer lineNumber, CsvTestCase testCase) { public JdbcCsvSpecIT(String fileName, String groupName, String testName, Integer lineNumber, CsvTestCase testCase) {

View File

@ -0,0 +1,42 @@
/*
* 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.qa.single_node;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.xpack.sql.qa.jdbc.CsvSpecTestCase;
import org.elasticsearch.xpack.sql.qa.jdbc.CsvTestUtils.CsvTestCase;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import static org.elasticsearch.xpack.sql.qa.jdbc.CsvTestUtils.specParser;
public class JdbcFrozenCsvSpecIT extends CsvSpecTestCase {
@ParametersFactory(argumentFormatting = PARAM_FORMATTING)
public static List<Object[]> readScriptSpec() throws Exception {
return readScriptSpec("/slow/frozen.csv-spec", specParser());
}
@Override
protected Properties connectionProperties() {
Properties props = new Properties(super.connectionProperties());
String timeout = String.valueOf(TimeUnit.MINUTES.toMillis(5));
props.setProperty("connect.timeout", timeout);
props.setProperty("network.timeout", timeout);
props.setProperty("query.timeout", timeout);
props.setProperty("page.timeout", timeout);
return props;
}
public JdbcFrozenCsvSpecIT(String fileName, String groupName, String testName, Integer lineNumber, CsvTestCase testCase) {
super(fileName, groupName, testName, lineNumber, testCase);
}
}

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack.sql.qa.jdbc; package org.elasticsearch.xpack.sql.qa.jdbc;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.elasticsearch.xpack.sql.qa.jdbc.CsvTestUtils.CsvTestCase; import org.elasticsearch.xpack.sql.qa.jdbc.CsvTestUtils.CsvTestCase;
@ -42,14 +43,8 @@ public abstract class CsvSpecTestCase extends SpecBaseIntegrationTestCase {
protected final void doTest() throws Throwable { protected final void doTest() throws Throwable {
// Run the time tests always in UTC // Run the time tests always in UTC
// TODO: https://github.com/elastic/elasticsearch/issues/40779 // TODO: https://github.com/elastic/elasticsearch/issues/40779
if ("time".equals(groupName)) { try (Connection csv = csvConnection(testCase); Connection es = esJdbc()) {
try (Connection csv = csvConnection(testCase); Connection es = esJdbc(connectionProperties())) { executeAndAssert(csv, es);
executeAndAssert(csv, es);
}
} else {
try (Connection csv = csvConnection(testCase); Connection es = esJdbc()) {
executeAndAssert(csv, es);
}
} }
} }

View File

@ -49,6 +49,9 @@ public class DataLoader {
loadLogsDatasetIntoEs(client, "logs", "logs"); loadLogsDatasetIntoEs(client, "logs", "logs");
makeAlias(client, "test_alias", "test_emp", "test_emp_copy"); makeAlias(client, "test_alias", "test_emp", "test_emp_copy");
makeAlias(client, "test_alias_emp", "test_emp", "test_emp_copy"); makeAlias(client, "test_alias_emp", "test_emp", "test_emp_copy");
// frozen index
loadEmpDatasetIntoEs(client, "frozen_emp", "employees");
freeze(client, "frozen_emp");
} }
public static void loadDocsDatasetIntoEs(RestClient client) throws Exception { public static void loadDocsDatasetIntoEs(RestClient client) throws Exception {
@ -292,6 +295,12 @@ public class DataLoader {
} }
} }
protected static void freeze(RestClient client, String... indices) throws Exception {
for (String index : indices) {
client.performRequest(new Request("POST", "/" + index + "/_freeze"));
}
}
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 {
String location = "/" + name + ".csv"; String location = "/" + name + ".csv";
URL dataSet = SqlSpecTestCase.class.getResource(location); URL dataSet = SqlSpecTestCase.class.getResource(location);

View File

@ -30,7 +30,7 @@ public class ShowTablesTestCase extends JdbcIntegrationTestCase {
for (int i = 0; i < indices; i++) { for (int i = 0; i < indices; i++) {
String index = String.format(Locale.ROOT, "test%02d", i); String index = String.format(Locale.ROOT, "test%02d", i);
index(index, builder -> builder.field("name", "bob")); index(index, builder -> builder.field("name", "bob"));
h2.createStatement().executeUpdate("INSERT INTO mock VALUES ('" + index + "', 'BASE TABLE');"); h2.createStatement().executeUpdate("INSERT INTO mock VALUES ('" + index + "', 'BASE TABLE', 'INDEX');");
} }
ResultSet expected = h2.createStatement().executeQuery("SELECT * FROM mock ORDER BY name"); ResultSet expected = h2.createStatement().executeQuery("SELECT * FROM mock ORDER BY name");

View File

@ -82,20 +82,20 @@ salary |INTEGER |integer
showAlias showAlias
SHOW TABLES LIKE 'test\_alias' ESCAPE '\'; SHOW TABLES LIKE 'test\_alias' ESCAPE '\';
name:s | type:s name:s | type:s | kind:s
test_alias | VIEW test_alias | VIEW | ALIAS
; ;
showPattern showPattern
SHOW TABLES LIKE 'test_%'; SHOW TABLES LIKE 'test_%';
name:s | type:s name:s | type:s | kind :s
test_alias | VIEW test_alias | VIEW | ALIAS
test_alias_emp | VIEW test_alias_emp | VIEW | ALIAS
test_emp | BASE TABLE test_emp | BASE TABLE | INDEX
test_emp_copy | BASE TABLE test_emp_copy | BASE TABLE | INDEX
; ;
groupByOnAlias groupByOnAlias

View File

@ -198,49 +198,49 @@ TODAY |SCALAR
showTables showTables
SHOW TABLES; SHOW TABLES;
name | type name | type | kind
logs |BASE TABLE logs |BASE TABLE |INDEX
test_alias |VIEW test_alias |VIEW |ALIAS
test_alias_emp |VIEW test_alias_emp |VIEW |ALIAS
test_emp |BASE TABLE test_emp |BASE TABLE |INDEX
test_emp_copy |BASE TABLE test_emp_copy |BASE TABLE |INDEX
; ;
showTablesSimpleLike showTablesSimpleLike
SHOW TABLES LIKE 'test_emp'; SHOW TABLES LIKE 'test_emp';
name:s | type:s name:s | type:s | kind:s
test_emp |BASE TABLE test_emp |BASE TABLE |INDEX
; ;
showTablesMultiLike showTablesMultiLike
SHOW TABLES LIKE 'test_emp%'; SHOW TABLES LIKE 'test_emp%';
name:s | type:s name:s | type:s |kind:s
test_emp |BASE TABLE test_emp |BASE TABLE |INDEX
test_emp_copy |BASE TABLE test_emp_copy |BASE TABLE |INDEX
; ;
showTablesIdentifier showTablesIdentifier
SHOW TABLES "test_emp"; SHOW TABLES "test_emp";
name:s | type:s name:s | type:s |kind:s
test_emp |BASE TABLE test_emp |BASE TABLE |INDEX
; ;
showTablesIdentifierPattern showTablesIdentifierPattern
SHOW TABLES "test_e*,-test_emp"; SHOW TABLES "test_e*,-test_emp";
name:s | type:s name:s | type:s |kind:s
test_emp_copy |BASE TABLE test_emp_copy |BASE TABLE |INDEX
; ;
showTablesIdentifierPatternOnAliases showTablesIdentifierPatternOnAliases
SHOW TABLES "test*,-test_emp*"; SHOW TABLES "test*,-test_emp*";
name:s | type:s name:s | type:s | kind:s
test_alias |VIEW test_alias |VIEW |ALIAS
test_alias_emp |VIEW test_alias_emp |VIEW |ALIAS
; ;
// DESCRIBE // DESCRIBE

View File

@ -93,11 +93,11 @@ showTables
// tag::showTables // tag::showTables
SHOW TABLES; SHOW TABLES;
name | type name | type | kind
---------------+--------------- ---------------+---------------+---------------
emp |BASE TABLE emp |BASE TABLE |INDEX
employees |VIEW employees |VIEW |ALIAS
library |BASE TABLE library |BASE TABLE |INDEX
// end::showTables // end::showTables
; ;
@ -106,9 +106,9 @@ showTablesLikeExact
// tag::showTablesLikeExact // tag::showTablesLikeExact
SHOW TABLES LIKE 'emp'; SHOW TABLES LIKE 'emp';
name | type name | type | kind
---------------+--------------- ---------------+---------------+---------------
emp |BASE TABLE emp |BASE TABLE |INDEX
// end::showTablesLikeExact // end::showTablesLikeExact
; ;
@ -117,10 +117,10 @@ showTablesLikeWildcard
// tag::showTablesLikeWildcard // tag::showTablesLikeWildcard
SHOW TABLES LIKE 'emp%'; SHOW TABLES LIKE 'emp%';
name | type name | type | kind
---------------+--------------- ---------------+---------------+---------------
emp |BASE TABLE emp |BASE TABLE |INDEX
employees |VIEW employees |VIEW |ALIAS
// end::showTablesLikeWildcard // end::showTablesLikeWildcard
; ;
@ -130,9 +130,9 @@ showTablesLikeOneChar
// tag::showTablesLikeOneChar // tag::showTablesLikeOneChar
SHOW TABLES LIKE 'em_'; SHOW TABLES LIKE 'em_';
name | type name | type | kind
---------------+--------------- ---------------+---------------+---------------
emp |BASE TABLE emp |BASE TABLE |INDEX
// end::showTablesLikeOneChar // end::showTablesLikeOneChar
; ;
@ -141,20 +141,20 @@ showTablesLikeMixed
// tag::showTablesLikeMixed // tag::showTablesLikeMixed
SHOW TABLES LIKE '%em_'; SHOW TABLES LIKE '%em_';
name | type name | type | kind
---------------+--------------- ---------------+---------------+---------------
emp |BASE TABLE emp |BASE TABLE |INDEX
// end::showTablesLikeMixed // end::showTablesLikeMixed
; ;
showTablesLikeEscape showTablesLikeEscape
schema::name:s|type:s schema::name:s|type:s|kind:s
// tag::showTablesLikeEscape // tag::showTablesLikeEscape
SHOW TABLES LIKE 'emp!%' ESCAPE '!'; SHOW TABLES LIKE 'emp!%' ESCAPE '!';
name | type name | type | kind
---------------+--------------- ---------------+---------------+---------------
// end::showTablesLikeEscape // end::showTablesLikeEscape
; ;
@ -164,10 +164,10 @@ showTablesEsMultiIndex
// tag::showTablesEsMultiIndex // tag::showTablesEsMultiIndex
SHOW TABLES "*,-l*"; SHOW TABLES "*,-l*";
name | type name | type | kind
---------------+--------------- ---------------+---------------+---------------
emp |BASE TABLE emp |BASE TABLE |INDEX
employees |VIEW employees |VIEW |ALIAS
// end::showTablesEsMultiIndex // end::showTablesEsMultiIndex
; ;

View File

@ -1,4 +1,5 @@
CREATE TABLE mock ( CREATE TABLE mock (
"name" VARCHAR, "name" VARCHAR,
"type" VARCHAR "type" VARCHAR,
"kind" VARCHAR
); );

View File

@ -0,0 +1,59 @@
//
// Frozen indices tests
//
showTables
SHOW TABLES INCLUDE FROZEN;
name | type | kind
frozen_emp |BASE TABLE |FROZEN INDEX
logs |BASE TABLE |INDEX
test_alias |VIEW |ALIAS
test_alias_emp |VIEW |ALIAS
test_emp |BASE TABLE |INDEX
test_emp_copy |BASE TABLE |INDEX
;
columnFromFrozen
SELECT gender FROM FROZEN frozen_emp ORDER BY gender LIMIT 5;
gender:s
F
F
F
F
F
;
percentileFrozen
SELECT gender, PERCENTILE(emp_no, 92.45) p1 FROM FROZEN frozen_emp GROUP BY gender;
gender:s | p1:d
null |10018.745
F |10098.0085
M |10091.393
;
countFromFrozen
SELECT gender, COUNT(*) AS c FROM FROZEN frozen_emp GROUP BY gender;
gender:s | c:l
null |10
F |33
M |57
;
sum
SELECT SUM(salary) FROM FROZEN frozen_emp;
SUM(salary)
---------------
4824855
;
kurtosisAndSkewnessNoGroup
SELECT KURTOSIS(emp_no) k, SKEWNESS(salary) s FROM FROZEN frozen_emp;
k:d | s:d
1.7997599759975997 | 0.2707722118423227
;

View File

@ -0,0 +1,3 @@
Slow tests are placed in this folder so that they don't get picked up accidently through the classpath discovery.
A good example are frozen tests, which by their nature, take a LOT more time to execute and thus would cause
the other 'normal' tests to time-out.

View File

@ -33,12 +33,14 @@ public class SqlQueryRequest extends AbstractSqlQueryRequest {
private static final ObjectParser<SqlQueryRequest, Void> PARSER = objectParser(SqlQueryRequest::new); private static final ObjectParser<SqlQueryRequest, Void> PARSER = objectParser(SqlQueryRequest::new);
static final ParseField COLUMNAR = new ParseField("columnar"); static final ParseField COLUMNAR = new ParseField("columnar");
static final ParseField FIELD_MULTI_VALUE_LENIENCY = new ParseField("field_multi_value_leniency"); static final ParseField FIELD_MULTI_VALUE_LENIENCY = new ParseField("field_multi_value_leniency");
static final ParseField INDEX_INCLUDE_FROZEN = new ParseField("index_include_frozen");
static { static {
PARSER.declareString(SqlQueryRequest::cursor, CURSOR); PARSER.declareString(SqlQueryRequest::cursor, CURSOR);
PARSER.declareBoolean(SqlQueryRequest::columnar, COLUMNAR); PARSER.declareBoolean(SqlQueryRequest::columnar, COLUMNAR);
PARSER.declareBoolean(SqlQueryRequest::fieldMultiValueLeniency, FIELD_MULTI_VALUE_LENIENCY); PARSER.declareBoolean(SqlQueryRequest::fieldMultiValueLeniency, FIELD_MULTI_VALUE_LENIENCY);
PARSER.declareBoolean(SqlQueryRequest::indexIncludeFrozen, INDEX_INCLUDE_FROZEN);
} }
private String cursor = ""; private String cursor = "";
@ -48,6 +50,7 @@ public class SqlQueryRequest extends AbstractSqlQueryRequest {
*/ */
private Boolean columnar = Boolean.FALSE; private Boolean columnar = Boolean.FALSE;
private boolean fieldMultiValueLeniency = Protocol.FIELD_MULTI_VALUE_LENIENCY; private boolean fieldMultiValueLeniency = Protocol.FIELD_MULTI_VALUE_LENIENCY;
private boolean indexIncludeFrozen = Protocol.INDEX_INCLUDE_FROZEN;
public SqlQueryRequest() { public SqlQueryRequest() {
super(); super();
@ -55,11 +58,12 @@ public class SqlQueryRequest extends AbstractSqlQueryRequest {
public SqlQueryRequest(String query, List<SqlTypedParamValue> params, QueryBuilder filter, ZoneId zoneId, public SqlQueryRequest(String query, List<SqlTypedParamValue> params, QueryBuilder filter, ZoneId zoneId,
int fetchSize, TimeValue requestTimeout, TimeValue pageTimeout, Boolean columnar, int fetchSize, TimeValue requestTimeout, TimeValue pageTimeout, Boolean columnar,
String cursor, RequestInfo requestInfo, boolean fieldMultiValueLeniency) { String cursor, RequestInfo requestInfo, boolean fieldMultiValueLeniency, boolean indexIncludeFrozen) {
super(query, params, filter, zoneId, fetchSize, requestTimeout, pageTimeout, requestInfo); super(query, params, filter, zoneId, fetchSize, requestTimeout, pageTimeout, requestInfo);
this.cursor = cursor; this.cursor = cursor;
this.columnar = columnar; this.columnar = columnar;
this.fieldMultiValueLeniency = fieldMultiValueLeniency; this.fieldMultiValueLeniency = fieldMultiValueLeniency;
this.indexIncludeFrozen = indexIncludeFrozen;
} }
@Override @Override
@ -115,11 +119,21 @@ public class SqlQueryRequest extends AbstractSqlQueryRequest {
return fieldMultiValueLeniency; return fieldMultiValueLeniency;
} }
public SqlQueryRequest indexIncludeFrozen(boolean include) {
this.indexIncludeFrozen = include;
return this;
}
public boolean indexIncludeFrozen() {
return indexIncludeFrozen;
}
public SqlQueryRequest(StreamInput in) throws IOException { public SqlQueryRequest(StreamInput in) throws IOException {
super(in); super(in);
cursor = in.readString(); cursor = in.readString();
columnar = in.readOptionalBoolean(); columnar = in.readOptionalBoolean();
fieldMultiValueLeniency = in.readBoolean(); fieldMultiValueLeniency = in.readBoolean();
indexIncludeFrozen = in.readBoolean();
} }
@Override @Override
@ -128,11 +142,12 @@ public class SqlQueryRequest extends AbstractSqlQueryRequest {
out.writeString(cursor); out.writeString(cursor);
out.writeOptionalBoolean(columnar); out.writeOptionalBoolean(columnar);
out.writeBoolean(fieldMultiValueLeniency); out.writeBoolean(fieldMultiValueLeniency);
out.writeBoolean(indexIncludeFrozen);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(super.hashCode(), cursor, columnar); return Objects.hash(super.hashCode(), cursor, columnar, fieldMultiValueLeniency, indexIncludeFrozen);
} }
@Override @Override
@ -140,7 +155,8 @@ public class SqlQueryRequest extends AbstractSqlQueryRequest {
return super.equals(obj) return super.equals(obj)
&& Objects.equals(cursor, ((SqlQueryRequest) obj).cursor) && Objects.equals(cursor, ((SqlQueryRequest) obj).cursor)
&& Objects.equals(columnar, ((SqlQueryRequest) obj).columnar) && Objects.equals(columnar, ((SqlQueryRequest) obj).columnar)
&& fieldMultiValueLeniency == ((SqlQueryRequest) obj).fieldMultiValueLeniency; && fieldMultiValueLeniency == ((SqlQueryRequest) obj).fieldMultiValueLeniency
&& indexIncludeFrozen == ((SqlQueryRequest) obj).indexIncludeFrozen;
} }
@Override @Override
@ -152,7 +168,7 @@ public class SqlQueryRequest extends AbstractSqlQueryRequest {
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
// This is needed just to test round-trip compatibility with proto.SqlQueryRequest // This is needed just to test round-trip compatibility with proto.SqlQueryRequest
return new org.elasticsearch.xpack.sql.proto.SqlQueryRequest(query(), params(), zoneId(), fetchSize(), requestTimeout(), return new org.elasticsearch.xpack.sql.proto.SqlQueryRequest(query(), params(), zoneId(), fetchSize(), requestTimeout(),
pageTimeout(), filter(), columnar(), cursor(), requestInfo(), fieldMultiValueLeniency()) pageTimeout(), filter(), columnar(), cursor(), requestInfo(), fieldMultiValueLeniency(), indexIncludeFrozen())
.toXContent(builder, params); .toXContent(builder, params);
} }

View File

@ -25,15 +25,16 @@ public class SqlQueryRequestBuilder extends ActionRequestBuilder<SqlQueryRequest
public SqlQueryRequestBuilder(ElasticsearchClient client, SqlQueryAction action) { public SqlQueryRequestBuilder(ElasticsearchClient client, SqlQueryAction action) {
this(client, action, "", Collections.emptyList(), null, Protocol.TIME_ZONE, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, this(client, action, "", Collections.emptyList(), null, Protocol.TIME_ZONE, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT,
Protocol.PAGE_TIMEOUT, false, "", new RequestInfo(Mode.PLAIN), Protocol.FIELD_MULTI_VALUE_LENIENCY); Protocol.PAGE_TIMEOUT, false, "", new RequestInfo(Mode.PLAIN), Protocol.FIELD_MULTI_VALUE_LENIENCY,
Protocol.INDEX_INCLUDE_FROZEN);
} }
public SqlQueryRequestBuilder(ElasticsearchClient client, SqlQueryAction action, String query, List<SqlTypedParamValue> params, public SqlQueryRequestBuilder(ElasticsearchClient client, SqlQueryAction action, String query, List<SqlTypedParamValue> params,
QueryBuilder filter, ZoneId zoneId, int fetchSize, TimeValue requestTimeout, QueryBuilder filter, ZoneId zoneId, int fetchSize, TimeValue requestTimeout,
TimeValue pageTimeout, boolean columnar, String nextPageInfo, RequestInfo requestInfo, TimeValue pageTimeout, boolean columnar, String nextPageInfo, RequestInfo requestInfo,
boolean multiValueFieldLeniency) { boolean multiValueFieldLeniency, boolean indexIncludeFrozen) {
super(client, action, new SqlQueryRequest(query, params, filter, zoneId, fetchSize, requestTimeout, pageTimeout, columnar, super(client, action, new SqlQueryRequest(query, params, filter, zoneId, fetchSize, requestTimeout, pageTimeout, columnar,
nextPageInfo, requestInfo, multiValueFieldLeniency)); nextPageInfo, requestInfo, multiValueFieldLeniency, indexIncludeFrozen));
} }
public SqlQueryRequestBuilder query(String query) { public SqlQueryRequestBuilder query(String query) {

View File

@ -69,7 +69,7 @@ public class SqlTranslateRequest extends AbstractSqlQueryRequest {
null, null,
null, null,
requestInfo(), requestInfo(),
false,
false).toXContent(builder, params); false).toXContent(builder, params);
} }
} }

View File

@ -56,7 +56,7 @@ public class SqlQueryRequestTests extends AbstractSerializingTestCase<SqlQueryRe
return new SqlQueryRequest(randomAlphaOfLength(10), randomParameters(), SqlTestUtils.randomFilterOrNull(random()), return new SqlQueryRequest(randomAlphaOfLength(10), randomParameters(), SqlTestUtils.randomFilterOrNull(random()),
randomZone(), between(1, Integer.MAX_VALUE), randomTV(), randomZone(), between(1, Integer.MAX_VALUE), randomTV(),
randomTV(), randomBoolean(), randomAlphaOfLength(10), requestInfo, randomTV(), randomBoolean(), randomAlphaOfLength(10), requestInfo,
randomBoolean() randomBoolean(), randomBoolean()
); );
} }
@ -115,7 +115,7 @@ public class SqlQueryRequestTests extends AbstractSerializingTestCase<SqlQueryRe
); );
SqlQueryRequest newRequest = new SqlQueryRequest(instance.query(), instance.params(), instance.filter(), SqlQueryRequest newRequest = new SqlQueryRequest(instance.query(), instance.params(), instance.filter(),
instance.zoneId(), instance.fetchSize(), instance.requestTimeout(), instance.pageTimeout(), instance.columnar(), instance.zoneId(), instance.fetchSize(), instance.requestTimeout(), instance.pageTimeout(), instance.columnar(),
instance.cursor(), instance.requestInfo(), instance.fieldMultiValueLeniency()); instance.cursor(), instance.requestInfo(), instance.fieldMultiValueLeniency(), instance.indexIncludeFrozen());
mutator.accept(newRequest); mutator.accept(newRequest);
return newRequest; return newRequest;
} }

View File

@ -64,13 +64,14 @@ public class HttpClient {
// TODO allow customizing the time zone - this is what session set/reset/get should be about // TODO allow customizing the time zone - this is what session set/reset/get should be about
// method called only from CLI // method called only from CLI
SqlQueryRequest sqlRequest = new SqlQueryRequest(query, Collections.emptyList(), Protocol.TIME_ZONE, SqlQueryRequest sqlRequest = new SqlQueryRequest(query, Collections.emptyList(), Protocol.TIME_ZONE,
fetchSize, fetchSize,
TimeValue.timeValueMillis(cfg.queryTimeout()), TimeValue.timeValueMillis(cfg.queryTimeout()),
TimeValue.timeValueMillis(cfg.pageTimeout()), TimeValue.timeValueMillis(cfg.pageTimeout()),
null, null,
Boolean.FALSE, Boolean.FALSE,
null, null,
new RequestInfo(Mode.CLI), new RequestInfo(Mode.CLI),
false,
false); false);
return query(sqlRequest); return query(sqlRequest);
} }

View File

@ -23,6 +23,7 @@ public final class Protocol {
public static final TimeValue REQUEST_TIMEOUT = TimeValue.timeValueSeconds(90); public static final TimeValue REQUEST_TIMEOUT = TimeValue.timeValueSeconds(90);
public static final TimeValue PAGE_TIMEOUT = TimeValue.timeValueSeconds(45); public static final TimeValue PAGE_TIMEOUT = TimeValue.timeValueSeconds(45);
public static final boolean FIELD_MULTI_VALUE_LENIENCY = false; public static final boolean FIELD_MULTI_VALUE_LENIENCY = false;
public static final boolean INDEX_INCLUDE_FROZEN = false;
/** /**
* SQL-related endpoints * SQL-related endpoints

View File

@ -33,12 +33,11 @@ public class SqlQueryRequest extends AbstractSqlRequest {
private final Boolean columnar; private final Boolean columnar;
private final List<SqlTypedParamValue> params; private final List<SqlTypedParamValue> params;
private final boolean fieldMultiValueLeniency; private final boolean fieldMultiValueLeniency;
private final boolean indexIncludeFrozen;
public SqlQueryRequest(String query, List<SqlTypedParamValue> params, ZoneId zoneId, int fetchSize, public SqlQueryRequest(String query, List<SqlTypedParamValue> params, ZoneId zoneId, int fetchSize,
TimeValue requestTimeout, TimeValue pageTimeout, ToXContent filter, Boolean columnar, TimeValue requestTimeout, TimeValue pageTimeout, ToXContent filter, Boolean columnar,
String cursor, RequestInfo requestInfo, String cursor, RequestInfo requestInfo, boolean fieldMultiValueLeniency, boolean indexIncludeFrozen) {
boolean fieldMultiValueLeniency) {
super(requestInfo); super(requestInfo);
this.query = query; this.query = query;
this.params = params; this.params = params;
@ -50,11 +49,12 @@ public class SqlQueryRequest extends AbstractSqlRequest {
this.columnar = columnar; this.columnar = columnar;
this.cursor = cursor; this.cursor = cursor;
this.fieldMultiValueLeniency = fieldMultiValueLeniency; this.fieldMultiValueLeniency = fieldMultiValueLeniency;
this.indexIncludeFrozen = indexIncludeFrozen;
} }
public SqlQueryRequest(String cursor, TimeValue requestTimeout, TimeValue pageTimeout, RequestInfo requestInfo) { public SqlQueryRequest(String cursor, TimeValue requestTimeout, TimeValue pageTimeout, RequestInfo requestInfo) {
this("", Collections.emptyList(), Protocol.TIME_ZONE, Protocol.FETCH_SIZE, requestTimeout, pageTimeout, this("", Collections.emptyList(), Protocol.TIME_ZONE, Protocol.FETCH_SIZE, requestTimeout, pageTimeout,
null, false, cursor, requestInfo, Protocol.FIELD_MULTI_VALUE_LENIENCY); null, false, cursor, requestInfo, Protocol.FIELD_MULTI_VALUE_LENIENCY, Protocol.INDEX_INCLUDE_FROZEN);
} }
/** /**
@ -127,6 +127,10 @@ public class SqlQueryRequest extends AbstractSqlRequest {
return fieldMultiValueLeniency; return fieldMultiValueLeniency;
} }
public boolean indexIncludeFrozen() {
return indexIncludeFrozen;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) { if (this == o) {
@ -148,13 +152,14 @@ public class SqlQueryRequest extends AbstractSqlRequest {
Objects.equals(filter, that.filter) && Objects.equals(filter, that.filter) &&
Objects.equals(columnar, that.columnar) && Objects.equals(columnar, that.columnar) &&
Objects.equals(cursor, that.cursor) && Objects.equals(cursor, that.cursor) &&
fieldMultiValueLeniency == that.fieldMultiValueLeniency; fieldMultiValueLeniency == that.fieldMultiValueLeniency &&
indexIncludeFrozen == that.indexIncludeFrozen;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(super.hashCode(), query, zoneId, fetchSize, requestTimeout, pageTimeout, return Objects.hash(super.hashCode(), query, zoneId, fetchSize, requestTimeout, pageTimeout,
filter, columnar, cursor, fieldMultiValueLeniency); filter, columnar, cursor, fieldMultiValueLeniency, indexIncludeFrozen);
} }
@Override @Override
@ -195,6 +200,9 @@ public class SqlQueryRequest extends AbstractSqlRequest {
if (fieldMultiValueLeniency) { if (fieldMultiValueLeniency) {
builder.field("field_multi_value_leniency", fieldMultiValueLeniency); builder.field("field_multi_value_leniency", fieldMultiValueLeniency);
} }
if (indexIncludeFrozen) {
builder.field("index_include_frozen", indexIncludeFrozen);
}
if (cursor != null) { if (cursor != null) {
builder.field("cursor", cursor); builder.field("cursor", cursor);
} }

View File

@ -50,9 +50,9 @@ statement
)* )*
')')? ')')?
statement #debug statement #debug
| SHOW TABLES (tableLike=likePattern | tableIdent=tableIdentifier)? #showTables | SHOW TABLES (INCLUDE FROZEN)? (tableLike=likePattern | tableIdent=tableIdentifier)? #showTables
| SHOW COLUMNS (FROM | IN) (tableLike=likePattern | tableIdent=tableIdentifier) #showColumns | SHOW COLUMNS (INCLUDE FROZEN)? (FROM | IN) (tableLike=likePattern | tableIdent=tableIdentifier) #showColumns
| (DESCRIBE | DESC) (tableLike=likePattern | tableIdent=tableIdentifier) #showColumns | (DESCRIBE | DESC) (INCLUDE FROZEN)? (tableLike=likePattern | tableIdent=tableIdentifier) #showColumns
| SHOW FUNCTIONS (likePattern)? #showFunctions | SHOW FUNCTIONS (likePattern)? #showFunctions
| SHOW SCHEMAS #showSchemas | SHOW SCHEMAS #showSchemas
| SYS TABLES (CATALOG clusterLike=likePattern)? | SYS TABLES (CATALOG clusterLike=likePattern)?
@ -149,7 +149,7 @@ joinCriteria
; ;
relationPrimary relationPrimary
: tableIdentifier (AS? qualifiedName)? #tableName : FROZEN? tableIdentifier (AS? qualifiedName)? #tableName
| '(' queryNoWith ')' (AS? qualifiedName)? #aliasedQuery | '(' queryNoWith ')' (AS? qualifiedName)? #aliasedQuery
| '(' relation ')' (AS? qualifiedName)? #aliasedRelation | '(' relation ')' (AS? qualifiedName)? #aliasedRelation
; ;
@ -399,6 +399,7 @@ FALSE: 'FALSE';
FIRST: 'FIRST'; FIRST: 'FIRST';
FORMAT: 'FORMAT'; FORMAT: 'FORMAT';
FROM: 'FROM'; FROM: 'FROM';
FROZEN: 'FROZEN';
FULL: 'FULL'; FULL: 'FULL';
FUNCTIONS: 'FUNCTIONS'; FUNCTIONS: 'FUNCTIONS';
GRAPHVIZ: 'GRAPHVIZ'; GRAPHVIZ: 'GRAPHVIZ';
@ -407,6 +408,7 @@ HAVING: 'HAVING';
HOUR: 'HOUR'; HOUR: 'HOUR';
HOURS: 'HOURS'; HOURS: 'HOURS';
IN: 'IN'; IN: 'IN';
INCLUDE: 'INCLUDE';
INNER: 'INNER'; INNER: 'INNER';
INTERVAL: 'INTERVAL'; INTERVAL: 'INTERVAL';
IS: 'IS'; IS: 'IS';

View File

@ -37,101 +37,103 @@ FALSE=36
FIRST=37 FIRST=37
FORMAT=38 FORMAT=38
FROM=39 FROM=39
FULL=40 FROZEN=40
FUNCTIONS=41 FULL=41
GRAPHVIZ=42 FUNCTIONS=42
GROUP=43 GRAPHVIZ=43
HAVING=44 GROUP=44
HOUR=45 HAVING=45
HOURS=46 HOUR=46
IN=47 HOURS=47
INNER=48 IN=48
INTERVAL=49 INCLUDE=49
IS=50 INNER=50
JOIN=51 INTERVAL=51
LAST=52 IS=52
LEFT=53 JOIN=53
LIKE=54 LAST=54
LIMIT=55 LEFT=55
MAPPED=56 LIKE=56
MATCH=57 LIMIT=57
MINUTE=58 MAPPED=58
MINUTES=59 MATCH=59
MONTH=60 MINUTE=60
MONTHS=61 MINUTES=61
NATURAL=62 MONTH=62
NOT=63 MONTHS=63
NULL=64 NATURAL=64
NULLS=65 NOT=65
ON=66 NULL=66
OPTIMIZED=67 NULLS=67
OR=68 ON=68
ORDER=69 OPTIMIZED=69
OUTER=70 OR=70
PARSED=71 ORDER=71
PHYSICAL=72 OUTER=72
PLAN=73 PARSED=73
RIGHT=74 PHYSICAL=74
RLIKE=75 PLAN=75
QUERY=76 RIGHT=76
SCHEMAS=77 RLIKE=77
SECOND=78 QUERY=78
SECONDS=79 SCHEMAS=79
SELECT=80 SECOND=80
SHOW=81 SECONDS=81
SYS=82 SELECT=82
TABLE=83 SHOW=83
TABLES=84 SYS=84
TEXT=85 TABLE=85
THEN=86 TABLES=86
TRUE=87 TEXT=87
TO=88 THEN=88
TYPE=89 TRUE=89
TYPES=90 TO=90
USING=91 TYPE=91
VERIFY=92 TYPES=92
WHEN=93 USING=93
WHERE=94 VERIFY=94
WITH=95 WHEN=95
YEAR=96 WHERE=96
YEARS=97 WITH=97
ESCAPE_ESC=98 YEAR=98
FUNCTION_ESC=99 YEARS=99
LIMIT_ESC=100 ESCAPE_ESC=100
DATE_ESC=101 FUNCTION_ESC=101
TIME_ESC=102 LIMIT_ESC=102
TIMESTAMP_ESC=103 DATE_ESC=103
GUID_ESC=104 TIME_ESC=104
ESC_END=105 TIMESTAMP_ESC=105
EQ=106 GUID_ESC=106
NULLEQ=107 ESC_END=107
NEQ=108 EQ=108
LT=109 NULLEQ=109
LTE=110 NEQ=110
GT=111 LT=111
GTE=112 LTE=112
PLUS=113 GT=113
MINUS=114 GTE=114
ASTERISK=115 PLUS=115
SLASH=116 MINUS=116
PERCENT=117 ASTERISK=117
CAST_OP=118 SLASH=118
CONCAT=119 PERCENT=119
DOT=120 CAST_OP=120
PARAM=121 CONCAT=121
STRING=122 DOT=122
INTEGER_VALUE=123 PARAM=123
DECIMAL_VALUE=124 STRING=124
IDENTIFIER=125 INTEGER_VALUE=125
DIGIT_IDENTIFIER=126 DECIMAL_VALUE=126
TABLE_IDENTIFIER=127 IDENTIFIER=127
QUOTED_IDENTIFIER=128 DIGIT_IDENTIFIER=128
BACKQUOTED_IDENTIFIER=129 TABLE_IDENTIFIER=129
SIMPLE_COMMENT=130 QUOTED_IDENTIFIER=130
BRACKETED_COMMENT=131 BACKQUOTED_IDENTIFIER=131
WS=132 SIMPLE_COMMENT=132
UNRECOGNIZED=133 BRACKETED_COMMENT=133
DELIMITER=134 WS=134
UNRECOGNIZED=135
DELIMITER=136
'('=1 '('=1
')'=2 ')'=2
','=3 ','=3
@ -171,84 +173,86 @@ DELIMITER=134
'FIRST'=37 'FIRST'=37
'FORMAT'=38 'FORMAT'=38
'FROM'=39 'FROM'=39
'FULL'=40 'FROZEN'=40
'FUNCTIONS'=41 'FULL'=41
'GRAPHVIZ'=42 'FUNCTIONS'=42
'GROUP'=43 'GRAPHVIZ'=43
'HAVING'=44 'GROUP'=44
'HOUR'=45 'HAVING'=45
'HOURS'=46 'HOUR'=46
'IN'=47 'HOURS'=47
'INNER'=48 'IN'=48
'INTERVAL'=49 'INCLUDE'=49
'IS'=50 'INNER'=50
'JOIN'=51 'INTERVAL'=51
'LAST'=52 'IS'=52
'LEFT'=53 'JOIN'=53
'LIKE'=54 'LAST'=54
'LIMIT'=55 'LEFT'=55
'MAPPED'=56 'LIKE'=56
'MATCH'=57 'LIMIT'=57
'MINUTE'=58 'MAPPED'=58
'MINUTES'=59 'MATCH'=59
'MONTH'=60 'MINUTE'=60
'MONTHS'=61 'MINUTES'=61
'NATURAL'=62 'MONTH'=62
'NOT'=63 'MONTHS'=63
'NULL'=64 'NATURAL'=64
'NULLS'=65 'NOT'=65
'ON'=66 'NULL'=66
'OPTIMIZED'=67 'NULLS'=67
'OR'=68 'ON'=68
'ORDER'=69 'OPTIMIZED'=69
'OUTER'=70 'OR'=70
'PARSED'=71 'ORDER'=71
'PHYSICAL'=72 'OUTER'=72
'PLAN'=73 'PARSED'=73
'RIGHT'=74 'PHYSICAL'=74
'RLIKE'=75 'PLAN'=75
'QUERY'=76 'RIGHT'=76
'SCHEMAS'=77 'RLIKE'=77
'SECOND'=78 'QUERY'=78
'SECONDS'=79 'SCHEMAS'=79
'SELECT'=80 'SECOND'=80
'SHOW'=81 'SECONDS'=81
'SYS'=82 'SELECT'=82
'TABLE'=83 'SHOW'=83
'TABLES'=84 'SYS'=84
'TEXT'=85 'TABLE'=85
'THEN'=86 'TABLES'=86
'TRUE'=87 'TEXT'=87
'TO'=88 'THEN'=88
'TYPE'=89 'TRUE'=89
'TYPES'=90 'TO'=90
'USING'=91 'TYPE'=91
'VERIFY'=92 'TYPES'=92
'WHEN'=93 'USING'=93
'WHERE'=94 'VERIFY'=94
'WITH'=95 'WHEN'=95
'YEAR'=96 'WHERE'=96
'YEARS'=97 'WITH'=97
'{ESCAPE'=98 'YEAR'=98
'{FN'=99 'YEARS'=99
'{LIMIT'=100 '{ESCAPE'=100
'{D'=101 '{FN'=101
'{T'=102 '{LIMIT'=102
'{TS'=103 '{D'=103
'{GUID'=104 '{T'=104
'}'=105 '{TS'=105
'='=106 '{GUID'=106
'<=>'=107 '}'=107
'<'=109 '='=108
'<='=110 '<=>'=109
'>'=111 '<'=111
'>='=112 '<='=112
'+'=113 '>'=113
'-'=114 '>='=114
'*'=115 '+'=115
'/'=116 '-'=116
'%'=117 '*'=117
'::'=118 '/'=118
'||'=119 '%'=119
'.'=120 '::'=120
'?'=121 '||'=121
'.'=122
'?'=123

View File

@ -37,100 +37,102 @@ FALSE=36
FIRST=37 FIRST=37
FORMAT=38 FORMAT=38
FROM=39 FROM=39
FULL=40 FROZEN=40
FUNCTIONS=41 FULL=41
GRAPHVIZ=42 FUNCTIONS=42
GROUP=43 GRAPHVIZ=43
HAVING=44 GROUP=44
HOUR=45 HAVING=45
HOURS=46 HOUR=46
IN=47 HOURS=47
INNER=48 IN=48
INTERVAL=49 INCLUDE=49
IS=50 INNER=50
JOIN=51 INTERVAL=51
LAST=52 IS=52
LEFT=53 JOIN=53
LIKE=54 LAST=54
LIMIT=55 LEFT=55
MAPPED=56 LIKE=56
MATCH=57 LIMIT=57
MINUTE=58 MAPPED=58
MINUTES=59 MATCH=59
MONTH=60 MINUTE=60
MONTHS=61 MINUTES=61
NATURAL=62 MONTH=62
NOT=63 MONTHS=63
NULL=64 NATURAL=64
NULLS=65 NOT=65
ON=66 NULL=66
OPTIMIZED=67 NULLS=67
OR=68 ON=68
ORDER=69 OPTIMIZED=69
OUTER=70 OR=70
PARSED=71 ORDER=71
PHYSICAL=72 OUTER=72
PLAN=73 PARSED=73
RIGHT=74 PHYSICAL=74
RLIKE=75 PLAN=75
QUERY=76 RIGHT=76
SCHEMAS=77 RLIKE=77
SECOND=78 QUERY=78
SECONDS=79 SCHEMAS=79
SELECT=80 SECOND=80
SHOW=81 SECONDS=81
SYS=82 SELECT=82
TABLE=83 SHOW=83
TABLES=84 SYS=84
TEXT=85 TABLE=85
THEN=86 TABLES=86
TRUE=87 TEXT=87
TO=88 THEN=88
TYPE=89 TRUE=89
TYPES=90 TO=90
USING=91 TYPE=91
VERIFY=92 TYPES=92
WHEN=93 USING=93
WHERE=94 VERIFY=94
WITH=95 WHEN=95
YEAR=96 WHERE=96
YEARS=97 WITH=97
ESCAPE_ESC=98 YEAR=98
FUNCTION_ESC=99 YEARS=99
LIMIT_ESC=100 ESCAPE_ESC=100
DATE_ESC=101 FUNCTION_ESC=101
TIME_ESC=102 LIMIT_ESC=102
TIMESTAMP_ESC=103 DATE_ESC=103
GUID_ESC=104 TIME_ESC=104
ESC_END=105 TIMESTAMP_ESC=105
EQ=106 GUID_ESC=106
NULLEQ=107 ESC_END=107
NEQ=108 EQ=108
LT=109 NULLEQ=109
LTE=110 NEQ=110
GT=111 LT=111
GTE=112 LTE=112
PLUS=113 GT=113
MINUS=114 GTE=114
ASTERISK=115 PLUS=115
SLASH=116 MINUS=116
PERCENT=117 ASTERISK=117
CAST_OP=118 SLASH=118
CONCAT=119 PERCENT=119
DOT=120 CAST_OP=120
PARAM=121 CONCAT=121
STRING=122 DOT=122
INTEGER_VALUE=123 PARAM=123
DECIMAL_VALUE=124 STRING=124
IDENTIFIER=125 INTEGER_VALUE=125
DIGIT_IDENTIFIER=126 DECIMAL_VALUE=126
TABLE_IDENTIFIER=127 IDENTIFIER=127
QUOTED_IDENTIFIER=128 DIGIT_IDENTIFIER=128
BACKQUOTED_IDENTIFIER=129 TABLE_IDENTIFIER=129
SIMPLE_COMMENT=130 QUOTED_IDENTIFIER=130
BRACKETED_COMMENT=131 BACKQUOTED_IDENTIFIER=131
WS=132 SIMPLE_COMMENT=132
UNRECOGNIZED=133 BRACKETED_COMMENT=133
WS=134
UNRECOGNIZED=135
'('=1 '('=1
')'=2 ')'=2
','=3 ','=3
@ -170,84 +172,86 @@ UNRECOGNIZED=133
'FIRST'=37 'FIRST'=37
'FORMAT'=38 'FORMAT'=38
'FROM'=39 'FROM'=39
'FULL'=40 'FROZEN'=40
'FUNCTIONS'=41 'FULL'=41
'GRAPHVIZ'=42 'FUNCTIONS'=42
'GROUP'=43 'GRAPHVIZ'=43
'HAVING'=44 'GROUP'=44
'HOUR'=45 'HAVING'=45
'HOURS'=46 'HOUR'=46
'IN'=47 'HOURS'=47
'INNER'=48 'IN'=48
'INTERVAL'=49 'INCLUDE'=49
'IS'=50 'INNER'=50
'JOIN'=51 'INTERVAL'=51
'LAST'=52 'IS'=52
'LEFT'=53 'JOIN'=53
'LIKE'=54 'LAST'=54
'LIMIT'=55 'LEFT'=55
'MAPPED'=56 'LIKE'=56
'MATCH'=57 'LIMIT'=57
'MINUTE'=58 'MAPPED'=58
'MINUTES'=59 'MATCH'=59
'MONTH'=60 'MINUTE'=60
'MONTHS'=61 'MINUTES'=61
'NATURAL'=62 'MONTH'=62
'NOT'=63 'MONTHS'=63
'NULL'=64 'NATURAL'=64
'NULLS'=65 'NOT'=65
'ON'=66 'NULL'=66
'OPTIMIZED'=67 'NULLS'=67
'OR'=68 'ON'=68
'ORDER'=69 'OPTIMIZED'=69
'OUTER'=70 'OR'=70
'PARSED'=71 'ORDER'=71
'PHYSICAL'=72 'OUTER'=72
'PLAN'=73 'PARSED'=73
'RIGHT'=74 'PHYSICAL'=74
'RLIKE'=75 'PLAN'=75
'QUERY'=76 'RIGHT'=76
'SCHEMAS'=77 'RLIKE'=77
'SECOND'=78 'QUERY'=78
'SECONDS'=79 'SCHEMAS'=79
'SELECT'=80 'SECOND'=80
'SHOW'=81 'SECONDS'=81
'SYS'=82 'SELECT'=82
'TABLE'=83 'SHOW'=83
'TABLES'=84 'SYS'=84
'TEXT'=85 'TABLE'=85
'THEN'=86 'TABLES'=86
'TRUE'=87 'TEXT'=87
'TO'=88 'THEN'=88
'TYPE'=89 'TRUE'=89
'TYPES'=90 'TO'=90
'USING'=91 'TYPE'=91
'VERIFY'=92 'TYPES'=92
'WHEN'=93 'USING'=93
'WHERE'=94 'VERIFY'=94
'WITH'=95 'WHEN'=95
'YEAR'=96 'WHERE'=96
'YEARS'=97 'WITH'=97
'{ESCAPE'=98 'YEAR'=98
'{FN'=99 'YEARS'=99
'{LIMIT'=100 '{ESCAPE'=100
'{D'=101 '{FN'=101
'{T'=102 '{LIMIT'=102
'{TS'=103 '{D'=103
'{GUID'=104 '{T'=104
'}'=105 '{TS'=105
'='=106 '{GUID'=106
'<=>'=107 '}'=107
'<'=109 '='=108
'<='=110 '<=>'=109
'>'=111 '<'=111
'>='=112 '<='=112
'+'=113 '>'=113
'-'=114 '>='=114
'*'=115 '+'=115
'/'=116 '-'=116
'%'=117 '*'=117
'::'=118 '/'=118
'||'=119 '%'=119
'.'=120 '::'=120
'?'=121 '||'=121
'.'=122
'?'=123

View File

@ -288,11 +288,11 @@ public class Analyzer extends RuleExecutor<LogicalPlan> {
protected LogicalPlan rule(UnresolvedRelation plan) { protected LogicalPlan rule(UnresolvedRelation plan) {
TableIdentifier table = plan.table(); TableIdentifier table = plan.table();
if (indexResolution.isValid() == false) { if (indexResolution.isValid() == false) {
return plan.unresolvedMessage().equals(indexResolution.toString()) ? plan : new UnresolvedRelation(plan.source(), return plan.unresolvedMessage().equals(indexResolution.toString()) ? plan :
plan.table(), plan.alias(), indexResolution.toString()); new UnresolvedRelation(plan.source(), plan.table(), plan.alias(), plan.frozen(), indexResolution.toString());
} }
assert indexResolution.matches(table.index()); assert indexResolution.matches(table.index());
LogicalPlan logicalPlan = new EsRelation(plan.source(), indexResolution.get()); LogicalPlan logicalPlan = new EsRelation(plan.source(), indexResolution.get(), plan.frozen());
SubQueryAlias sa = new SubQueryAlias(plan.source(), logicalPlan, table.index()); SubQueryAlias sa = new SubQueryAlias(plan.source(), logicalPlan, table.index());
if (plan.alias() != null) { if (plan.alias() != null) {

View File

@ -5,7 +5,6 @@
*/ */
package org.elasticsearch.xpack.sql.analysis.analyzer; package org.elasticsearch.xpack.sql.analysis.analyzer;
import org.elasticsearch.xpack.sql.plan.TableIdentifier;
import org.elasticsearch.xpack.sql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.sql.plan.logical.LogicalPlan;
import org.elasticsearch.xpack.sql.plan.logical.UnresolvedRelation; import org.elasticsearch.xpack.sql.plan.logical.UnresolvedRelation;
@ -23,9 +22,9 @@ public class PreAnalyzer {
public static class PreAnalysis { public static class PreAnalysis {
public static final PreAnalysis EMPTY = new PreAnalysis(emptyList()); public static final PreAnalysis EMPTY = new PreAnalysis(emptyList());
public final List<TableIdentifier> indices; public final List<TableInfo> indices;
PreAnalysis(List<TableIdentifier> indices) { PreAnalysis(List<TableInfo> indices) {
this.indices = indices; this.indices = indices;
} }
} }
@ -39,9 +38,9 @@ public class PreAnalyzer {
} }
private PreAnalysis doPreAnalyze(LogicalPlan plan) { private PreAnalysis doPreAnalyze(LogicalPlan plan) {
List<TableIdentifier> indices = new ArrayList<>(); List<TableInfo> indices = new ArrayList<>();
plan.forEachUp(p -> indices.add(p.table()), UnresolvedRelation.class); plan.forEachUp(p -> indices.add(new TableInfo(p.table(), p.frozen())), UnresolvedRelation.class);
// mark plan as preAnalyzed (if it were marked, there would be no analysis) // mark plan as preAnalyzed (if it were marked, there would be no analysis)
plan.forEachUp(LogicalPlan::setPreAnalyzed); plan.forEachUp(LogicalPlan::setPreAnalyzed);

View File

@ -0,0 +1,28 @@
/*
* 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.analyzer;
import org.elasticsearch.xpack.sql.plan.TableIdentifier;
public class TableInfo {
private final TableIdentifier id;
private final boolean isFrozen;
TableInfo(TableIdentifier id, boolean isFrozen) {
this.id = id;
this.isFrozen = isFrozen;
}
public TableIdentifier id() {
return id;
}
public boolean isFrozen() {
return isFrozen;
}
}

View File

@ -23,6 +23,7 @@ import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.metadata.AliasMetaData; import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.type.DataType;
import org.elasticsearch.xpack.sql.type.DateEsField; import org.elasticsearch.xpack.sql.type.DateEsField;
@ -42,7 +43,6 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Objects; import java.util.Objects;
@ -57,38 +57,39 @@ import static java.util.Arrays.asList;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap; import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet; import static java.util.Collections.emptySet;
import static org.elasticsearch.action.ActionListener.wrap;
public class IndexResolver { public class IndexResolver {
public enum IndexType { public enum IndexType {
STANDARD_INDEX("BASE TABLE", "INDEX"),
INDEX("BASE TABLE"), ALIAS("VIEW", "ALIAS"),
ALIAS("VIEW"), FROZEN_INDEX("BASE TABLE", "FROZEN INDEX"),
// value for user types unrecognized // value for user types unrecognized
UNKNOWN("UNKNOWN"); UNKNOWN("UNKNOWN", "UNKNOWN");
public static final EnumSet<IndexType> VALID = EnumSet.of(INDEX, ALIAS); public static final String SQL_BASE_TABLE = "BASE TABLE";
public static final String SQL_TABLE = "TABLE";
public static final String SQL_VIEW = "VIEW";
public static final EnumSet<IndexType> VALID_INCLUDE_FROZEN = EnumSet.of(STANDARD_INDEX, ALIAS, FROZEN_INDEX);
public static final EnumSet<IndexType> VALID_REGULAR = EnumSet.of(STANDARD_INDEX, ALIAS);
public static final EnumSet<IndexType> INDICES_ONLY = EnumSet.of(STANDARD_INDEX, FROZEN_INDEX);
private final String toSql; private final String toSql;
private final String toNative;
IndexType(String sql) { IndexType(String sql, String toNative) {
this.toSql = sql; this.toSql = sql;
this.toNative = toNative;
} }
public String toSql() { public String toSql() {
return toSql; return toSql;
} }
public static IndexType from(String name) { public String toNative() {
if (name != null) { return toNative;
name = name.toUpperCase(Locale.ROOT);
for (IndexType type : IndexType.VALID) {
if (type.toSql.equals(name)) {
return type;
}
}
}
return IndexType.UNKNOWN;
} }
} }
@ -136,7 +137,17 @@ public class IndexResolver {
} }
private static final IndicesOptions INDICES_ONLY_OPTIONS = new IndicesOptions( private static final IndicesOptions INDICES_ONLY_OPTIONS = new IndicesOptions(
EnumSet.of(Option.ALLOW_NO_INDICES, Option.IGNORE_UNAVAILABLE, Option.IGNORE_ALIASES, Option.IGNORE_THROTTLED),
EnumSet.of(WildcardStates.OPEN));
private static final IndicesOptions FROZEN_INDICES_OPTIONS = new IndicesOptions(
EnumSet.of(Option.ALLOW_NO_INDICES, Option.IGNORE_UNAVAILABLE, Option.IGNORE_ALIASES), EnumSet.of(WildcardStates.OPEN)); EnumSet.of(Option.ALLOW_NO_INDICES, Option.IGNORE_UNAVAILABLE, Option.IGNORE_ALIASES), EnumSet.of(WildcardStates.OPEN));
public static final IndicesOptions FIELD_CAPS_INDICES_OPTIONS = new IndicesOptions(
EnumSet.of(Option.ALLOW_NO_INDICES, Option.IGNORE_UNAVAILABLE, Option.IGNORE_THROTTLED), EnumSet.of(WildcardStates.OPEN));
public static final IndicesOptions FIELD_CAPS_FROZEN_INDICES_OPTIONS = new IndicesOptions(
EnumSet.of(Option.ALLOW_NO_INDICES, Option.IGNORE_UNAVAILABLE), EnumSet.of(WildcardStates.OPEN));
private static final List<String> FIELD_NAMES_BLACKLIST = Arrays.asList("_size"); private static final List<String> FIELD_NAMES_BLACKLIST = Arrays.asList("_size");
private static final String UNMAPPED = "unmapped"; private static final String UNMAPPED = "unmapped";
@ -161,7 +172,8 @@ public class IndexResolver {
// first get aliases (if specified) // first get aliases (if specified)
boolean retrieveAliases = CollectionUtils.isEmpty(types) || types.contains(IndexType.ALIAS); boolean retrieveAliases = CollectionUtils.isEmpty(types) || types.contains(IndexType.ALIAS);
boolean retrieveIndices = CollectionUtils.isEmpty(types) || types.contains(IndexType.INDEX); boolean retrieveIndices = CollectionUtils.isEmpty(types) || types.contains(IndexType.STANDARD_INDEX);
boolean retrieveFrozenIndices = CollectionUtils.isEmpty(types) || types.contains(IndexType.FROZEN_INDEX);
String[] indices = Strings.commaDelimitedListToStringArray(indexWildcard); String[] indices = Strings.commaDelimitedListToStringArray(indexWildcard);
if (retrieveAliases) { if (retrieveAliases) {
@ -170,8 +182,8 @@ public class IndexResolver {
.aliases(indices) .aliases(indices)
.indicesOptions(IndicesOptions.lenientExpandOpen()); .indicesOptions(IndicesOptions.lenientExpandOpen());
client.admin().indices().getAliases(aliasRequest, ActionListener.wrap(aliases -> client.admin().indices().getAliases(aliasRequest, wrap(aliases ->
resolveIndices(indices, javaRegex, aliases, retrieveIndices, listener), resolveIndices(indices, javaRegex, aliases, retrieveIndices, retrieveFrozenIndices, listener),
ex -> { ex -> {
// with security, two exception can be thrown: // with security, two exception can be thrown:
// INFE - if no alias matches // INFE - if no alias matches
@ -179,36 +191,46 @@ public class IndexResolver {
// in both cases, that is allowed and we continue with the indices request // in both cases, that is allowed and we continue with the indices request
if (ex instanceof IndexNotFoundException || ex instanceof ElasticsearchSecurityException) { if (ex instanceof IndexNotFoundException || ex instanceof ElasticsearchSecurityException) {
resolveIndices(indices, javaRegex, null, retrieveIndices, listener); resolveIndices(indices, javaRegex, null, retrieveIndices, retrieveFrozenIndices, listener);
} else { } else {
listener.onFailure(ex); listener.onFailure(ex);
} }
})); }));
} else { } else {
resolveIndices(indices, javaRegex, null, retrieveIndices, listener); resolveIndices(indices, javaRegex, null, retrieveIndices, retrieveFrozenIndices, listener);
} }
} }
private void resolveIndices(String[] indices, String javaRegex, GetAliasesResponse aliases, private void resolveIndices(String[] indices, String javaRegex, GetAliasesResponse aliases,
boolean retrieveIndices, ActionListener<Set<IndexInfo>> listener) { boolean retrieveIndices, boolean retrieveFrozenIndices, ActionListener<Set<IndexInfo>> listener) {
if (retrieveIndices) { if (retrieveIndices || retrieveFrozenIndices) {
GetIndexRequest indexRequest = new GetIndexRequest() GetIndexRequest indexRequest = new GetIndexRequest()
.local(true) .local(true)
.indices(indices) .indices(indices)
.features(Feature.SETTINGS) .features(Feature.SETTINGS)
.includeDefaults(false) .includeDefaults(false)
.indicesOptions(INDICES_ONLY_OPTIONS); .indicesOptions(INDICES_ONLY_OPTIONS);
// if frozen indices are requested, make sure to update the request accordingly
if (retrieveFrozenIndices) {
indexRequest.indicesOptions(FROZEN_INDICES_OPTIONS);
}
client.admin().indices().getIndex(indexRequest, client.admin().indices().getIndex(indexRequest,
ActionListener.wrap(response -> filterResults(javaRegex, aliases, response, listener), wrap(response -> filterResults(javaRegex, aliases, response, retrieveIndices, retrieveFrozenIndices, listener),
listener::onFailure)); listener::onFailure));
} else { } else {
filterResults(javaRegex, aliases, null, listener); filterResults(javaRegex, aliases, null, false, false, listener);
} }
} }
private void filterResults(String javaRegex, GetAliasesResponse aliases, GetIndexResponse indices, private void filterResults(String javaRegex, GetAliasesResponse aliases, GetIndexResponse indices,
// these are needed to filter out the different results from the same index response
boolean retrieveIndices,
boolean retrieveFrozenIndices,
ActionListener<Set<IndexInfo>> listener) { ActionListener<Set<IndexInfo>> listener) {
// since the index name does not support ?, filter the results manually // since the index name does not support ?, filter the results manually
@ -226,12 +248,16 @@ public class IndexResolver {
} }
} }
} }
// filter indices (if present) // filter indices (if present)
String[] indicesNames = indices != null ? indices.indices() : null; String[] indicesNames = indices != null ? indices.indices() : null;
if (indicesNames != null) { if (indicesNames != null) {
for (String indexName : indicesNames) { for (String indexName : indicesNames) {
boolean isFrozen = retrieveFrozenIndices
&& IndexSettings.INDEX_SEARCH_THROTTLED.get(indices.getSettings().get(indexName)) == Boolean.TRUE;
if (pattern == null || pattern.matcher(indexName).matches()) { if (pattern == null || pattern.matcher(indexName).matches()) {
result.add(new IndexInfo(indexName, IndexType.INDEX)); result.add(new IndexInfo(indexName, isFrozen ? IndexType.FROZEN_INDEX : IndexType.STANDARD_INDEX));
} }
} }
} }
@ -242,8 +268,9 @@ public class IndexResolver {
/** /**
* Resolves a pattern to one (potentially compound meaning that spawns multiple indices) mapping. * Resolves a pattern to one (potentially compound meaning that spawns multiple indices) mapping.
*/ */
public void resolveAsMergedMapping(String indexWildcard, String javaRegex, ActionListener<IndexResolution> listener) { public void resolveAsMergedMapping(String indexWildcard, String javaRegex, boolean includeFrozen,
FieldCapabilitiesRequest fieldRequest = createFieldCapsRequest(indexWildcard); ActionListener<IndexResolution> listener) {
FieldCapabilitiesRequest fieldRequest = createFieldCapsRequest(indexWildcard, includeFrozen);
client.fieldCaps(fieldRequest, client.fieldCaps(fieldRequest,
ActionListener.wrap( ActionListener.wrap(
response -> listener.onResponse(mergedMappings(indexWildcard, response.getIndices(), response.get())), response -> listener.onResponse(mergedMappings(indexWildcard, response.getIndices(), response.get())),
@ -287,7 +314,7 @@ public class IndexResolver {
// type is okay, check aggregation // type is okay, check aggregation
else { else {
FieldCapabilities fieldCap = types.values().iterator().next(); FieldCapabilities fieldCap = types.values().iterator().next();
// validate search/agg-able // validate search/agg-able
if (fieldCap.isAggregatable() && fieldCap.nonAggregatableIndices() != null) { if (fieldCap.isAggregatable() && fieldCap.nonAggregatableIndices() != null) {
errorMessage.append("mapped as aggregatable except in "); errorMessage.append("mapped as aggregatable except in ");
@ -305,16 +332,16 @@ public class IndexResolver {
return new InvalidMappedField(n, errorMessage.toString()); return new InvalidMappedField(n, errorMessage.toString());
} }
} }
// everything checks // everything checks
return null; return null;
}); });
if (indices.size() != 1) { if (indices.size() != 1) {
throw new SqlIllegalArgumentException("Incorrect merging of mappings (likely due to a bug) - expect 1 but found [{}]", throw new SqlIllegalArgumentException("Incorrect merging of mappings (likely due to a bug) - expect 1 but found [{}]",
indices.size()); indices.size());
} }
return IndexResolution.valid(indices.get(0)); return IndexResolution.valid(indices.get(0));
} }
@ -356,7 +383,7 @@ public class IndexResolver {
} }
EsField esField = field.apply(fieldName); EsField esField = field.apply(fieldName);
parentProps.put(fieldName, esField); parentProps.put(fieldName, esField);
flattedMapping.put(fullFieldName, esField); flattedMapping.put(fullFieldName, esField);
@ -382,17 +409,27 @@ public class IndexResolver {
} }
} }
private static FieldCapabilitiesRequest createFieldCapsRequest(String index, boolean includeFrozen) {
return new FieldCapabilitiesRequest()
.indices(Strings.commaDelimitedListToStringArray(index))
.fields("*")
.includeUnmapped(true)
//lenient because we throw our own errors looking at the response e.g. if something was not resolved
//also because this way security doesn't throw authorization exceptions but rather honors ignore_unavailable
.indicesOptions(includeFrozen ? FIELD_CAPS_FROZEN_INDICES_OPTIONS : FIELD_CAPS_INDICES_OPTIONS);
}
/** /**
* Resolves a pattern to multiple, separate indices. Doesn't perform validation. * Resolves a pattern to multiple, separate indices. Doesn't perform validation.
*/ */
public void resolveAsSeparateMappings(String indexWildcard, String javaRegex, ActionListener<List<EsIndex>> listener) { public void resolveAsSeparateMappings(String indexWildcard, String javaRegex, boolean includeFrozen,
FieldCapabilitiesRequest fieldRequest = createFieldCapsRequest(indexWildcard); ActionListener<List<EsIndex>> listener) {
FieldCapabilitiesRequest fieldRequest = createFieldCapsRequest(indexWildcard, includeFrozen);
client.fieldCaps(fieldRequest, client.fieldCaps(fieldRequest,
ActionListener.wrap( ActionListener.wrap(
response -> listener.onResponse(separateMappings(indexWildcard, javaRegex, response.getIndices(), response.get())), response -> listener.onResponse(separateMappings(indexWildcard, javaRegex, response.getIndices(), response.get())),
listener::onFailure)); listener::onFailure));
} }
static List<EsIndex> separateMappings(String indexPattern, String javaRegex, String[] indexNames, static List<EsIndex> separateMappings(String indexPattern, String javaRegex, String[] indexNames,
@ -430,7 +467,7 @@ public class IndexResolver {
for (Entry<String, Map<String, FieldCapabilities>> entry : sortedFields) { for (Entry<String, Map<String, FieldCapabilities>> entry : sortedFields) {
String fieldName = entry.getKey(); String fieldName = entry.getKey();
Map<String, FieldCapabilities> types = entry.getValue(); Map<String, FieldCapabilities> types = entry.getValue();
// ignore size added by the mapper plugin // ignore size added by the mapper plugin
if (FIELD_NAMES_BLACKLIST.contains(fieldName)) { if (FIELD_NAMES_BLACKLIST.contains(fieldName)) {
continue; continue;
@ -438,7 +475,7 @@ public class IndexResolver {
// apply verification // apply verification
final InvalidMappedField invalidField = validityVerifier.apply(fieldName, types); final InvalidMappedField invalidField = validityVerifier.apply(fieldName, types);
// filter meta fields and unmapped // filter meta fields and unmapped
FieldCapabilities unmapped = types.get(UNMAPPED); FieldCapabilities unmapped = types.get(UNMAPPED);
Set<String> unmappedIndices = unmapped != null ? new HashSet<>(asList(unmapped.indices())) : emptySet(); Set<String> unmappedIndices = unmapped != null ? new HashSet<>(asList(unmapped.indices())) : emptySet();
@ -447,7 +484,7 @@ public class IndexResolver {
for (Entry<String, FieldCapabilities> typeEntry : types.entrySet()) { for (Entry<String, FieldCapabilities> typeEntry : types.entrySet()) {
FieldCapabilities typeCap = typeEntry.getValue(); FieldCapabilities typeCap = typeEntry.getValue();
String[] capIndices = typeCap.indices(); String[] capIndices = typeCap.indices();
// Skip internal fields (name starting with underscore and its type reported by field_caps starts // Skip internal fields (name starting with underscore and its type reported by field_caps starts
// with underscore as well). A meta field named "_version", for example, has the type named "_version". // with underscore as well). A meta field named "_version", for example, has the type named "_version".
if (typeEntry.getKey().startsWith("_") && typeCap.getType().startsWith("_")) { if (typeEntry.getKey().startsWith("_") && typeCap.getType().startsWith("_")) {
@ -483,9 +520,9 @@ public class IndexResolver {
} }
EsField field = indexFields.flattedMapping.get(fieldName); EsField field = indexFields.flattedMapping.get(fieldName);
if (field == null || (invalidField != null && (field instanceof InvalidMappedField) == false)) { if (field == null || (invalidField != null && (field instanceof InvalidMappedField) == false)) {
createField(fieldName, fieldCaps, indexFields.hierarchicalMapping, indexFields.flattedMapping, s -> createField(fieldName, fieldCaps, indexFields.hierarchicalMapping, indexFields.flattedMapping,
invalidField != null ? invalidField : s -> invalidField != null ? invalidField : createField(s, typeCap.getType(), emptyMap(),
createField(s, typeCap.getType(), emptyMap(), typeCap.isAggregatable())); typeCap.isAggregatable()));
} }
} }
} }
@ -500,14 +537,4 @@ public class IndexResolver {
foundIndices.sort(Comparator.comparing(EsIndex::name)); foundIndices.sort(Comparator.comparing(EsIndex::name));
return foundIndices; return foundIndices;
} }
private static FieldCapabilitiesRequest createFieldCapsRequest(String index) {
return new FieldCapabilitiesRequest()
.indices(Strings.commaDelimitedListToStringArray(index))
.fields("*")
.includeUnmapped(true)
//lenient because we throw our own errors looking at the response e.g. if something was not resolved
//also because this way security doesn't throw authorization exceptions but rather honors ignore_unavailable
.indicesOptions(IndicesOptions.lenientExpandOpen());
}
} }

View File

@ -52,13 +52,16 @@ public class CompositeAggregationCursor implements Cursor {
private final List<BucketExtractor> extractors; private final List<BucketExtractor> extractors;
private final BitSet mask; private final BitSet mask;
private final int limit; private final int limit;
private final boolean includeFrozen;
CompositeAggregationCursor(byte[] next, List<BucketExtractor> exts, BitSet mask, int remainingLimit, String... indices) { CompositeAggregationCursor(byte[] next, List<BucketExtractor> exts, BitSet mask, int remainingLimit, boolean includeFrozen,
String... indices) {
this.indices = indices; this.indices = indices;
this.nextQuery = next; this.nextQuery = next;
this.extractors = exts; this.extractors = exts;
this.mask = mask; this.mask = mask;
this.limit = remainingLimit; this.limit = remainingLimit;
this.includeFrozen = includeFrozen;
} }
public CompositeAggregationCursor(StreamInput in) throws IOException { public CompositeAggregationCursor(StreamInput in) throws IOException {
@ -68,6 +71,7 @@ public class CompositeAggregationCursor implements Cursor {
extractors = in.readNamedWriteableList(BucketExtractor.class); extractors = in.readNamedWriteableList(BucketExtractor.class);
mask = BitSet.valueOf(in.readByteArray()); mask = BitSet.valueOf(in.readByteArray());
includeFrozen = in.readBoolean();
} }
@Override @Override
@ -78,6 +82,8 @@ public class CompositeAggregationCursor implements Cursor {
out.writeNamedWriteableList(extractors); out.writeNamedWriteableList(extractors);
out.writeByteArray(mask.toByteArray()); out.writeByteArray(mask.toByteArray());
out.writeBoolean(includeFrozen);
} }
@Override @Override
@ -105,6 +111,10 @@ public class CompositeAggregationCursor implements Cursor {
return limit; return limit;
} }
boolean includeFrozen() {
return includeFrozen;
}
@Override @Override
public void nextPage(Configuration cfg, Client client, NamedWriteableRegistry registry, ActionListener<RowSet> listener) { public void nextPage(Configuration cfg, Client client, NamedWriteableRegistry registry, ActionListener<RowSet> listener) {
SearchSourceBuilder q; SearchSourceBuilder q;
@ -120,7 +130,7 @@ public class CompositeAggregationCursor implements Cursor {
log.trace("About to execute composite query {} on {}", StringUtils.toString(query), indices); log.trace("About to execute composite query {} on {}", StringUtils.toString(query), indices);
} }
SearchRequest search = Querier.prepareRequest(client, query, cfg.pageTimeout(), indices); SearchRequest search = Querier.prepareRequest(client, query, cfg.pageTimeout(), includeFrozen, indices);
client.search(search, new ActionListener<SearchResponse>() { client.search(search, new ActionListener<SearchResponse>() {
@Override @Override
@ -134,7 +144,8 @@ public class CompositeAggregationCursor implements Cursor {
} }
updateCompositeAfterKey(r, query); updateCompositeAfterKey(r, query);
CompositeAggsRowSet rowSet = new CompositeAggsRowSet(extractors, mask, r, limit, serializeQuery(query), indices); CompositeAggsRowSet rowSet = new CompositeAggsRowSet(extractors, mask, r, limit, serializeQuery(query), includeFrozen,
indices);
listener.onResponse(rowSet); listener.onResponse(rowSet);
} catch (Exception ex) { } catch (Exception ex) {
listener.onFailure(ex); listener.onFailure(ex);

View File

@ -28,7 +28,8 @@ class CompositeAggsRowSet extends ResultRowSet<BucketExtractor> {
private final int size; private final int size;
private int row = 0; private int row = 0;
CompositeAggsRowSet(List<BucketExtractor> exts, BitSet mask, SearchResponse response, int limit, byte[] next, String... indices) { CompositeAggsRowSet(List<BucketExtractor> exts, BitSet mask, SearchResponse response, int limit, byte[] next,
boolean includeFrozen, String... indices) {
super(exts, mask); super(exts, mask);
CompositeAggregation composite = CompositeAggregationCursor.getComposite(response); CompositeAggregation composite = CompositeAggregationCursor.getComposite(response);
@ -53,7 +54,7 @@ class CompositeAggsRowSet extends ResultRowSet<BucketExtractor> {
if (next == null || size == 0 || remainingLimit == 0) { if (next == null || size == 0 || remainingLimit == 0) {
cursor = Cursor.EMPTY; cursor = Cursor.EMPTY;
} else { } else {
cursor = new CompositeAggregationCursor(next, exts, mask, remainingLimit, indices); cursor = new CompositeAggregationCursor(next, exts, mask, remainingLimit, includeFrozen, indices);
} }
} }
} }

View File

@ -27,6 +27,7 @@ import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation.Buck
import org.elasticsearch.search.aggregations.bucket.filter.Filters; import org.elasticsearch.search.aggregations.bucket.filter.Filters;
import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
import org.elasticsearch.xpack.sql.analysis.index.IndexResolver;
import org.elasticsearch.xpack.sql.execution.PlanExecutor; import org.elasticsearch.xpack.sql.execution.PlanExecutor;
import org.elasticsearch.xpack.sql.execution.search.extractor.BucketExtractor; import org.elasticsearch.xpack.sql.execution.search.extractor.BucketExtractor;
import org.elasticsearch.xpack.sql.execution.search.extractor.CompositeKeyExtractor; import org.elasticsearch.xpack.sql.execution.search.extractor.CompositeKeyExtractor;
@ -108,7 +109,8 @@ public class Querier {
log.trace("About to execute query {} on {}", StringUtils.toString(sourceBuilder), index); log.trace("About to execute query {} on {}", StringUtils.toString(sourceBuilder), index);
} }
SearchRequest search = prepareRequest(client, sourceBuilder, timeout, Strings.commaDelimitedListToStringArray(index)); SearchRequest search = prepareRequest(client, sourceBuilder, timeout, query.shouldIncludeFrozen(),
Strings.commaDelimitedListToStringArray(index));
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
List<Tuple<Integer, Comparator>> sortingColumns = query.sortingColumns(); List<Tuple<Integer, Comparator>> sortingColumns = query.sortingColumns();
@ -130,13 +132,16 @@ public class Querier {
client.search(search, l); client.search(search, l);
} }
public static SearchRequest prepareRequest(Client client, SearchSourceBuilder source, TimeValue timeout, String... indices) { public static SearchRequest prepareRequest(Client client, SearchSourceBuilder source, TimeValue timeout, boolean includeFrozen,
String... indices) {
SearchRequest search = client.prepareSearch(indices) SearchRequest search = client.prepareSearch(indices)
// always track total hits accurately // always track total hits accurately
.setTrackTotalHits(true) .setTrackTotalHits(true)
.setAllowPartialSearchResults(false) .setAllowPartialSearchResults(false)
.setSource(source) .setSource(source)
.setTimeout(timeout) .setTimeout(timeout)
.setIndicesOptions(
includeFrozen ? IndexResolver.FIELD_CAPS_FROZEN_INDICES_OPTIONS : IndexResolver.FIELD_CAPS_INDICES_OPTIONS)
.request(); .request();
return search; return search;
} }
@ -175,7 +180,7 @@ public class Querier {
} }
} }
this.data = new PriorityQueue<Tuple<List<?>, Integer>>(size) { this.data = new PriorityQueue<>(size) {
// compare row based on the received attribute sort // compare row based on the received attribute sort
// if a sort item is not in the list, it is assumed the sorting happened in ES // if a sort item is not in the list, it is assumed the sorting happened in ES
@ -389,6 +394,7 @@ public class Querier {
listener.onResponse( listener.onResponse(
new SchemaCompositeAggsRowSet(schema, initBucketExtractors(response), mask, response, query.limit(), new SchemaCompositeAggsRowSet(schema, initBucketExtractors(response), mask, response, query.limit(),
nextSearch, nextSearch,
query.shouldIncludeFrozen(),
request.indices())); request.indices()));
} }
// no results // no results

View File

@ -24,8 +24,9 @@ class SchemaCompositeAggsRowSet extends CompositeAggsRowSet implements SchemaRow
SchemaCompositeAggsRowSet(Schema schema, List<BucketExtractor> exts, BitSet mask, SearchResponse response, int limitAggs, SchemaCompositeAggsRowSet(Schema schema, List<BucketExtractor> exts, BitSet mask, SearchResponse response, int limitAggs,
byte[] next, byte[] next,
boolean includeFrozen,
String... indices) { String... indices) {
super(exts, mask, response, limitAggs, next, indices); super(exts, mask, response, limitAggs, next, includeFrozen, indices);
this.schema = schema; this.schema = schema;
} }

View File

@ -125,7 +125,7 @@ abstract class CommandBuilder extends LogicalPlanBuilder {
public Object visitShowTables(ShowTablesContext ctx) { public Object visitShowTables(ShowTablesContext ctx) {
TableIdentifier ti = visitTableIdentifier(ctx.tableIdent); TableIdentifier ti = visitTableIdentifier(ctx.tableIdent);
String index = ti != null ? ti.qualifiedIndex() : null; String index = ti != null ? ti.qualifiedIndex() : null;
return new ShowTables(source(ctx), index, visitLikePattern(ctx.likePattern())); return new ShowTables(source(ctx), index, visitLikePattern(ctx.likePattern()), ctx.FROZEN() != null);
} }
@Override @Override
@ -137,7 +137,7 @@ abstract class CommandBuilder extends LogicalPlanBuilder {
public Object visitShowColumns(ShowColumnsContext ctx) { public Object visitShowColumns(ShowColumnsContext ctx) {
TableIdentifier ti = visitTableIdentifier(ctx.tableIdent); TableIdentifier ti = visitTableIdentifier(ctx.tableIdent);
String index = ti != null ? ti.qualifiedIndex() : null; String index = ti != null ? ti.qualifiedIndex() : null;
return new ShowColumns(source(ctx), index, visitLikePattern(ctx.likePattern())); return new ShowColumns(source(ctx), index, visitLikePattern(ctx.likePattern()), ctx.FROZEN() != null);
} }
@Override @Override
@ -154,12 +154,21 @@ abstract class CommandBuilder extends LogicalPlanBuilder {
} }
// special case for legacy apps (like msquery) that always asks for 'TABLE' // special case for legacy apps (like msquery) that always asks for 'TABLE'
// which we manually map to all concrete tables supported // which we manually map to all concrete tables supported
else if (value.toUpperCase(Locale.ROOT).equals("TABLE")) { else {
legacyTableType = true; switch (value.toUpperCase(Locale.ROOT)) {
types.add(IndexType.INDEX); case IndexType.SQL_TABLE:
} else { legacyTableType = true;
IndexType type = IndexType.from(value); types.add(IndexType.STANDARD_INDEX);
types.add(type); break;
case IndexType.SQL_BASE_TABLE:
types.add(IndexType.STANDARD_INDEX);
break;
case IndexType.SQL_VIEW:
types.add(IndexType.ALIAS);
break;
default:
types.add(IndexType.UNKNOWN);
}
} }
} }
} }

View File

@ -211,6 +211,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());
return new UnresolvedRelation(source(ctx), tableIdentifier, alias); return new UnresolvedRelation(source(ctx), tableIdentifier, alias, ctx.FROZEN() != null);
} }
} }

View File

@ -1,16 +1,13 @@
// ANTLR GENERATED CODE: DO NOT EDIT // ANTLR GENERATED CODE: DO NOT EDIT
package org.elasticsearch.xpack.sql.parser; package org.elasticsearch.xpack.sql.parser;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Lexer; import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.RuntimeMetaData; import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Vocabulary; import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.VocabularyImpl; import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.atn.ATN; import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.ATNDeserializer; import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.atn.LexerATNSimulator;
import org.antlr.v4.runtime.atn.PredictionContextCache;
import org.antlr.v4.runtime.dfa.DFA; import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.misc.*;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
class SqlBaseLexer extends Lexer { class SqlBaseLexer extends Lexer {
@ -25,21 +22,21 @@ class SqlBaseLexer extends Lexer {
COLUMNS=18, CONVERT=19, CURRENT_DATE=20, CURRENT_TIME=21, CURRENT_TIMESTAMP=22, COLUMNS=18, CONVERT=19, CURRENT_DATE=20, CURRENT_TIME=21, CURRENT_TIMESTAMP=22,
DAY=23, DAYS=24, DEBUG=25, DESC=26, DESCRIBE=27, DISTINCT=28, ELSE=29, DAY=23, DAYS=24, DEBUG=25, DESC=26, DESCRIBE=27, DISTINCT=28, ELSE=29,
END=30, ESCAPE=31, EXECUTABLE=32, EXISTS=33, EXPLAIN=34, EXTRACT=35, FALSE=36, END=30, ESCAPE=31, EXECUTABLE=32, EXISTS=33, EXPLAIN=34, EXTRACT=35, FALSE=36,
FIRST=37, FORMAT=38, FROM=39, FULL=40, FUNCTIONS=41, GRAPHVIZ=42, GROUP=43, FIRST=37, FORMAT=38, FROM=39, FROZEN=40, FULL=41, FUNCTIONS=42, GRAPHVIZ=43,
HAVING=44, HOUR=45, HOURS=46, IN=47, INNER=48, INTERVAL=49, IS=50, JOIN=51, GROUP=44, HAVING=45, HOUR=46, HOURS=47, IN=48, INCLUDE=49, INNER=50, INTERVAL=51,
LAST=52, LEFT=53, LIKE=54, LIMIT=55, MAPPED=56, MATCH=57, MINUTE=58, MINUTES=59, IS=52, JOIN=53, LAST=54, LEFT=55, LIKE=56, LIMIT=57, MAPPED=58, MATCH=59,
MONTH=60, MONTHS=61, NATURAL=62, NOT=63, NULL=64, NULLS=65, ON=66, OPTIMIZED=67, MINUTE=60, MINUTES=61, MONTH=62, MONTHS=63, NATURAL=64, NOT=65, NULL=66,
OR=68, ORDER=69, OUTER=70, PARSED=71, PHYSICAL=72, PLAN=73, RIGHT=74, NULLS=67, ON=68, OPTIMIZED=69, OR=70, ORDER=71, OUTER=72, PARSED=73, PHYSICAL=74,
RLIKE=75, QUERY=76, SCHEMAS=77, SECOND=78, SECONDS=79, SELECT=80, SHOW=81, PLAN=75, RIGHT=76, RLIKE=77, QUERY=78, SCHEMAS=79, SECOND=80, SECONDS=81,
SYS=82, TABLE=83, TABLES=84, TEXT=85, THEN=86, TRUE=87, TO=88, TYPE=89, SELECT=82, SHOW=83, SYS=84, TABLE=85, TABLES=86, TEXT=87, THEN=88, TRUE=89,
TYPES=90, USING=91, VERIFY=92, WHEN=93, WHERE=94, WITH=95, YEAR=96, YEARS=97, TO=90, TYPE=91, TYPES=92, USING=93, VERIFY=94, WHEN=95, WHERE=96, WITH=97,
ESCAPE_ESC=98, FUNCTION_ESC=99, LIMIT_ESC=100, DATE_ESC=101, TIME_ESC=102, YEAR=98, YEARS=99, ESCAPE_ESC=100, FUNCTION_ESC=101, LIMIT_ESC=102, DATE_ESC=103,
TIMESTAMP_ESC=103, GUID_ESC=104, ESC_END=105, EQ=106, NULLEQ=107, NEQ=108, TIME_ESC=104, TIMESTAMP_ESC=105, GUID_ESC=106, ESC_END=107, EQ=108, NULLEQ=109,
LT=109, LTE=110, GT=111, GTE=112, PLUS=113, MINUS=114, ASTERISK=115, SLASH=116, NEQ=110, LT=111, LTE=112, GT=113, GTE=114, PLUS=115, MINUS=116, ASTERISK=117,
PERCENT=117, CAST_OP=118, CONCAT=119, DOT=120, PARAM=121, STRING=122, SLASH=118, PERCENT=119, CAST_OP=120, CONCAT=121, DOT=122, PARAM=123, STRING=124,
INTEGER_VALUE=123, DECIMAL_VALUE=124, IDENTIFIER=125, DIGIT_IDENTIFIER=126, INTEGER_VALUE=125, DECIMAL_VALUE=126, IDENTIFIER=127, DIGIT_IDENTIFIER=128,
TABLE_IDENTIFIER=127, QUOTED_IDENTIFIER=128, BACKQUOTED_IDENTIFIER=129, TABLE_IDENTIFIER=129, QUOTED_IDENTIFIER=130, BACKQUOTED_IDENTIFIER=131,
SIMPLE_COMMENT=130, BRACKETED_COMMENT=131, WS=132, UNRECOGNIZED=133; SIMPLE_COMMENT=132, BRACKETED_COMMENT=133, WS=134, UNRECOGNIZED=135;
public static String[] modeNames = { public static String[] modeNames = {
"DEFAULT_MODE" "DEFAULT_MODE"
}; };
@ -50,20 +47,20 @@ class SqlBaseLexer extends Lexer {
"CONVERT", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "DAY", "CONVERT", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "DAY",
"DAYS", "DEBUG", "DESC", "DESCRIBE", "DISTINCT", "ELSE", "END", "ESCAPE", "DAYS", "DEBUG", "DESC", "DESCRIBE", "DISTINCT", "ELSE", "END", "ESCAPE",
"EXECUTABLE", "EXISTS", "EXPLAIN", "EXTRACT", "FALSE", "FIRST", "FORMAT", "EXECUTABLE", "EXISTS", "EXPLAIN", "EXTRACT", "FALSE", "FIRST", "FORMAT",
"FROM", "FULL", "FUNCTIONS", "GRAPHVIZ", "GROUP", "HAVING", "HOUR", "HOURS", "FROM", "FROZEN", "FULL", "FUNCTIONS", "GRAPHVIZ", "GROUP", "HAVING",
"IN", "INNER", "INTERVAL", "IS", "JOIN", "LAST", "LEFT", "LIKE", "LIMIT", "HOUR", "HOURS", "IN", "INCLUDE", "INNER", "INTERVAL", "IS", "JOIN", "LAST",
"MAPPED", "MATCH", "MINUTE", "MINUTES", "MONTH", "MONTHS", "NATURAL", "LEFT", "LIKE", "LIMIT", "MAPPED", "MATCH", "MINUTE", "MINUTES", "MONTH",
"NOT", "NULL", "NULLS", "ON", "OPTIMIZED", "OR", "ORDER", "OUTER", "PARSED", "MONTHS", "NATURAL", "NOT", "NULL", "NULLS", "ON", "OPTIMIZED", "OR",
"PHYSICAL", "PLAN", "RIGHT", "RLIKE", "QUERY", "SCHEMAS", "SECOND", "SECONDS", "ORDER", "OUTER", "PARSED", "PHYSICAL", "PLAN", "RIGHT", "RLIKE", "QUERY",
"SELECT", "SHOW", "SYS", "TABLE", "TABLES", "TEXT", "THEN", "TRUE", "TO", "SCHEMAS", "SECOND", "SECONDS", "SELECT", "SHOW", "SYS", "TABLE", "TABLES",
"TYPE", "TYPES", "USING", "VERIFY", "WHEN", "WHERE", "WITH", "YEAR", "YEARS", "TEXT", "THEN", "TRUE", "TO", "TYPE", "TYPES", "USING", "VERIFY", "WHEN",
"ESCAPE_ESC", "FUNCTION_ESC", "LIMIT_ESC", "DATE_ESC", "TIME_ESC", "TIMESTAMP_ESC", "WHERE", "WITH", "YEAR", "YEARS", "ESCAPE_ESC", "FUNCTION_ESC", "LIMIT_ESC",
"GUID_ESC", "ESC_END", "EQ", "NULLEQ", "NEQ", "LT", "LTE", "GT", "GTE", "DATE_ESC", "TIME_ESC", "TIMESTAMP_ESC", "GUID_ESC", "ESC_END", "EQ",
"PLUS", "MINUS", "ASTERISK", "SLASH", "PERCENT", "CAST_OP", "CONCAT", "NULLEQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", "MINUS", "ASTERISK",
"DOT", "PARAM", "STRING", "INTEGER_VALUE", "DECIMAL_VALUE", "IDENTIFIER", "SLASH", "PERCENT", "CAST_OP", "CONCAT", "DOT", "PARAM", "STRING", "INTEGER_VALUE",
"DIGIT_IDENTIFIER", "TABLE_IDENTIFIER", "QUOTED_IDENTIFIER", "BACKQUOTED_IDENTIFIER", "DECIMAL_VALUE", "IDENTIFIER", "DIGIT_IDENTIFIER", "TABLE_IDENTIFIER",
"EXPONENT", "DIGIT", "LETTER", "SIMPLE_COMMENT", "BRACKETED_COMMENT", "QUOTED_IDENTIFIER", "BACKQUOTED_IDENTIFIER", "EXPONENT", "DIGIT", "LETTER",
"WS", "UNRECOGNIZED" "SIMPLE_COMMENT", "BRACKETED_COMMENT", "WS", "UNRECOGNIZED"
}; };
private static final String[] _LITERAL_NAMES = { private static final String[] _LITERAL_NAMES = {
@ -73,18 +70,18 @@ class SqlBaseLexer extends Lexer {
"'CURRENT_TIME'", "'CURRENT_TIMESTAMP'", "'DAY'", "'DAYS'", "'DEBUG'", "'CURRENT_TIME'", "'CURRENT_TIMESTAMP'", "'DAY'", "'DAYS'", "'DEBUG'",
"'DESC'", "'DESCRIBE'", "'DISTINCT'", "'ELSE'", "'END'", "'ESCAPE'", "'EXECUTABLE'", "'DESC'", "'DESCRIBE'", "'DISTINCT'", "'ELSE'", "'END'", "'ESCAPE'", "'EXECUTABLE'",
"'EXISTS'", "'EXPLAIN'", "'EXTRACT'", "'FALSE'", "'FIRST'", "'FORMAT'", "'EXISTS'", "'EXPLAIN'", "'EXTRACT'", "'FALSE'", "'FIRST'", "'FORMAT'",
"'FROM'", "'FULL'", "'FUNCTIONS'", "'GRAPHVIZ'", "'GROUP'", "'HAVING'", "'FROM'", "'FROZEN'", "'FULL'", "'FUNCTIONS'", "'GRAPHVIZ'", "'GROUP'",
"'HOUR'", "'HOURS'", "'IN'", "'INNER'", "'INTERVAL'", "'IS'", "'JOIN'", "'HAVING'", "'HOUR'", "'HOURS'", "'IN'", "'INCLUDE'", "'INNER'", "'INTERVAL'",
"'LAST'", "'LEFT'", "'LIKE'", "'LIMIT'", "'MAPPED'", "'MATCH'", "'MINUTE'", "'IS'", "'JOIN'", "'LAST'", "'LEFT'", "'LIKE'", "'LIMIT'", "'MAPPED'",
"'MINUTES'", "'MONTH'", "'MONTHS'", "'NATURAL'", "'NOT'", "'NULL'", "'NULLS'", "'MATCH'", "'MINUTE'", "'MINUTES'", "'MONTH'", "'MONTHS'", "'NATURAL'",
"'ON'", "'OPTIMIZED'", "'OR'", "'ORDER'", "'OUTER'", "'PARSED'", "'PHYSICAL'", "'NOT'", "'NULL'", "'NULLS'", "'ON'", "'OPTIMIZED'", "'OR'", "'ORDER'",
"'PLAN'", "'RIGHT'", "'RLIKE'", "'QUERY'", "'SCHEMAS'", "'SECOND'", "'SECONDS'", "'OUTER'", "'PARSED'", "'PHYSICAL'", "'PLAN'", "'RIGHT'", "'RLIKE'", "'QUERY'",
"'SELECT'", "'SHOW'", "'SYS'", "'TABLE'", "'TABLES'", "'TEXT'", "'THEN'", "'SCHEMAS'", "'SECOND'", "'SECONDS'", "'SELECT'", "'SHOW'", "'SYS'", "'TABLE'",
"'TRUE'", "'TO'", "'TYPE'", "'TYPES'", "'USING'", "'VERIFY'", "'WHEN'", "'TABLES'", "'TEXT'", "'THEN'", "'TRUE'", "'TO'", "'TYPE'", "'TYPES'",
"'WHERE'", "'WITH'", "'YEAR'", "'YEARS'", "'{ESCAPE'", "'{FN'", "'{LIMIT'", "'USING'", "'VERIFY'", "'WHEN'", "'WHERE'", "'WITH'", "'YEAR'", "'YEARS'",
"'{D'", "'{T'", "'{TS'", "'{GUID'", "'}'", "'='", "'<=>'", null, "'<'", "'{ESCAPE'", "'{FN'", "'{LIMIT'", "'{D'", "'{T'", "'{TS'", "'{GUID'",
"'<='", "'>'", "'>='", "'+'", "'-'", "'*'", "'/'", "'%'", "'::'", "'||'", "'}'", "'='", "'<=>'", null, "'<'", "'<='", "'>'", "'>='", "'+'", "'-'",
"'.'", "'?'" "'*'", "'/'", "'%'", "'::'", "'||'", "'.'", "'?'"
}; };
private static final String[] _SYMBOLIC_NAMES = { private static final String[] _SYMBOLIC_NAMES = {
null, null, null, null, null, "ALL", "ANALYZE", "ANALYZED", "AND", "ANY", null, null, null, null, null, "ALL", "ANALYZE", "ANALYZED", "AND", "ANY",
@ -92,19 +89,20 @@ class SqlBaseLexer extends Lexer {
"CONVERT", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "DAY", "CONVERT", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "DAY",
"DAYS", "DEBUG", "DESC", "DESCRIBE", "DISTINCT", "ELSE", "END", "ESCAPE", "DAYS", "DEBUG", "DESC", "DESCRIBE", "DISTINCT", "ELSE", "END", "ESCAPE",
"EXECUTABLE", "EXISTS", "EXPLAIN", "EXTRACT", "FALSE", "FIRST", "FORMAT", "EXECUTABLE", "EXISTS", "EXPLAIN", "EXTRACT", "FALSE", "FIRST", "FORMAT",
"FROM", "FULL", "FUNCTIONS", "GRAPHVIZ", "GROUP", "HAVING", "HOUR", "HOURS", "FROM", "FROZEN", "FULL", "FUNCTIONS", "GRAPHVIZ", "GROUP", "HAVING",
"IN", "INNER", "INTERVAL", "IS", "JOIN", "LAST", "LEFT", "LIKE", "LIMIT", "HOUR", "HOURS", "IN", "INCLUDE", "INNER", "INTERVAL", "IS", "JOIN", "LAST",
"MAPPED", "MATCH", "MINUTE", "MINUTES", "MONTH", "MONTHS", "NATURAL", "LEFT", "LIKE", "LIMIT", "MAPPED", "MATCH", "MINUTE", "MINUTES", "MONTH",
"NOT", "NULL", "NULLS", "ON", "OPTIMIZED", "OR", "ORDER", "OUTER", "PARSED", "MONTHS", "NATURAL", "NOT", "NULL", "NULLS", "ON", "OPTIMIZED", "OR",
"PHYSICAL", "PLAN", "RIGHT", "RLIKE", "QUERY", "SCHEMAS", "SECOND", "SECONDS", "ORDER", "OUTER", "PARSED", "PHYSICAL", "PLAN", "RIGHT", "RLIKE", "QUERY",
"SELECT", "SHOW", "SYS", "TABLE", "TABLES", "TEXT", "THEN", "TRUE", "TO", "SCHEMAS", "SECOND", "SECONDS", "SELECT", "SHOW", "SYS", "TABLE", "TABLES",
"TYPE", "TYPES", "USING", "VERIFY", "WHEN", "WHERE", "WITH", "YEAR", "YEARS", "TEXT", "THEN", "TRUE", "TO", "TYPE", "TYPES", "USING", "VERIFY", "WHEN",
"ESCAPE_ESC", "FUNCTION_ESC", "LIMIT_ESC", "DATE_ESC", "TIME_ESC", "TIMESTAMP_ESC", "WHERE", "WITH", "YEAR", "YEARS", "ESCAPE_ESC", "FUNCTION_ESC", "LIMIT_ESC",
"GUID_ESC", "ESC_END", "EQ", "NULLEQ", "NEQ", "LT", "LTE", "GT", "GTE", "DATE_ESC", "TIME_ESC", "TIMESTAMP_ESC", "GUID_ESC", "ESC_END", "EQ",
"PLUS", "MINUS", "ASTERISK", "SLASH", "PERCENT", "CAST_OP", "CONCAT", "NULLEQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", "MINUS", "ASTERISK",
"DOT", "PARAM", "STRING", "INTEGER_VALUE", "DECIMAL_VALUE", "IDENTIFIER", "SLASH", "PERCENT", "CAST_OP", "CONCAT", "DOT", "PARAM", "STRING", "INTEGER_VALUE",
"DIGIT_IDENTIFIER", "TABLE_IDENTIFIER", "QUOTED_IDENTIFIER", "BACKQUOTED_IDENTIFIER", "DECIMAL_VALUE", "IDENTIFIER", "DIGIT_IDENTIFIER", "TABLE_IDENTIFIER",
"SIMPLE_COMMENT", "BRACKETED_COMMENT", "WS", "UNRECOGNIZED" "QUOTED_IDENTIFIER", "BACKQUOTED_IDENTIFIER", "SIMPLE_COMMENT", "BRACKETED_COMMENT",
"WS", "UNRECOGNIZED"
}; };
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
@ -161,7 +159,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\2\u0087\u045e\b\1\4"+ "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2\u0089\u0471\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"+ "\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\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"+ "\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\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\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"+
@ -177,375 +175,384 @@ class SqlBaseLexer extends Lexer {
"\4w\tw\4x\tx\4y\ty\4z\tz\4{\t{\4|\t|\4}\t}\4~\t~\4\177\t\177\4\u0080\t"+ "\4w\tw\4x\tx\4y\ty\4z\tz\4{\t{\4|\t|\4}\t}\4~\t~\4\177\t\177\4\u0080\t"+
"\u0080\4\u0081\t\u0081\4\u0082\t\u0082\4\u0083\t\u0083\4\u0084\t\u0084"+ "\u0080\4\u0081\t\u0081\4\u0082\t\u0082\4\u0083\t\u0083\4\u0084\t\u0084"+
"\4\u0085\t\u0085\4\u0086\t\u0086\4\u0087\t\u0087\4\u0088\t\u0088\4\u0089"+ "\4\u0085\t\u0085\4\u0086\t\u0086\4\u0087\t\u0087\4\u0088\t\u0088\4\u0089"+
"\t\u0089\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3"+ "\t\u0089\4\u008a\t\u008a\4\u008b\t\u008b\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3"+
"\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t"+ "\5\3\6\3\6\3\6\3\6\3\7\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\n\3\n\3\n\3\n\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3"+ "\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\f\3"+
"\r\3\r\3\r\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20"+ "\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\17\3\17\3"+
"\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22"+ "\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3"+
"\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24"+ "\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3"+
"\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25"+ "\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3"+
"\3\25\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26"+ "\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\26\3\26\3"+
"\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27"+ "\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3"+
"\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3\31\3\31"+ "\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3"+
"\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\32\3\33\3\33\3\33\3\33\3\33"+ "\27\3\30\3\30\3\30\3\30\3\31\3\31\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3"+
"\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\35\3\35\3\35\3\35\3\35"+ "\32\3\32\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\36\3\36\3\36\3\36\3\36\3\37\3\37\3\37\3\37\3 \3"+ "\34\3\34\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\36\3\36\3\36\3"+
" \3 \3 \3 \3 \3 \3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3\"\3\"\3\"\3\"\3\""+ "\36\3\36\3\37\3\37\3\37\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(\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\60\3\60\3\61\3\61\3\61\3\61\3\61\3\61\3\62\3\62\3\62\3\62\3\62"+ "-\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"+
"\3\62\3\62\3\62\3\62\3\63\3\63\3\63\3\64\3\64\3\64\3\64\3\64\3\65\3\65"+ "\61\3\61\3\61\3\62\3\62\3\62\3\62\3\62\3\62\3\62\3\62\3\63\3\63\3\63\3"+
"\3\65\3\65\3\65\3\66\3\66\3\66\3\66\3\66\3\67\3\67\3\67\3\67\3\67\38\3"+ "\63\3\63\3\63\3\64\3\64\3\64\3\64\3\64\3\64\3\64\3\64\3\64\3\65\3\65\3"+
"8\38\38\38\38\39\39\39\39\39\39\39\3:\3:\3:\3:\3:\3:\3;\3;\3;\3;\3;\3"+ "\65\3\66\3\66\3\66\3\66\3\66\3\67\3\67\3\67\3\67\3\67\38\38\38\38\38\3"+
";\3;\3<\3<\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\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\3"+ "<\3=\3=\3=\3=\3=\3=\3=\3>\3>\3>\3>\3>\3>\3>\3>\3?\3?\3?\3?\3?\3?\3@\3"+
"C\3C\3C\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3E\3E\3E\3F\3F\3F\3F\3F\3F\3G\3"+ "@\3@\3@\3@\3@\3@\3A\3A\3A\3A\3A\3A\3A\3A\3B\3B\3B\3B\3C\3C\3C\3C\3C\3"+
"G\3G\3G\3G\3G\3H\3H\3H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3I\3I\3I\3I\3J\3J\3"+ "D\3D\3D\3D\3D\3D\3E\3E\3E\3F\3F\3F\3F\3F\3F\3F\3F\3F\3F\3G\3G\3G\3H\3"+
"J\3J\3J\3K\3K\3K\3K\3K\3K\3L\3L\3L\3L\3L\3L\3M\3M\3M\3M\3M\3M\3N\3N\3"+ "H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3I\3J\3J\3J\3J\3J\3J\3J\3K\3K\3K\3K\3K\3"+
"N\3N\3N\3N\3N\3N\3O\3O\3O\3O\3O\3O\3O\3P\3P\3P\3P\3P\3P\3P\3P\3Q\3Q\3"+ "K\3K\3K\3K\3L\3L\3L\3L\3L\3M\3M\3M\3M\3M\3M\3N\3N\3N\3N\3N\3N\3O\3O\3"+
"Q\3Q\3Q\3Q\3Q\3R\3R\3R\3R\3R\3S\3S\3S\3S\3T\3T\3T\3T\3T\3T\3U\3U\3U\3"+ "O\3O\3O\3O\3P\3P\3P\3P\3P\3P\3P\3P\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3R\3R\3R\3R\3"+
"U\3U\3U\3U\3V\3V\3V\3V\3V\3W\3W\3W\3W\3W\3X\3X\3X\3X\3X\3Y\3Y\3Y\3Z\3"+ "R\3R\3R\3R\3S\3S\3S\3S\3S\3S\3S\3T\3T\3T\3T\3T\3U\3U\3U\3U\3V\3V\3V\3"+
"Z\3Z\3Z\3Z\3[\3[\3[\3[\3[\3[\3\\\3\\\3\\\3\\\3\\\3\\\3]\3]\3]\3]\3]\3"+ "V\3V\3V\3W\3W\3W\3W\3W\3W\3W\3X\3X\3X\3X\3X\3Y\3Y\3Y\3Y\3Y\3Z\3Z\3Z\3"+
"]\3]\3^\3^\3^\3^\3^\3_\3_\3_\3_\3_\3_\3`\3`\3`\3`\3`\3a\3a\3a\3a\3a\3"+ "Z\3Z\3[\3[\3[\3\\\3\\\3\\\3\\\3\\\3]\3]\3]\3]\3]\3]\3^\3^\3^\3^\3^\3^"+
"b\3b\3b\3b\3b\3b\3c\3c\3c\3c\3c\3c\3c\3c\3d\3d\3d\3d\3e\3e\3e\3e\3e\3"+ "\3_\3_\3_\3_\3_\3_\3_\3`\3`\3`\3`\3`\3a\3a\3a\3a\3a\3a\3b\3b\3b\3b\3b"+
"e\3e\3f\3f\3f\3g\3g\3g\3h\3h\3h\3h\3i\3i\3i\3i\3i\3i\3j\3j\3k\3k\3l\3"+ "\3c\3c\3c\3c\3c\3d\3d\3d\3d\3d\3d\3e\3e\3e\3e\3e\3e\3e\3e\3f\3f\3f\3f"+
"l\3l\3l\3m\3m\3m\3m\5m\u039c\nm\3n\3n\3o\3o\3o\3p\3p\3q\3q\3q\3r\3r\3"+ "\3g\3g\3g\3g\3g\3g\3g\3h\3h\3h\3i\3i\3i\3j\3j\3j\3j\3k\3k\3k\3k\3k\3k"+
"s\3s\3t\3t\3u\3u\3v\3v\3w\3w\3w\3x\3x\3x\3y\3y\3z\3z\3{\3{\3{\3{\7{\u03c0"+ "\3l\3l\3m\3m\3n\3n\3n\3n\3o\3o\3o\3o\5o\u03af\no\3p\3p\3q\3q\3q\3r\3r"+
"\n{\f{\16{\u03c3\13{\3{\3{\3|\6|\u03c8\n|\r|\16|\u03c9\3}\6}\u03cd\n}"+ "\3s\3s\3s\3t\3t\3u\3u\3v\3v\3w\3w\3x\3x\3y\3y\3y\3z\3z\3z\3{\3{\3|\3|"+
"\r}\16}\u03ce\3}\3}\7}\u03d3\n}\f}\16}\u03d6\13}\3}\3}\6}\u03da\n}\r}"+ "\3}\3}\3}\3}\7}\u03d3\n}\f}\16}\u03d6\13}\3}\3}\3~\6~\u03db\n~\r~\16~"+
"\16}\u03db\3}\6}\u03df\n}\r}\16}\u03e0\3}\3}\7}\u03e5\n}\f}\16}\u03e8"+ "\u03dc\3\177\6\177\u03e0\n\177\r\177\16\177\u03e1\3\177\3\177\7\177\u03e6"+
"\13}\5}\u03ea\n}\3}\3}\3}\3}\6}\u03f0\n}\r}\16}\u03f1\3}\3}\5}\u03f6\n"+ "\n\177\f\177\16\177\u03e9\13\177\3\177\3\177\6\177\u03ed\n\177\r\177\16"+
"}\3~\3~\5~\u03fa\n~\3~\3~\3~\7~\u03ff\n~\f~\16~\u0402\13~\3\177\3\177"+ "\177\u03ee\3\177\6\177\u03f2\n\177\r\177\16\177\u03f3\3\177\3\177\7\177"+
"\3\177\3\177\6\177\u0408\n\177\r\177\16\177\u0409\3\u0080\3\u0080\3\u0080"+ "\u03f8\n\177\f\177\16\177\u03fb\13\177\5\177\u03fd\n\177\3\177\3\177\3"+
"\6\u0080\u040f\n\u0080\r\u0080\16\u0080\u0410\3\u0081\3\u0081\3\u0081"+ "\177\3\177\6\177\u0403\n\177\r\177\16\177\u0404\3\177\3\177\5\177\u0409"+
"\3\u0081\7\u0081\u0417\n\u0081\f\u0081\16\u0081\u041a\13\u0081\3\u0081"+ "\n\177\3\u0080\3\u0080\5\u0080\u040d\n\u0080\3\u0080\3\u0080\3\u0080\7"+
"\3\u0081\3\u0082\3\u0082\3\u0082\3\u0082\7\u0082\u0422\n\u0082\f\u0082"+ "\u0080\u0412\n\u0080\f\u0080\16\u0080\u0415\13\u0080\3\u0081\3\u0081\3"+
"\16\u0082\u0425\13\u0082\3\u0082\3\u0082\3\u0083\3\u0083\5\u0083\u042b"+ "\u0081\3\u0081\6\u0081\u041b\n\u0081\r\u0081\16\u0081\u041c\3\u0082\3"+
"\n\u0083\3\u0083\6\u0083\u042e\n\u0083\r\u0083\16\u0083\u042f\3\u0084"+ "\u0082\3\u0082\6\u0082\u0422\n\u0082\r\u0082\16\u0082\u0423\3\u0083\3"+
"\3\u0084\3\u0085\3\u0085\3\u0086\3\u0086\3\u0086\3\u0086\7\u0086\u043a"+ "\u0083\3\u0083\3\u0083\7\u0083\u042a\n\u0083\f\u0083\16\u0083\u042d\13"+
"\n\u0086\f\u0086\16\u0086\u043d\13\u0086\3\u0086\5\u0086\u0440\n\u0086"+ "\u0083\3\u0083\3\u0083\3\u0084\3\u0084\3\u0084\3\u0084\7\u0084\u0435\n"+
"\3\u0086\5\u0086\u0443\n\u0086\3\u0086\3\u0086\3\u0087\3\u0087\3\u0087"+ "\u0084\f\u0084\16\u0084\u0438\13\u0084\3\u0084\3\u0084\3\u0085\3\u0085"+
"\3\u0087\3\u0087\7\u0087\u044c\n\u0087\f\u0087\16\u0087\u044f\13\u0087"+ "\5\u0085\u043e\n\u0085\3\u0085\6\u0085\u0441\n\u0085\r\u0085\16\u0085"+
"\3\u0087\3\u0087\3\u0087\3\u0087\3\u0087\3\u0088\6\u0088\u0457\n\u0088"+ "\u0442\3\u0086\3\u0086\3\u0087\3\u0087\3\u0088\3\u0088\3\u0088\3\u0088"+
"\r\u0088\16\u0088\u0458\3\u0088\3\u0088\3\u0089\3\u0089\3\u044d\2\u008a"+ "\7\u0088\u044d\n\u0088\f\u0088\16\u0088\u0450\13\u0088\3\u0088\5\u0088"+
"\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20"+ "\u0453\n\u0088\3\u0088\5\u0088\u0456\n\u0088\3\u0088\3\u0088\3\u0089\3"+
"\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37"+ "\u0089\3\u0089\3\u0089\3\u0089\7\u0089\u045f\n\u0089\f\u0089\16\u0089"+
"= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o"+ "\u0462\13\u0089\3\u0089\3\u0089\3\u0089\3\u0089\3\u0089\3\u008a\6\u008a"+
"9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH"+ "\u046a\n\u008a\r\u008a\16\u008a\u046b\3\u008a\3\u008a\3\u008b\3\u008b"+
"\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1"+ "\3\u0460\2\u008c\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31"+
"R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5"+ "\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65"+
"\\\u00b7]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5d\u00c7e\u00c9"+ "\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64"+
"f\u00cbg\u00cdh\u00cfi\u00d1j\u00d3k\u00d5l\u00d7m\u00d9n\u00dbo\u00dd"+ "g\65i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089"+
"p\u00dfq\u00e1r\u00e3s\u00e5t\u00e7u\u00e9v\u00ebw\u00edx\u00efy\u00f1"+ "F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009d"+
"z\u00f3{\u00f5|\u00f7}\u00f9~\u00fb\177\u00fd\u0080\u00ff\u0081\u0101"+ "P\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1"+
"\u0082\u0103\u0083\u0105\2\u0107\2\u0109\2\u010b\u0084\u010d\u0085\u010f"+ "Z\u00b3[\u00b5\\\u00b7]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5"+
"\u0086\u0111\u0087\3\2\13\3\2))\4\2BBaa\3\2$$\3\2bb\4\2--//\3\2\62;\3"+ "d\u00c7e\u00c9f\u00cbg\u00cdh\u00cfi\u00d1j\u00d3k\u00d5l\u00d7m\u00d9"+
"\2C\\\4\2\f\f\17\17\5\2\13\f\17\17\"\"\u047e\2\3\3\2\2\2\2\5\3\2\2\2\2"+ "n\u00dbo\u00ddp\u00dfq\u00e1r\u00e3s\u00e5t\u00e7u\u00e9v\u00ebw\u00ed"+
"\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"+ "x\u00efy\u00f1z\u00f3{\u00f5|\u00f7}\u00f9~\u00fb\177\u00fd\u0080\u00ff"+
"\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\2"+ "\u0081\u0101\u0082\u0103\u0083\u0105\u0084\u0107\u0085\u0109\2\u010b\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"+ "\u010d\2\u010f\u0086\u0111\u0087\u0113\u0088\u0115\u0089\3\2\13\3\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"+ "\4\2BBaa\3\2$$\3\2bb\4\2--//\3\2\62;\3\2C\\\4\2\f\f\17\17\5\2\13\f\17"+
"\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\2"+ "\17\"\"\u0491\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\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\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\25\3\2\2\2\2"+
"M\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\3"+ "\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\2\2!\3\2"+
"\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\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\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\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\3\2\2\2\29\3"+
"s\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"+ "\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\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\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\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"+ "S\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"+
"\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"+ "\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\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\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\2"+
"\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"+ "y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083"+
"\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"+ "\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2"+
"\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"+ "\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\u0095"+
"\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"+ "\3\2\2\2\2\u0097\3\2\2\2\2\u0099\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2"+
"\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"+ "\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\u00a7"+
"\2\2\u00d1\3\2\2\2\2\u00d3\3\2\2\2\2\u00d5\3\2\2\2\2\u00d7\3\2\2\2\2\u00d9"+ "\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2\2\2\u00af\3\2\2"+
"\3\2\2\2\2\u00db\3\2\2\2\2\u00dd\3\2\2\2\2\u00df\3\2\2\2\2\u00e1\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\u00b9"+
"\2\2\u00e3\3\2\2\2\2\u00e5\3\2\2\2\2\u00e7\3\2\2\2\2\u00e9\3\2\2\2\2\u00eb"+ "\3\2\2\2\2\u00bb\3\2\2\2\2\u00bd\3\2\2\2\2\u00bf\3\2\2\2\2\u00c1\3\2\2"+
"\3\2\2\2\2\u00ed\3\2\2\2\2\u00ef\3\2\2\2\2\u00f1\3\2\2\2\2\u00f3\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\u00cb"+
"\2\2\u00f5\3\2\2\2\2\u00f7\3\2\2\2\2\u00f9\3\2\2\2\2\u00fb\3\2\2\2\2\u00fd"+ "\3\2\2\2\2\u00cd\3\2\2\2\2\u00cf\3\2\2\2\2\u00d1\3\2\2\2\2\u00d3\3\2\2"+
"\3\2\2\2\2\u00ff\3\2\2\2\2\u0101\3\2\2\2\2\u0103\3\2\2\2\2\u010b\3\2\2"+ "\2\2\u00d5\3\2\2\2\2\u00d7\3\2\2\2\2\u00d9\3\2\2\2\2\u00db\3\2\2\2\2\u00dd"+
"\2\2\u010d\3\2\2\2\2\u010f\3\2\2\2\2\u0111\3\2\2\2\3\u0113\3\2\2\2\5\u0115"+ "\3\2\2\2\2\u00df\3\2\2\2\2\u00e1\3\2\2\2\2\u00e3\3\2\2\2\2\u00e5\3\2\2"+
"\3\2\2\2\7\u0117\3\2\2\2\t\u0119\3\2\2\2\13\u011b\3\2\2\2\r\u011f\3\2"+ "\2\2\u00e7\3\2\2\2\2\u00e9\3\2\2\2\2\u00eb\3\2\2\2\2\u00ed\3\2\2\2\2\u00ef"+
"\2\2\17\u0127\3\2\2\2\21\u0130\3\2\2\2\23\u0134\3\2\2\2\25\u0138\3\2\2"+ "\3\2\2\2\2\u00f1\3\2\2\2\2\u00f3\3\2\2\2\2\u00f5\3\2\2\2\2\u00f7\3\2\2"+
"\2\27\u013b\3\2\2\2\31\u013f\3\2\2\2\33\u0147\3\2\2\2\35\u014a\3\2\2\2"+ "\2\2\u00f9\3\2\2\2\2\u00fb\3\2\2\2\2\u00fd\3\2\2\2\2\u00ff\3\2\2\2\2\u0101"+
"\37\u014f\3\2\2\2!\u0154\3\2\2\2#\u015c\3\2\2\2%\u0165\3\2\2\2\'\u016d"+ "\3\2\2\2\2\u0103\3\2\2\2\2\u0105\3\2\2\2\2\u0107\3\2\2\2\2\u010f\3\2\2"+
"\3\2\2\2)\u0175\3\2\2\2+\u0182\3\2\2\2-\u018f\3\2\2\2/\u01a1\3\2\2\2\61"+ "\2\2\u0111\3\2\2\2\2\u0113\3\2\2\2\2\u0115\3\2\2\2\3\u0117\3\2\2\2\5\u0119"+
"\u01a5\3\2\2\2\63\u01aa\3\2\2\2\65\u01b0\3\2\2\2\67\u01b5\3\2\2\29\u01be"+ "\3\2\2\2\7\u011b\3\2\2\2\t\u011d\3\2\2\2\13\u011f\3\2\2\2\r\u0123\3\2"+
"\3\2\2\2;\u01c7\3\2\2\2=\u01cc\3\2\2\2?\u01d0\3\2\2\2A\u01d7\3\2\2\2C"+ "\2\2\17\u012b\3\2\2\2\21\u0134\3\2\2\2\23\u0138\3\2\2\2\25\u013c\3\2\2"+
"\u01e2\3\2\2\2E\u01e9\3\2\2\2G\u01f1\3\2\2\2I\u01f9\3\2\2\2K\u01ff\3\2"+ "\2\27\u013f\3\2\2\2\31\u0143\3\2\2\2\33\u014b\3\2\2\2\35\u014e\3\2\2\2"+
"\2\2M\u0205\3\2\2\2O\u020c\3\2\2\2Q\u0211\3\2\2\2S\u0216\3\2\2\2U\u0220"+ "\37\u0153\3\2\2\2!\u0158\3\2\2\2#\u0160\3\2\2\2%\u0169\3\2\2\2\'\u0171"+
"\3\2\2\2W\u0229\3\2\2\2Y\u022f\3\2\2\2[\u0236\3\2\2\2]\u023b\3\2\2\2_"+ "\3\2\2\2)\u0179\3\2\2\2+\u0186\3\2\2\2-\u0193\3\2\2\2/\u01a5\3\2\2\2\61"+
"\u0241\3\2\2\2a\u0244\3\2\2\2c\u024a\3\2\2\2e\u0253\3\2\2\2g\u0256\3\2"+ "\u01a9\3\2\2\2\63\u01ae\3\2\2\2\65\u01b4\3\2\2\2\67\u01b9\3\2\2\29\u01c2"+
"\2\2i\u025b\3\2\2\2k\u0260\3\2\2\2m\u0265\3\2\2\2o\u026a\3\2\2\2q\u0270"+ "\3\2\2\2;\u01cb\3\2\2\2=\u01d0\3\2\2\2?\u01d4\3\2\2\2A\u01db\3\2\2\2C"+
"\3\2\2\2s\u0277\3\2\2\2u\u027d\3\2\2\2w\u0284\3\2\2\2y\u028c\3\2\2\2{"+ "\u01e6\3\2\2\2E\u01ed\3\2\2\2G\u01f5\3\2\2\2I\u01fd\3\2\2\2K\u0203\3\2"+
"\u0292\3\2\2\2}\u0299\3\2\2\2\177\u02a1\3\2\2\2\u0081\u02a5\3\2\2\2\u0083"+ "\2\2M\u0209\3\2\2\2O\u0210\3\2\2\2Q\u0215\3\2\2\2S\u021c\3\2\2\2U\u0221"+
"\u02aa\3\2\2\2\u0085\u02b0\3\2\2\2\u0087\u02b3\3\2\2\2\u0089\u02bd\3\2"+ "\3\2\2\2W\u022b\3\2\2\2Y\u0234\3\2\2\2[\u023a\3\2\2\2]\u0241\3\2\2\2_"+
"\2\2\u008b\u02c0\3\2\2\2\u008d\u02c6\3\2\2\2\u008f\u02cc\3\2\2\2\u0091"+ "\u0246\3\2\2\2a\u024c\3\2\2\2c\u024f\3\2\2\2e\u0257\3\2\2\2g\u025d\3\2"+
"\u02d3\3\2\2\2\u0093\u02dc\3\2\2\2\u0095\u02e1\3\2\2\2\u0097\u02e7\3\2"+ "\2\2i\u0266\3\2\2\2k\u0269\3\2\2\2m\u026e\3\2\2\2o\u0273\3\2\2\2q\u0278"+
"\2\2\u0099\u02ed\3\2\2\2\u009b\u02f3\3\2\2\2\u009d\u02fb\3\2\2\2\u009f"+ "\3\2\2\2s\u027d\3\2\2\2u\u0283\3\2\2\2w\u028a\3\2\2\2y\u0290\3\2\2\2{"+
"\u0302\3\2\2\2\u00a1\u030a\3\2\2\2\u00a3\u0311\3\2\2\2\u00a5\u0316\3\2"+ "\u0297\3\2\2\2}\u029f\3\2\2\2\177\u02a5\3\2\2\2\u0081\u02ac\3\2\2\2\u0083"+
"\2\2\u00a7\u031a\3\2\2\2\u00a9\u0320\3\2\2\2\u00ab\u0327\3\2\2\2\u00ad"+ "\u02b4\3\2\2\2\u0085\u02b8\3\2\2\2\u0087\u02bd\3\2\2\2\u0089\u02c3\3\2"+
"\u032c\3\2\2\2\u00af\u0331\3\2\2\2\u00b1\u0336\3\2\2\2\u00b3\u0339\3\2"+ "\2\2\u008b\u02c6\3\2\2\2\u008d\u02d0\3\2\2\2\u008f\u02d3\3\2\2\2\u0091"+
"\2\2\u00b5\u033e\3\2\2\2\u00b7\u0344\3\2\2\2\u00b9\u034a\3\2\2\2\u00bb"+ "\u02d9\3\2\2\2\u0093\u02df\3\2\2\2\u0095\u02e6\3\2\2\2\u0097\u02ef\3\2"+
"\u0351\3\2\2\2\u00bd\u0356\3\2\2\2\u00bf\u035c\3\2\2\2\u00c1\u0361\3\2"+ "\2\2\u0099\u02f4\3\2\2\2\u009b\u02fa\3\2\2\2\u009d\u0300\3\2\2\2\u009f"+
"\2\2\u00c3\u0366\3\2\2\2\u00c5\u036c\3\2\2\2\u00c7\u0374\3\2\2\2\u00c9"+ "\u0306\3\2\2\2\u00a1\u030e\3\2\2\2\u00a3\u0315\3\2\2\2\u00a5\u031d\3\2"+
"\u0378\3\2\2\2\u00cb\u037f\3\2\2\2\u00cd\u0382\3\2\2\2\u00cf\u0385\3\2"+ "\2\2\u00a7\u0324\3\2\2\2\u00a9\u0329\3\2\2\2\u00ab\u032d\3\2\2\2\u00ad"+
"\2\2\u00d1\u0389\3\2\2\2\u00d3\u038f\3\2\2\2\u00d5\u0391\3\2\2\2\u00d7"+ "\u0333\3\2\2\2\u00af\u033a\3\2\2\2\u00b1\u033f\3\2\2\2\u00b3\u0344\3\2"+
"\u0393\3\2\2\2\u00d9\u039b\3\2\2\2\u00db\u039d\3\2\2\2\u00dd\u039f\3\2"+ "\2\2\u00b5\u0349\3\2\2\2\u00b7\u034c\3\2\2\2\u00b9\u0351\3\2\2\2\u00bb"+
"\2\2\u00df\u03a2\3\2\2\2\u00e1\u03a4\3\2\2\2\u00e3\u03a7\3\2\2\2\u00e5"+ "\u0357\3\2\2\2\u00bd\u035d\3\2\2\2\u00bf\u0364\3\2\2\2\u00c1\u0369\3\2"+
"\u03a9\3\2\2\2\u00e7\u03ab\3\2\2\2\u00e9\u03ad\3\2\2\2\u00eb\u03af\3\2"+ "\2\2\u00c3\u036f\3\2\2\2\u00c5\u0374\3\2\2\2\u00c7\u0379\3\2\2\2\u00c9"+
"\2\2\u00ed\u03b1\3\2\2\2\u00ef\u03b4\3\2\2\2\u00f1\u03b7\3\2\2\2\u00f3"+ "\u037f\3\2\2\2\u00cb\u0387\3\2\2\2\u00cd\u038b\3\2\2\2\u00cf\u0392\3\2"+
"\u03b9\3\2\2\2\u00f5\u03bb\3\2\2\2\u00f7\u03c7\3\2\2\2\u00f9\u03f5\3\2"+ "\2\2\u00d1\u0395\3\2\2\2\u00d3\u0398\3\2\2\2\u00d5\u039c\3\2\2\2\u00d7"+
"\2\2\u00fb\u03f9\3\2\2\2\u00fd\u0403\3\2\2\2\u00ff\u040e\3\2\2\2\u0101"+ "\u03a2\3\2\2\2\u00d9\u03a4\3\2\2\2\u00db\u03a6\3\2\2\2\u00dd\u03ae\3\2"+
"\u0412\3\2\2\2\u0103\u041d\3\2\2\2\u0105\u0428\3\2\2\2\u0107\u0431\3\2"+ "\2\2\u00df\u03b0\3\2\2\2\u00e1\u03b2\3\2\2\2\u00e3\u03b5\3\2\2\2\u00e5"+
"\2\2\u0109\u0433\3\2\2\2\u010b\u0435\3\2\2\2\u010d\u0446\3\2\2\2\u010f"+ "\u03b7\3\2\2\2\u00e7\u03ba\3\2\2\2\u00e9\u03bc\3\2\2\2\u00eb\u03be\3\2"+
"\u0456\3\2\2\2\u0111\u045c\3\2\2\2\u0113\u0114\7*\2\2\u0114\4\3\2\2\2"+ "\2\2\u00ed\u03c0\3\2\2\2\u00ef\u03c2\3\2\2\2\u00f1\u03c4\3\2\2\2\u00f3"+
"\u0115\u0116\7+\2\2\u0116\6\3\2\2\2\u0117\u0118\7.\2\2\u0118\b\3\2\2\2"+ "\u03c7\3\2\2\2\u00f5\u03ca\3\2\2\2\u00f7\u03cc\3\2\2\2\u00f9\u03ce\3\2"+
"\u0119\u011a\7<\2\2\u011a\n\3\2\2\2\u011b\u011c\7C\2\2\u011c\u011d\7N"+ "\2\2\u00fb\u03da\3\2\2\2\u00fd\u0408\3\2\2\2\u00ff\u040c\3\2\2\2\u0101"+
"\2\2\u011d\u011e\7N\2\2\u011e\f\3\2\2\2\u011f\u0120\7C\2\2\u0120\u0121"+ "\u0416\3\2\2\2\u0103\u0421\3\2\2\2\u0105\u0425\3\2\2\2\u0107\u0430\3\2"+
"\7P\2\2\u0121\u0122\7C\2\2\u0122\u0123\7N\2\2\u0123\u0124\7[\2\2\u0124"+ "\2\2\u0109\u043b\3\2\2\2\u010b\u0444\3\2\2\2\u010d\u0446\3\2\2\2\u010f"+
"\u0125\7\\\2\2\u0125\u0126\7G\2\2\u0126\16\3\2\2\2\u0127\u0128\7C\2\2"+ "\u0448\3\2\2\2\u0111\u0459\3\2\2\2\u0113\u0469\3\2\2\2\u0115\u046f\3\2"+
"\u0128\u0129\7P\2\2\u0129\u012a\7C\2\2\u012a\u012b\7N\2\2\u012b\u012c"+ "\2\2\u0117\u0118\7*\2\2\u0118\4\3\2\2\2\u0119\u011a\7+\2\2\u011a\6\3\2"+
"\7[\2\2\u012c\u012d\7\\\2\2\u012d\u012e\7G\2\2\u012e\u012f\7F\2\2\u012f"+ "\2\2\u011b\u011c\7.\2\2\u011c\b\3\2\2\2\u011d\u011e\7<\2\2\u011e\n\3\2"+
"\20\3\2\2\2\u0130\u0131\7C\2\2\u0131\u0132\7P\2\2\u0132\u0133\7F\2\2\u0133"+ "\2\2\u011f\u0120\7C\2\2\u0120\u0121\7N\2\2\u0121\u0122\7N\2\2\u0122\f"+
"\22\3\2\2\2\u0134\u0135\7C\2\2\u0135\u0136\7P\2\2\u0136\u0137\7[\2\2\u0137"+ "\3\2\2\2\u0123\u0124\7C\2\2\u0124\u0125\7P\2\2\u0125\u0126\7C\2\2\u0126"+
"\24\3\2\2\2\u0138\u0139\7C\2\2\u0139\u013a\7U\2\2\u013a\26\3\2\2\2\u013b"+ "\u0127\7N\2\2\u0127\u0128\7[\2\2\u0128\u0129\7\\\2\2\u0129\u012a\7G\2"+
"\u013c\7C\2\2\u013c\u013d\7U\2\2\u013d\u013e\7E\2\2\u013e\30\3\2\2\2\u013f"+ "\2\u012a\16\3\2\2\2\u012b\u012c\7C\2\2\u012c\u012d\7P\2\2\u012d\u012e"+
"\u0140\7D\2\2\u0140\u0141\7G\2\2\u0141\u0142\7V\2\2\u0142\u0143\7Y\2\2"+ "\7C\2\2\u012e\u012f\7N\2\2\u012f\u0130\7[\2\2\u0130\u0131\7\\\2\2\u0131"+
"\u0143\u0144\7G\2\2\u0144\u0145\7G\2\2\u0145\u0146\7P\2\2\u0146\32\3\2"+ "\u0132\7G\2\2\u0132\u0133\7F\2\2\u0133\20\3\2\2\2\u0134\u0135\7C\2\2\u0135"+
"\2\2\u0147\u0148\7D\2\2\u0148\u0149\7[\2\2\u0149\34\3\2\2\2\u014a\u014b"+ "\u0136\7P\2\2\u0136\u0137\7F\2\2\u0137\22\3\2\2\2\u0138\u0139\7C\2\2\u0139"+
"\7E\2\2\u014b\u014c\7C\2\2\u014c\u014d\7U\2\2\u014d\u014e\7G\2\2\u014e"+ "\u013a\7P\2\2\u013a\u013b\7[\2\2\u013b\24\3\2\2\2\u013c\u013d\7C\2\2\u013d"+
"\36\3\2\2\2\u014f\u0150\7E\2\2\u0150\u0151\7C\2\2\u0151\u0152\7U\2\2\u0152"+ "\u013e\7U\2\2\u013e\26\3\2\2\2\u013f\u0140\7C\2\2\u0140\u0141\7U\2\2\u0141"+
"\u0153\7V\2\2\u0153 \3\2\2\2\u0154\u0155\7E\2\2\u0155\u0156\7C\2\2\u0156"+ "\u0142\7E\2\2\u0142\30\3\2\2\2\u0143\u0144\7D\2\2\u0144\u0145\7G\2\2\u0145"+
"\u0157\7V\2\2\u0157\u0158\7C\2\2\u0158\u0159\7N\2\2\u0159\u015a\7Q\2\2"+ "\u0146\7V\2\2\u0146\u0147\7Y\2\2\u0147\u0148\7G\2\2\u0148\u0149\7G\2\2"+
"\u015a\u015b\7I\2\2\u015b\"\3\2\2\2\u015c\u015d\7E\2\2\u015d\u015e\7C"+ "\u0149\u014a\7P\2\2\u014a\32\3\2\2\2\u014b\u014c\7D\2\2\u014c\u014d\7"+
"\2\2\u015e\u015f\7V\2\2\u015f\u0160\7C\2\2\u0160\u0161\7N\2\2\u0161\u0162"+ "[\2\2\u014d\34\3\2\2\2\u014e\u014f\7E\2\2\u014f\u0150\7C\2\2\u0150\u0151"+
"\7Q\2\2\u0162\u0163\7I\2\2\u0163\u0164\7U\2\2\u0164$\3\2\2\2\u0165\u0166"+ "\7U\2\2\u0151\u0152\7G\2\2\u0152\36\3\2\2\2\u0153\u0154\7E\2\2\u0154\u0155"+
"\7E\2\2\u0166\u0167\7Q\2\2\u0167\u0168\7N\2\2\u0168\u0169\7W\2\2\u0169"+ "\7C\2\2\u0155\u0156\7U\2\2\u0156\u0157\7V\2\2\u0157 \3\2\2\2\u0158\u0159"+
"\u016a\7O\2\2\u016a\u016b\7P\2\2\u016b\u016c\7U\2\2\u016c&\3\2\2\2\u016d"+ "\7E\2\2\u0159\u015a\7C\2\2\u015a\u015b\7V\2\2\u015b\u015c\7C\2\2\u015c"+
"\u016e\7E\2\2\u016e\u016f\7Q\2\2\u016f\u0170\7P\2\2\u0170\u0171\7X\2\2"+ "\u015d\7N\2\2\u015d\u015e\7Q\2\2\u015e\u015f\7I\2\2\u015f\"\3\2\2\2\u0160"+
"\u0171\u0172\7G\2\2\u0172\u0173\7T\2\2\u0173\u0174\7V\2\2\u0174(\3\2\2"+ "\u0161\7E\2\2\u0161\u0162\7C\2\2\u0162\u0163\7V\2\2\u0163\u0164\7C\2\2"+
"\2\u0175\u0176\7E\2\2\u0176\u0177\7W\2\2\u0177\u0178\7T\2\2\u0178\u0179"+ "\u0164\u0165\7N\2\2\u0165\u0166\7Q\2\2\u0166\u0167\7I\2\2\u0167\u0168"+
"\7T\2\2\u0179\u017a\7G\2\2\u017a\u017b\7P\2\2\u017b\u017c\7V\2\2\u017c"+ "\7U\2\2\u0168$\3\2\2\2\u0169\u016a\7E\2\2\u016a\u016b\7Q\2\2\u016b\u016c"+
"\u017d\7a\2\2\u017d\u017e\7F\2\2\u017e\u017f\7C\2\2\u017f\u0180\7V\2\2"+ "\7N\2\2\u016c\u016d\7W\2\2\u016d\u016e\7O\2\2\u016e\u016f\7P\2\2\u016f"+
"\u0180\u0181\7G\2\2\u0181*\3\2\2\2\u0182\u0183\7E\2\2\u0183\u0184\7W\2"+ "\u0170\7U\2\2\u0170&\3\2\2\2\u0171\u0172\7E\2\2\u0172\u0173\7Q\2\2\u0173"+
"\2\u0184\u0185\7T\2\2\u0185\u0186\7T\2\2\u0186\u0187\7G\2\2\u0187\u0188"+ "\u0174\7P\2\2\u0174\u0175\7X\2\2\u0175\u0176\7G\2\2\u0176\u0177\7T\2\2"+
"\7P\2\2\u0188\u0189\7V\2\2\u0189\u018a\7a\2\2\u018a\u018b\7V\2\2\u018b"+ "\u0177\u0178\7V\2\2\u0178(\3\2\2\2\u0179\u017a\7E\2\2\u017a\u017b\7W\2"+
"\u018c\7K\2\2\u018c\u018d\7O\2\2\u018d\u018e\7G\2\2\u018e,\3\2\2\2\u018f"+ "\2\u017b\u017c\7T\2\2\u017c\u017d\7T\2\2\u017d\u017e\7G\2\2\u017e\u017f"+
"\u0190\7E\2\2\u0190\u0191\7W\2\2\u0191\u0192\7T\2\2\u0192\u0193\7T\2\2"+ "\7P\2\2\u017f\u0180\7V\2\2\u0180\u0181\7a\2\2\u0181\u0182\7F\2\2\u0182"+
"\u0193\u0194\7G\2\2\u0194\u0195\7P\2\2\u0195\u0196\7V\2\2\u0196\u0197"+ "\u0183\7C\2\2\u0183\u0184\7V\2\2\u0184\u0185\7G\2\2\u0185*\3\2\2\2\u0186"+
"\7a\2\2\u0197\u0198\7V\2\2\u0198\u0199\7K\2\2\u0199\u019a\7O\2\2\u019a"+ "\u0187\7E\2\2\u0187\u0188\7W\2\2\u0188\u0189\7T\2\2\u0189\u018a\7T\2\2"+
"\u019b\7G\2\2\u019b\u019c\7U\2\2\u019c\u019d\7V\2\2\u019d\u019e\7C\2\2"+ "\u018a\u018b\7G\2\2\u018b\u018c\7P\2\2\u018c\u018d\7V\2\2\u018d\u018e"+
"\u019e\u019f\7O\2\2\u019f\u01a0\7R\2\2\u01a0.\3\2\2\2\u01a1\u01a2\7F\2"+ "\7a\2\2\u018e\u018f\7V\2\2\u018f\u0190\7K\2\2\u0190\u0191\7O\2\2\u0191"+
"\2\u01a2\u01a3\7C\2\2\u01a3\u01a4\7[\2\2\u01a4\60\3\2\2\2\u01a5\u01a6"+ "\u0192\7G\2\2\u0192,\3\2\2\2\u0193\u0194\7E\2\2\u0194\u0195\7W\2\2\u0195"+
"\7F\2\2\u01a6\u01a7\7C\2\2\u01a7\u01a8\7[\2\2\u01a8\u01a9\7U\2\2\u01a9"+ "\u0196\7T\2\2\u0196\u0197\7T\2\2\u0197\u0198\7G\2\2\u0198\u0199\7P\2\2"+
"\62\3\2\2\2\u01aa\u01ab\7F\2\2\u01ab\u01ac\7G\2\2\u01ac\u01ad\7D\2\2\u01ad"+ "\u0199\u019a\7V\2\2\u019a\u019b\7a\2\2\u019b\u019c\7V\2\2\u019c\u019d"+
"\u01ae\7W\2\2\u01ae\u01af\7I\2\2\u01af\64\3\2\2\2\u01b0\u01b1\7F\2\2\u01b1"+ "\7K\2\2\u019d\u019e\7O\2\2\u019e\u019f\7G\2\2\u019f\u01a0\7U\2\2\u01a0"+
"\u01b2\7G\2\2\u01b2\u01b3\7U\2\2\u01b3\u01b4\7E\2\2\u01b4\66\3\2\2\2\u01b5"+ "\u01a1\7V\2\2\u01a1\u01a2\7C\2\2\u01a2\u01a3\7O\2\2\u01a3\u01a4\7R\2\2"+
"\u01b6\7F\2\2\u01b6\u01b7\7G\2\2\u01b7\u01b8\7U\2\2\u01b8\u01b9\7E\2\2"+ "\u01a4.\3\2\2\2\u01a5\u01a6\7F\2\2\u01a6\u01a7\7C\2\2\u01a7\u01a8\7[\2"+
"\u01b9\u01ba\7T\2\2\u01ba\u01bb\7K\2\2\u01bb\u01bc\7D\2\2\u01bc\u01bd"+ "\2\u01a8\60\3\2\2\2\u01a9\u01aa\7F\2\2\u01aa\u01ab\7C\2\2\u01ab\u01ac"+
"\7G\2\2\u01bd8\3\2\2\2\u01be\u01bf\7F\2\2\u01bf\u01c0\7K\2\2\u01c0\u01c1"+ "\7[\2\2\u01ac\u01ad\7U\2\2\u01ad\62\3\2\2\2\u01ae\u01af\7F\2\2\u01af\u01b0"+
"\7U\2\2\u01c1\u01c2\7V\2\2\u01c2\u01c3\7K\2\2\u01c3\u01c4\7P\2\2\u01c4"+ "\7G\2\2\u01b0\u01b1\7D\2\2\u01b1\u01b2\7W\2\2\u01b2\u01b3\7I\2\2\u01b3"+
"\u01c5\7E\2\2\u01c5\u01c6\7V\2\2\u01c6:\3\2\2\2\u01c7\u01c8\7G\2\2\u01c8"+ "\64\3\2\2\2\u01b4\u01b5\7F\2\2\u01b5\u01b6\7G\2\2\u01b6\u01b7\7U\2\2\u01b7"+
"\u01c9\7N\2\2\u01c9\u01ca\7U\2\2\u01ca\u01cb\7G\2\2\u01cb<\3\2\2\2\u01cc"+ "\u01b8\7E\2\2\u01b8\66\3\2\2\2\u01b9\u01ba\7F\2\2\u01ba\u01bb\7G\2\2\u01bb"+
"\u01cd\7G\2\2\u01cd\u01ce\7P\2\2\u01ce\u01cf\7F\2\2\u01cf>\3\2\2\2\u01d0"+ "\u01bc\7U\2\2\u01bc\u01bd\7E\2\2\u01bd\u01be\7T\2\2\u01be\u01bf\7K\2\2"+
"\u01d1\7G\2\2\u01d1\u01d2\7U\2\2\u01d2\u01d3\7E\2\2\u01d3\u01d4\7C\2\2"+ "\u01bf\u01c0\7D\2\2\u01c0\u01c1\7G\2\2\u01c18\3\2\2\2\u01c2\u01c3\7F\2"+
"\u01d4\u01d5\7R\2\2\u01d5\u01d6\7G\2\2\u01d6@\3\2\2\2\u01d7\u01d8\7G\2"+ "\2\u01c3\u01c4\7K\2\2\u01c4\u01c5\7U\2\2\u01c5\u01c6\7V\2\2\u01c6\u01c7"+
"\2\u01d8\u01d9\7Z\2\2\u01d9\u01da\7G\2\2\u01da\u01db\7E\2\2\u01db\u01dc"+ "\7K\2\2\u01c7\u01c8\7P\2\2\u01c8\u01c9\7E\2\2\u01c9\u01ca\7V\2\2\u01ca"+
"\7W\2\2\u01dc\u01dd\7V\2\2\u01dd\u01de\7C\2\2\u01de\u01df\7D\2\2\u01df"+ ":\3\2\2\2\u01cb\u01cc\7G\2\2\u01cc\u01cd\7N\2\2\u01cd\u01ce\7U\2\2\u01ce"+
"\u01e0\7N\2\2\u01e0\u01e1\7G\2\2\u01e1B\3\2\2\2\u01e2\u01e3\7G\2\2\u01e3"+ "\u01cf\7G\2\2\u01cf<\3\2\2\2\u01d0\u01d1\7G\2\2\u01d1\u01d2\7P\2\2\u01d2"+
"\u01e4\7Z\2\2\u01e4\u01e5\7K\2\2\u01e5\u01e6\7U\2\2\u01e6\u01e7\7V\2\2"+ "\u01d3\7F\2\2\u01d3>\3\2\2\2\u01d4\u01d5\7G\2\2\u01d5\u01d6\7U\2\2\u01d6"+
"\u01e7\u01e8\7U\2\2\u01e8D\3\2\2\2\u01e9\u01ea\7G\2\2\u01ea\u01eb\7Z\2"+ "\u01d7\7E\2\2\u01d7\u01d8\7C\2\2\u01d8\u01d9\7R\2\2\u01d9\u01da\7G\2\2"+
"\2\u01eb\u01ec\7R\2\2\u01ec\u01ed\7N\2\2\u01ed\u01ee\7C\2\2\u01ee\u01ef"+ "\u01da@\3\2\2\2\u01db\u01dc\7G\2\2\u01dc\u01dd\7Z\2\2\u01dd\u01de\7G\2"+
"\7K\2\2\u01ef\u01f0\7P\2\2\u01f0F\3\2\2\2\u01f1\u01f2\7G\2\2\u01f2\u01f3"+ "\2\u01de\u01df\7E\2\2\u01df\u01e0\7W\2\2\u01e0\u01e1\7V\2\2\u01e1\u01e2"+
"\7Z\2\2\u01f3\u01f4\7V\2\2\u01f4\u01f5\7T\2\2\u01f5\u01f6\7C\2\2\u01f6"+ "\7C\2\2\u01e2\u01e3\7D\2\2\u01e3\u01e4\7N\2\2\u01e4\u01e5\7G\2\2\u01e5"+
"\u01f7\7E\2\2\u01f7\u01f8\7V\2\2\u01f8H\3\2\2\2\u01f9\u01fa\7H\2\2\u01fa"+ "B\3\2\2\2\u01e6\u01e7\7G\2\2\u01e7\u01e8\7Z\2\2\u01e8\u01e9\7K\2\2\u01e9"+
"\u01fb\7C\2\2\u01fb\u01fc\7N\2\2\u01fc\u01fd\7U\2\2\u01fd\u01fe\7G\2\2"+ "\u01ea\7U\2\2\u01ea\u01eb\7V\2\2\u01eb\u01ec\7U\2\2\u01ecD\3\2\2\2\u01ed"+
"\u01feJ\3\2\2\2\u01ff\u0200\7H\2\2\u0200\u0201\7K\2\2\u0201\u0202\7T\2"+ "\u01ee\7G\2\2\u01ee\u01ef\7Z\2\2\u01ef\u01f0\7R\2\2\u01f0\u01f1\7N\2\2"+
"\2\u0202\u0203\7U\2\2\u0203\u0204\7V\2\2\u0204L\3\2\2\2\u0205\u0206\7"+ "\u01f1\u01f2\7C\2\2\u01f2\u01f3\7K\2\2\u01f3\u01f4\7P\2\2\u01f4F\3\2\2"+
"H\2\2\u0206\u0207\7Q\2\2\u0207\u0208\7T\2\2\u0208\u0209\7O\2\2\u0209\u020a"+ "\2\u01f5\u01f6\7G\2\2\u01f6\u01f7\7Z\2\2\u01f7\u01f8\7V\2\2\u01f8\u01f9"+
"\7C\2\2\u020a\u020b\7V\2\2\u020bN\3\2\2\2\u020c\u020d\7H\2\2\u020d\u020e"+ "\7T\2\2\u01f9\u01fa\7C\2\2\u01fa\u01fb\7E\2\2\u01fb\u01fc\7V\2\2\u01fc"+
"\7T\2\2\u020e\u020f\7Q\2\2\u020f\u0210\7O\2\2\u0210P\3\2\2\2\u0211\u0212"+ "H\3\2\2\2\u01fd\u01fe\7H\2\2\u01fe\u01ff\7C\2\2\u01ff\u0200\7N\2\2\u0200"+
"\7H\2\2\u0212\u0213\7W\2\2\u0213\u0214\7N\2\2\u0214\u0215\7N\2\2\u0215"+ "\u0201\7U\2\2\u0201\u0202\7G\2\2\u0202J\3\2\2\2\u0203\u0204\7H\2\2\u0204"+
"R\3\2\2\2\u0216\u0217\7H\2\2\u0217\u0218\7W\2\2\u0218\u0219\7P\2\2\u0219"+ "\u0205\7K\2\2\u0205\u0206\7T\2\2\u0206\u0207\7U\2\2\u0207\u0208\7V\2\2"+
"\u021a\7E\2\2\u021a\u021b\7V\2\2\u021b\u021c\7K\2\2\u021c\u021d\7Q\2\2"+ "\u0208L\3\2\2\2\u0209\u020a\7H\2\2\u020a\u020b\7Q\2\2\u020b\u020c\7T\2"+
"\u021d\u021e\7P\2\2\u021e\u021f\7U\2\2\u021fT\3\2\2\2\u0220\u0221\7I\2"+ "\2\u020c\u020d\7O\2\2\u020d\u020e\7C\2\2\u020e\u020f\7V\2\2\u020fN\3\2"+
"\2\u0221\u0222\7T\2\2\u0222\u0223\7C\2\2\u0223\u0224\7R\2\2\u0224\u0225"+ "\2\2\u0210\u0211\7H\2\2\u0211\u0212\7T\2\2\u0212\u0213\7Q\2\2\u0213\u0214"+
"\7J\2\2\u0225\u0226\7X\2\2\u0226\u0227\7K\2\2\u0227\u0228\7\\\2\2\u0228"+ "\7O\2\2\u0214P\3\2\2\2\u0215\u0216\7H\2\2\u0216\u0217\7T\2\2\u0217\u0218"+
"V\3\2\2\2\u0229\u022a\7I\2\2\u022a\u022b\7T\2\2\u022b\u022c\7Q\2\2\u022c"+ "\7Q\2\2\u0218\u0219\7\\\2\2\u0219\u021a\7G\2\2\u021a\u021b\7P\2\2\u021b"+
"\u022d\7W\2\2\u022d\u022e\7R\2\2\u022eX\3\2\2\2\u022f\u0230\7J\2\2\u0230"+ "R\3\2\2\2\u021c\u021d\7H\2\2\u021d\u021e\7W\2\2\u021e\u021f\7N\2\2\u021f"+
"\u0231\7C\2\2\u0231\u0232\7X\2\2\u0232\u0233\7K\2\2\u0233\u0234\7P\2\2"+ "\u0220\7N\2\2\u0220T\3\2\2\2\u0221\u0222\7H\2\2\u0222\u0223\7W\2\2\u0223"+
"\u0234\u0235\7I\2\2\u0235Z\3\2\2\2\u0236\u0237\7J\2\2\u0237\u0238\7Q\2"+ "\u0224\7P\2\2\u0224\u0225\7E\2\2\u0225\u0226\7V\2\2\u0226\u0227\7K\2\2"+
"\2\u0238\u0239\7W\2\2\u0239\u023a\7T\2\2\u023a\\\3\2\2\2\u023b\u023c\7"+ "\u0227\u0228\7Q\2\2\u0228\u0229\7P\2\2\u0229\u022a\7U\2\2\u022aV\3\2\2"+
"J\2\2\u023c\u023d\7Q\2\2\u023d\u023e\7W\2\2\u023e\u023f\7T\2\2\u023f\u0240"+ "\2\u022b\u022c\7I\2\2\u022c\u022d\7T\2\2\u022d\u022e\7C\2\2\u022e\u022f"+
"\7U\2\2\u0240^\3\2\2\2\u0241\u0242\7K\2\2\u0242\u0243\7P\2\2\u0243`\3"+ "\7R\2\2\u022f\u0230\7J\2\2\u0230\u0231\7X\2\2\u0231\u0232\7K\2\2\u0232"+
"\2\2\2\u0244\u0245\7K\2\2\u0245\u0246\7P\2\2\u0246\u0247\7P\2\2\u0247"+ "\u0233\7\\\2\2\u0233X\3\2\2\2\u0234\u0235\7I\2\2\u0235\u0236\7T\2\2\u0236"+
"\u0248\7G\2\2\u0248\u0249\7T\2\2\u0249b\3\2\2\2\u024a\u024b\7K\2\2\u024b"+ "\u0237\7Q\2\2\u0237\u0238\7W\2\2\u0238\u0239\7R\2\2\u0239Z\3\2\2\2\u023a"+
"\u024c\7P\2\2\u024c\u024d\7V\2\2\u024d\u024e\7G\2\2\u024e\u024f\7T\2\2"+ "\u023b\7J\2\2\u023b\u023c\7C\2\2\u023c\u023d\7X\2\2\u023d\u023e\7K\2\2"+
"\u024f\u0250\7X\2\2\u0250\u0251\7C\2\2\u0251\u0252\7N\2\2\u0252d\3\2\2"+ "\u023e\u023f\7P\2\2\u023f\u0240\7I\2\2\u0240\\\3\2\2\2\u0241\u0242\7J"+
"\2\u0253\u0254\7K\2\2\u0254\u0255\7U\2\2\u0255f\3\2\2\2\u0256\u0257\7"+ "\2\2\u0242\u0243\7Q\2\2\u0243\u0244\7W\2\2\u0244\u0245\7T\2\2\u0245^\3"+
"L\2\2\u0257\u0258\7Q\2\2\u0258\u0259\7K\2\2\u0259\u025a\7P\2\2\u025ah"+ "\2\2\2\u0246\u0247\7J\2\2\u0247\u0248\7Q\2\2\u0248\u0249\7W\2\2\u0249"+
"\3\2\2\2\u025b\u025c\7N\2\2\u025c\u025d\7C\2\2\u025d\u025e\7U\2\2\u025e"+ "\u024a\7T\2\2\u024a\u024b\7U\2\2\u024b`\3\2\2\2\u024c\u024d\7K\2\2\u024d"+
"\u025f\7V\2\2\u025fj\3\2\2\2\u0260\u0261\7N\2\2\u0261\u0262\7G\2\2\u0262"+ "\u024e\7P\2\2\u024eb\3\2\2\2\u024f\u0250\7K\2\2\u0250\u0251\7P\2\2\u0251"+
"\u0263\7H\2\2\u0263\u0264\7V\2\2\u0264l\3\2\2\2\u0265\u0266\7N\2\2\u0266"+ "\u0252\7E\2\2\u0252\u0253\7N\2\2\u0253\u0254\7W\2\2\u0254\u0255\7F\2\2"+
"\u0267\7K\2\2\u0267\u0268\7M\2\2\u0268\u0269\7G\2\2\u0269n\3\2\2\2\u026a"+ "\u0255\u0256\7G\2\2\u0256d\3\2\2\2\u0257\u0258\7K\2\2\u0258\u0259\7P\2"+
"\u026b\7N\2\2\u026b\u026c\7K\2\2\u026c\u026d\7O\2\2\u026d\u026e\7K\2\2"+ "\2\u0259\u025a\7P\2\2\u025a\u025b\7G\2\2\u025b\u025c\7T\2\2\u025cf\3\2"+
"\u026e\u026f\7V\2\2\u026fp\3\2\2\2\u0270\u0271\7O\2\2\u0271\u0272\7C\2"+ "\2\2\u025d\u025e\7K\2\2\u025e\u025f\7P\2\2\u025f\u0260\7V\2\2\u0260\u0261"+
"\2\u0272\u0273\7R\2\2\u0273\u0274\7R\2\2\u0274\u0275\7G\2\2\u0275\u0276"+ "\7G\2\2\u0261\u0262\7T\2\2\u0262\u0263\7X\2\2\u0263\u0264\7C\2\2\u0264"+
"\7F\2\2\u0276r\3\2\2\2\u0277\u0278\7O\2\2\u0278\u0279\7C\2\2\u0279\u027a"+ "\u0265\7N\2\2\u0265h\3\2\2\2\u0266\u0267\7K\2\2\u0267\u0268\7U\2\2\u0268"+
"\7V\2\2\u027a\u027b\7E\2\2\u027b\u027c\7J\2\2\u027ct\3\2\2\2\u027d\u027e"+ "j\3\2\2\2\u0269\u026a\7L\2\2\u026a\u026b\7Q\2\2\u026b\u026c\7K\2\2\u026c"+
"\7O\2\2\u027e\u027f\7K\2\2\u027f\u0280\7P\2\2\u0280\u0281\7W\2\2\u0281"+ "\u026d\7P\2\2\u026dl\3\2\2\2\u026e\u026f\7N\2\2\u026f\u0270\7C\2\2\u0270"+
"\u0282\7V\2\2\u0282\u0283\7G\2\2\u0283v\3\2\2\2\u0284\u0285\7O\2\2\u0285"+ "\u0271\7U\2\2\u0271\u0272\7V\2\2\u0272n\3\2\2\2\u0273\u0274\7N\2\2\u0274"+
"\u0286\7K\2\2\u0286\u0287\7P\2\2\u0287\u0288\7W\2\2\u0288\u0289\7V\2\2"+ "\u0275\7G\2\2\u0275\u0276\7H\2\2\u0276\u0277\7V\2\2\u0277p\3\2\2\2\u0278"+
"\u0289\u028a\7G\2\2\u028a\u028b\7U\2\2\u028bx\3\2\2\2\u028c\u028d\7O\2"+ "\u0279\7N\2\2\u0279\u027a\7K\2\2\u027a\u027b\7M\2\2\u027b\u027c\7G\2\2"+
"\2\u028d\u028e\7Q\2\2\u028e\u028f\7P\2\2\u028f\u0290\7V\2\2\u0290\u0291"+ "\u027cr\3\2\2\2\u027d\u027e\7N\2\2\u027e\u027f\7K\2\2\u027f\u0280\7O\2"+
"\7J\2\2\u0291z\3\2\2\2\u0292\u0293\7O\2\2\u0293\u0294\7Q\2\2\u0294\u0295"+ "\2\u0280\u0281\7K\2\2\u0281\u0282\7V\2\2\u0282t\3\2\2\2\u0283\u0284\7"+
"\7P\2\2\u0295\u0296\7V\2\2\u0296\u0297\7J\2\2\u0297\u0298\7U\2\2\u0298"+ "O\2\2\u0284\u0285\7C\2\2\u0285\u0286\7R\2\2\u0286\u0287\7R\2\2\u0287\u0288"+
"|\3\2\2\2\u0299\u029a\7P\2\2\u029a\u029b\7C\2\2\u029b\u029c\7V\2\2\u029c"+ "\7G\2\2\u0288\u0289\7F\2\2\u0289v\3\2\2\2\u028a\u028b\7O\2\2\u028b\u028c"+
"\u029d\7W\2\2\u029d\u029e\7T\2\2\u029e\u029f\7C\2\2\u029f\u02a0\7N\2\2"+ "\7C\2\2\u028c\u028d\7V\2\2\u028d\u028e\7E\2\2\u028e\u028f\7J\2\2\u028f"+
"\u02a0~\3\2\2\2\u02a1\u02a2\7P\2\2\u02a2\u02a3\7Q\2\2\u02a3\u02a4\7V\2"+ "x\3\2\2\2\u0290\u0291\7O\2\2\u0291\u0292\7K\2\2\u0292\u0293\7P\2\2\u0293"+
"\2\u02a4\u0080\3\2\2\2\u02a5\u02a6\7P\2\2\u02a6\u02a7\7W\2\2\u02a7\u02a8"+ "\u0294\7W\2\2\u0294\u0295\7V\2\2\u0295\u0296\7G\2\2\u0296z\3\2\2\2\u0297"+
"\7N\2\2\u02a8\u02a9\7N\2\2\u02a9\u0082\3\2\2\2\u02aa\u02ab\7P\2\2\u02ab"+ "\u0298\7O\2\2\u0298\u0299\7K\2\2\u0299\u029a\7P\2\2\u029a\u029b\7W\2\2"+
"\u02ac\7W\2\2\u02ac\u02ad\7N\2\2\u02ad\u02ae\7N\2\2\u02ae\u02af\7U\2\2"+ "\u029b\u029c\7V\2\2\u029c\u029d\7G\2\2\u029d\u029e\7U\2\2\u029e|\3\2\2"+
"\u02af\u0084\3\2\2\2\u02b0\u02b1\7Q\2\2\u02b1\u02b2\7P\2\2\u02b2\u0086"+ "\2\u029f\u02a0\7O\2\2\u02a0\u02a1\7Q\2\2\u02a1\u02a2\7P\2\2\u02a2\u02a3"+
"\3\2\2\2\u02b3\u02b4\7Q\2\2\u02b4\u02b5\7R\2\2\u02b5\u02b6\7V\2\2\u02b6"+ "\7V\2\2\u02a3\u02a4\7J\2\2\u02a4~\3\2\2\2\u02a5\u02a6\7O\2\2\u02a6\u02a7"+
"\u02b7\7K\2\2\u02b7\u02b8\7O\2\2\u02b8\u02b9\7K\2\2\u02b9\u02ba\7\\\2"+ "\7Q\2\2\u02a7\u02a8\7P\2\2\u02a8\u02a9\7V\2\2\u02a9\u02aa\7J\2\2\u02aa"+
"\2\u02ba\u02bb\7G\2\2\u02bb\u02bc\7F\2\2\u02bc\u0088\3\2\2\2\u02bd\u02be"+ "\u02ab\7U\2\2\u02ab\u0080\3\2\2\2\u02ac\u02ad\7P\2\2\u02ad\u02ae\7C\2"+
"\7Q\2\2\u02be\u02bf\7T\2\2\u02bf\u008a\3\2\2\2\u02c0\u02c1\7Q\2\2\u02c1"+ "\2\u02ae\u02af\7V\2\2\u02af\u02b0\7W\2\2\u02b0\u02b1\7T\2\2\u02b1\u02b2"+
"\u02c2\7T\2\2\u02c2\u02c3\7F\2\2\u02c3\u02c4\7G\2\2\u02c4\u02c5\7T\2\2"+ "\7C\2\2\u02b2\u02b3\7N\2\2\u02b3\u0082\3\2\2\2\u02b4\u02b5\7P\2\2\u02b5"+
"\u02c5\u008c\3\2\2\2\u02c6\u02c7\7Q\2\2\u02c7\u02c8\7W\2\2\u02c8\u02c9"+ "\u02b6\7Q\2\2\u02b6\u02b7\7V\2\2\u02b7\u0084\3\2\2\2\u02b8\u02b9\7P\2"+
"\7V\2\2\u02c9\u02ca\7G\2\2\u02ca\u02cb\7T\2\2\u02cb\u008e\3\2\2\2\u02cc"+ "\2\u02b9\u02ba\7W\2\2\u02ba\u02bb\7N\2\2\u02bb\u02bc\7N\2\2\u02bc\u0086"+
"\u02cd\7R\2\2\u02cd\u02ce\7C\2\2\u02ce\u02cf\7T\2\2\u02cf\u02d0\7U\2\2"+ "\3\2\2\2\u02bd\u02be\7P\2\2\u02be\u02bf\7W\2\2\u02bf\u02c0\7N\2\2\u02c0"+
"\u02d0\u02d1\7G\2\2\u02d1\u02d2\7F\2\2\u02d2\u0090\3\2\2\2\u02d3\u02d4"+ "\u02c1\7N\2\2\u02c1\u02c2\7U\2\2\u02c2\u0088\3\2\2\2\u02c3\u02c4\7Q\2"+
"\7R\2\2\u02d4\u02d5\7J\2\2\u02d5\u02d6\7[\2\2\u02d6\u02d7\7U\2\2\u02d7"+ "\2\u02c4\u02c5\7P\2\2\u02c5\u008a\3\2\2\2\u02c6\u02c7\7Q\2\2\u02c7\u02c8"+
"\u02d8\7K\2\2\u02d8\u02d9\7E\2\2\u02d9\u02da\7C\2\2\u02da\u02db\7N\2\2"+ "\7R\2\2\u02c8\u02c9\7V\2\2\u02c9\u02ca\7K\2\2\u02ca\u02cb\7O\2\2\u02cb"+
"\u02db\u0092\3\2\2\2\u02dc\u02dd\7R\2\2\u02dd\u02de\7N\2\2\u02de\u02df"+ "\u02cc\7K\2\2\u02cc\u02cd\7\\\2\2\u02cd\u02ce\7G\2\2\u02ce\u02cf\7F\2"+
"\7C\2\2\u02df\u02e0\7P\2\2\u02e0\u0094\3\2\2\2\u02e1\u02e2\7T\2\2\u02e2"+ "\2\u02cf\u008c\3\2\2\2\u02d0\u02d1\7Q\2\2\u02d1\u02d2\7T\2\2\u02d2\u008e"+
"\u02e3\7K\2\2\u02e3\u02e4\7I\2\2\u02e4\u02e5\7J\2\2\u02e5\u02e6\7V\2\2"+ "\3\2\2\2\u02d3\u02d4\7Q\2\2\u02d4\u02d5\7T\2\2\u02d5\u02d6\7F\2\2\u02d6"+
"\u02e6\u0096\3\2\2\2\u02e7\u02e8\7T\2\2\u02e8\u02e9\7N\2\2\u02e9\u02ea"+ "\u02d7\7G\2\2\u02d7\u02d8\7T\2\2\u02d8\u0090\3\2\2\2\u02d9\u02da\7Q\2"+
"\7K\2\2\u02ea\u02eb\7M\2\2\u02eb\u02ec\7G\2\2\u02ec\u0098\3\2\2\2\u02ed"+ "\2\u02da\u02db\7W\2\2\u02db\u02dc\7V\2\2\u02dc\u02dd\7G\2\2\u02dd\u02de"+
"\u02ee\7S\2\2\u02ee\u02ef\7W\2\2\u02ef\u02f0\7G\2\2\u02f0\u02f1\7T\2\2"+ "\7T\2\2\u02de\u0092\3\2\2\2\u02df\u02e0\7R\2\2\u02e0\u02e1\7C\2\2\u02e1"+
"\u02f1\u02f2\7[\2\2\u02f2\u009a\3\2\2\2\u02f3\u02f4\7U\2\2\u02f4\u02f5"+ "\u02e2\7T\2\2\u02e2\u02e3\7U\2\2\u02e3\u02e4\7G\2\2\u02e4\u02e5\7F\2\2"+
"\7E\2\2\u02f5\u02f6\7J\2\2\u02f6\u02f7\7G\2\2\u02f7\u02f8\7O\2\2\u02f8"+ "\u02e5\u0094\3\2\2\2\u02e6\u02e7\7R\2\2\u02e7\u02e8\7J\2\2\u02e8\u02e9"+
"\u02f9\7C\2\2\u02f9\u02fa\7U\2\2\u02fa\u009c\3\2\2\2\u02fb\u02fc\7U\2"+ "\7[\2\2\u02e9\u02ea\7U\2\2\u02ea\u02eb\7K\2\2\u02eb\u02ec\7E\2\2\u02ec"+
"\2\u02fc\u02fd\7G\2\2\u02fd\u02fe\7E\2\2\u02fe\u02ff\7Q\2\2\u02ff\u0300"+ "\u02ed\7C\2\2\u02ed\u02ee\7N\2\2\u02ee\u0096\3\2\2\2\u02ef\u02f0\7R\2"+
"\7P\2\2\u0300\u0301\7F\2\2\u0301\u009e\3\2\2\2\u0302\u0303\7U\2\2\u0303"+ "\2\u02f0\u02f1\7N\2\2\u02f1\u02f2\7C\2\2\u02f2\u02f3\7P\2\2\u02f3\u0098"+
"\u0304\7G\2\2\u0304\u0305\7E\2\2\u0305\u0306\7Q\2\2\u0306\u0307\7P\2\2"+ "\3\2\2\2\u02f4\u02f5\7T\2\2\u02f5\u02f6\7K\2\2\u02f6\u02f7\7I\2\2\u02f7"+
"\u0307\u0308\7F\2\2\u0308\u0309\7U\2\2\u0309\u00a0\3\2\2\2\u030a\u030b"+ "\u02f8\7J\2\2\u02f8\u02f9\7V\2\2\u02f9\u009a\3\2\2\2\u02fa\u02fb\7T\2"+
"\7U\2\2\u030b\u030c\7G\2\2\u030c\u030d\7N\2\2\u030d\u030e\7G\2\2\u030e"+ "\2\u02fb\u02fc\7N\2\2\u02fc\u02fd\7K\2\2\u02fd\u02fe\7M\2\2\u02fe\u02ff"+
"\u030f\7E\2\2\u030f\u0310\7V\2\2\u0310\u00a2\3\2\2\2\u0311\u0312\7U\2"+ "\7G\2\2\u02ff\u009c\3\2\2\2\u0300\u0301\7S\2\2\u0301\u0302\7W\2\2\u0302"+
"\2\u0312\u0313\7J\2\2\u0313\u0314\7Q\2\2\u0314\u0315\7Y\2\2\u0315\u00a4"+ "\u0303\7G\2\2\u0303\u0304\7T\2\2\u0304\u0305\7[\2\2\u0305\u009e\3\2\2"+
"\3\2\2\2\u0316\u0317\7U\2\2\u0317\u0318\7[\2\2\u0318\u0319\7U\2\2\u0319"+ "\2\u0306\u0307\7U\2\2\u0307\u0308\7E\2\2\u0308\u0309\7J\2\2\u0309\u030a"+
"\u00a6\3\2\2\2\u031a\u031b\7V\2\2\u031b\u031c\7C\2\2\u031c\u031d\7D\2"+ "\7G\2\2\u030a\u030b\7O\2\2\u030b\u030c\7C\2\2\u030c\u030d\7U\2\2\u030d"+
"\2\u031d\u031e\7N\2\2\u031e\u031f\7G\2\2\u031f\u00a8\3\2\2\2\u0320\u0321"+ "\u00a0\3\2\2\2\u030e\u030f\7U\2\2\u030f\u0310\7G\2\2\u0310\u0311\7E\2"+
"\7V\2\2\u0321\u0322\7C\2\2\u0322\u0323\7D\2\2\u0323\u0324\7N\2\2\u0324"+ "\2\u0311\u0312\7Q\2\2\u0312\u0313\7P\2\2\u0313\u0314\7F\2\2\u0314\u00a2"+
"\u0325\7G\2\2\u0325\u0326\7U\2\2\u0326\u00aa\3\2\2\2\u0327\u0328\7V\2"+ "\3\2\2\2\u0315\u0316\7U\2\2\u0316\u0317\7G\2\2\u0317\u0318\7E\2\2\u0318"+
"\2\u0328\u0329\7G\2\2\u0329\u032a\7Z\2\2\u032a\u032b\7V\2\2\u032b\u00ac"+ "\u0319\7Q\2\2\u0319\u031a\7P\2\2\u031a\u031b\7F\2\2\u031b\u031c\7U\2\2"+
"\3\2\2\2\u032c\u032d\7V\2\2\u032d\u032e\7J\2\2\u032e\u032f\7G\2\2\u032f"+ "\u031c\u00a4\3\2\2\2\u031d\u031e\7U\2\2\u031e\u031f\7G\2\2\u031f\u0320"+
"\u0330\7P\2\2\u0330\u00ae\3\2\2\2\u0331\u0332\7V\2\2\u0332\u0333\7T\2"+ "\7N\2\2\u0320\u0321\7G\2\2\u0321\u0322\7E\2\2\u0322\u0323\7V\2\2\u0323"+
"\2\u0333\u0334\7W\2\2\u0334\u0335\7G\2\2\u0335\u00b0\3\2\2\2\u0336\u0337"+ "\u00a6\3\2\2\2\u0324\u0325\7U\2\2\u0325\u0326\7J\2\2\u0326\u0327\7Q\2"+
"\7V\2\2\u0337\u0338\7Q\2\2\u0338\u00b2\3\2\2\2\u0339\u033a\7V\2\2\u033a"+ "\2\u0327\u0328\7Y\2\2\u0328\u00a8\3\2\2\2\u0329\u032a\7U\2\2\u032a\u032b"+
"\u033b\7[\2\2\u033b\u033c\7R\2\2\u033c\u033d\7G\2\2\u033d\u00b4\3\2\2"+ "\7[\2\2\u032b\u032c\7U\2\2\u032c\u00aa\3\2\2\2\u032d\u032e\7V\2\2\u032e"+
"\2\u033e\u033f\7V\2\2\u033f\u0340\7[\2\2\u0340\u0341\7R\2\2\u0341\u0342"+ "\u032f\7C\2\2\u032f\u0330\7D\2\2\u0330\u0331\7N\2\2\u0331\u0332\7G\2\2"+
"\7G\2\2\u0342\u0343\7U\2\2\u0343\u00b6\3\2\2\2\u0344\u0345\7W\2\2\u0345"+ "\u0332\u00ac\3\2\2\2\u0333\u0334\7V\2\2\u0334\u0335\7C\2\2\u0335\u0336"+
"\u0346\7U\2\2\u0346\u0347\7K\2\2\u0347\u0348\7P\2\2\u0348\u0349\7I\2\2"+ "\7D\2\2\u0336\u0337\7N\2\2\u0337\u0338\7G\2\2\u0338\u0339\7U\2\2\u0339"+
"\u0349\u00b8\3\2\2\2\u034a\u034b\7X\2\2\u034b\u034c\7G\2\2\u034c\u034d"+ "\u00ae\3\2\2\2\u033a\u033b\7V\2\2\u033b\u033c\7G\2\2\u033c\u033d\7Z\2"+
"\7T\2\2\u034d\u034e\7K\2\2\u034e\u034f\7H\2\2\u034f\u0350\7[\2\2\u0350"+ "\2\u033d\u033e\7V\2\2\u033e\u00b0\3\2\2\2\u033f\u0340\7V\2\2\u0340\u0341"+
"\u00ba\3\2\2\2\u0351\u0352\7Y\2\2\u0352\u0353\7J\2\2\u0353\u0354\7G\2"+ "\7J\2\2\u0341\u0342\7G\2\2\u0342\u0343\7P\2\2\u0343\u00b2\3\2\2\2\u0344"+
"\2\u0354\u0355\7P\2\2\u0355\u00bc\3\2\2\2\u0356\u0357\7Y\2\2\u0357\u0358"+ "\u0345\7V\2\2\u0345\u0346\7T\2\2\u0346\u0347\7W\2\2\u0347\u0348\7G\2\2"+
"\7J\2\2\u0358\u0359\7G\2\2\u0359\u035a\7T\2\2\u035a\u035b\7G\2\2\u035b"+ "\u0348\u00b4\3\2\2\2\u0349\u034a\7V\2\2\u034a\u034b\7Q\2\2\u034b\u00b6"+
"\u00be\3\2\2\2\u035c\u035d\7Y\2\2\u035d\u035e\7K\2\2\u035e\u035f\7V\2"+ "\3\2\2\2\u034c\u034d\7V\2\2\u034d\u034e\7[\2\2\u034e\u034f\7R\2\2\u034f"+
"\2\u035f\u0360\7J\2\2\u0360\u00c0\3\2\2\2\u0361\u0362\7[\2\2\u0362\u0363"+ "\u0350\7G\2\2\u0350\u00b8\3\2\2\2\u0351\u0352\7V\2\2\u0352\u0353\7[\2"+
"\7G\2\2\u0363\u0364\7C\2\2\u0364\u0365\7T\2\2\u0365\u00c2\3\2\2\2\u0366"+ "\2\u0353\u0354\7R\2\2\u0354\u0355\7G\2\2\u0355\u0356\7U\2\2\u0356\u00ba"+
"\u0367\7[\2\2\u0367\u0368\7G\2\2\u0368\u0369\7C\2\2\u0369\u036a\7T\2\2"+ "\3\2\2\2\u0357\u0358\7W\2\2\u0358\u0359\7U\2\2\u0359\u035a\7K\2\2\u035a"+
"\u036a\u036b\7U\2\2\u036b\u00c4\3\2\2\2\u036c\u036d\7}\2\2\u036d\u036e"+ "\u035b\7P\2\2\u035b\u035c\7I\2\2\u035c\u00bc\3\2\2\2\u035d\u035e\7X\2"+
"\7G\2\2\u036e\u036f\7U\2\2\u036f\u0370\7E\2\2\u0370\u0371\7C\2\2\u0371"+ "\2\u035e\u035f\7G\2\2\u035f\u0360\7T\2\2\u0360\u0361\7K\2\2\u0361\u0362"+
"\u0372\7R\2\2\u0372\u0373\7G\2\2\u0373\u00c6\3\2\2\2\u0374\u0375\7}\2"+ "\7H\2\2\u0362\u0363\7[\2\2\u0363\u00be\3\2\2\2\u0364\u0365\7Y\2\2\u0365"+
"\2\u0375\u0376\7H\2\2\u0376\u0377\7P\2\2\u0377\u00c8\3\2\2\2\u0378\u0379"+ "\u0366\7J\2\2\u0366\u0367\7G\2\2\u0367\u0368\7P\2\2\u0368\u00c0\3\2\2"+
"\7}\2\2\u0379\u037a\7N\2\2\u037a\u037b\7K\2\2\u037b\u037c\7O\2\2\u037c"+ "\2\u0369\u036a\7Y\2\2\u036a\u036b\7J\2\2\u036b\u036c\7G\2\2\u036c\u036d"+
"\u037d\7K\2\2\u037d\u037e\7V\2\2\u037e\u00ca\3\2\2\2\u037f\u0380\7}\2"+ "\7T\2\2\u036d\u036e\7G\2\2\u036e\u00c2\3\2\2\2\u036f\u0370\7Y\2\2\u0370"+
"\2\u0380\u0381\7F\2\2\u0381\u00cc\3\2\2\2\u0382\u0383\7}\2\2\u0383\u0384"+ "\u0371\7K\2\2\u0371\u0372\7V\2\2\u0372\u0373\7J\2\2\u0373\u00c4\3\2\2"+
"\7V\2\2\u0384\u00ce\3\2\2\2\u0385\u0386\7}\2\2\u0386\u0387\7V\2\2\u0387"+ "\2\u0374\u0375\7[\2\2\u0375\u0376\7G\2\2\u0376\u0377\7C\2\2\u0377\u0378"+
"\u0388\7U\2\2\u0388\u00d0\3\2\2\2\u0389\u038a\7}\2\2\u038a\u038b\7I\2"+ "\7T\2\2\u0378\u00c6\3\2\2\2\u0379\u037a\7[\2\2\u037a\u037b\7G\2\2\u037b"+
"\2\u038b\u038c\7W\2\2\u038c\u038d\7K\2\2\u038d\u038e\7F\2\2\u038e\u00d2"+ "\u037c\7C\2\2\u037c\u037d\7T\2\2\u037d\u037e\7U\2\2\u037e\u00c8\3\2\2"+
"\3\2\2\2\u038f\u0390\7\177\2\2\u0390\u00d4\3\2\2\2\u0391\u0392\7?\2\2"+ "\2\u037f\u0380\7}\2\2\u0380\u0381\7G\2\2\u0381\u0382\7U\2\2\u0382\u0383"+
"\u0392\u00d6\3\2\2\2\u0393\u0394\7>\2\2\u0394\u0395\7?\2\2\u0395\u0396"+ "\7E\2\2\u0383\u0384\7C\2\2\u0384\u0385\7R\2\2\u0385\u0386\7G\2\2\u0386"+
"\7@\2\2\u0396\u00d8\3\2\2\2\u0397\u0398\7>\2\2\u0398\u039c\7@\2\2\u0399"+ "\u00ca\3\2\2\2\u0387\u0388\7}\2\2\u0388\u0389\7H\2\2\u0389\u038a\7P\2"+
"\u039a\7#\2\2\u039a\u039c\7?\2\2\u039b\u0397\3\2\2\2\u039b\u0399\3\2\2"+ "\2\u038a\u00cc\3\2\2\2\u038b\u038c\7}\2\2\u038c\u038d\7N\2\2\u038d\u038e"+
"\2\u039c\u00da\3\2\2\2\u039d\u039e\7>\2\2\u039e\u00dc\3\2\2\2\u039f\u03a0"+ "\7K\2\2\u038e\u038f\7O\2\2\u038f\u0390\7K\2\2\u0390\u0391\7V\2\2\u0391"+
"\7>\2\2\u03a0\u03a1\7?\2\2\u03a1\u00de\3\2\2\2\u03a2\u03a3\7@\2\2\u03a3"+ "\u00ce\3\2\2\2\u0392\u0393\7}\2\2\u0393\u0394\7F\2\2\u0394\u00d0\3\2\2"+
"\u00e0\3\2\2\2\u03a4\u03a5\7@\2\2\u03a5\u03a6\7?\2\2\u03a6\u00e2\3\2\2"+ "\2\u0395\u0396\7}\2\2\u0396\u0397\7V\2\2\u0397\u00d2\3\2\2\2\u0398\u0399"+
"\2\u03a7\u03a8\7-\2\2\u03a8\u00e4\3\2\2\2\u03a9\u03aa\7/\2\2\u03aa\u00e6"+ "\7}\2\2\u0399\u039a\7V\2\2\u039a\u039b\7U\2\2\u039b\u00d4\3\2\2\2\u039c"+
"\3\2\2\2\u03ab\u03ac\7,\2\2\u03ac\u00e8\3\2\2\2\u03ad\u03ae\7\61\2\2\u03ae"+ "\u039d\7}\2\2\u039d\u039e\7I\2\2\u039e\u039f\7W\2\2\u039f\u03a0\7K\2\2"+
"\u00ea\3\2\2\2\u03af\u03b0\7\'\2\2\u03b0\u00ec\3\2\2\2\u03b1\u03b2\7<"+ "\u03a0\u03a1\7F\2\2\u03a1\u00d6\3\2\2\2\u03a2\u03a3\7\177\2\2\u03a3\u00d8"+
"\2\2\u03b2\u03b3\7<\2\2\u03b3\u00ee\3\2\2\2\u03b4\u03b5\7~\2\2\u03b5\u03b6"+ "\3\2\2\2\u03a4\u03a5\7?\2\2\u03a5\u00da\3\2\2\2\u03a6\u03a7\7>\2\2\u03a7"+
"\7~\2\2\u03b6\u00f0\3\2\2\2\u03b7\u03b8\7\60\2\2\u03b8\u00f2\3\2\2\2\u03b9"+ "\u03a8\7?\2\2\u03a8\u03a9\7@\2\2\u03a9\u00dc\3\2\2\2\u03aa\u03ab\7>\2"+
"\u03ba\7A\2\2\u03ba\u00f4\3\2\2\2\u03bb\u03c1\7)\2\2\u03bc\u03c0\n\2\2"+ "\2\u03ab\u03af\7@\2\2\u03ac\u03ad\7#\2\2\u03ad\u03af\7?\2\2\u03ae\u03aa"+
"\2\u03bd\u03be\7)\2\2\u03be\u03c0\7)\2\2\u03bf\u03bc\3\2\2\2\u03bf\u03bd"+ "\3\2\2\2\u03ae\u03ac\3\2\2\2\u03af\u00de\3\2\2\2\u03b0\u03b1\7>\2\2\u03b1"+
"\3\2\2\2\u03c0\u03c3\3\2\2\2\u03c1\u03bf\3\2\2\2\u03c1\u03c2\3\2\2\2\u03c2"+ "\u00e0\3\2\2\2\u03b2\u03b3\7>\2\2\u03b3\u03b4\7?\2\2\u03b4\u00e2\3\2\2"+
"\u03c4\3\2\2\2\u03c3\u03c1\3\2\2\2\u03c4\u03c5\7)\2\2\u03c5\u00f6\3\2"+ "\2\u03b5\u03b6\7@\2\2\u03b6\u00e4\3\2\2\2\u03b7\u03b8\7@\2\2\u03b8\u03b9"+
"\2\2\u03c6\u03c8\5\u0107\u0084\2\u03c7\u03c6\3\2\2\2\u03c8\u03c9\3\2\2"+ "\7?\2\2\u03b9\u00e6\3\2\2\2\u03ba\u03bb\7-\2\2\u03bb\u00e8\3\2\2\2\u03bc"+
"\2\u03c9\u03c7\3\2\2\2\u03c9\u03ca\3\2\2\2\u03ca\u00f8\3\2\2\2\u03cb\u03cd"+ "\u03bd\7/\2\2\u03bd\u00ea\3\2\2\2\u03be\u03bf\7,\2\2\u03bf\u00ec\3\2\2"+
"\5\u0107\u0084\2\u03cc\u03cb\3\2\2\2\u03cd\u03ce\3\2\2\2\u03ce\u03cc\3"+ "\2\u03c0\u03c1\7\61\2\2\u03c1\u00ee\3\2\2\2\u03c2\u03c3\7\'\2\2\u03c3"+
"\2\2\2\u03ce\u03cf\3\2\2\2\u03cf\u03d0\3\2\2\2\u03d0\u03d4\5\u00f1y\2"+ "\u00f0\3\2\2\2\u03c4\u03c5\7<\2\2\u03c5\u03c6\7<\2\2\u03c6\u00f2\3\2\2"+
"\u03d1\u03d3\5\u0107\u0084\2\u03d2\u03d1\3\2\2\2\u03d3\u03d6\3\2\2\2\u03d4"+ "\2\u03c7\u03c8\7~\2\2\u03c8\u03c9\7~\2\2\u03c9\u00f4\3\2\2\2\u03ca\u03cb"+
"\u03d2\3\2\2\2\u03d4\u03d5\3\2\2\2\u03d5\u03f6\3\2\2\2\u03d6\u03d4\3\2"+ "\7\60\2\2\u03cb\u00f6\3\2\2\2\u03cc\u03cd\7A\2\2\u03cd\u00f8\3\2\2\2\u03ce"+
"\2\2\u03d7\u03d9\5\u00f1y\2\u03d8\u03da\5\u0107\u0084\2\u03d9\u03d8\3"+ "\u03d4\7)\2\2\u03cf\u03d3\n\2\2\2\u03d0\u03d1\7)\2\2\u03d1\u03d3\7)\2"+
"\2\2\2\u03da\u03db\3\2\2\2\u03db\u03d9\3\2\2\2\u03db\u03dc\3\2\2\2\u03dc"+ "\2\u03d2\u03cf\3\2\2\2\u03d2\u03d0\3\2\2\2\u03d3\u03d6\3\2\2\2\u03d4\u03d2"+
"\u03f6\3\2\2\2\u03dd\u03df\5\u0107\u0084\2\u03de\u03dd\3\2\2\2\u03df\u03e0"+ "\3\2\2\2\u03d4\u03d5\3\2\2\2\u03d5\u03d7\3\2\2\2\u03d6\u03d4\3\2\2\2\u03d7"+
"\3\2\2\2\u03e0\u03de\3\2\2\2\u03e0\u03e1\3\2\2\2\u03e1\u03e9\3\2\2\2\u03e2"+ "\u03d8\7)\2\2\u03d8\u00fa\3\2\2\2\u03d9\u03db\5\u010b\u0086\2\u03da\u03d9"+
"\u03e6\5\u00f1y\2\u03e3\u03e5\5\u0107\u0084\2\u03e4\u03e3\3\2\2\2\u03e5"+ "\3\2\2\2\u03db\u03dc\3\2\2\2\u03dc\u03da\3\2\2\2\u03dc\u03dd\3\2\2\2\u03dd"+
"\u03e8\3\2\2\2\u03e6\u03e4\3\2\2\2\u03e6\u03e7\3\2\2\2\u03e7\u03ea\3\2"+ "\u00fc\3\2\2\2\u03de\u03e0\5\u010b\u0086\2\u03df\u03de\3\2\2\2\u03e0\u03e1"+
"\2\2\u03e8\u03e6\3\2\2\2\u03e9\u03e2\3\2\2\2\u03e9\u03ea\3\2\2\2\u03ea"+ "\3\2\2\2\u03e1\u03df\3\2\2\2\u03e1\u03e2\3\2\2\2\u03e2\u03e3\3\2\2\2\u03e3"+
"\u03eb\3\2\2\2\u03eb\u03ec\5\u0105\u0083\2\u03ec\u03f6\3\2\2\2\u03ed\u03ef"+ "\u03e7\5\u00f5{\2\u03e4\u03e6\5\u010b\u0086\2\u03e5\u03e4\3\2\2\2\u03e6"+
"\5\u00f1y\2\u03ee\u03f0\5\u0107\u0084\2\u03ef\u03ee\3\2\2\2\u03f0\u03f1"+ "\u03e9\3\2\2\2\u03e7\u03e5\3\2\2\2\u03e7\u03e8\3\2\2\2\u03e8\u0409\3\2"+
"\3\2\2\2\u03f1\u03ef\3\2\2\2\u03f1\u03f2\3\2\2\2\u03f2\u03f3\3\2\2\2\u03f3"+ "\2\2\u03e9\u03e7\3\2\2\2\u03ea\u03ec\5\u00f5{\2\u03eb\u03ed\5\u010b\u0086"+
"\u03f4\5\u0105\u0083\2\u03f4\u03f6\3\2\2\2\u03f5\u03cc\3\2\2\2\u03f5\u03d7"+ "\2\u03ec\u03eb\3\2\2\2\u03ed\u03ee\3\2\2\2\u03ee\u03ec\3\2\2\2\u03ee\u03ef"+
"\3\2\2\2\u03f5\u03de\3\2\2\2\u03f5\u03ed\3\2\2\2\u03f6\u00fa\3\2\2\2\u03f7"+ "\3\2\2\2\u03ef\u0409\3\2\2\2\u03f0\u03f2\5\u010b\u0086\2\u03f1\u03f0\3"+
"\u03fa\5\u0109\u0085\2\u03f8\u03fa\7a\2\2\u03f9\u03f7\3\2\2\2\u03f9\u03f8"+ "\2\2\2\u03f2\u03f3\3\2\2\2\u03f3\u03f1\3\2\2\2\u03f3\u03f4\3\2\2\2\u03f4"+
"\3\2\2\2\u03fa\u0400\3\2\2\2\u03fb\u03ff\5\u0109\u0085\2\u03fc\u03ff\5"+ "\u03fc\3\2\2\2\u03f5\u03f9\5\u00f5{\2\u03f6\u03f8\5\u010b\u0086\2\u03f7"+
"\u0107\u0084\2\u03fd\u03ff\t\3\2\2\u03fe\u03fb\3\2\2\2\u03fe\u03fc\3\2"+ "\u03f6\3\2\2\2\u03f8\u03fb\3\2\2\2\u03f9\u03f7\3\2\2\2\u03f9\u03fa\3\2"+
"\2\2\u03fe\u03fd\3\2\2\2\u03ff\u0402\3\2\2\2\u0400\u03fe\3\2\2\2\u0400"+ "\2\2\u03fa\u03fd\3\2\2\2\u03fb\u03f9\3\2\2\2\u03fc\u03f5\3\2\2\2\u03fc"+
"\u0401\3\2\2\2\u0401\u00fc\3\2\2\2\u0402\u0400\3\2\2\2\u0403\u0407\5\u0107"+ "\u03fd\3\2\2\2\u03fd\u03fe\3\2\2\2\u03fe\u03ff\5\u0109\u0085\2\u03ff\u0409"+
"\u0084\2\u0404\u0408\5\u0109\u0085\2\u0405\u0408\5\u0107\u0084\2\u0406"+ "\3\2\2\2\u0400\u0402\5\u00f5{\2\u0401\u0403\5\u010b\u0086\2\u0402\u0401"+
"\u0408\t\3\2\2\u0407\u0404\3\2\2\2\u0407\u0405\3\2\2\2\u0407\u0406\3\2"+ "\3\2\2\2\u0403\u0404\3\2\2\2\u0404\u0402\3\2\2\2\u0404\u0405\3\2\2\2\u0405"+
"\2\2\u0408\u0409\3\2\2\2\u0409\u0407\3\2\2\2\u0409\u040a\3\2\2\2\u040a"+ "\u0406\3\2\2\2\u0406\u0407\5\u0109\u0085\2\u0407\u0409\3\2\2\2\u0408\u03df"+
"\u00fe\3\2\2\2\u040b\u040f\5\u0109\u0085\2\u040c\u040f\5\u0107\u0084\2"+ "\3\2\2\2\u0408\u03ea\3\2\2\2\u0408\u03f1\3\2\2\2\u0408\u0400\3\2\2\2\u0409"+
"\u040d\u040f\7a\2\2\u040e\u040b\3\2\2\2\u040e\u040c\3\2\2\2\u040e\u040d"+ "\u00fe\3\2\2\2\u040a\u040d\5\u010d\u0087\2\u040b\u040d\7a\2\2\u040c\u040a"+
"\3\2\2\2\u040f\u0410\3\2\2\2\u0410\u040e\3\2\2\2\u0410\u0411\3\2\2\2\u0411"+ "\3\2\2\2\u040c\u040b\3\2\2\2\u040d\u0413\3\2\2\2\u040e\u0412\5\u010d\u0087"+
"\u0100\3\2\2\2\u0412\u0418\7$\2\2\u0413\u0417\n\4\2\2\u0414\u0415\7$\2"+ "\2\u040f\u0412\5\u010b\u0086\2\u0410\u0412\t\3\2\2\u0411\u040e\3\2\2\2"+
"\2\u0415\u0417\7$\2\2\u0416\u0413\3\2\2\2\u0416\u0414\3\2\2\2\u0417\u041a"+ "\u0411\u040f\3\2\2\2\u0411\u0410\3\2\2\2\u0412\u0415\3\2\2\2\u0413\u0411"+
"\3\2\2\2\u0418\u0416\3\2\2\2\u0418\u0419\3\2\2\2\u0419\u041b\3\2\2\2\u041a"+ "\3\2\2\2\u0413\u0414\3\2\2\2\u0414\u0100\3\2\2\2\u0415\u0413\3\2\2\2\u0416"+
"\u0418\3\2\2\2\u041b\u041c\7$\2\2\u041c\u0102\3\2\2\2\u041d\u0423\7b\2"+ "\u041a\5\u010b\u0086\2\u0417\u041b\5\u010d\u0087\2\u0418\u041b\5\u010b"+
"\2\u041e\u0422\n\5\2\2\u041f\u0420\7b\2\2\u0420\u0422\7b\2\2\u0421\u041e"+ "\u0086\2\u0419\u041b\t\3\2\2\u041a\u0417\3\2\2\2\u041a\u0418\3\2\2\2\u041a"+
"\3\2\2\2\u0421\u041f\3\2\2\2\u0422\u0425\3\2\2\2\u0423\u0421\3\2\2\2\u0423"+ "\u0419\3\2\2\2\u041b\u041c\3\2\2\2\u041c\u041a\3\2\2\2\u041c\u041d\3\2"+
"\u0424\3\2\2\2\u0424\u0426\3\2\2\2\u0425\u0423\3\2\2\2\u0426\u0427\7b"+ "\2\2\u041d\u0102\3\2\2\2\u041e\u0422\5\u010d\u0087\2\u041f\u0422\5\u010b"+
"\2\2\u0427\u0104\3\2\2\2\u0428\u042a\7G\2\2\u0429\u042b\t\6\2\2\u042a"+ "\u0086\2\u0420\u0422\7a\2\2\u0421\u041e\3\2\2\2\u0421\u041f\3\2\2\2\u0421"+
"\u0429\3\2\2\2\u042a\u042b\3\2\2\2\u042b\u042d\3\2\2\2\u042c\u042e\5\u0107"+ "\u0420\3\2\2\2\u0422\u0423\3\2\2\2\u0423\u0421\3\2\2\2\u0423\u0424\3\2"+
"\u0084\2\u042d\u042c\3\2\2\2\u042e\u042f\3\2\2\2\u042f\u042d\3\2\2\2\u042f"+ "\2\2\u0424\u0104\3\2\2\2\u0425\u042b\7$\2\2\u0426\u042a\n\4\2\2\u0427"+
"\u0430\3\2\2\2\u0430\u0106\3\2\2\2\u0431\u0432\t\7\2\2\u0432\u0108\3\2"+ "\u0428\7$\2\2\u0428\u042a\7$\2\2\u0429\u0426\3\2\2\2\u0429\u0427\3\2\2"+
"\2\2\u0433\u0434\t\b\2\2\u0434\u010a\3\2\2\2\u0435\u0436\7/\2\2\u0436"+ "\2\u042a\u042d\3\2\2\2\u042b\u0429\3\2\2\2\u042b\u042c\3\2\2\2\u042c\u042e"+
"\u0437\7/\2\2\u0437\u043b\3\2\2\2\u0438\u043a\n\t\2\2\u0439\u0438\3\2"+ "\3\2\2\2\u042d\u042b\3\2\2\2\u042e\u042f\7$\2\2\u042f\u0106\3\2\2\2\u0430"+
"\2\2\u043a\u043d\3\2\2\2\u043b\u0439\3\2\2\2\u043b\u043c\3\2\2\2\u043c"+ "\u0436\7b\2\2\u0431\u0435\n\5\2\2\u0432\u0433\7b\2\2\u0433\u0435\7b\2"+
"\u043f\3\2\2\2\u043d\u043b\3\2\2\2\u043e\u0440\7\17\2\2\u043f\u043e\3"+ "\2\u0434\u0431\3\2\2\2\u0434\u0432\3\2\2\2\u0435\u0438\3\2\2\2\u0436\u0434"+
"\2\2\2\u043f\u0440\3\2\2\2\u0440\u0442\3\2\2\2\u0441\u0443\7\f\2\2\u0442"+ "\3\2\2\2\u0436\u0437\3\2\2\2\u0437\u0439\3\2\2\2\u0438\u0436\3\2\2\2\u0439"+
"\u0441\3\2\2\2\u0442\u0443\3\2\2\2\u0443\u0444\3\2\2\2\u0444\u0445\b\u0086"+ "\u043a\7b\2\2\u043a\u0108\3\2\2\2\u043b\u043d\7G\2\2\u043c\u043e\t\6\2"+
"\2\2\u0445\u010c\3\2\2\2\u0446\u0447\7\61\2\2\u0447\u0448\7,\2\2\u0448"+ "\2\u043d\u043c\3\2\2\2\u043d\u043e\3\2\2\2\u043e\u0440\3\2\2\2\u043f\u0441"+
"\u044d\3\2\2\2\u0449\u044c\5\u010d\u0087\2\u044a\u044c\13\2\2\2\u044b"+ "\5\u010b\u0086\2\u0440\u043f\3\2\2\2\u0441\u0442\3\2\2\2\u0442\u0440\3"+
"\u0449\3\2\2\2\u044b\u044a\3\2\2\2\u044c\u044f\3\2\2\2\u044d\u044e\3\2"+ "\2\2\2\u0442\u0443\3\2\2\2\u0443\u010a\3\2\2\2\u0444\u0445\t\7\2\2\u0445"+
"\2\2\u044d\u044b\3\2\2\2\u044e\u0450\3\2\2\2\u044f\u044d\3\2\2\2\u0450"+ "\u010c\3\2\2\2\u0446\u0447\t\b\2\2\u0447\u010e\3\2\2\2\u0448\u0449\7/"+
"\u0451\7,\2\2\u0451\u0452\7\61\2\2\u0452\u0453\3\2\2\2\u0453\u0454\b\u0087"+ "\2\2\u0449\u044a\7/\2\2\u044a\u044e\3\2\2\2\u044b\u044d\n\t\2\2\u044c"+
"\2\2\u0454\u010e\3\2\2\2\u0455\u0457\t\n\2\2\u0456\u0455\3\2\2\2\u0457"+ "\u044b\3\2\2\2\u044d\u0450\3\2\2\2\u044e\u044c\3\2\2\2\u044e\u044f\3\2"+
"\u0458\3\2\2\2\u0458\u0456\3\2\2\2\u0458\u0459\3\2\2\2\u0459\u045a\3\2"+ "\2\2\u044f\u0452\3\2\2\2\u0450\u044e\3\2\2\2\u0451\u0453\7\17\2\2\u0452"+
"\2\2\u045a\u045b\b\u0088\2\2\u045b\u0110\3\2\2\2\u045c\u045d\13\2\2\2"+ "\u0451\3\2\2\2\u0452\u0453\3\2\2\2\u0453\u0455\3\2\2\2\u0454\u0456\7\f"+
"\u045d\u0112\3\2\2\2\"\2\u039b\u03bf\u03c1\u03c9\u03ce\u03d4\u03db\u03e0"+ "\2\2\u0455\u0454\3\2\2\2\u0455\u0456\3\2\2\2\u0456\u0457\3\2\2\2\u0457"+
"\u03e6\u03e9\u03f1\u03f5\u03f9\u03fe\u0400\u0407\u0409\u040e\u0410\u0416"+ "\u0458\b\u0088\2\2\u0458\u0110\3\2\2\2\u0459\u045a\7\61\2\2\u045a\u045b"+
"\u0418\u0421\u0423\u042a\u042f\u043b\u043f\u0442\u044b\u044d\u0458\3\2"+ "\7,\2\2\u045b\u0460\3\2\2\2\u045c\u045f\5\u0111\u0089\2\u045d\u045f\13"+
"\3\2"; "\2\2\2\u045e\u045c\3\2\2\2\u045e\u045d\3\2\2\2\u045f\u0462\3\2\2\2\u0460"+
"\u0461\3\2\2\2\u0460\u045e\3\2\2\2\u0461\u0463\3\2\2\2\u0462\u0460\3\2"+
"\2\2\u0463\u0464\7,\2\2\u0464\u0465\7\61\2\2\u0465\u0466\3\2\2\2\u0466"+
"\u0467\b\u0089\2\2\u0467\u0112\3\2\2\2\u0468\u046a\t\n\2\2\u0469\u0468"+
"\3\2\2\2\u046a\u046b\3\2\2\2\u046b\u0469\3\2\2\2\u046b\u046c\3\2\2\2\u046c"+
"\u046d\3\2\2\2\u046d\u046e\b\u008a\2\2\u046e\u0114\3\2\2\2\u046f\u0470"+
"\13\2\2\2\u0470\u0116\3\2\2\2\"\2\u03ae\u03d2\u03d4\u03dc\u03e1\u03e7"+
"\u03ee\u03f3\u03f9\u03fc\u0404\u0408\u040c\u0411\u0413\u041a\u041c\u0421"+
"\u0423\u0429\u042b\u0434\u0436\u043d\u0442\u044e\u0452\u0455\u045e\u0460"+
"\u046b\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

@ -24,16 +24,18 @@ public class EsRelation extends LeafPlan {
private final EsIndex index; private final EsIndex index;
private final List<Attribute> attrs; private final List<Attribute> attrs;
private final boolean frozen;
public EsRelation(Source source, EsIndex index) { public EsRelation(Source source, EsIndex index, boolean frozen) {
super(source); super(source);
this.index = index; this.index = index;
attrs = flatten(source, index.mapping()); this.attrs = flatten(source, index.mapping());
this.frozen = frozen;
} }
@Override @Override
protected NodeInfo<EsRelation> info() { protected NodeInfo<EsRelation> info() {
return NodeInfo.create(this, EsRelation::new, index); return NodeInfo.create(this, EsRelation::new, index, frozen);
} }
private static List<Attribute> flatten(Source source, Map<String, EsField> mapping) { private static List<Attribute> flatten(Source source, Map<String, EsField> mapping) {
@ -63,6 +65,10 @@ public class EsRelation extends LeafPlan {
return index; return index;
} }
public boolean frozen() {
return frozen;
}
@Override @Override
public List<Attribute> output() { public List<Attribute> output() {
return attrs; return attrs;
@ -75,7 +81,7 @@ public class EsRelation extends LeafPlan {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(index); return Objects.hash(index, frozen);
} }
@Override @Override
@ -89,7 +95,8 @@ public class EsRelation extends LeafPlan {
} }
EsRelation other = (EsRelation) obj; EsRelation other = (EsRelation) obj;
return Objects.equals(index, other.index); return Objects.equals(index, other.index)
&& frozen == other.frozen;
} }
private static final int TO_STRING_LIMIT = 52; private static final int TO_STRING_LIMIT = 52;

View File

@ -20,23 +20,25 @@ import static java.util.Collections.singletonList;
public class UnresolvedRelation extends LeafPlan implements Unresolvable { public class UnresolvedRelation extends LeafPlan implements Unresolvable {
private final TableIdentifier table; private final TableIdentifier table;
private final boolean frozen;
private final String alias; private final String alias;
private final String unresolvedMsg; private final String unresolvedMsg;
public UnresolvedRelation(Source source, TableIdentifier table, String alias) { public UnresolvedRelation(Source source, TableIdentifier table, String alias, boolean frozen) {
this(source, table, alias, null); this(source, table, alias, frozen, null);
} }
public UnresolvedRelation(Source source, TableIdentifier table, String alias, String unresolvedMessage) { public UnresolvedRelation(Source source, TableIdentifier table, String alias, boolean frozen, String unresolvedMessage) {
super(source); super(source);
this.table = table; this.table = table;
this.alias = alias; this.alias = alias;
this.frozen = frozen;
this.unresolvedMsg = unresolvedMessage == null ? "Unknown index [" + table.index() + "]" : unresolvedMessage; this.unresolvedMsg = unresolvedMessage == null ? "Unknown index [" + table.index() + "]" : unresolvedMessage;
} }
@Override @Override
protected NodeInfo<UnresolvedRelation> info() { protected NodeInfo<UnresolvedRelation> info() {
return NodeInfo.create(this, UnresolvedRelation::new, table, alias, unresolvedMsg); return NodeInfo.create(this, UnresolvedRelation::new, table, alias, frozen, unresolvedMsg);
} }
public TableIdentifier table() { public TableIdentifier table() {
@ -47,6 +49,10 @@ public class UnresolvedRelation extends LeafPlan implements Unresolvable {
return alias; return alias;
} }
public boolean frozen() {
return frozen;
}
@Override @Override
public boolean resolved() { public boolean resolved() {
return false; return false;
@ -86,6 +92,7 @@ public class UnresolvedRelation extends LeafPlan implements Unresolvable {
return source().equals(other.source()) return source().equals(other.source())
&& table.equals(other.table) && table.equals(other.table)
&& Objects.equals(alias, other.alias) && Objects.equals(alias, other.alias)
&& Objects.equals(frozen, other.frozen)
&& unresolvedMsg.equals(other.unresolvedMsg); && unresolvedMsg.equals(other.unresolvedMsg);
} }

View File

@ -31,11 +31,13 @@ public class ShowColumns extends Command {
private final String index; private final String index;
private final LikePattern pattern; private final LikePattern pattern;
private final boolean includeFrozen;
public ShowColumns(Source source, String index, LikePattern pattern) { public ShowColumns(Source source, String index, LikePattern pattern, boolean includeFrozen) {
super(source); super(source);
this.index = index; this.index = index;
this.pattern = pattern; this.pattern = pattern;
this.includeFrozen = includeFrozen;
} }
public String index() { public String index() {
@ -48,7 +50,7 @@ public class ShowColumns extends Command {
@Override @Override
protected NodeInfo<ShowColumns> info() { protected NodeInfo<ShowColumns> info() {
return NodeInfo.create(this, ShowColumns::new, index, pattern); return NodeInfo.create(this, ShowColumns::new, index, pattern, includeFrozen);
} }
@Override @Override
@ -62,7 +64,9 @@ public class ShowColumns extends Command {
public void execute(SqlSession session, ActionListener<SchemaRowSet> listener) { public void execute(SqlSession session, ActionListener<SchemaRowSet> listener) {
String idx = index != null ? index : (pattern != null ? pattern.asIndexNameWildcard() : "*"); String idx = index != null ? index : (pattern != null ? pattern.asIndexNameWildcard() : "*");
String regex = pattern != null ? pattern.asJavaRegex() : null; String regex = pattern != null ? pattern.asJavaRegex() : null;
session.indexResolver().resolveAsMergedMapping(idx, regex, ActionListener.wrap(
boolean withFrozen = includeFrozen || session.configuration().includeFrozen();
session.indexResolver().resolveAsMergedMapping(idx, regex, withFrozen, ActionListener.wrap(
indexResult -> { indexResult -> {
List<List<?>> rows = emptyList(); List<List<?>> rows = emptyList();
if (indexResult.isValid()) { if (indexResult.isValid()) {
@ -92,7 +96,7 @@ public class ShowColumns extends Command {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(index, pattern); return Objects.hash(index, pattern, includeFrozen);
} }
@Override @Override
@ -107,6 +111,7 @@ 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(pattern, other.pattern); && Objects.equals(pattern, other.pattern)
&& includeFrozen == other.includeFrozen;
} }
} }

View File

@ -6,14 +6,16 @@
package org.elasticsearch.xpack.sql.plan.logical.command; package org.elasticsearch.xpack.sql.plan.logical.command;
import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionListener;
import org.elasticsearch.xpack.sql.analysis.index.IndexResolver.IndexType;
import org.elasticsearch.xpack.sql.expression.Attribute; import org.elasticsearch.xpack.sql.expression.Attribute;
import org.elasticsearch.xpack.sql.expression.predicate.regex.LikePattern; import org.elasticsearch.xpack.sql.expression.predicate.regex.LikePattern;
import org.elasticsearch.xpack.sql.session.Rows; import org.elasticsearch.xpack.sql.session.Rows;
import org.elasticsearch.xpack.sql.session.SchemaRowSet; import org.elasticsearch.xpack.sql.session.SchemaRowSet;
import org.elasticsearch.xpack.sql.session.SqlSession; import org.elasticsearch.xpack.sql.session.SqlSession;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.tree.NodeInfo; import org.elasticsearch.xpack.sql.tree.NodeInfo;
import org.elasticsearch.xpack.sql.tree.Source;
import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -24,16 +26,18 @@ public class ShowTables extends Command {
private final String index; private final String index;
private final LikePattern pattern; private final LikePattern pattern;
private final boolean includeFrozen;
public ShowTables(Source source, String index, LikePattern pattern) { public ShowTables(Source source, String index, LikePattern pattern, boolean includeFrozen) {
super(source); super(source);
this.index = index; this.index = index;
this.pattern = pattern; this.pattern = pattern;
this.includeFrozen = includeFrozen;
} }
@Override @Override
protected NodeInfo<ShowTables> info() { protected NodeInfo<ShowTables> info() {
return NodeInfo.create(this, ShowTables::new, index, pattern); return NodeInfo.create(this, ShowTables::new, index, pattern, includeFrozen);
} }
public String index() { public String index() {
@ -46,23 +50,28 @@ public class ShowTables extends Command {
@Override @Override
public List<Attribute> output() { public List<Attribute> output() {
return asList(keyword("name"), keyword("type")); return asList(keyword("name"), keyword("type"), keyword("kind"));
} }
@Override @Override
public final void execute(SqlSession session, ActionListener<SchemaRowSet> listener) { public final void execute(SqlSession session, ActionListener<SchemaRowSet> listener) {
String idx = index != null ? index : (pattern != null ? pattern.asIndexNameWildcard() : "*"); String idx = index != null ? index : (pattern != null ? pattern.asIndexNameWildcard() : "*");
String regex = pattern != null ? pattern.asJavaRegex() : null; String regex = pattern != null ? pattern.asJavaRegex() : null;
session.indexResolver().resolveNames(idx, regex, null, ActionListener.wrap(result -> {
// to avoid redundancy, indicate whether frozen fields are required by specifying the type
EnumSet<IndexType> withFrozen = session.configuration().includeFrozen() || includeFrozen ?
IndexType.VALID_INCLUDE_FROZEN : IndexType.VALID_REGULAR;
session.indexResolver().resolveNames(idx, regex, withFrozen, ActionListener.wrap(result -> {
listener.onResponse(Rows.of(output(), result.stream() listener.onResponse(Rows.of(output(), result.stream()
.map(t -> asList(t.name(), t.type().toSql())) .map(t -> asList(t.name(), t.type().toSql(), t.type().toNative()))
.collect(toList()))); .collect(toList())));
}, listener::onFailure)); }, listener::onFailure));
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(index, pattern); return Objects.hash(index, pattern, includeFrozen);
} }
@Override @Override
@ -76,7 +85,8 @@ public class ShowTables extends Command {
} }
ShowTables other = (ShowTables) obj; ShowTables other = (ShowTables) obj;
return Objects.equals(index, other.index) return Objects.equals(index, other.index)
&& Objects.equals(pattern, other.pattern); && Objects.equals(pattern, other.pattern)
&& includeFrozen == other.includeFrozen;
} }
} }

View File

@ -109,16 +109,17 @@ public class SysColumns extends Command {
} }
// save original index name (as the pattern can contain special chars) // save original index name (as the pattern can contain special chars)
String indexName = index != null ? index : (pattern != null ? StringUtils.likeToUnescaped(pattern.pattern(), String indexName = index != null ? index :
pattern.escape()) : ""); (pattern != null ? StringUtils.likeToUnescaped(pattern.pattern(), pattern.escape()) : "");
String idx = index != null ? index : (pattern != null ? pattern.asIndexNameWildcard() : "*"); String idx = index != null ? index : (pattern != null ? pattern.asIndexNameWildcard() : "*");
String regex = pattern != null ? pattern.asJavaRegex() : null; String regex = pattern != null ? pattern.asJavaRegex() : null;
Pattern columnMatcher = columnPattern != null ? Pattern.compile(columnPattern.asJavaRegex()) : null; Pattern columnMatcher = columnPattern != null ? Pattern.compile(columnPattern.asJavaRegex()) : null;
boolean includeFrozen = session.configuration().includeFrozen();
// special case for '%' (translated to *) // special case for '%' (translated to *)
if ("*".equals(idx)) { if ("*".equals(idx)) {
session.indexResolver().resolveAsSeparateMappings(idx, regex, ActionListener.wrap(esIndices -> { session.indexResolver().resolveAsSeparateMappings(idx, regex, includeFrozen, ActionListener.wrap(esIndices -> {
List<List<?>> rows = new ArrayList<>(); List<List<?>> rows = new ArrayList<>();
for (EsIndex esIndex : esIndices) { for (EsIndex esIndex : esIndices) {
fillInRows(cluster, esIndex.name(), esIndex.mapping(), null, rows, columnMatcher, mode); fillInRows(cluster, esIndex.name(), esIndex.mapping(), null, rows, columnMatcher, mode);
@ -129,7 +130,7 @@ public class SysColumns extends Command {
} }
// otherwise use a merged mapping // otherwise use a merged mapping
else { else {
session.indexResolver().resolveAsMergedMapping(idx, regex, ActionListener.wrap(r -> { session.indexResolver().resolveAsMergedMapping(idx, regex, includeFrozen, ActionListener.wrap(r -> {
List<List<?>> rows = new ArrayList<>(); List<List<?>> rows = new ArrayList<>();
// populate the data only when a target is found // populate the data only when a target is found
if (r.isValid() == true) { if (r.isValid() == true) {

View File

@ -22,6 +22,7 @@ import java.util.Comparator;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
@ -89,6 +90,8 @@ public class SysTables extends Command {
} }
} }
boolean includeFrozen = session.configuration().includeFrozen();
// enumerate types // enumerate types
// if no types are specified (the parser takes care of the % case) // if no types are specified (the parser takes care of the % case)
if (types == null) { if (types == null) {
@ -98,7 +101,10 @@ public class SysTables extends Command {
&& pattern != null && pattern.pattern().isEmpty() && index == null) { && pattern != null && pattern.pattern().isEmpty() && index == null) {
List<List<?>> values = new ArrayList<>(); List<List<?>> values = new ArrayList<>();
// send only the types, everything else is made of empty strings // send only the types, everything else is made of empty strings
for (IndexType type : IndexType.VALID) { // NB: since the types are sent in SQL, frozen doesn't have to be taken into account since
// it's just another BASE TABLE
Set<IndexType> typeSet = IndexType.VALID_REGULAR;
for (IndexType type : typeSet) {
Object[] enumeration = new Object[10]; Object[] enumeration = new Object[10];
enumeration[3] = type.toSql(); enumeration[3] = type.toSql();
values.add(asList(enumeration)); values.add(asList(enumeration));
@ -110,6 +116,7 @@ public class SysTables extends Command {
} }
} }
// no enumeration pattern found, list actual tables // no enumeration pattern found, list actual tables
String cRegex = clusterPattern != null ? clusterPattern.asJavaRegex() : null; String cRegex = clusterPattern != null ? clusterPattern.asJavaRegex() : null;
@ -122,7 +129,18 @@ public class SysTables extends Command {
String idx = index != null ? index : (pattern != null ? pattern.asIndexNameWildcard() : "*"); String idx = index != null ? index : (pattern != null ? pattern.asIndexNameWildcard() : "*");
String regex = pattern != null ? pattern.asJavaRegex() : null; String regex = pattern != null ? pattern.asJavaRegex() : null;
session.indexResolver().resolveNames(idx, regex, types, ActionListener.wrap(result -> listener.onResponse( EnumSet<IndexType> tableTypes = types;
// initialize types for name resolution
if (tableTypes == null) {
tableTypes = includeFrozen ? IndexType.VALID_INCLUDE_FROZEN : IndexType.VALID_REGULAR;
} else {
if (includeFrozen && tableTypes.contains(IndexType.FROZEN_INDEX) == false) {
tableTypes.add(IndexType.FROZEN_INDEX);
}
}
session.indexResolver().resolveNames(idx, regex, tableTypes, ActionListener.wrap(result -> listener.onResponse(
Rows.of(output(), result.stream() Rows.of(output(), result.stream()
// sort by type (which might be legacy), then by name // sort by type (which might be legacy), then by name
.sorted(Comparator.<IndexInfo, String> comparing(i -> legacyName(i.type())) .sorted(Comparator.<IndexInfo, String> comparing(i -> legacyName(i.type()))
@ -142,7 +160,7 @@ public class SysTables extends Command {
} }
private String legacyName(IndexType indexType) { private String legacyName(IndexType indexType) {
return legacyTableTypes && indexType == IndexType.INDEX ? "TABLE" : indexType.toSql(); return legacyTableTypes && IndexType.INDICES_ONLY.contains(indexType) ? IndexType.SQL_TABLE : indexType.toSql();
} }
@Override @Override

View File

@ -11,10 +11,10 @@ import org.elasticsearch.xpack.sql.plan.logical.EsRelation;
import org.elasticsearch.xpack.sql.plan.logical.Filter; import org.elasticsearch.xpack.sql.plan.logical.Filter;
import org.elasticsearch.xpack.sql.plan.logical.Join; import org.elasticsearch.xpack.sql.plan.logical.Join;
import org.elasticsearch.xpack.sql.plan.logical.Limit; import org.elasticsearch.xpack.sql.plan.logical.Limit;
import org.elasticsearch.xpack.sql.plan.logical.LocalRelation;
import org.elasticsearch.xpack.sql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.sql.plan.logical.LogicalPlan;
import org.elasticsearch.xpack.sql.plan.logical.OrderBy; import org.elasticsearch.xpack.sql.plan.logical.OrderBy;
import org.elasticsearch.xpack.sql.plan.logical.Project; import org.elasticsearch.xpack.sql.plan.logical.Project;
import org.elasticsearch.xpack.sql.plan.logical.LocalRelation;
import org.elasticsearch.xpack.sql.plan.logical.With; import org.elasticsearch.xpack.sql.plan.logical.With;
import org.elasticsearch.xpack.sql.plan.logical.command.Command; import org.elasticsearch.xpack.sql.plan.logical.command.Command;
import org.elasticsearch.xpack.sql.plan.physical.AggregateExec; import org.elasticsearch.xpack.sql.plan.physical.AggregateExec;
@ -22,10 +22,10 @@ import org.elasticsearch.xpack.sql.plan.physical.CommandExec;
import org.elasticsearch.xpack.sql.plan.physical.EsQueryExec; import org.elasticsearch.xpack.sql.plan.physical.EsQueryExec;
import org.elasticsearch.xpack.sql.plan.physical.FilterExec; import org.elasticsearch.xpack.sql.plan.physical.FilterExec;
import org.elasticsearch.xpack.sql.plan.physical.LimitExec; import org.elasticsearch.xpack.sql.plan.physical.LimitExec;
import org.elasticsearch.xpack.sql.plan.physical.LocalExec;
import org.elasticsearch.xpack.sql.plan.physical.OrderExec; import org.elasticsearch.xpack.sql.plan.physical.OrderExec;
import org.elasticsearch.xpack.sql.plan.physical.PhysicalPlan; import org.elasticsearch.xpack.sql.plan.physical.PhysicalPlan;
import org.elasticsearch.xpack.sql.plan.physical.ProjectExec; import org.elasticsearch.xpack.sql.plan.physical.ProjectExec;
import org.elasticsearch.xpack.sql.plan.physical.LocalExec;
import org.elasticsearch.xpack.sql.plan.physical.UnplannedExec; import org.elasticsearch.xpack.sql.plan.physical.UnplannedExec;
import org.elasticsearch.xpack.sql.querydsl.container.QueryContainer; import org.elasticsearch.xpack.sql.querydsl.container.QueryContainer;
import org.elasticsearch.xpack.sql.rule.Rule; import org.elasticsearch.xpack.sql.rule.Rule;
@ -91,7 +91,11 @@ class Mapper extends RuleExecutor<PhysicalPlan> {
if (p instanceof EsRelation) { if (p instanceof EsRelation) {
EsRelation c = (EsRelation) p; EsRelation c = (EsRelation) p;
List<Attribute> output = c.output(); List<Attribute> output = c.output();
return new EsQueryExec(p.source(), c.index().name(), output, new QueryContainer()); QueryContainer container = new QueryContainer();
if (c.frozen()) {
container = container.withFrozen();
}
return new EsQueryExec(p.source(), c.index().name(), output, container);
} }
if (p instanceof Limit) { if (p instanceof Limit) {

View File

@ -149,7 +149,8 @@ class QueryFolder extends RuleExecutor<PhysicalPlan> {
new AttributeMap<>(processors), new AttributeMap<>(processors),
queryC.sort(), queryC.sort(),
queryC.limit(), queryC.limit(),
queryC.shouldTrackHits()); queryC.shouldTrackHits(),
queryC.shouldIncludeFrozen());
return new EsQueryExec(exec.source(), exec.index(), project.output(), clone); return new EsQueryExec(exec.source(), exec.index(), project.output(), clone);
} }
return project; return project;
@ -178,7 +179,8 @@ class QueryFolder extends RuleExecutor<PhysicalPlan> {
qContainer.scalarFunctions(), qContainer.scalarFunctions(),
qContainer.sort(), qContainer.sort(),
qContainer.limit(), qContainer.limit(),
qContainer.shouldTrackHits()); qContainer.shouldTrackHits(),
qContainer.shouldIncludeFrozen());
return exec.with(qContainer); return exec.with(qContainer);
} }

View File

@ -137,5 +137,4 @@ public class RestSqlQueryAction extends BaseRestHandler {
public String getName() { public String getName() {
return "sql_query"; return "sql_query";
} }
} }

View File

@ -47,7 +47,8 @@ public class TransportSqlClearCursorAction extends HandledTransportAction<SqlCle
Cursor cursor = Cursors.decodeFromString(request.getCursor()); Cursor cursor = Cursors.decodeFromString(request.getCursor());
planExecutor.cleanCursor( planExecutor.cleanCursor(
new Configuration(DateUtils.UTC, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, new Configuration(DateUtils.UTC, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null,
request.mode(), StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, Protocol.FIELD_MULTI_VALUE_LENIENCY), request.mode(), StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, Protocol.FIELD_MULTI_VALUE_LENIENCY,
Protocol.INDEX_INCLUDE_FROZEN),
cursor, ActionListener.wrap( cursor, ActionListener.wrap(
success -> listener.onResponse(new SqlClearCursorResponse(success)), listener::onFailure)); success -> listener.onResponse(new SqlClearCursorResponse(success)), listener::onFailure));
} }

View File

@ -72,7 +72,8 @@ public class TransportSqlQueryAction extends HandledTransportAction<SqlQueryRequ
// The configuration is always created however when dealing with the next page, only the timeouts are relevant // The configuration is always created however when dealing with the next page, only the timeouts are relevant
// the rest having default values (since the query is already created) // the rest having default values (since the query is already created)
Configuration cfg = new Configuration(request.zoneId(), request.fetchSize(), request.requestTimeout(), request.pageTimeout(), Configuration cfg = new Configuration(request.zoneId(), request.fetchSize(), request.requestTimeout(), request.pageTimeout(),
request.filter(), request.mode(), request.clientId(), username, clusterName, request.fieldMultiValueLeniency()); request.filter(), request.mode(), request.clientId(), username, clusterName, request.fieldMultiValueLeniency(),
request.indexIncludeFrozen());
if (Strings.hasText(request.cursor()) == false) { if (Strings.hasText(request.cursor()) == false) {
planExecutor.sql(cfg, request.query(), request.params(), planExecutor.sql(cfg, request.query(), request.params(),

View File

@ -56,7 +56,8 @@ public class TransportSqlTranslateAction extends HandledTransportAction<SqlTrans
Configuration cfg = new Configuration(request.zoneId(), request.fetchSize(), Configuration cfg = new Configuration(request.zoneId(), request.fetchSize(),
request.requestTimeout(), request.pageTimeout(), request.filter(), request.requestTimeout(), request.pageTimeout(), request.filter(),
request.mode(), request.clientId(), request.mode(), request.clientId(),
username(securityContext), clusterName(clusterService), Protocol.FIELD_MULTI_VALUE_LENIENCY); username(securityContext), clusterName(clusterService), Protocol.FIELD_MULTI_VALUE_LENIENCY,
Protocol.INDEX_INCLUDE_FROZEN);
planExecutor.searchSource(cfg, request.query(), request.params(), ActionListener.wrap( planExecutor.searchSource(cfg, request.query(), request.params(), ActionListener.wrap(
searchSourceBuilder -> listener.onResponse(new SqlTranslateResponse(searchSourceBuilder)), listener::onFailure)); searchSourceBuilder -> listener.onResponse(new SqlTranslateResponse(searchSourceBuilder)), listener::onFailure));

View File

@ -81,25 +81,27 @@ public class QueryContainer {
private final Set<Sort> sort; private final Set<Sort> sort;
private final int limit; private final int limit;
private final boolean trackHits; private final boolean trackHits;
private final boolean includeFrozen;
// computed // computed
private Boolean aggsOnly; private Boolean aggsOnly;
private Boolean customSort; private Boolean customSort;
public QueryContainer() { public QueryContainer() {
this(null, null, null, null, null, null, null, -1, false); this(null, null, null, null, null, null, null, -1, false, false);
} }
public QueryContainer(Query query, public QueryContainer(Query query,
Aggs aggs, Aggs aggs,
List<Tuple<FieldExtraction, List<Tuple<FieldExtraction,
ExpressionId>> fields, ExpressionId>> fields,
AttributeMap<Attribute> aliases, AttributeMap<Attribute> aliases,
Map<String, GroupByKey> pseudoFunctions, Map<String, GroupByKey> pseudoFunctions,
AttributeMap<Pipe> scalarFunctions, AttributeMap<Pipe> scalarFunctions,
Set<Sort> sort, Set<Sort> sort,
int limit, int limit,
boolean trackHits) { boolean trackHits,
boolean includeFrozen) {
this.query = query; this.query = query;
this.aggs = aggs == null ? Aggs.EMPTY : aggs; this.aggs = aggs == null ? Aggs.EMPTY : aggs;
this.fields = fields == null || fields.isEmpty() ? emptyList() : fields; this.fields = fields == null || fields.isEmpty() ? emptyList() : fields;
@ -109,6 +111,7 @@ public class QueryContainer {
this.sort = sort == null || sort.isEmpty() ? emptySet() : sort; this.sort = sort == null || sort.isEmpty() ? emptySet() : sort;
this.limit = limit; this.limit = limit;
this.trackHits = trackHits; this.trackHits = trackHits;
this.includeFrozen = includeFrozen;
} }
/** /**
@ -237,42 +240,53 @@ public class QueryContainer {
return trackHits; return trackHits;
} }
public boolean shouldIncludeFrozen() {
return includeFrozen;
}
// //
// copy methods // copy methods
// //
public QueryContainer with(Query q) { public QueryContainer with(Query q) {
return new QueryContainer(q, aggs, fields, aliases, pseudoFunctions, scalarFunctions, sort, limit, trackHits); return new QueryContainer(q, aggs, fields, aliases, pseudoFunctions, scalarFunctions, sort, limit, trackHits, includeFrozen);
} }
public QueryContainer withAliases(AttributeMap<Attribute> a) { public QueryContainer withAliases(AttributeMap<Attribute> a) {
return new QueryContainer(query, aggs, fields, a, pseudoFunctions, scalarFunctions, sort, limit, trackHits); return new QueryContainer(query, aggs, fields, a, pseudoFunctions, scalarFunctions, sort, limit, trackHits, includeFrozen);
} }
public QueryContainer withPseudoFunctions(Map<String, GroupByKey> p) { public QueryContainer withPseudoFunctions(Map<String, GroupByKey> p) {
return new QueryContainer(query, aggs, fields, aliases, p, scalarFunctions, sort, limit, trackHits); return new QueryContainer(query, aggs, fields, aliases, p, scalarFunctions, sort, limit, trackHits, includeFrozen);
} }
public QueryContainer with(Aggs a) { public QueryContainer with(Aggs a) {
return new QueryContainer(query, a, fields, aliases, pseudoFunctions, scalarFunctions, sort, limit, trackHits); return new QueryContainer(query, a, fields, aliases, pseudoFunctions, scalarFunctions, sort, limit, trackHits, includeFrozen);
} }
public QueryContainer withLimit(int l) { public QueryContainer withLimit(int l) {
return l == limit ? this : new QueryContainer(query, aggs, fields, aliases, pseudoFunctions, scalarFunctions, sort, l, trackHits); return l == limit ? this : new QueryContainer(query, aggs, fields, aliases, pseudoFunctions, scalarFunctions, sort, l, trackHits,
includeFrozen);
} }
public QueryContainer withTrackHits() { public QueryContainer withTrackHits() {
return trackHits ? this : new QueryContainer(query, aggs, fields, aliases, pseudoFunctions, scalarFunctions, sort, limit, true); return trackHits ? this : new QueryContainer(query, aggs, fields, aliases, pseudoFunctions, scalarFunctions, sort, limit, true,
includeFrozen);
}
public QueryContainer withFrozen() {
return includeFrozen ? this : new QueryContainer(query, aggs, fields, aliases, pseudoFunctions, scalarFunctions, sort, limit,
trackHits, true);
} }
public QueryContainer withScalarProcessors(AttributeMap<Pipe> procs) { public QueryContainer withScalarProcessors(AttributeMap<Pipe> procs) {
return new QueryContainer(query, aggs, fields, aliases, pseudoFunctions, procs, sort, limit, trackHits); return new QueryContainer(query, aggs, fields, aliases, pseudoFunctions, procs, sort, limit, trackHits, includeFrozen);
} }
public QueryContainer addSort(Sort sortable) { public QueryContainer addSort(Sort sortable) {
Set<Sort> sort = new LinkedHashSet<>(this.sort); Set<Sort> sort = new LinkedHashSet<>(this.sort);
sort.add(sortable); sort.add(sortable);
return new QueryContainer(query, aggs, fields, aliases, pseudoFunctions, scalarFunctions, sort, limit, trackHits); return new QueryContainer(query, aggs, fields, aliases, pseudoFunctions, scalarFunctions, sort, limit, trackHits, includeFrozen);
} }
private String aliasName(Attribute attr) { private String aliasName(Attribute attr) {
@ -294,7 +308,8 @@ public class QueryContainer {
SearchHitFieldRef nestedFieldRef = new SearchHitFieldRef(name, attr.field().getDataType(), SearchHitFieldRef nestedFieldRef = new SearchHitFieldRef(name, attr.field().getDataType(),
attr.field().isAggregatable(), attr.parent().name()); attr.field().isAggregatable(), attr.parent().name());
return new Tuple<>(new QueryContainer(q, aggs, fields, aliases, pseudoFunctions, scalarFunctions, sort, limit, trackHits), return new Tuple<>(
new QueryContainer(q, aggs, fields, aliases, pseudoFunctions, scalarFunctions, sort, limit, trackHits, includeFrozen),
nestedFieldRef); nestedFieldRef);
} }
@ -397,7 +412,7 @@ public class QueryContainer {
ExpressionId id = attr instanceof AggregateFunctionAttribute ? ((AggregateFunctionAttribute) attr).innerId() : attr.id(); ExpressionId id = attr instanceof AggregateFunctionAttribute ? ((AggregateFunctionAttribute) attr).innerId() : attr.id();
return new QueryContainer(query, aggs, combine(fields, new Tuple<>(ref, id)), aliases, pseudoFunctions, return new QueryContainer(query, aggs, combine(fields, new Tuple<>(ref, id)), aliases, pseudoFunctions,
scalarFunctions, scalarFunctions,
sort, limit, trackHits); sort, limit, trackHits, includeFrozen);
} }
public AttributeMap<Pipe> scalarFunctions() { public AttributeMap<Pipe> scalarFunctions() {
@ -430,7 +445,7 @@ public class QueryContainer {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(query, aggs, fields, aliases, sort, limit); return Objects.hash(query, aggs, fields, aliases, sort, limit, trackHits, includeFrozen);
} }
@Override @Override
@ -449,7 +464,9 @@ public class QueryContainer {
&& Objects.equals(fields, other.fields) && Objects.equals(fields, other.fields)
&& Objects.equals(aliases, other.aliases) && Objects.equals(aliases, other.aliases)
&& Objects.equals(sort, other.sort) && Objects.equals(sort, other.sort)
&& Objects.equals(limit, other.limit); && Objects.equals(limit, other.limit)
&& Objects.equals(trackHits, other.trackHits)
&& Objects.equals(includeFrozen, other.includeFrozen);
} }
@Override @Override

View File

@ -25,6 +25,7 @@ public class Configuration {
private final String clusterName; private final String clusterName;
private final boolean multiValueFieldLeniency; private final boolean multiValueFieldLeniency;
private final ZonedDateTime now; private final ZonedDateTime now;
private final boolean includeFrozenIndices;
@Nullable @Nullable
private QueryBuilder filter; private QueryBuilder filter;
@ -32,7 +33,8 @@ public class Configuration {
public Configuration(ZoneId zi, int pageSize, TimeValue requestTimeout, TimeValue pageTimeout, QueryBuilder filter, public Configuration(ZoneId zi, int pageSize, TimeValue requestTimeout, TimeValue pageTimeout, QueryBuilder filter,
Mode mode, String clientId, Mode mode, String clientId,
String username, String clusterName, String username, String clusterName,
boolean multiValueFieldLeniency) { boolean multiValueFieldLeniency,
boolean includeFrozen) {
this.zoneId = zi.normalized(); this.zoneId = zi.normalized();
this.pageSize = pageSize; this.pageSize = pageSize;
this.requestTimeout = requestTimeout; this.requestTimeout = requestTimeout;
@ -44,6 +46,7 @@ public class Configuration {
this.clusterName = clusterName; this.clusterName = clusterName;
this.multiValueFieldLeniency = multiValueFieldLeniency; this.multiValueFieldLeniency = multiValueFieldLeniency;
this.now = ZonedDateTime.now(zoneId); this.now = ZonedDateTime.now(zoneId);
this.includeFrozenIndices = includeFrozen;
} }
public ZoneId zoneId() { public ZoneId zoneId() {
@ -80,7 +83,7 @@ public class Configuration {
public String clusterName() { public String clusterName() {
return clusterName; return clusterName;
} }
public ZonedDateTime now() { public ZonedDateTime now() {
return now; return now;
} }
@ -88,4 +91,8 @@ public class Configuration {
public boolean multiValueFieldLeniency() { public boolean multiValueFieldLeniency() {
return multiValueFieldLeniency; return multiValueFieldLeniency;
} }
public boolean includeFrozen() {
return includeFrozenIndices;
}
} }

View File

@ -11,6 +11,7 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer; import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer;
import org.elasticsearch.xpack.sql.analysis.analyzer.PreAnalyzer; import org.elasticsearch.xpack.sql.analysis.analyzer.PreAnalyzer;
import org.elasticsearch.xpack.sql.analysis.analyzer.PreAnalyzer.PreAnalysis; import org.elasticsearch.xpack.sql.analysis.analyzer.PreAnalyzer.PreAnalysis;
import org.elasticsearch.xpack.sql.analysis.analyzer.TableInfo;
import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier; import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier;
import org.elasticsearch.xpack.sql.analysis.index.IndexResolution; import org.elasticsearch.xpack.sql.analysis.index.IndexResolution;
import org.elasticsearch.xpack.sql.analysis.index.IndexResolver; import org.elasticsearch.xpack.sql.analysis.index.IndexResolver;
@ -128,7 +129,8 @@ public class SqlSession {
// Note: JOINs are not supported but we detect them when // Note: JOINs are not supported but we detect them when
listener.onFailure(new MappingException("Queries with multiple indices are not supported")); listener.onFailure(new MappingException("Queries with multiple indices are not supported"));
} else if (preAnalysis.indices.size() == 1) { } else if (preAnalysis.indices.size() == 1) {
TableIdentifier table = preAnalysis.indices.get(0); TableInfo tableInfo = preAnalysis.indices.get(0);
TableIdentifier table = tableInfo.id();
String cluster = table.cluster(); String cluster = table.cluster();
@ -136,7 +138,8 @@ public class SqlSession {
listener.onFailure(new MappingException("Cannot inspect indices in cluster/catalog [{}]", cluster)); listener.onFailure(new MappingException("Cannot inspect indices in cluster/catalog [{}]", cluster));
} }
indexResolver.resolveAsMergedMapping(table.index(), null, boolean includeFrozen = configuration.includeFrozen() || tableInfo.isFrozen();
indexResolver.resolveAsMergedMapping(table.index(), null, includeFrozen,
wrap(indexResult -> listener.onResponse(action.apply(indexResult)), listener::onFailure)); wrap(indexResult -> listener.onResponse(action.apply(indexResult)), listener::onFailure));
} else { } else {
try { try {

View File

@ -18,6 +18,7 @@ import java.time.ZonedDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import static org.elasticsearch.test.ESTestCase.randomAlphaOfLength; import static org.elasticsearch.test.ESTestCase.randomAlphaOfLength;
import static org.elasticsearch.test.ESTestCase.randomBoolean;
import static org.elasticsearch.test.ESTestCase.randomFrom; import static org.elasticsearch.test.ESTestCase.randomFrom;
import static org.elasticsearch.test.ESTestCase.randomIntBetween; import static org.elasticsearch.test.ESTestCase.randomIntBetween;
import static org.elasticsearch.test.ESTestCase.randomNonNegativeLong; import static org.elasticsearch.test.ESTestCase.randomNonNegativeLong;
@ -30,7 +31,7 @@ public class TestUtils {
public static final Configuration TEST_CFG = new Configuration(DateUtils.UTC, Protocol.FETCH_SIZE, public static final Configuration TEST_CFG = new Configuration(DateUtils.UTC, Protocol.FETCH_SIZE,
Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, Mode.PLAIN, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, Mode.PLAIN,
null, null, null, false); null, null, null, false, false);
/** /**
* Returns the current UTC date-time with milliseconds precision. * Returns the current UTC date-time with milliseconds precision.
@ -55,7 +56,8 @@ public class TestUtils {
randomAlphaOfLength(10), randomAlphaOfLength(10),
randomAlphaOfLength(10), randomAlphaOfLength(10),
randomAlphaOfLength(10), randomAlphaOfLength(10),
false); false,
randomBoolean());
} }
public static Configuration randomConfiguration(ZoneId providedZoneId) { public static Configuration randomConfiguration(ZoneId providedZoneId) {
@ -68,7 +70,8 @@ public class TestUtils {
randomAlphaOfLength(10), randomAlphaOfLength(10),
randomAlphaOfLength(10), randomAlphaOfLength(10),
randomAlphaOfLength(10), randomAlphaOfLength(10),
false); false,
randomBoolean());
} }
} }

View File

@ -24,8 +24,8 @@ public class PreAnalyzerTests extends ESTestCase {
PreAnalysis result = preAnalyzer.preAnalyze(plan); PreAnalysis result = preAnalyzer.preAnalyze(plan);
assertThat(plan.preAnalyzed(), is(true)); assertThat(plan.preAnalyzed(), is(true));
assertThat(result.indices, hasSize(1)); assertThat(result.indices, hasSize(1));
assertThat(result.indices.get(0).cluster(), nullValue()); assertThat(result.indices.get(0).id().cluster(), nullValue());
assertThat(result.indices.get(0).index(), is("index")); assertThat(result.indices.get(0).id().index(), is("index"));
} }
public void testBasicIndexWithCatalog() { public void testBasicIndexWithCatalog() {
@ -33,8 +33,8 @@ public class PreAnalyzerTests extends ESTestCase {
PreAnalysis result = preAnalyzer.preAnalyze(plan); PreAnalysis result = preAnalyzer.preAnalyze(plan);
assertThat(plan.preAnalyzed(), is(true)); assertThat(plan.preAnalyzed(), is(true));
assertThat(result.indices, hasSize(1)); assertThat(result.indices, hasSize(1));
assertThat(result.indices.get(0).cluster(), is("elastic")); assertThat(result.indices.get(0).id().cluster(), is("elastic"));
assertThat(result.indices.get(0).index(), is("index")); assertThat(result.indices.get(0).id().index(), is("index"));
} }
public void testWildIndexWithCatalog() { public void testWildIndexWithCatalog() {
@ -42,8 +42,8 @@ public class PreAnalyzerTests extends ESTestCase {
PreAnalysis result = preAnalyzer.preAnalyze(plan); PreAnalysis result = preAnalyzer.preAnalyze(plan);
assertThat(plan.preAnalyzed(), is(true)); assertThat(plan.preAnalyzed(), is(true));
assertThat(result.indices, hasSize(1)); assertThat(result.indices, hasSize(1));
assertThat(result.indices.get(0).cluster(), is("elastic")); assertThat(result.indices.get(0).id().cluster(), is("elastic"));
assertThat(result.indices.get(0).index(), is("index*")); assertThat(result.indices.get(0).id().index(), is("index*"));
} }
public void testQuotedIndex() { public void testQuotedIndex() {
@ -51,8 +51,8 @@ public class PreAnalyzerTests extends ESTestCase {
PreAnalysis result = preAnalyzer.preAnalyze(plan); PreAnalysis result = preAnalyzer.preAnalyze(plan);
assertThat(plan.preAnalyzed(), is(true)); assertThat(plan.preAnalyzed(), is(true));
assertThat(result.indices, hasSize(1)); assertThat(result.indices, hasSize(1));
assertThat(result.indices.get(0).cluster(), nullValue()); assertThat(result.indices.get(0).id().cluster(), nullValue());
assertThat(result.indices.get(0).index(), is("aaa")); assertThat(result.indices.get(0).id().index(), is("aaa"));
} }
public void testQuotedCatalog() { public void testQuotedCatalog() {
@ -60,8 +60,8 @@ public class PreAnalyzerTests extends ESTestCase {
PreAnalysis result = preAnalyzer.preAnalyze(plan); PreAnalysis result = preAnalyzer.preAnalyze(plan);
assertThat(plan.preAnalyzed(), is(true)); assertThat(plan.preAnalyzed(), is(true));
assertThat(result.indices, hasSize(1)); assertThat(result.indices, hasSize(1));
assertThat(result.indices.get(0).cluster(), is("elastic")); assertThat(result.indices.get(0).id().cluster(), is("elastic"));
assertThat(result.indices.get(0).index(), is("aaa")); assertThat(result.indices.get(0).id().index(), is("aaa"));
} }
public void testComplicatedQuery() { public void testComplicatedQuery() {
@ -69,7 +69,7 @@ public class PreAnalyzerTests extends ESTestCase {
PreAnalysis result = preAnalyzer.preAnalyze(plan); PreAnalysis result = preAnalyzer.preAnalyze(plan);
assertThat(plan.preAnalyzed(), is(true)); assertThat(plan.preAnalyzed(), is(true));
assertThat(result.indices, hasSize(1)); assertThat(result.indices, hasSize(1));
assertThat(result.indices.get(0).cluster(), nullValue()); assertThat(result.indices.get(0).id().cluster(), nullValue());
assertThat(result.indices.get(0).index(), is("aaa")); assertThat(result.indices.get(0).id().index(), is("aaa"));
} }
} }

View File

@ -30,7 +30,7 @@ public class CompositeAggregationCursorTests extends AbstractWireSerializingTest
} }
return new CompositeAggregationCursor(new byte[randomInt(256)], extractors, randomBitSet(extractorsSize), return new CompositeAggregationCursor(new byte[randomInt(256)], extractors, randomBitSet(extractorsSize),
randomIntBetween(10, 1024), randomAlphaOfLength(5)); randomIntBetween(10, 1024), randomBoolean(), randomAlphaOfLength(5));
} }
static BucketExtractor randomBucketExtractor() { static BucketExtractor randomBucketExtractor() {
@ -46,7 +46,7 @@ public class CompositeAggregationCursorTests extends AbstractWireSerializingTest
return new CompositeAggregationCursor(instance.next(), instance.extractors(), return new CompositeAggregationCursor(instance.next(), instance.extractors(),
randomValueOtherThan(instance.mask(), () -> randomBitSet(instance.extractors().size())), randomValueOtherThan(instance.mask(), () -> randomBitSet(instance.extractors().size())),
randomValueOtherThan(instance.limit(), () -> randomIntBetween(1, 512)), randomValueOtherThan(instance.limit(), () -> randomIntBetween(1, 512)),
instance.indices()); randomBoolean(), instance.indices());
} }
@Override @Override

View File

@ -29,9 +29,9 @@ public class DatabaseFunctionTests extends ESTestCase {
EsIndex test = new EsIndex("test", TypesTests.loadMapping("mapping-basic.json", true)); EsIndex test = new EsIndex("test", TypesTests.loadMapping("mapping-basic.json", true));
Analyzer analyzer = new Analyzer( Analyzer analyzer = new Analyzer(
new Configuration(DateUtils.UTC, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, new Configuration(DateUtils.UTC, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT,
Protocol.PAGE_TIMEOUT, null, Protocol.PAGE_TIMEOUT, null,
randomFrom(Mode.values()), randomAlphaOfLength(10), randomFrom(Mode.values()), randomAlphaOfLength(10),
null, clusterName, randomBoolean()), null, clusterName, randomBoolean(), randomBoolean()),
new FunctionRegistry(), new FunctionRegistry(),
IndexResolution.valid(test), IndexResolution.valid(test),
new Verifier(new Metrics()) new Verifier(new Metrics())

View File

@ -30,7 +30,8 @@ public class UserFunctionTests extends ESTestCase {
new Configuration(DateUtils.UTC, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, new Configuration(DateUtils.UTC, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT,
Protocol.PAGE_TIMEOUT, null, Protocol.PAGE_TIMEOUT, null,
randomFrom(Mode.values()), randomAlphaOfLength(10), randomFrom(Mode.values()), randomAlphaOfLength(10),
null, randomAlphaOfLengthBetween(1, 15), randomBoolean()), null, randomAlphaOfLengthBetween(1, 15),
randomBoolean(), randomBoolean()),
new FunctionRegistry(), new FunctionRegistry(),
IndexResolution.valid(test), IndexResolution.valid(test),
new Verifier(new Metrics()) new Verifier(new Metrics())

View File

@ -196,7 +196,7 @@ public class OptimizerTests extends ESTestCase {
} }
public void testPruneSubqueryAliases() { public void testPruneSubqueryAliases() {
ShowTables s = new ShowTables(EMPTY, null, null); ShowTables s = new ShowTables(EMPTY, null, null, false);
SubQueryAlias plan = new SubQueryAlias(EMPTY, s, "show"); SubQueryAlias plan = new SubQueryAlias(EMPTY, s, "show");
LogicalPlan result = new PruneSubqueryAliases().apply(plan); LogicalPlan result = new PruneSubqueryAliases().apply(plan);
assertEquals(result, s); assertEquals(result, s);

View File

@ -7,8 +7,8 @@ package org.elasticsearch.xpack.sql.plan.logical;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.plan.TableIdentifier; import org.elasticsearch.xpack.sql.plan.TableIdentifier;
import org.elasticsearch.xpack.sql.tree.SourceTests;
import org.elasticsearch.xpack.sql.tree.Source; import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.tree.SourceTests;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -23,17 +23,19 @@ public class UnresolvedRelationTests extends ESTestCase {
TableIdentifier table = new TableIdentifier(source, randomAlphaOfLength(5), randomAlphaOfLength(5)); TableIdentifier table = new TableIdentifier(source, randomAlphaOfLength(5), randomAlphaOfLength(5));
String alias = randomBoolean() ? null : randomAlphaOfLength(5); String alias = randomBoolean() ? null : randomAlphaOfLength(5);
String unresolvedMessage = randomAlphaOfLength(5); String unresolvedMessage = randomAlphaOfLength(5);
UnresolvedRelation relation = new UnresolvedRelation(source, table, alias, unresolvedMessage); UnresolvedRelation relation = new UnresolvedRelation(source, table, alias, randomBoolean(), unresolvedMessage);
List<Function<UnresolvedRelation, UnresolvedRelation>> mutators = new ArrayList<>(); List<Function<UnresolvedRelation, UnresolvedRelation>> mutators = new ArrayList<>();
mutators.add(r -> new UnresolvedRelation( mutators.add(r -> new UnresolvedRelation(
SourceTests.mutate(r.source()), SourceTests.mutate(r.source()),
r.table(), r.table(),
r.alias(), r.alias(),
r.frozen(),
r.unresolvedMessage())); r.unresolvedMessage()));
mutators.add(r -> new UnresolvedRelation( mutators.add(r -> new UnresolvedRelation(
r.source(), r.source(),
new TableIdentifier(r.source(), r.table().cluster(), r.table().index() + "m"), new TableIdentifier(r.source(), r.table().cluster(), r.table().index() + "m"),
r.alias(), r.alias(),
r.frozen(),
r.unresolvedMessage())); r.unresolvedMessage()));
mutators.add(r -> new UnresolvedRelation( mutators.add(r -> new UnresolvedRelation(
r.source(), r.source(),
@ -41,14 +43,16 @@ public class UnresolvedRelationTests extends ESTestCase {
randomValueOtherThanMany( randomValueOtherThanMany(
a -> Objects.equals(a, r.alias()), a -> Objects.equals(a, r.alias()),
() -> randomBoolean() ? null : randomAlphaOfLength(5)), () -> randomBoolean() ? null : randomAlphaOfLength(5)),
r.frozen(),
r.unresolvedMessage())); r.unresolvedMessage()));
mutators.add(r -> new UnresolvedRelation( mutators.add(r -> new UnresolvedRelation(
r.source(), r.source(),
r.table(), r.table(),
r.alias(), r.alias(),
r.frozen(),
randomValueOtherThan(r.unresolvedMessage(), () -> randomAlphaOfLength(5)))); randomValueOtherThan(r.unresolvedMessage(), () -> randomAlphaOfLength(5))));
checkEqualsAndHashCode(relation, checkEqualsAndHashCode(relation,
r -> new UnresolvedRelation(r.source(), r.table(), r.alias(), r.unresolvedMessage()), r -> new UnresolvedRelation(r.source(), r.table(), r.alias(), r.frozen(), r.unresolvedMessage()),
r -> randomFrom(mutators).apply(r)); r -> randomFrom(mutators).apply(r));
} }
} }

View File

@ -37,6 +37,7 @@ import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.elasticsearch.action.ActionListener.wrap; import static org.elasticsearch.action.ActionListener.wrap;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -47,7 +48,7 @@ public class SysColumnsTests extends ESTestCase {
private final SqlParser parser = new SqlParser(); private final SqlParser parser = new SqlParser();
private final Map<String, EsField> mapping = TypesTests.loadMapping("mapping-multi-field-with-nested.json", true); private final Map<String, EsField> mapping = TypesTests.loadMapping("mapping-multi-field-with-nested.json", true);
private final IndexInfo index = new IndexInfo("test_emp", IndexType.INDEX); private final IndexInfo index = new IndexInfo("test_emp", IndexType.STANDARD_INDEX);
private final IndexInfo alias = new IndexInfo("alias", IndexType.ALIAS); private final IndexInfo alias = new IndexInfo("alias", IndexType.ALIAS);
@ -509,9 +510,9 @@ public class SysColumnsTests extends ESTestCase {
EsIndex test = new EsIndex("test", mapping); EsIndex test = new EsIndex("test", mapping);
doAnswer(invocation -> { doAnswer(invocation -> {
((ActionListener<IndexResolution>) invocation.getArguments()[2]).onResponse(IndexResolution.valid(test)); ((ActionListener<IndexResolution>) invocation.getArguments()[3]).onResponse(IndexResolution.valid(test));
return Void.TYPE; return Void.TYPE;
}).when(resolver).resolveAsMergedMapping(any(), any(), any()); }).when(resolver).resolveAsMergedMapping(any(), any(), anyBoolean(), any());
tuple.v1().execute(tuple.v2(), wrap(consumer::accept, ex -> fail(ex.getMessage()))); tuple.v1().execute(tuple.v2(), wrap(consumer::accept, ex -> fail(ex.getMessage())));
} }

View File

@ -48,8 +48,9 @@ public class SysTablesTests extends ESTestCase {
private final SqlParser parser = new SqlParser(); private final SqlParser parser = new SqlParser();
private final Map<String, EsField> mapping = TypesTests.loadMapping("mapping-multi-field-with-nested.json", true); private final Map<String, EsField> mapping = TypesTests.loadMapping("mapping-multi-field-with-nested.json", true);
private final IndexInfo index = new IndexInfo("test", IndexType.INDEX); private final IndexInfo index = new IndexInfo("test", IndexType.STANDARD_INDEX);
private final IndexInfo alias = new IndexInfo("alias", IndexType.ALIAS); private final IndexInfo alias = new IndexInfo("alias", IndexType.ALIAS);
private final IndexInfo frozen = new IndexInfo("frozen", IndexType.FROZEN_INDEX);
// //
// catalog enumeration // catalog enumeration
@ -107,7 +108,7 @@ public class SysTablesTests extends ESTestCase {
executeCommand("SYS TABLES CATALOG LIKE '' LIKE '' TYPE '%'", r -> { executeCommand("SYS TABLES CATALOG LIKE '' LIKE '' TYPE '%'", r -> {
assertEquals(2, r.size()); assertEquals(2, r.size());
Iterator<IndexType> it = IndexType.VALID.stream().sorted(Comparator.comparing(IndexType::toSql)).iterator(); Iterator<IndexType> it = IndexType.VALID_REGULAR.stream().sorted(Comparator.comparing(IndexType::toSql)).iterator();
for (int t = 0; t < r.size(); t++) { for (int t = 0; t < r.size(); t++) {
assertEquals(it.next().toSql(), r.column(3)); assertEquals(it.next().toSql(), r.column(3));
@ -171,6 +172,20 @@ public class SysTablesTests extends ESTestCase {
}, index, alias); }, index, alias);
} }
public void testSysTablesWithProperTypesAndFrozen() throws Exception {
executeCommand("SYS TABLES TYPE 'BASE TABLE', 'ALIAS'", r -> {
assertEquals(3, r.size());
assertEquals("frozen", r.column(2));
assertEquals("BASE TABLE", r.column(3));
assertTrue(r.advanceRow());
assertEquals("test", r.column(2));
assertEquals("BASE TABLE", r.column(3));
assertTrue(r.advanceRow());
assertEquals("alias", r.column(2));
assertEquals("VIEW", r.column(3));
}, index, frozen, alias);
}
public void testSysTablesPattern() throws Exception { public void testSysTablesPattern() throws Exception {
executeCommand("SYS TABLES LIKE '%'", r -> { executeCommand("SYS TABLES LIKE '%'", r -> {
assertEquals(2, r.size()); assertEquals(2, r.size());
@ -213,6 +228,15 @@ public class SysTablesTests extends ESTestCase {
}, index); }, index);
} }
public void testSysTablesOnlyIndicesWithFrozen() throws Exception {
executeCommand("SYS TABLES LIKE 'test' TYPE 'BASE TABLE'", r -> {
assertEquals(2, r.size());
assertEquals("frozen", r.column(2));
assertTrue(r.advanceRow());
assertEquals("test", r.column(2));
}, index, frozen);
}
public void testSysTablesOnlyIndicesInLegacyMode() throws Exception { public void testSysTablesOnlyIndicesInLegacyMode() throws Exception {
executeCommand("SYS TABLES LIKE 'test' TYPE 'TABLE'", r -> { executeCommand("SYS TABLES LIKE 'test' TYPE 'TABLE'", r -> {
assertEquals(1, r.size()); assertEquals(1, r.size());