aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvvvv <vvvv@ydb.tech>2023-11-29 14:45:00 +0300
committervvvv <vvvv@ydb.tech>2023-11-29 16:52:53 +0300
commitf1fff7b08e554137ba4015c332d072cfdc954621 (patch)
treec602fe8dd5175490bb59f07ca869d95bb19f8388
parent07d2ecc7f0770d65dc3d853051d526ae27f72976 (diff)
downloadydb-f1fff7b08e554137ba4015c332d072cfdc954621.tar.gz
YQL-17246 List <-> Tuple
-rw-r--r--ydb/docs/ru/core/yql/reference/yql-core/builtins/_includes/list.md35
-rw-r--r--ydb/library/yql/mount/lib/yql/core.yql38
-rw-r--r--ydb/library/yql/sql/v1/builtin.cpp2
-rw-r--r--ydb/library/yql/tests/sql/dq_file/part4/canondata/result.json22
-rw-r--r--ydb/library/yql/tests/sql/sql2yql/canondata/result.json14
-rw-r--r--ydb/library/yql/tests/sql/suites/expr/list_to_from_tuple.sql11
-rw-r--r--ydb/library/yql/tests/sql/yt_native_file/part4/canondata/result.json21
7 files changed, 143 insertions, 0 deletions
diff --git a/ydb/docs/ru/core/yql/reference/yql-core/builtins/_includes/list.md b/ydb/docs/ru/core/yql/reference/yql-core/builtins/_includes/list.md
index dfa7da4afd..1674d290dd 100644
--- a/ydb/docs/ru/core/yql/reference/yql-core/builtins/_includes/list.md
+++ b/ydb/docs/ru/core/yql/reference/yql-core/builtins/_includes/list.md
@@ -857,3 +857,38 @@ SELECT ToSet($l); -- {1,2,3}
ToSet(List<T>)->Set<T>
ToSet(List<T>?)->Set<T>?
```
+
+## ListFromTuple
+Строит список из кортежа, в котором типы элементов совместимы друг с другом. Для опционального кортежа на выходе получается опциональный список. Для NULL аргумента - NULL. Для пустого кортежа - EmptyList.
+
+**Примеры**
+```yql
+$t = (1,2,3);
+SELECT ListFromTuple($t); -- [1,2,3]
+```
+
+**Сигнатура**
+```
+ListFromTuple(Null)->Null
+ListFromTuple(Tuple<>)->EmptyList
+ListFromTuple(Tuple<T1,T2,...>)->List<T>
+ListFromTuple(Tuple<T1,T2,...>?)->List<T>?
+```
+
+## ListToTuple
+Строит кортеж из списка и явно указанной ширины кортежа. Все элементы кортежа будут иметь тот же тип, что и тип элемента списка. Если длина списка не соотвествует указанной ширине кортежа, будет возвращена ошибка. Для опционального списка на выходе получается опциональный кортеж. Для NULL аргумента - NULL.
+
+**Примеры**
+```yql
+$l = [1,2,3];
+SELECT ListToTuple($l, 3); -- (1,2,3)
+```
+
+**Сигнатура**
+```
+ListToTuple(Null,N)->Null
+ListToTuple(EmptyList,N)->()) -- N должен быть 0
+ListToTuple(List<T>, N)->Tuple<T,T,...T> -- ширина кортежа N
+ListToTuple(List<T>?, N)->Tuple<T,T,...T>? -- ширина кортежа N
+```
+
diff --git a/ydb/library/yql/mount/lib/yql/core.yql b/ydb/library/yql/mount/lib/yql/core.yql
index f297cafde3..ea51d9b5fc 100644
--- a/ydb/library/yql/mount/lib/yql/core.yql
+++ b/ydb/library/yql/mount/lib/yql/core.yql
@@ -442,6 +442,42 @@ def signature(script, name):
(lambda '() (Apply SpreadMembersImpl list fields (Bool '1)))))
)))
+(let ListFromTupleImpl (lambda '(tuple) (block '(
+ (let n (MatchType tuple 'Tuple (lambda '() (Length (TupleTypeComponents (TypeHandle (TypeOf tuple))))) (lambda '() (Uint32 '0))))
+ (let lambdaCode (LambdaCode (lambda '(tupleCode) (block '(
+ (let items (Map (ListFromRange (Uint32 '0) n) (lambda '(i)
+ (FuncCode (String 'Nth) tupleCode (AtomCode (SafeCast i (DataType 'String)))))))
+ (return (FuncCode (String 'AsList) items))
+ )))))
+ (return (Apply (EvaluateCode lambdaCode) tuple))
+))))
+
+(let ListToTupleImpl (lambda '(list n) (block '(
+ (let list (Ensure list (== (Length list) n) (String '"Mismatch length of list")))
+ (let lambdaCode (LambdaCode (lambda '(listCode) (block '(
+ (let indexDictCode (FuncCode (String 'ToIndexDict) listCode))
+ (let items (Map (ListFromRange (Uint32 '0) n) (lambda '(i)
+ (FuncCode (String 'Unwrap) (FuncCode (String 'Lookup) indexDictCode (ReprCode i))))))
+ (return (ListCode items))
+ )))))
+ (return (Apply (EvaluateCode lambdaCode) list))))
+))
+
+(let ListFromTuple (lambda '(tuple)
+ (MatchType tuple
+ 'Null (lambda '() (Null))
+ 'Optional (lambda '() (Map tuple (lambda '(unpacked) (Apply ListFromTupleImpl unpacked))))
+ (lambda '() (Apply ListFromTupleImpl tuple)))
+))
+
+(let ListToTuple (lambda '(list n)
+ (MatchType list
+ 'Null (lambda '() (Null))
+ 'EmptyList (lambda '() (Ensure '() (== n (Uint32 '0)) (String '"Expected empty tuple") ))
+ 'Optional (lambda '() (Map list (lambda '(unpacked) (Apply ListToTupleImpl unpacked n))))
+ (lambda '() (Apply ListToTupleImpl list n)))
+))
+
(export Equals)
(export Unequals)
(export FindIndex)
@@ -477,4 +513,6 @@ def signature(script, name):
(export ForceRenameMembers)
(export SpreadMembers)
(export ForceSpreadMembers)
+(export ListFromTuple)
+(export ListToTuple)
)
diff --git a/ydb/library/yql/sql/v1/builtin.cpp b/ydb/library/yql/sql/v1/builtin.cpp
index a9f6eb563d..70e5177c5b 100644
--- a/ydb/library/yql/sql/v1/builtin.cpp
+++ b/ydb/library/yql/sql/v1/builtin.cpp
@@ -3242,6 +3242,8 @@ struct TBuiltinFuncData {
{"forcerenamemembers", { "ForceRenameMembers", 2, 2}},
{"spreadmembers", { "SpreadMembers", 2, 2}},
{"forcespreadmembers", { "ForceSpreadMembers", 2, 2}},
+ {"listfromtuple", { "ListFromTuple", 1, 1}},
+ {"listtotuple", { "ListToTuple", 2, 2}},
};
return coreFuncs;
}
diff --git a/ydb/library/yql/tests/sql/dq_file/part4/canondata/result.json b/ydb/library/yql/tests/sql/dq_file/part4/canondata/result.json
index ffad629cfa..c3ac485c08 100644
--- a/ydb/library/yql/tests/sql/dq_file/part4/canondata/result.json
+++ b/ydb/library/yql/tests/sql/dq_file/part4/canondata/result.json
@@ -1605,6 +1605,28 @@
}
],
"test.test[expr-list_from_range_opt-default.txt-Results]": [],
+ "test.test[expr-list_to_from_tuple-default.txt-Analyze]": [
+ {
+ "checksum": "b4dd508a329723c74293d80f0278c705",
+ "size": 505,
+ "uri": "https://{canondata_backend}/1814674/8156a7ce6ad6eceb82586ac4874de57d87023039/resource.tar.gz#test.test_expr-list_to_from_tuple-default.txt-Analyze_/plan.txt"
+ }
+ ],
+ "test.test[expr-list_to_from_tuple-default.txt-Debug]": [
+ {
+ "checksum": "a91b3f2ddb772f271fd781c18455db2e",
+ "size": 1084,
+ "uri": "https://{canondata_backend}/1814674/8156a7ce6ad6eceb82586ac4874de57d87023039/resource.tar.gz#test.test_expr-list_to_from_tuple-default.txt-Debug_/opt.yql_patched"
+ }
+ ],
+ "test.test[expr-list_to_from_tuple-default.txt-Plan]": [
+ {
+ "checksum": "b4dd508a329723c74293d80f0278c705",
+ "size": 505,
+ "uri": "https://{canondata_backend}/1814674/8156a7ce6ad6eceb82586ac4874de57d87023039/resource.tar.gz#test.test_expr-list_to_from_tuple-default.txt-Plan_/plan.txt"
+ }
+ ],
+ "test.test[expr-list_to_from_tuple-default.txt-Results]": [],
"test.test[expr-longint_builtins-default.txt-Analyze]": [
{
"checksum": "b4dd508a329723c74293d80f0278c705",
diff --git a/ydb/library/yql/tests/sql/sql2yql/canondata/result.json b/ydb/library/yql/tests/sql/sql2yql/canondata/result.json
index cafcecc751..161b564769 100644
--- a/ydb/library/yql/tests/sql/sql2yql/canondata/result.json
+++ b/ydb/library/yql/tests/sql/sql2yql/canondata/result.json
@@ -5347,6 +5347,13 @@
"uri": "https://{canondata_backend}/1936997/00f46808be87e2ae2d4ac3ac45675b659c5ace45/resource.tar.gz#test_sql2yql.test_expr-list_takeskipwhileinclusive_/sql.yql"
}
],
+ "test_sql2yql.test[expr-list_to_from_tuple]": [
+ {
+ "checksum": "b6e85e05feb47c4c14e1fa9954ce5c95",
+ "size": 3018,
+ "uri": "https://{canondata_backend}/1936273/66a638a4446d7760fa83194c4f6ab8e79a46abc6/resource.tar.gz#test_sql2yql.test_expr-list_to_from_tuple_/sql.yql"
+ }
+ ],
"test_sql2yql.test[expr-list_uniq]": [
{
"checksum": "338a9dbb192084a632be4c818c35e5de",
@@ -22420,6 +22427,13 @@
"uri": "https://{canondata_backend}/1880306/64654158d6bfb1289c66c626a8162239289559d0/resource.tar.gz#test_sql_format.test_expr-list_takeskipwhileinclusive_/formatted.sql"
}
],
+ "test_sql_format.test[expr-list_to_from_tuple]": [
+ {
+ "checksum": "a96e9960eb98c3d4417630c94783cea1",
+ "size": 318,
+ "uri": "https://{canondata_backend}/1936273/66a638a4446d7760fa83194c4f6ab8e79a46abc6/resource.tar.gz#test_sql_format.test_expr-list_to_from_tuple_/formatted.sql"
+ }
+ ],
"test_sql_format.test[expr-list_uniq]": [
{
"checksum": "5c0e33f6414470dbe607fc1cb11bba4a",
diff --git a/ydb/library/yql/tests/sql/suites/expr/list_to_from_tuple.sql b/ydb/library/yql/tests/sql/suites/expr/list_to_from_tuple.sql
new file mode 100644
index 0000000000..4f80b8976e
--- /dev/null
+++ b/ydb/library/yql/tests/sql/suites/expr/list_to_from_tuple.sql
@@ -0,0 +1,11 @@
+select
+ ListFromTuple(null),
+ ListFromTuple(()),
+ ListFromTuple((1,2)),
+ ListFromTuple(just((3,4))),
+ ListFromTuple(Nothing(Tuple<Int32,Int32>?)),
+ ListToTuple(null,10),
+ ListToTuple([],0),
+ ListToTuple(ListCreate(Int32),0),
+ ListToTuple([1,2],2),
+ ListToTuple(just([3,4]),2);
diff --git a/ydb/library/yql/tests/sql/yt_native_file/part4/canondata/result.json b/ydb/library/yql/tests/sql/yt_native_file/part4/canondata/result.json
index 579203812d..685d21a1f9 100644
--- a/ydb/library/yql/tests/sql/yt_native_file/part4/canondata/result.json
+++ b/ydb/library/yql/tests/sql/yt_native_file/part4/canondata/result.json
@@ -1536,6 +1536,27 @@
"uri": "https://{canondata_backend}/1599023/401beb8b5eecc3a5fa746a4e9edc1175fdf7326f/resource.tar.gz#test.test_expr-list_from_range_opt-default.txt-Results_/results.txt"
}
],
+ "test.test[expr-list_to_from_tuple-default.txt-Debug]": [
+ {
+ "checksum": "6d90d912c1af13e53aec4013f17cc329",
+ "size": 1013,
+ "uri": "https://{canondata_backend}/1942525/5a2542f1fecc574bc61de9c75af61860fe531746/resource.tar.gz#test.test_expr-list_to_from_tuple-default.txt-Debug_/opt.yql"
+ }
+ ],
+ "test.test[expr-list_to_from_tuple-default.txt-Plan]": [
+ {
+ "checksum": "b4dd508a329723c74293d80f0278c705",
+ "size": 505,
+ "uri": "https://{canondata_backend}/1942525/5a2542f1fecc574bc61de9c75af61860fe531746/resource.tar.gz#test.test_expr-list_to_from_tuple-default.txt-Plan_/plan.txt"
+ }
+ ],
+ "test.test[expr-list_to_from_tuple-default.txt-Results]": [
+ {
+ "checksum": "e9c21674215af8aa0f13da3ae6068031",
+ "size": 5347,
+ "uri": "https://{canondata_backend}/1942525/5a2542f1fecc574bc61de9c75af61860fe531746/resource.tar.gz#test.test_expr-list_to_from_tuple-default.txt-Results_/results.txt"
+ }
+ ],
"test.test[expr-longint_builtins-default.txt-Debug]": [
{
"checksum": "218bfaa432db3a6726a4c6f033b9646d",