[feature-wip](array-type)Add element_at and subscript functions (#8597)

Describe the overview of changes.
1. add function element_at;
2. support element_subscript([]) to get element of array, col_array[N] <==> element_at(col_array, N);
3. return error message instead of BE crash while array function execute failed;

element_at(array, index) desc:
>   Returns element of array at given **(1-based)** index. 
  If **index < 0**, accesses elements from the last to the first. 
  Returns NULL if the index exceeds the length of the array or the array is NULL.

Usage example:
1. create table with ARRAY type column and insert some data:
```
+------+------+--------+
| k1   | k2   | k3     |
+------+------+--------+
|    1 |    2 | [1, 2] |
|    2 |    3 | NULL   |
|    4 | NULL | []     |
|    3 | NULL | NULL   |
+------+------+--------+
```
2. enable vectorized:
```
set enable_vectorized_engine=true;
```
3. element_subscript([]) usage example:
```
> select k1,k3,k3[1] from array_test;
+------+--------+----------------------------+
| k1   | k3     | %element_extract%(`k3`, 1) |
+------+--------+----------------------------+
|    3 | NULL   |                       NULL |
|    1 | [1, 2] |                          1 |
|    2 | NULL   |                       NULL |
|    4 | []     |                       NULL |
+------+--------+----------------------------+
```
4. element_at function usage example:
```
> select k1,k3 from array_test where element_at(k3, -1) = 2;
+------+--------+
| k1   | k3     |
+------+--------+
|    1 | [1, 2] |
+------+--------+
```
This commit is contained in:
camby
2022-04-02 12:03:56 +08:00
committed by GitHub
parent 8bb16bfeb3
commit 4d516bece8
14 changed files with 519 additions and 66 deletions

View File

@ -1100,6 +1100,10 @@ public class FunctionSet<min_initIN9doris_udf12DecimalV2ValEEEvPNS2_15FunctionCo
final Type[] candicateArgTypes = candicate.getArgs();
if (!(descArgTypes[0] instanceof ScalarType)
|| !(candicateArgTypes[0] instanceof ScalarType)) {
if (candicateArgTypes[0] instanceof ArrayType) {
return candicateArgTypes[0].matchesType(descArgTypes[0]);
}
return false;
}
if (functionName.equalsIgnoreCase("hex")
@ -1151,27 +1155,27 @@ public class FunctionSet<min_initIN9doris_udf12DecimalV2ValEEEvPNS2_15FunctionCo
*/
public void addScalarBuiltin(String fnName, String symbol, boolean userVisible,
String prepareFnSymbol, String closeFnSymbol,
Function.NullableMode nullableMode, PrimitiveType retType,
boolean varArgs, PrimitiveType ... args) {
Function.NullableMode nullableMode, Type retType,
boolean varArgs, Type ... args) {
ArrayList<Type> argsType = new ArrayList<Type>();
for (PrimitiveType type : args) {
argsType.add(Type.fromPrimitiveType(type));
for (Type type : args) {
argsType.add(type);
}
addBuiltin(ScalarFunction.createBuiltin(
fnName, Type.fromPrimitiveType(retType), nullableMode, argsType, varArgs,
fnName, retType, nullableMode, argsType, varArgs,
symbol, prepareFnSymbol, closeFnSymbol, userVisible));
}
public void addScalarAndVectorizedBuiltin(String fnName, String symbol, boolean userVisible,
String prepareFnSymbol, String closeFnSymbol,
Function.NullableMode nullableMode, PrimitiveType retType,
boolean varArgs, PrimitiveType ... args) {
Function.NullableMode nullableMode, Type retType,
boolean varArgs, Type ... args) {
ArrayList<Type> argsType = new ArrayList<Type>();
for (PrimitiveType type : args) {
argsType.add(Type.fromPrimitiveType(type));
for (Type type : args) {
argsType.add(type);
}
addBuiltinBothScalaAndVectorized(ScalarFunction.createBuiltin(
fnName, Type.fromPrimitiveType(retType), nullableMode, argsType, varArgs,
fnName, retType, nullableMode, argsType, varArgs,
symbol, prepareFnSymbol, closeFnSymbol, userVisible));
}

View File

@ -81,8 +81,9 @@ public abstract class Type {
public static final ScalarType QUANTILE_STATE = new ScalarType(PrimitiveType.QUANTILE_STATE);
// Only used for alias function, to represent any type in function args
public static final ScalarType ALL = new ScalarType(PrimitiveType.ALL);
public static final MapType Map = new MapType();
public static final MapType MAP = new MapType();
public static final ArrayType ARRAY = ArrayType.create();
public static final StructType STRUCT = new StructType();
private static ArrayList<ScalarType> integerTypes;
private static ArrayList<ScalarType> numericTypes;
@ -380,7 +381,9 @@ public abstract class Type {
}
if (t1.isComplexType() || t2.isComplexType()) {
if (t1.isArrayType() && t2.isArrayType()) {
return true;
// Subtype of Array do not support cast now, for example:
// Array<Int8> can not cast to Array<Int32>
return t1.matchesType(t2);
} else if (t1.isMapType() && t2.isMapType()) {
return true;
} else if (t1.isStructType() && t2.isStructType()) {