aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimunkin <imunkin@yandex-team.com>2025-04-25 18:31:10 +0300
committerimunkin <imunkin@yandex-team.com>2025-04-25 18:49:19 +0300
commit2fc987c2d9ad520feffd30043d6ab5db479a4a6b (patch)
tree05a420ed216b47b1ba05f61bae9afba094b042e2
parent7e30239a11e3f6f829826805a1ba51e5118195c9 (diff)
downloadydb-2fc987c2d9ad520feffd30043d6ab5db479a4a6b.tar.gz
YQL-19901: Fix TestBit for string argument
commit_hash:8ca44c4f80502be7e9c4c970f05b64ad9b50b13f
-rw-r--r--yql/essentials/docs/en/builtins/basic.md10
-rw-r--r--yql/essentials/docs/ru/builtins/basic.md12
-rwxr-xr-xyql/essentials/mount/lib/yql/core.yqls4
-rw-r--r--yql/essentials/tests/s-expressions/minirun/part0/canondata/result.json12
-rw-r--r--yql/essentials/tests/s-expressions/suites/InMem/BitCore.yqls5
-rw-r--r--yql/essentials/tests/sql/minirun/part1/canondata/result.json6
6 files changed, 34 insertions, 15 deletions
diff --git a/yql/essentials/docs/en/builtins/basic.md b/yql/essentials/docs/en/builtins/basic.md
index f92a303295d..59c52a65dbc 100644
--- a/yql/essentials/docs/en/builtins/basic.md
+++ b/yql/essentials/docs/en/builtins/basic.md
@@ -959,16 +959,22 @@ SELECT
Arguments:
-1. An unsigned number that's subject to the operation. TestBit is also implemented for strings.
+1. An unsigned number that's subject to the operation. `TestBit` is also implemented for strings (see the description below).
2. Number of the bit.
-TestBit returns `true/false`. The other functions return a copy of their first argument with the corresponding conversion.
+`TestBit` returns `true/false`. The other functions return a copy of their first argument with the corresponding conversion.
+
+`TestBit` works the following way for the string argument:
+
+1. For the second argument (the number of the bit) the corresponding byte **from the beginning of the string** is chosen.
+2. Next, for the given byte the corresponding LSB is chosen.
#### Examples
```yql
SELECT
TestBit(1u, 0), -- true
+ TestBit('ax', 12) -- true (second byte, fourth bit)
SetBit(8u, 0); -- 9
```
diff --git a/yql/essentials/docs/ru/builtins/basic.md b/yql/essentials/docs/ru/builtins/basic.md
index 83690a3aae0..0dae688bd3e 100644
--- a/yql/essentials/docs/ru/builtins/basic.md
+++ b/yql/essentials/docs/ru/builtins/basic.md
@@ -1252,6 +1252,8 @@ SELECT
```yql
TestBit(T, Uint8)->Bool
TestBit(T?, Uint8)->Bool?
+TestBit(String, Uint8)->Bool?
+TestBit(String?, Uint8)->Bool?
ClearBit(T, Uint8)->T
ClearBit(T?, Uint8)->T?
@@ -1265,16 +1267,22 @@ FlipBit(T?, Uint8)->T?
Аргументы:
-1. Беззнаковое число, над которым выполнять требуемую операцию. TestBit также реализован и для строк.
+1. Беззнаковое число, над которым выполнять требуемую операцию. `TestBit` также реализован и для строк (см. ниже описание).
2. Номер бита.
-TestBit возвращает `true/false`. Остальные функции возвращают копию своего первого аргумента с проведенным соответствующим преобразованием.
+`TestBit` возвращает `true/false`. Остальные функции возвращают копию своего первого аргумента с проведенным соответствующим преобразованием.
+
+`TestBit` для строковых аргументов работает следующим образом:
+
+1. По второму аргументу (номеру бита) выбирается соответсвующий байт *с начала строки*.
+2. Затем в выбранном байте выбирается соответствующий младший бит.
#### Примеры
```yql
SELECT
TestBit(1u, 0), -- true
+ TestBit('ax', 12) -- true (второй байт, четвертый бит)
SetBit(8u, 0); -- 9
```
diff --git a/yql/essentials/mount/lib/yql/core.yqls b/yql/essentials/mount/lib/yql/core.yqls
index 4dbb358d545..8b6e1798804 100755
--- a/yql/essentials/mount/lib/yql/core.yqls
+++ b/yql/essentials/mount/lib/yql/core.yqls
@@ -13,7 +13,9 @@
(let MaskBit (lambda '(value index) (ShiftLeft (Data (Apply RemoveOptionalType (TypeOf value)) '1) index)))
(let TestBitInt (lambda '(value index) (Convert (BitAnd value (Apply MaskBit value index)) 'Bool)))
-(let TestBitStr (lambda '(value index) (Apply TestBitInt (ByteAt value (Convert (ShiftRight (Convert index 'Uint64) (Uint8 '8)) 'Uint32)) (BitAnd (Convert index 'Uint8) (Uint8 '7)))))
+# XXX: Coalesce drops the Optional type returned by ByteAt, so to
+# respect the current signature, the result is wrapped with Just.
+(let TestBitStr (lambda '(value index) (Just (Coalesce (Apply TestBitInt (ByteAt value (Convert (ShiftRight (Convert index 'Uint64) (Uint8 '3)) 'Uint32)) (BitAnd (Convert index 'Uint8) (Uint8 '7))) (Bool 'false)))))
(let TestBit (lambda '(value index) (block '(
(let x (InstanceOf (Apply RemoveOptionalType (TypeOf value))))
(return (IfType x (DataType 'String)
diff --git a/yql/essentials/tests/s-expressions/minirun/part0/canondata/result.json b/yql/essentials/tests/s-expressions/minirun/part0/canondata/result.json
index 5902893a5ac..e203f265ac5 100644
--- a/yql/essentials/tests/s-expressions/minirun/part0/canondata/result.json
+++ b/yql/essentials/tests/s-expressions/minirun/part0/canondata/result.json
@@ -211,16 +211,16 @@
],
"test.test[InMem-BitCore-default.txt-Debug]": [
{
- "checksum": "3fab26087d7f76a6ef31ed20f9ec0573",
- "size": 2021,
- "uri": "https://{canondata_backend}/1871002/8daca6f2a7b63a0a94f426a2b401ad3af26d4985/resource.tar.gz#test.test_InMem-BitCore-default.txt-Debug_/opt.yql"
+ "checksum": "2e88c6c546707f0923c3f4a5cb6061b1",
+ "size": 2750,
+ "uri": "https://{canondata_backend}/1871182/13a5336c3cbff0a7768aef57bd68f03fe757b446/resource.tar.gz#test.test_InMem-BitCore-default.txt-Debug_/opt.yql"
}
],
"test.test[InMem-BitCore-default.txt-Results]": [
{
- "checksum": "35cecef4cdd5e75ae9060c89f7af2f9c",
- "size": 3977,
- "uri": "https://{canondata_backend}/1871002/8daca6f2a7b63a0a94f426a2b401ad3af26d4985/resource.tar.gz#test.test_InMem-BitCore-default.txt-Results_/results.txt"
+ "checksum": "1b2d2884e64e3e9a2ea816e9e714110e",
+ "size": 4861,
+ "uri": "https://{canondata_backend}/1871182/13a5336c3cbff0a7768aef57bd68f03fe757b446/resource.tar.gz#test.test_InMem-BitCore-default.txt-Results_/results.txt"
}
],
"test.test[InMem-ByteAt-default.txt-Debug]": [
diff --git a/yql/essentials/tests/s-expressions/suites/InMem/BitCore.yqls b/yql/essentials/tests/s-expressions/suites/InMem/BitCore.yqls
index 406f7e22703..ea70273ce70 100644
--- a/yql/essentials/tests/s-expressions/suites/InMem/BitCore.yqls
+++ b/yql/essentials/tests/s-expressions/suites/InMem/BitCore.yqls
@@ -9,8 +9,11 @@
))))
(let world (Apply test world (Apply (bind core_module 'TestBit) (String '"\x05\x04") (Uint64 '0))))
+(let world (Apply test world (Apply (bind core_module 'TestBit) (String '"\x05\x04") (Uint64 '2))))
+(let world (Apply test world (Apply (bind core_module 'TestBit) (String '"\x05\x04") (Uint64 '7))))
+(let world (Apply test world (Apply (bind core_module 'TestBit) (String '"\x05\x04") (Uint64 '8))))
(let world (Apply test world (Apply (bind core_module 'TestBit) (String '"\x05\x04") (Uint64 '10))))
-(let world (Apply test world (Apply (bind core_module 'TestBit) (String '"\x05\x04") (Uint64 '11))))
+(let world (Apply test world (Apply (bind core_module 'TestBit) (String '"\x05\x04") (Uint64 '15))))
(let world (Apply test world (Apply (bind core_module 'TestBit) (String '"\x05\x04") (Uint64 '23))))
(let world (Apply test world (Apply (bind core_module 'TestBit) (Just (String '"\x05\x04")) (Uint64 '0))))
(let world (Apply test world (Apply (bind core_module 'TestBit) (Just (Utf8 '"\x05\x04")) (Uint64 '0))))
diff --git a/yql/essentials/tests/sql/minirun/part1/canondata/result.json b/yql/essentials/tests/sql/minirun/part1/canondata/result.json
index baec7526562..b5d225b7f0b 100644
--- a/yql/essentials/tests/sql/minirun/part1/canondata/result.json
+++ b/yql/essentials/tests/sql/minirun/part1/canondata/result.json
@@ -1232,9 +1232,9 @@
],
"test.test[select-core_func_test_bit-default.txt-Debug]": [
{
- "checksum": "bab2b83b596cd2b7e76f7b15cdc71fcf",
- "size": 548,
- "uri": "https://{canondata_backend}/1936842/f457790bc6a954bcb4a6a17ab144af05c57a7754/resource.tar.gz#test.test_select-core_func_test_bit-default.txt-Debug_/opt.yql"
+ "checksum": "77122d9689e5286e7f1072e93e70a723",
+ "size": 613,
+ "uri": "https://{canondata_backend}/1881367/f5d048c3de61bd751328e99d5916444547ba4d0c/resource.tar.gz#test.test_select-core_func_test_bit-default.txt-Debug_/opt.yql"
}
],
"test.test[select-core_func_test_bit-default.txt-Results]": [