Skip to content

Commit

Permalink
SQL: Implement CONVERT, an alternative to CAST (#34660)
Browse files Browse the repository at this point in the history
`CONVERT` works exactly like cast with slightly different syntax:
`CONVERT(<value>, <data_type)` as opposed to `CAST(<value> AS <data_type>)`

Moreover it support format of the MS-SQL data types `SQL_<type>`,
e.g.: `SQL_INTEGER`

Closes: #34513
  • Loading branch information
Marios Trivyzas authored Oct 23, 2018
1 parent 5fb4f32 commit e9e1407
Show file tree
Hide file tree
Showing 15 changed files with 1,841 additions and 1,482 deletions.
33 changes: 31 additions & 2 deletions docs/reference/sql/functions/type-conversion.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ CAST ( expression<1> AS data_type<2> )

.Description

Casts the result of the given expression to the target type.
Casts the result of the given expression to the target <<sql-data-types, data type>>.
If the cast is not possible (for example because of target type is too narrow or because
the value itself cannot be converted), the query fails.

Expand All @@ -36,4 +36,33 @@ include-tagged::{sql-specs}/docs.csv-spec[conversionIntToStringCast]
["source","sql",subs="attributes,callouts,macros"]
----
include-tagged::{sql-specs}/docs.csv-spec[conversionStringToDateCast]
----
----


[[sql-functions-type-conversion-convert]]
==== `CONVERT`

.Synopsis
[source, sql]
----
CONVERT ( expression<1>, data_type<2> )
----

<1> Expression to convert
<2> Target data type to convert to

.Description

Works exactly like <<sql-functions-type-conversion-cast>> with slightly different syntax.
Moreover, apart from the standard <<sql-data-types, data types>> it supports the corresponding
https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/explicit-data-type-conversion-function?view=sql-server-2017[ODBC data types].

["source","sql",subs="attributes,callouts,macros"]
----
include-tagged::{sql-specs}/docs.csv-spec[conversionStringToIntConvertODBCDataType]
----

["source","sql",subs="attributes,callouts,macros"]
----
include-tagged::{sql-specs}/docs.csv-spec[conversionStringToIntConvertESDataType]
----
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.sql.SQLType;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -44,12 +45,63 @@ public enum DataType {
DATE( JDBCType.TIMESTAMP, Timestamp.class, Long.BYTES, 24, 24);
// @formatter:on

public static final String ODBC_DATATYPE_PREFIX = "SQL_";

private static final Map<SQLType, DataType> jdbcToEs;
private static final Map<String, DataType> odbcToEs;

static {
jdbcToEs = Arrays.stream(DataType.values())
.filter(dataType -> dataType != TEXT && dataType != NESTED && dataType != SCALED_FLOAT) // Remove duplicates
.collect(Collectors.toMap(dataType -> dataType.jdbcType, dataType -> dataType));

odbcToEs = new HashMap<>(36);

// Numeric
odbcToEs.put("SQL_BIT", BOOLEAN);
odbcToEs.put("SQL_TINYINT", BYTE);
odbcToEs.put("SQL_SMALLINT", SHORT);
odbcToEs.put("SQL_INTEGER", INTEGER);
odbcToEs.put("SQL_BIGINT", LONG);
odbcToEs.put("SQL_FLOAT", FLOAT);
odbcToEs.put("SQL_REAL", FLOAT);
odbcToEs.put("SQL_DOUBLE", DOUBLE);
odbcToEs.put("SQL_DECIMAL", DOUBLE);
odbcToEs.put("SQL_NUMERIC", DOUBLE);

// String
odbcToEs.put("SQL_GUID", KEYWORD);
odbcToEs.put("SQL_CHAR", KEYWORD);
odbcToEs.put("SQL_WCHAR", KEYWORD);
odbcToEs.put("SQL_VARCHAR", TEXT);
odbcToEs.put("SQL_WVARCHAR", TEXT);
odbcToEs.put("SQL_LONGVARCHAR", TEXT);
odbcToEs.put("SQL_WLONGVARCHAR", TEXT);

// Binary
odbcToEs.put("SQL_BINARY", BINARY);
odbcToEs.put("SQL_VARBINARY", BINARY);
odbcToEs.put("SQL_LONGVARBINARY", BINARY);

// Date
odbcToEs.put("SQL_DATE", DATE);
odbcToEs.put("SQL_TIME", DATE);
odbcToEs.put("SQL_TIMESTAMP", DATE);

// Intervals - Currently Not Supported
odbcToEs.put("SQL_INTERVAL_HOUR_TO_MINUTE", UNSUPPORTED);
odbcToEs.put("SQL_INTERVAL_HOUR_TO_SECOND", UNSUPPORTED);
odbcToEs.put("SQL_INTERVAL_MINUTE_TO_SECOND", UNSUPPORTED);
odbcToEs.put("SQL_INTERVAL_MONTH", UNSUPPORTED);
odbcToEs.put("SQL_INTERVAL_YEAR", UNSUPPORTED);
odbcToEs.put("SQL_INTERVAL_YEAR_TO_MONTH", UNSUPPORTED);
odbcToEs.put("SQL_INTERVAL_DAY", UNSUPPORTED);
odbcToEs.put("SQL_INTERVAL_HOUR", UNSUPPORTED);
odbcToEs.put("SQL_INTERVAL_MINUTE", UNSUPPORTED);
odbcToEs.put("SQL_INTERVAL_SECOND", UNSUPPORTED);
odbcToEs.put("SQL_INTERVAL_DAY_TO_HOUR", UNSUPPORTED);
odbcToEs.put("SQL_INTERVAL_DAY_TO_MINUTE", UNSUPPORTED);
odbcToEs.put("SQL_INTERVAL_DAY_TO_SECOND", UNSUPPORTED);
}

/**
Expand Down Expand Up @@ -162,6 +214,9 @@ public static Class<?> fromJdbcTypeToJava(SQLType jdbcType) {
return jdbcToEs.get(jdbcType).javaClass();
}

public static DataType fromODBCType(String odbcType) {
return odbcToEs.get(odbcType);
}
/**
* Creates returns DataType enum coresponding to the specified es type
* <p>
Expand All @@ -170,4 +225,4 @@ public static Class<?> fromJdbcTypeToJava(SQLType jdbcType) {
public static DataType fromEsType(String esType) {
return DataType.valueOf(esType.toUpperCase(Locale.ROOT));
}
}
}
13 changes: 10 additions & 3 deletions x-pack/plugin/sql/src/main/antlr/SqlBase.g4
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,20 @@ primaryExpression
;

castExpression
: castTemplate
| FUNCTION_ESC castTemplate ESC_END
: castTemplate
| FUNCTION_ESC castTemplate ESC_END
| convertTemplate
| FUNCTION_ESC convertTemplate ESC_END
;

castTemplate
: CAST '(' expression AS dataType ')'
;


convertTemplate
: CONVERT '(' expression ',' dataType ')'
;

extractExpression
: extractTemplate
| FUNCTION_ESC extractTemplate ESC_END
Expand Down Expand Up @@ -347,6 +353,7 @@ CAST: 'CAST';
CATALOG: 'CATALOG';
CATALOGS: 'CATALOGS';
COLUMNS: 'COLUMNS';
CONVERT: 'CONVERT';
DEBUG: 'DEBUG';
DESC: 'DESC';
DESCRIBE: 'DESCRIBE';
Expand Down
Loading

0 comments on commit e9e1407

Please sign in to comment.