提交 92b49439 authored 作者: sylvain-ilm's avatar sylvain-ilm

Add functions ARRAY_CAT(), ARRAY_APPEND() and ARRAY_SLICE()

上级 78155dab
......@@ -4842,6 +4842,34 @@ Returns NULL if the specified array is NULL.
CALL ARRAY_CONTAINS(ARRAY['Hello', 'World'], 'Hello')
"
"Functions (System)","ARRAY_CAT","
ARRAY_CAT(arrayExpression, arrayExpression)
","
Returns the concatenation of two arrays.
Returns NULL if any parameter is NULL.
","
CALL ARRAY_CAT(ARRAY[1, 2], ARRAY[3, 4])
"
"Functions (System)","ARRAY_APPEND","
ARRAY_APPEND(arrayExpression, value)
","
Append an element to the end of an array.
Returns NULL if any parameter is NULL.
","
CALL ARRAY_APPEND(ARRAY[1, 2], 3)
"
"Functions (System)","ARRAY_SLICE","
ARRAY_SLICE(arrayExpression, lowerBoundInt, upperBoundInt)
","
Returns elements from the array as specified by the lower and upper bound parameters.
Both parameters are inclusive and the first element has index 1, i.e. ARRAY_SLICE(a, 2, 2) has only the second element.
Returns NULL if any parameter is NULL or if an index is out of bounds.
","
CALL ARRAY_SLICE(ARRAY[1, 2, 3, 4], 1, 3)
"
"Functions (System)","AUTOCOMMIT","
AUTOCOMMIT()
","
......
......@@ -21,6 +21,8 @@ Change Log
<h2>Next Version (unreleased)</h2>
<ul>
<li>Add functions ARRAY_CAT(), ARRAY_APPEND() and ARRAY_SLICE()
</li>
<li>PR #1638: Add support for Java 11 to test suite
</li>
<li>PR #1637: Remove explicit unboxing
......
......@@ -16,6 +16,7 @@ import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
......@@ -27,6 +28,7 @@ import org.h2.command.Parser;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.Mode;
import org.h2.engine.Mode.ModeEnum;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionColumn;
......@@ -61,6 +63,7 @@ import org.h2.util.Utils;
import org.h2.value.DataType;
import org.h2.value.ExtTypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueArray;
import org.h2.value.ValueBoolean;
import org.h2.value.ValueBytes;
import org.h2.value.ValueCollectionBase;
......@@ -135,7 +138,7 @@ public class Function extends Expression implements FunctionCall {
CANCEL_SESSION = 221, SET = 222, TABLE = 223, TABLE_DISTINCT = 224,
FILE_READ = 225, TRANSACTION_ID = 226, TRUNCATE_VALUE = 227,
NVL2 = 228, DECODE = 229, ARRAY_CONTAINS = 230, FILE_WRITE = 232,
UNNEST = 233;
UNNEST = 233, ARRAY_CONCAT = 234, ARRAY_APPEND = 235, ARRAY_SLICE = 236;
public static final int REGEXP_LIKE = 240;
......@@ -419,6 +422,9 @@ public class Function extends Expression implements FunctionCall {
addFunction("ARRAY_GET", ARRAY_GET,
2, Value.NULL);
addFunctionWithNull("ARRAY_CONTAINS", ARRAY_CONTAINS, 2, Value.BOOLEAN);
addFunction("ARRAY_CAT", ARRAY_CONCAT, 2, Value.ARRAY);
addFunction("ARRAY_APPEND", ARRAY_APPEND, 2, Value.ARRAY);
addFunction("ARRAY_SLICE", ARRAY_SLICE, 3, Value.ARRAY);
addFunction("CSVREAD", CSVREAD,
VAR_ARGS, Value.RESULT_SET, false, false, false, true);
addFunction("CSVWRITE", CSVWRITE,
......@@ -1542,6 +1548,43 @@ public class Function extends Expression implements FunctionCall {
}
break;
}
case ARRAY_CONCAT: {
final ValueArray array = (ValueArray) v0.convertTo(Value.ARRAY);
final ValueArray array2 = (ValueArray) v1.convertTo(Value.ARRAY);
result = array.concatenate(array2);
break;
}
case ARRAY_APPEND: {
final ValueArray array = (ValueArray) v0.convertTo(Value.ARRAY);
result = array.append(v1);
break;
}
case ARRAY_SLICE: {
result = null;
final ValueArray array = (ValueArray) v0.convertTo(Value.ARRAY);
// SQL is 1-based
int index1 = v1.getInt() - 1;
// 1-based and inclusive as postgreSQL (-1+1)
int index2 = v2.getInt();
// https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING
// For historical reasons postgreSQL ignore invalid indexes
final boolean isPG = database.getMode().getEnum() == ModeEnum.PostgreSQL;
if (index1 < 0) {
if (isPG)
index1 = 0;
else
result = ValueNull.INSTANCE;
}
if (index2 > array.getList().length) {
if (isPG)
index2 = array.getList().length;
else
result = ValueNull.INSTANCE;
}
if (result == null)
result = ValueArray.get(array.getComponentType(), Arrays.copyOfRange(array.getList(), index1, index2));
break;
}
case LINK_SCHEMA: {
session.getUser().checkAdmin();
Connection conn = session.createConnection(false);
......
......@@ -61,6 +61,25 @@ public class ValueArray extends ValueCollectionBase {
return (ValueArray) EMPTY;
}
public Value concatenate(ValueArray o) {
if (!this.getComponentType().equals(o.getComponentType()))
throw new IllegalArgumentException(
"Expected component type " + this.getComponentType() + " but got " + o.getComponentType());
final Value[] res = Arrays.copyOf(this.values, this.values.length + o.values.length);
System.arraycopy(o.values, 0, res, this.values.length, o.values.length);
return ValueArray.get(this.getComponentType(), res);
}
public Value append(Value item) {
System.err.println("ValueArray.append( item ) getComponentType() " + getComponentType());
if (item != ValueNull.INSTANCE && !this.getComponentType().isInstance(item.getObject()))
throw new IllegalArgumentException(
"Expected component type " + this.getComponentType() + " but got " + item.getClass());
final Value[] res = Arrays.copyOf(this.values, this.values.length + 1);
res[this.values.length] = item;
return ValueArray.get(this.getComponentType(), res);
}
@Override
public int getType() {
return Value.ARRAY;
......
......@@ -186,8 +186,8 @@ public class TestScript extends TestDb {
"xmlnode", "xmlstartdoc", "xmltext" }) {
testScript("functions/string/" + s + ".sql");
}
for (String s : new String[] { "array-contains", "array-get",
"array-length", "autocommit", "cancel-session", "casewhen",
for (String s : new String[] { "array-cat", "array-contains", "array-get",
"array-length","array-slice", "autocommit", "cancel-session", "casewhen",
"cast", "coalesce", "convert", "csvread", "csvwrite", "currval",
"database-path", "database", "decode", "disk-space-used",
"file-read", "file-write", "greatest", "h2version", "identity",
......
-- Copyright 2004-2019 H2 Group. Multiple-Licensed under the MPL 2.0,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
--
select array_cat(ARRAY[1, 2], ARRAY[3, 4]) = ARRAY[1, 2, 3, 4];
>> TRUE
select array_cat(ARRAY[1, 2], null) is null;
>> TRUE
select array_cat(null, ARRAY[1, 2]) is null;
>> TRUE
select array_append(ARRAY[1, 2], 3) = ARRAY[1, 2, 3];
>> TRUE
select array_append(ARRAY[1, 2], null) is null;
>> TRUE
select array_append(null, 3) is null;
>> TRUE
-- Copyright 2004-2019 H2 Group. Multiple-Licensed under the MPL 2.0,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
--
select array_slice(ARRAY[1, 2, 3, 4], 1, 1) = ARRAY[1];
>> TRUE
select array_slice(ARRAY[1, 2, 3, 4], 1, 3) = ARRAY[1, 2, 3];
>> TRUE
select array_slice(ARRAY[1, 2, 3, 4], 0, 3) is null;
>> TRUE
select array_slice(ARRAY[1, 2, 3, 4], 1, 5) is null;
>> TRUE
......@@ -383,6 +383,31 @@ public class TestValue extends TestDb {
got = src.convertPrecision(0, true);
assertEquals(exp, got);
assertEquals(String.class, ((ValueArray) got).getComponentType());
// concat
// test here rather than in a script since we can't specify the componentType in SQL.
{
ValueArray stringArray_1 = ValueArray.get(String.class, new Value[] { ValueString.get("1") });
ValueArray stringArray_2 = ValueArray.get(String.class, new Value[] { ValueString.get("2") });
final ValueArray stringArray_1_2 = ValueArray.get(String.class,
new Value[] { ValueString.get("1"), ValueString.get("2") });
assertEquals(stringArray_1_2, stringArray_1.append(stringArray_2.getList()[0]));
assertEquals(stringArray_1_2, stringArray_1.concatenate(stringArray_2));
ValueArray intArray = ValueArray.get(Integer.class, new Value[] { ValueInt.get(2) });
try {
stringArray_1.append(intArray.getList()[0]);
fail("Should have thrown since an int cannot be added to String[]");
} catch (IllegalArgumentException e) {
// OK
}
try {
stringArray_1.concatenate(intArray);
fail("Should have thrown since an int[] cannot be added to String[]");
} catch (IllegalArgumentException e) {
// OK
}
}
}
private void testUUID() {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论