parent
8daa854f90
commit
971299baf4
|
@ -62,7 +62,7 @@ statement
|
|||
| SYS COLUMNS (CATALOG cluster=string)?
|
||||
(TABLE tableLike=likePattern | tableIdent=tableIdentifier)?
|
||||
(columnPattern=likePattern)? #sysColumns
|
||||
| SYS TYPES #sysTypes
|
||||
| SYS TYPES ((PLUS | MINUS)? type=number)? #sysTypes
|
||||
| SYS TABLE TYPES #sysTableTypes
|
||||
;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.elasticsearch.xpack.sql.parser;
|
|||
import org.antlr.v4.runtime.Token;
|
||||
import org.elasticsearch.common.Booleans;
|
||||
import org.elasticsearch.xpack.sql.analysis.index.IndexResolver.IndexType;
|
||||
import org.elasticsearch.xpack.sql.expression.Literal;
|
||||
import org.elasticsearch.xpack.sql.parser.SqlBaseParser.DebugContext;
|
||||
import org.elasticsearch.xpack.sql.parser.SqlBaseParser.ExplainContext;
|
||||
import org.elasticsearch.xpack.sql.parser.SqlBaseParser.ShowColumnsContext;
|
||||
|
@ -190,7 +191,13 @@ abstract class CommandBuilder extends LogicalPlanBuilder {
|
|||
|
||||
@Override
|
||||
public SysTypes visitSysTypes(SysTypesContext ctx) {
|
||||
return new SysTypes(source(ctx));
|
||||
int type = 0;
|
||||
if (ctx.type != null) {
|
||||
Literal value = (Literal) visit(ctx.type);
|
||||
type = ((Number) value.fold()).intValue();
|
||||
}
|
||||
|
||||
return new SysTypes(source(ctx), Integer.valueOf(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,9 +26,9 @@ import org.elasticsearch.xpack.sql.expression.function.UnresolvedFunction;
|
|||
import org.elasticsearch.xpack.sql.expression.function.scalar.Cast;
|
||||
import org.elasticsearch.xpack.sql.expression.literal.Interval;
|
||||
import org.elasticsearch.xpack.sql.expression.literal.IntervalDayTime;
|
||||
import org.elasticsearch.xpack.sql.expression.literal.IntervalYearMonth;
|
||||
import org.elasticsearch.xpack.sql.expression.literal.Intervals;
|
||||
import org.elasticsearch.xpack.sql.expression.literal.Intervals.TimeUnit;
|
||||
import org.elasticsearch.xpack.sql.expression.literal.IntervalYearMonth;
|
||||
import org.elasticsearch.xpack.sql.expression.predicate.Range;
|
||||
import org.elasticsearch.xpack.sql.expression.predicate.fulltext.MatchQueryPredicate;
|
||||
import org.elasticsearch.xpack.sql.expression.predicate.fulltext.MultiMatchQueryPredicate;
|
||||
|
@ -97,6 +97,7 @@ import org.elasticsearch.xpack.sql.parser.SqlBaseParser.StringContext;
|
|||
import org.elasticsearch.xpack.sql.parser.SqlBaseParser.StringLiteralContext;
|
||||
import org.elasticsearch.xpack.sql.parser.SqlBaseParser.StringQueryContext;
|
||||
import org.elasticsearch.xpack.sql.parser.SqlBaseParser.SubqueryExpressionContext;
|
||||
import org.elasticsearch.xpack.sql.parser.SqlBaseParser.SysTypesContext;
|
||||
import org.elasticsearch.xpack.sql.parser.SqlBaseParser.TimeEscapedLiteralContext;
|
||||
import org.elasticsearch.xpack.sql.parser.SqlBaseParser.TimestampEscapedLiteralContext;
|
||||
import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue;
|
||||
|
@ -653,12 +654,14 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
|
|||
throw new ParsingException(source(ctx), siae.getMessage());
|
||||
}
|
||||
|
||||
Object val = Long.valueOf(value);
|
||||
DataType type = DataType.LONG;
|
||||
// try to downsize to int if possible (since that's the most common type)
|
||||
if ((int) value == value) {
|
||||
type = DataType.INTEGER;
|
||||
val = Integer.valueOf((int) value);
|
||||
}
|
||||
return new Literal(source(ctx), value, type);
|
||||
return new Literal(source(ctx), val, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -836,6 +839,8 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
|
|||
} else if (parentCtx instanceof SqlBaseParser.IntervalContext) {
|
||||
IntervalContext ic = (IntervalContext) parentCtx;
|
||||
return ic.sign != null && ic.sign.getType() == SqlBaseParser.MINUS;
|
||||
} else if (parentCtx instanceof SqlBaseParser.SysTypesContext) {
|
||||
return ((SysTypesContext) parentCtx).MINUS() != null;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -28,15 +28,23 @@ import static org.elasticsearch.xpack.sql.type.DataType.BOOLEAN;
|
|||
import static org.elasticsearch.xpack.sql.type.DataType.INTEGER;
|
||||
import static org.elasticsearch.xpack.sql.type.DataType.SHORT;
|
||||
|
||||
/**
|
||||
* System command designed to be used by JDBC / ODBC for column metadata.
|
||||
* In JDBC it used for {@link DatabaseMetaData#getTypeInfo()},
|
||||
* in ODBC for <a href="https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlgettypeinfo-function">SQLGetTypeInfo</a>
|
||||
*/
|
||||
public class SysTypes extends Command {
|
||||
|
||||
public SysTypes(Location location) {
|
||||
private final Integer type;
|
||||
|
||||
public SysTypes(Location location, int type) {
|
||||
super(location);
|
||||
this.type = Integer.valueOf(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<SysTypes> info() {
|
||||
return NodeInfo.create(this);
|
||||
return NodeInfo.create(this, SysTypes::new, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -66,7 +74,11 @@ public class SysTypes extends Command {
|
|||
|
||||
@Override
|
||||
public final void execute(SqlSession session, ActionListener<SchemaRowSet> listener) {
|
||||
List<List<?>> rows = Stream.of(DataType.values())
|
||||
Stream<DataType> values = Stream.of(DataType.values());
|
||||
if (type.intValue() != 0) {
|
||||
values = values.filter(t -> type.equals(t.sqlType.getVendorTypeNumber()));
|
||||
}
|
||||
List<List<?>> rows = values
|
||||
// sort by SQL int type (that's what the JDBC/ODBC specs want) followed by name
|
||||
.sorted(Comparator.comparing((DataType t) -> t.sqlType.getVendorTypeNumber()).thenComparing(DataType::sqlName))
|
||||
.map(t -> asList(t.esType.toUpperCase(Locale.ROOT),
|
||||
|
@ -105,7 +117,7 @@ public class SysTypes extends Command {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getClass().hashCode();
|
||||
return type.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -118,6 +130,6 @@ public class SysTypes extends Command {
|
|||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return type.equals(((SysTypes) obj).type);
|
||||
}
|
||||
}
|
|
@ -39,14 +39,15 @@ public class SysTableTypesTests extends ESTestCase {
|
|||
return new Tuple<>(cmd, session);
|
||||
}
|
||||
|
||||
public void testSysCatalogs() throws Exception {
|
||||
public void testSysTableTypes() throws Exception {
|
||||
Tuple<Command, SqlSession> sql = sql("SYS TABLE TYPES");
|
||||
|
||||
sql.v1().execute(sql.v2(), ActionListener.wrap(r -> {
|
||||
assertEquals(2, r.size());
|
||||
assertEquals("ALIAS", r.column(0));
|
||||
r.advanceRow();
|
||||
assertTrue(r.advanceRow());
|
||||
assertEquals("BASE TABLE", r.column(0));
|
||||
}, ex -> fail(ex.getMessage())));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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.plan.logical.command.sys;
|
||||
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer;
|
||||
import org.elasticsearch.xpack.sql.analysis.index.EsIndex;
|
||||
import org.elasticsearch.xpack.sql.analysis.index.IndexResolution;
|
||||
import org.elasticsearch.xpack.sql.analysis.index.IndexResolver;
|
||||
import org.elasticsearch.xpack.sql.expression.function.FunctionRegistry;
|
||||
import org.elasticsearch.xpack.sql.parser.SqlParser;
|
||||
import org.elasticsearch.xpack.sql.plan.logical.command.Command;
|
||||
import org.elasticsearch.xpack.sql.session.SqlSession;
|
||||
import org.elasticsearch.xpack.sql.type.DataType;
|
||||
import org.elasticsearch.xpack.sql.type.TypesTests;
|
||||
|
||||
import java.sql.JDBCType;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.elasticsearch.action.ActionListener.wrap;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class SysTypesTests extends ESTestCase {
|
||||
|
||||
private final SqlParser parser = new SqlParser();
|
||||
|
||||
private Tuple<Command, SqlSession> sql(String sql) {
|
||||
EsIndex test = new EsIndex("test", TypesTests.loadMapping("mapping-multi-field-with-nested.json", true));
|
||||
Analyzer analyzer = new Analyzer(new FunctionRegistry(), IndexResolution.valid(test), TimeZone.getTimeZone("UTC"));
|
||||
Command cmd = (Command) analyzer.analyze(parser.createStatement(sql), true);
|
||||
|
||||
IndexResolver resolver = mock(IndexResolver.class);
|
||||
SqlSession session = new SqlSession(null, null, null, resolver, null, null, null);
|
||||
return new Tuple<>(cmd, session);
|
||||
}
|
||||
|
||||
public void testSysTypes() throws Exception {
|
||||
Command cmd = sql("SYS TYPES").v1();
|
||||
|
||||
List<String> names = asList("BYTE", "LONG", "BINARY", "NULL", "INTEGER", "SHORT", "HALF_FLOAT", "SCALED_FLOAT", "FLOAT", "DOUBLE",
|
||||
"KEYWORD", "TEXT", "IP", "BOOLEAN", "DATE",
|
||||
"INTERVAL_YEAR", "INTERVAL_MONTH", "INTERVAL_DAY", "INTERVAL_HOUR", "INTERVAL_MINUTE", "INTERVAL_SECOND",
|
||||
"INTERVAL_YEAR_TO_MONTH", "INTERVAL_DAY_TO_HOUR", "INTERVAL_DAY_TO_MINUTE", "INTERVAL_DAY_TO_SECOND",
|
||||
"INTERVAL_HOUR_TO_MINUTE", "INTERVAL_HOUR_TO_SECOND", "INTERVAL_MINUTE_TO_SECOND",
|
||||
"UNSUPPORTED", "OBJECT", "NESTED");
|
||||
|
||||
cmd.execute(null, wrap(r -> {
|
||||
assertEquals(19, r.columnCount());
|
||||
assertEquals(DataType.values().length, r.size());
|
||||
assertFalse(r.schema().types().contains(DataType.NULL));
|
||||
// test numeric as signed
|
||||
assertFalse(r.column(9, Boolean.class));
|
||||
// make sure precision is returned as boolean (not int)
|
||||
assertFalse(r.column(10, Boolean.class));
|
||||
// no auto-increment
|
||||
assertFalse(r.column(11, Boolean.class));
|
||||
|
||||
for (int i = 0; i < r.size(); i++) {
|
||||
assertEquals(names.get(i), r.column(0));
|
||||
r.advanceRow();
|
||||
}
|
||||
|
||||
}, ex -> fail(ex.getMessage())));
|
||||
}
|
||||
|
||||
public void testSysTypesDefaultFiltering() throws Exception {
|
||||
Command cmd = sql("SYS TYPES 0").v1();
|
||||
|
||||
cmd.execute(null, wrap(r -> {
|
||||
assertEquals(DataType.values().length, r.size());
|
||||
}, ex -> fail(ex.getMessage())));
|
||||
}
|
||||
|
||||
public void testSysTypesPositiveFiltering() throws Exception {
|
||||
// boolean = 16
|
||||
Command cmd = sql("SYS TYPES " + JDBCType.BOOLEAN.getVendorTypeNumber()).v1();
|
||||
|
||||
cmd.execute(null, wrap(r -> {
|
||||
assertEquals(1, r.size());
|
||||
assertEquals("BOOLEAN", r.column(0));
|
||||
}, ex -> fail(ex.getMessage())));
|
||||
}
|
||||
|
||||
public void testSysTypesNegativeFiltering() throws Exception {
|
||||
Command cmd = sql("SYS TYPES " + JDBCType.TINYINT.getVendorTypeNumber()).v1();
|
||||
|
||||
cmd.execute(null, wrap(r -> {
|
||||
assertEquals(1, r.size());
|
||||
assertEquals("BYTE", r.column(0));
|
||||
}, ex -> fail(ex.getMessage())));
|
||||
}
|
||||
|
||||
public void testSysTypesMultipleMatches() throws Exception {
|
||||
Command cmd = sql("SYS TYPES " + JDBCType.VARCHAR.getVendorTypeNumber()).v1();
|
||||
|
||||
cmd.execute(null, wrap(r -> {
|
||||
assertEquals(3, r.size());
|
||||
assertEquals("KEYWORD", r.column(0));
|
||||
assertTrue(r.advanceRow());
|
||||
assertEquals("TEXT", r.column(0));
|
||||
assertTrue(r.advanceRow());
|
||||
assertEquals("IP", r.column(0));
|
||||
}, ex -> fail(ex.getMessage())));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue