mirror of
https://github.com/duckdb/duckdb.git
synced 2026-10-28 16:55:13 +08:00
InsertPadding decoded one pad character per output character, flushing the pad whenever it ran out, so a 200-character pad cost 200 decodes and as many one-byte inserts per row. Since the decoder became an out-of-line call (#26485) and the result size check counted the pad again per row (#26482), lpad(x, 200, '0') took 1.75x as long on v2.0.0 as on v1.5.5 (#27846), and about ten times as long as repeat('0', 200) || x on both. The pad's geometry is now counted once per call: its characters, the whole copies the padding needs and the bytes of the remainder. The size check uses the same plan instead of counting again, the buffer is reserved to the result size, and the padding is copied whole, a single byte at a time for a one-byte pad. LEFT and RIGHT share the function. On an M-series Mac, one thread, 2M rows (seconds, min of 3): v1.5.5 v2.0.0 main this lpad(i, 18, '0') 0.131 0.151 0.145 0.098 lpad(i, 50, '0') 0.277 0.347 0.328 0.115 lpad(i, 200, '0') 0.984 1.227 1.114 0.126 rpad(i, 200, '0') 0.966 1.212 1.112 0.129 lpad(i, 200, 'ab😀') 0.979 1.313 1.264 0.628 repeat('0', 200) || i 0.102 0.085 0.081 0.082 test_pad.test gains one-byte, one-character multibyte and longer-than- needed pads, a multibyte pad counted in characters, and the empty pad with and without padding needed. benchmark/micro/string/lpad.benchmark tracks the one-byte case.
173 lines
3.9 KiB
SQL
173 lines
3.9 KiB
SQL
# name: test/sql/function/string/test_pad.test
|
|
# description: LPAD/RPAD test
|
|
# group: [string]
|
|
|
|
# test lpad on NULLs
|
|
query TTTTTTT
|
|
select LPAD(NULL, 7, '-'), LPAD('Base', NULL, '-'), LPAD('Base', 7, NULL), LPAD(NULL, NULL, '-'), LPAD(NULL, 7, NULL), LPAD('Base', NULL, NULL), LPAD(NULL, NULL, NULL)
|
|
----
|
|
NULL NULL NULL NULL NULL NULL NULL
|
|
|
|
# test rpad on NULLs
|
|
query TTTTTTT
|
|
select RPAD(NULL, 7, '-'), RPAD('Base', NULL, '-'), RPAD('Base', 7, NULL), RPAD(NULL, NULL, '-'), RPAD(NULL, 7, NULL), RPAD('Base', NULL, NULL), RPAD(NULL, NULL, NULL)
|
|
----
|
|
NULL NULL NULL NULL NULL NULL NULL
|
|
|
|
# test lpad/rpad on scalar values
|
|
query TTTT
|
|
select LPAD('Base', 7, '-'), LPAD('Base', 4, '-'), LPAD('Base', 2, ''), LPAD('Base', -1, '-')
|
|
----
|
|
---Base Base Ba (empty)
|
|
|
|
query TTTT
|
|
select RPAD('Base', 7, '-'), RPAD('Base', 4, '-'), RPAD('Base', 2, ''), RPAD('Base', -1, '-')
|
|
----
|
|
Base--- Base Ba (empty)
|
|
|
|
query TTTT
|
|
select LPAD('Base', 7, '-|'), LPAD('Base', 6, '-|'), LPAD('Base', 5, '-|'), LPAD('Base', 4, '-|')
|
|
----
|
|
-|-Base -|Base -Base Base
|
|
|
|
query TTTT
|
|
select RPAD('Base', 7, '-|'), RPAD('Base', 6, '-|'), RPAD('Base', 5, '-|'), RPAD('Base', 4, '-|')
|
|
----
|
|
Base-|- Base-| Base- Base
|
|
|
|
query TTT
|
|
select LPAD('MotörHead', 16, 'RÄcks'), LPAD('MotörHead', 12, 'RÄcks'), LPAD('MotörHead', 10, 'RÄcks')
|
|
----
|
|
RÄcksRÄMotörHead RÄcMotörHead RMotörHead
|
|
|
|
query TTT
|
|
select RPAD('MotörHead', 16, 'RÄcks'), RPAD('MotörHead', 12, 'RÄcks'), RPAD('MotörHead', 10, 'RÄcks')
|
|
----
|
|
MotörHeadRÄcksRÄ MotörHeadRÄc MotörHeadR
|
|
|
|
# test on entire tables
|
|
statement ok
|
|
CREATE TABLE strings(a STRING, b STRING)
|
|
|
|
statement ok
|
|
INSERT INTO strings VALUES ('Hello', 'World'), ('HuLlD', NULL), ('MotörHead','RÄcks')
|
|
|
|
query TT
|
|
select LPAD(a, 16, b), RPAD(a, 16, b) FROM strings
|
|
----
|
|
WorldWorldWHello HelloWorldWorldW
|
|
NULL NULL
|
|
RÄcksRÄMotörHead MotörHeadRÄcksRÄ
|
|
|
|
# test with selection vector
|
|
query TTTT
|
|
select LPAD(a, 12, b), RPAD(a, 12, b), UCASE(a), LCASE(a) FROM strings WHERE b IS NOT NULL
|
|
----
|
|
WorldWoHello HelloWorldWo HELLO hello
|
|
RÄcMotörHead MotörHeadRÄc MOTÖRHEAD motörhead
|
|
|
|
# test incorrect usage
|
|
statement error
|
|
select LPAD()
|
|
----
|
|
|
|
statement error
|
|
select LPAD(1)
|
|
----
|
|
|
|
statement error
|
|
select LPAD(1, 2)
|
|
----
|
|
|
|
statement error
|
|
select LPAD('Hello', 10, '')
|
|
----
|
|
|
|
statement error
|
|
select LPAD('a', 100000000000000000, 0)
|
|
----
|
|
|
|
statement error
|
|
select RPAD()
|
|
----
|
|
|
|
statement error
|
|
select RPAD(1)
|
|
----
|
|
|
|
statement error
|
|
select RPAD(1, 2)
|
|
----
|
|
|
|
statement error
|
|
select RPAD('Hello', 10, '')
|
|
----
|
|
|
|
statement error
|
|
select RPAD('a', 100000000000000000, 0)
|
|
----
|
|
|
|
# results larger than the maximum string size
|
|
statement error
|
|
select LPAD('', 1100000000, '😀')
|
|
----
|
|
<REGEX>:.*Out of Range Error.*maximum supported string size.*
|
|
|
|
statement error
|
|
select RPAD('', 1100000000, '😀')
|
|
----
|
|
<REGEX>:.*Out of Range Error.*maximum supported string size.*
|
|
|
|
statement error
|
|
select LPAD('😀😀', 1073741824, '😀')
|
|
----
|
|
<REGEX>:.*Out of Range Error.*maximum supported string size.*
|
|
|
|
statement error
|
|
select RPAD('😀😀', 1073741824, '😀')
|
|
----
|
|
<REGEX>:.*Out of Range Error.*maximum supported string size.*
|
|
|
|
statement error
|
|
select LPAD('abc', 2147483647, 'xyz😀😀')
|
|
----
|
|
<REGEX>:.*Out of Range Error.*maximum supported string size.*
|
|
|
|
query I
|
|
select LPAD('ab', 7, 'xy😀')
|
|
----
|
|
xy😀xyab
|
|
|
|
query I
|
|
select RPAD('ab', 7, 'xy😀')
|
|
----
|
|
abxy😀xy
|
|
|
|
# a one-byte pad, a one-character multibyte pad, and a pad longer than the padding
|
|
query IIII
|
|
select LPAD('x', 10, '0'), LPAD('x', 4, '😀'), LPAD('x', 3, '😀ab'), RPAD('x', 3, '😀ab')
|
|
----
|
|
000000000x 😀😀😀x 😀ax x😀a
|
|
|
|
# the padding is counted in characters whatever the byte width of the pad
|
|
query III
|
|
select length(LPAD('', 1000, 'é')), strlen(LPAD('', 1000, 'é')), LPAD('ab', 5, 'é') = 'éééab'
|
|
----
|
|
1000 2000 true
|
|
|
|
# no padding needed: the pad is not read
|
|
query II
|
|
select LPAD('abc', 3, ''), RPAD('abcd', 3, '')
|
|
----
|
|
abc abc
|
|
|
|
statement error
|
|
select LPAD('abc', 4, '')
|
|
----
|
|
Insufficient padding in LPAD
|
|
|
|
statement error
|
|
select RPAD('abc', 4, '')
|
|
----
|
|
Insufficient padding in RPAD
|