blob: 793e910b1bd38762cf0cbfe5208ff5e1a2858636 [file] [log] [blame]
/*
*
* Functional tests
* Parameter combination tests
* Improve code coverage tests
*/
CREATE SCHEMA ic_udp_test;
SET search_path = ic_udp_test;
-- Prepare some tables
CREATE TABLE small_table(dkey INT, jkey INT, rval REAL, tval TEXT default 'abcdefghijklmnopqrstuvwxyz') DISTRIBUTED BY (dkey);
INSERT INTO small_table VALUES(generate_series(1, 500), generate_series(501, 1000), sqrt(generate_series(501, 1000)));
-- Functional tests
-- Skew with gather+redistribute
SELECT ROUND(foo.rval * foo.rval)::INT % 30 AS rval2, COUNT(*) AS count, SUM(length(foo.tval)) AS sum_len_tval
FROM (SELECT 501 AS jkey, rval, tval FROM small_table ORDER BY dkey LIMIT 3000) foo
JOIN small_table USING(jkey)
GROUP BY rval2
ORDER BY rval2;
rval2 | count | sum_len_tval
-------+-------+--------------
0 | 17 | 442
1 | 17 | 442
2 | 17 | 442
3 | 17 | 442
4 | 17 | 442
5 | 17 | 442
6 | 17 | 442
7 | 17 | 442
8 | 17 | 442
9 | 17 | 442
10 | 17 | 442
11 | 16 | 416
12 | 16 | 416
13 | 16 | 416
14 | 16 | 416
15 | 16 | 416
16 | 16 | 416
17 | 16 | 416
18 | 16 | 416
19 | 16 | 416
20 | 16 | 416
21 | 17 | 442
22 | 17 | 442
23 | 17 | 442
24 | 17 | 442
25 | 17 | 442
26 | 17 | 442
27 | 17 | 442
28 | 17 | 442
29 | 17 | 442
(30 rows)
-- Union
SELECT jkey2, SUM(length(digits_string)) AS sum_len_dstring
FROM (
(SELECT jkey % 30 AS jkey2, repeat('0123456789', 200) AS digits_string FROM small_table GROUP BY jkey2)
UNION ALL
(SELECT jkey % 30 AS jkey2, repeat('0123456789', 200) AS digits_string FROM small_table GROUP BY jkey2)
UNION ALL
(SELECT jkey % 30 AS jkey2, repeat('0123456789', 200) AS digits_string FROM small_table GROUP BY jkey2)
UNION ALL
(SELECT jkey % 30 AS jkey2, repeat('0123456789', 200) AS digits_string FROM small_table GROUP BY jkey2)
UNION ALL
(SELECT jkey % 30 AS jkey2, repeat('0123456789', 200) AS digits_string FROM small_table GROUP BY jkey2)
UNION ALL
(SELECT jkey % 30 AS jkey2, repeat('0123456789', 200) AS digits_string FROM small_table GROUP BY jkey2)
UNION ALL
(SELECT jkey % 30 AS jkey2, repeat('0123456789', 200) AS digits_string FROM small_table GROUP BY jkey2)
UNION ALL
(SELECT jkey % 30 AS jkey2, repeat('0123456789', 200) AS digits_string FROM small_table GROUP BY jkey2)
UNION ALL
(SELECT jkey % 30 AS jkey2, repeat('0123456789', 200) AS digits_string FROM small_table GROUP BY jkey2)
UNION ALL
(SELECT jkey % 30 AS jkey2, repeat('0123456789', 200) AS digits_string FROM small_table GROUP BY jkey2)
UNION ALL
(SELECT jkey % 30 AS jkey2, repeat('0123456789', 200) AS digits_string FROM small_table GROUP BY jkey2)
UNION ALL
(SELECT jkey % 30 AS jkey2, repeat('0123456789', 200) AS digits_string FROM small_table GROUP BY jkey2)
UNION ALL
(SELECT jkey % 30 AS jkey2, repeat('0123456789', 200) AS digits_string FROM small_table GROUP BY jkey2)
UNION ALL
(SELECT jkey % 30 AS jkey2, repeat('0123456789', 200) AS digits_string FROM small_table GROUP BY jkey2)) foo
GROUP BY jkey2
ORDER BY jkey2
LIMIT 30;
jkey2 | sum_len_dstring
-------+-----------------
0 | 28000
1 | 28000
2 | 28000
3 | 28000
4 | 28000
5 | 28000
6 | 28000
7 | 28000
8 | 28000
9 | 28000
10 | 28000
11 | 28000
12 | 28000
13 | 28000
14 | 28000
15 | 28000
16 | 28000
17 | 28000
18 | 28000
19 | 28000
20 | 28000
21 | 28000
22 | 28000
23 | 28000
24 | 28000
25 | 28000
26 | 28000
27 | 28000
28 | 28000
29 | 28000
(30 rows)
-- Huge tuple (May need to split) 26 * 200000
SELECT SUM(length(long_tval)) AS sum_len_tval
FROM (SELECT jkey, repeat(tval, 200000) AS long_tval
FROM small_table ORDER BY dkey LIMIT 20) foo
JOIN (SELECT * FROM small_table ORDER BY dkey LIMIT 50) bar USING(jkey);
sum_len_tval
--------------
104000000
(1 row)
-- Gather motion (Window function)
SELECT dkey % 30 AS dkey2, MIN(rank) AS min_rank, AVG(foo.rval) AS avg_rval
FROM (SELECT RANK() OVER(ORDER BY rval DESC) AS rank, jkey, rval
FROM small_table) foo
JOIN small_table USING(jkey)
GROUP BY dkey2
ORDER BY dkey2;
dkey2 | min_rank | avg_rval
-------+----------+--------------------
0 | 21 | 27.35977816581726
1 | 20 | 27.084374147302963
2 | 19 | 27.103021397310144
3 | 18 | 27.121655295876895
4 | 17 | 27.14027561860926
5 | 16 | 27.158882702098172
6 | 15 | 27.177476658540613
7 | 14 | 27.196057375739603
8 | 13 | 27.214624404907227
9 | 12 | 27.23317875581629
10 | 11 | 27.251719867481906
11 | 10 | 27.270247739904068
12 | 9 | 27.288762597476733
13 | 8 | 27.30726444019991
14 | 7 | 27.32575315587661
15 | 6 | 27.344228632309857
16 | 5 | 27.36269131828757
17 | 4 | 27.381141101612766
18 | 3 | 27.39957753349753
19 | 2 | 27.418001848108627
20 | 1 | 27.436412811279297
21 | 30 | 27.19332504272461
22 | 29 | 27.21187174320221
23 | 28 | 27.230405688285828
24 | 27 | 27.248926639556885
25 | 26 | 27.267434239387512
26 | 25 | 27.285928964614868
27 | 24 | 27.304410696029663
28 | 23 | 27.322879433631897
29 | 22 | 27.34133517742157
(30 rows)
-- Broadcast (call genereate_series to multiply result set)
SELECT COUNT(*) AS count
FROM (SELECT generate_series(501, 530) AS jkey FROM small_table) foo
JOIN small_table USING(jkey);
count
-------
15000
(1 row)
-- Subquery
SELECT (SELECT tval FROM small_table bar WHERE bar.dkey + 500 = foo.jkey) AS tval
FROM (SELECT * FROM small_table ORDER BY jkey LIMIT 200) foo LIMIT 15;
tval
----------------------------
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
(15 rows)
SELECT (SELECT tval FROM small_table bar WHERE bar.dkey = 1) AS tval
FROM (SELECT * FROM small_table ORDER BY jkey LIMIT 300) foo LIMIT 15;
tval
----------------------------
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
(15 rows)
-- Target dispatch
CREATE TABLE target_table AS SELECT * FROM small_table LIMIT 0 DISTRIBUTED BY (dkey);
INSERT INTO target_table VALUES(1, 1, 1.0, '1');
SELECT * FROM target_table WHERE dkey = 1;
dkey | jkey | rval | tval
------+------+------+------
1 | 1 | 1 | 1
(1 row)
DROP TABLE target_table;
-- CURSOR tests
BEGIN;
DECLARE c1 CURSOR FOR SELECT dkey % 500 AS dkey2
FROM (SELECT jkey FROM small_table) foo
JOIN small_table USING(jkey)
GROUP BY dkey2
ORDER BY dkey2;
DECLARE c2 CURSOR FOR SELECT dkey % 500 AS dkey2
FROM (SELECT jkey FROM small_table) foo
JOIN small_table USING(jkey)
GROUP BY dkey2
ORDER BY dkey2;
DECLARE c3 CURSOR FOR SELECT dkey % 500 AS dkey2
FROM (SELECT jkey FROM small_table) foo
JOIN small_table USING(jkey)
GROUP BY dkey2
ORDER BY dkey2;
DECLARE c4 CURSOR FOR SELECT dkey % 500 AS dkey2
FROM (SELECT jkey FROM small_table) foo
JOIN small_table USING(jkey)
GROUP BY dkey2
ORDER BY dkey2;
FETCH 20 FROM c1;
dkey2
-------
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(20 rows)
FETCH 20 FROM c2;
dkey2
-------
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(20 rows)
FETCH 20 FROM c3;
dkey2
-------
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(20 rows)
FETCH 20 FROM c4;
dkey2
-------
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(20 rows)
CLOSE c1;
CLOSE c2;
CLOSE c3;
CLOSE c4;
END;
-- Redistribute all tuples with normal settings
SET gp_interconnect_snd_queue_depth TO 8;
SET gp_interconnect_queue_depth TO 8;
SELECT SUM(length(long_tval)) AS sum_len_tval
FROM (SELECT jkey, repeat(tval, 10000) AS long_tval
FROM small_table ORDER BY dkey LIMIT 20) foo
JOIN (SELECT * FROM small_table ORDER BY dkey LIMIT 100) bar USING(jkey);
sum_len_tval
--------------
5200000
(1 row)
-- Redistribute all tuples with minimize settings
SET gp_interconnect_snd_queue_depth TO 1;
SET gp_interconnect_queue_depth TO 1;
SELECT SUM(length(long_tval)) AS sum_len_tval
FROM (SELECT jkey, repeat(tval, 10000) AS long_tval
FROM small_table ORDER BY dkey LIMIT 20) foo
JOIN (SELECT * FROM small_table ORDER BY dkey LIMIT 100) bar USING(jkey);
sum_len_tval
--------------
5200000
(1 row)
-- Redistribute all tuples
SET gp_interconnect_snd_queue_depth TO 4096;
SET gp_interconnect_queue_depth TO 1;
SELECT SUM(length(long_tval)) AS sum_len_tval
FROM (SELECT jkey, repeat(tval, 10000) AS long_tval
FROM small_table ORDER BY dkey LIMIT 20) foo
JOIN (SELECT * FROM small_table ORDER BY dkey LIMIT 100) bar USING(jkey);
sum_len_tval
--------------
5200000
(1 row)
-- Redistribute all tuples
SET gp_interconnect_snd_queue_depth TO 1;
SET gp_interconnect_queue_depth TO 4096;
SELECT SUM(length(long_tval)) AS sum_len_tval
FROM (SELECT jkey, repeat(tval, 10000) AS long_tval
FROM small_table ORDER BY dkey LIMIT 20) foo
JOIN (SELECT * FROM small_table ORDER BY dkey LIMIT 100) bar USING(jkey);
sum_len_tval
--------------
5200000
(1 row)
-- Redistribute all tuples
SET gp_interconnect_snd_queue_depth TO 1024;
SET gp_interconnect_queue_depth TO 1024;
SELECT SUM(length(long_tval)) AS sum_len_tval
FROM (SELECT jkey, repeat(tval, 10000) AS long_tval
FROM small_table ORDER BY dkey LIMIT 20) foo
JOIN (SELECT * FROM small_table ORDER BY dkey LIMIT 100) bar USING(jkey);
sum_len_tval
--------------
5200000
(1 row)
-- MPP-21916
CREATE TABLE a (i INT, j INT) DISTRIBUTED BY (i);
INSERT INTO a (SELECT i, i * i FROM generate_series(1, 10) as i);
SELECT a.* FROM a WHERE a.j NOT IN (SELECT j FROM a a2 WHERE a2.j = a.j AND a2.i = 1) AND a.i = 1;
i | j
---+---
(0 rows)
SELECT a.* FROM a INNER JOIN a b ON a.i = b.i WHERE a.j NOT IN (SELECT j FROM a a2 WHERE a2.j = b.j) AND a.i = 1;
i | j
---+---
(0 rows)
-- Paramter range
SET gp_interconnect_snd_queue_depth TO -1; -- ERROR
ERROR: -1 is outside the valid range for parameter "gp_interconnect_snd_queue_depth" (1 .. 4096)
SET gp_interconnect_snd_queue_depth TO 0; -- ERROR
ERROR: 0 is outside the valid range for parameter "gp_interconnect_snd_queue_depth" (1 .. 4096)
SET gp_interconnect_snd_queue_depth TO 4097; -- ERROR
ERROR: 4097 is outside the valid range for parameter "gp_interconnect_snd_queue_depth" (1 .. 4096)
SET gp_interconnect_queue_depth TO -1; -- ERROR
ERROR: -1 is outside the valid range for parameter "gp_interconnect_queue_depth" (1 .. 4096)
SET gp_interconnect_queue_depth TO 0; -- ERROR
ERROR: 0 is outside the valid range for parameter "gp_interconnect_queue_depth" (1 .. 4096)
SET gp_interconnect_queue_depth TO 4097; -- ERROR
ERROR: 4097 is outside the valid range for parameter "gp_interconnect_queue_depth" (1 .. 4096)
-- Cleanup
DROP TABLE small_table;
DROP TABLE a;
RESET search_path;
DROP SCHEMA ic_udp_test CASCADE;
/*
* If ack packet is lost in SendStopMessageUDPIFC(), transaction with cursor
* should still be able to commit.
*/
--start_ignore
drop table if exists ic_test_1;
NOTICE: table "ic_test_1" does not exist, skipping
--end_ignore
create table ic_test_1 as select i as c1, i as c2 from generate_series(1, 100000) i;
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column(s) named 'c1' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
begin;
declare ic_test_cursor_c1 cursor for select * from ic_test_1;
select gp_inject_fault('interconnect_stop_ack_is_lost', 'reset', 1);
gp_inject_fault
-----------------
Success:
(1 row)
select gp_inject_fault('interconnect_stop_ack_is_lost', 'skip', 1);
gp_inject_fault
-----------------
Success:
(1 row)
commit;
drop table ic_test_1;
/*
* If message queue of connection is failed to be allocated in
* SetupUDPIFCInterconnect_Internal(), it should be handled properly
* in TeardownUDPIFCInterconnect_Internal().
*/
CREATE TABLE a (i INT, j INT) DISTRIBUTED BY (i);
INSERT INTO a (SELECT i, i * i FROM generate_series(1, 10) as i);
SELECT gp_inject_fault('interconnect_setup_palloc', 'error', 1);
gp_inject_fault
-----------------
Success:
(1 row)
SELECT * FROM a;
ERROR: fault triggered, fault name:'interconnect_setup_palloc' fault type:'error'
SELECT gp_inject_fault('interconnect_setup_palloc', 'reset', 1);
gp_inject_fault
-----------------
Success:
(1 row)
-- The same, but the fault happens while dispatching an Init Plan.
SELECT gp_inject_fault('interconnect_setup_palloc', 'error', 1);
gp_inject_fault
-----------------
Success:
(1 row)
SELECT * FROM generate_series(1, 5) g WHERE g < (SELECT max(a.j) FROM a);
ERROR: fault triggered, fault name:'interconnect_setup_palloc' fault type:'error'
SELECT gp_inject_fault('interconnect_setup_palloc', 'reset', 1);
gp_inject_fault
-----------------
Success:
(1 row)
DROP TABLE a;
-- Test sender QE errors out when setup outgoing connection, the receiver QE is waiting,
-- at this time, QD should be able to process the error and cancel the receiver QE.
CREATE TABLE test_ic_error(a INT, b int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
SELECT gp_inject_fault('interconnect_setup_palloc', 'error', 2);
gp_inject_fault
-----------------
Success:
(1 row)
SELECT * FROM test_ic_error t1, test_ic_error t2 where t1.a=t2.b;
ERROR: fault triggered, fault name:'interconnect_setup_palloc' fault type:'error' (seg0 slice2 172.17.0.4:25432 pid=68446)
SELECT gp_inject_fault('interconnect_setup_palloc', 'reset', 2);
gp_inject_fault
-----------------
Success:
(1 row)
DROP TABLE test_ic_error;
-- Use WITH RECURSIVE to construct a one-time filter result node that executed
-- on QD, meanwhile, let the result node has a outer node which contain motion.
-- It's used to test that result node on QD can send a stop message to sender in
-- one-time filter case.
RESET gp_interconnect_snd_queue_depth;
RESET gp_interconnect_queue_depth;
CREATE TABLE recursive_table_ic (a INT) DISTRIBUTED BY (a);
-- Insert enough data so interconnect sender don't quit earlier.
INSERT INTO recursive_table_ic SELECT * FROM generate_series(20, 30000);
WITH RECURSIVE
r(i) AS (
SELECT 1
),
y(i) AS (
SELECT 1
UNION ALL
SELECT i + 1 FROM y, recursive_table_ic WHERE NOT EXISTS (SELECT * FROM r LIMIT 10)
)
SELECT * FROM y LIMIT 10;
i
---
1
(1 row)
DROP TABLE recursive_table_ic;
-- Test QD can notice the errors in QEs for initplan
CREATE TABLE qe_errors_ic (a INT, b INT);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
INSERT INTO qe_errors_ic SELECT i, i FROM generate_series(1, 10) i;
SELECT count(*) FROM qe_errors_ic
GROUP BY a, b
HAVING sum(a) > (SELECT max(a) FROM qe_errors_ic WHERE a/0 > 1);
ERROR: division by zero (seg2 slice3 127.0.0.1:7004 pid=20627)
-- Test QD can notice the errors in QEs for cursors
-- In past, bellow DECLARE and FETCH commands had chances to report
-- no errors, it was not expected, we expect either DECLARE or FETCH
-- to report 'division by zero' errors.
--
-- In TCP interconnect mode, DECLARE or FETCH all have chance to
-- report 'division by zero' errors, it depends on the speed of QD
-- and QEs to set up interconnect, so ignore the output of DECLARE
-- and FETCH, we verify the test case by checking the fact that the
-- following commands in the transaction will failed.
BEGIN;
--start_ignore
DECLARE qe_errors_cursor CURSOR FOR SELECT * FROM qe_errors_ic WHERE qe_errors_ic.b / 0 >1;
ERROR: division by zero (seg0 slice1 127.0.0.1:7002 pid=20667)
FETCH ALL FROM qe_errors_cursor;
ERROR: current transaction is aborted, commands ignored until end of transaction block
--end_ignore
select 1;
ERROR: current transaction is aborted, commands ignored until end of transaction block
ROLLBACK;
-- Test whether QD detects a QE error in time
-- In previous code, QD only watchs *one* QE event, if an error doesn't
-- happen on this specific QE, QD may delay receiving this event.
--
-- After refactoring by WaitEventSet, QD watches all QEs's event, so it
-- can detect event in time now.
-- Note: this refactor is only performed under gp_interconnect_type=udpifc,
-- and gp_interconnect_type=tcp is still previous behavior (watch one QE).
-- block QE1 and QE3, generate an error on QE2
select gp_inject_fault('exec_mpp_query_start', 'sleep', '', '', '', 1, 1, 10, 2);
gp_inject_fault
-----------------
Success:
(1 row)
select gp_inject_fault('exec_mpp_query_start', 'error', 3);
gp_inject_fault
-----------------
Success:
(1 row)
select gp_inject_fault('exec_mpp_query_start', 'sleep', '', '', '', 1, 1, 10, 4);
gp_inject_fault
-----------------
Success:
(1 row)
set statement_timeout to 150; -- 150ms < MAIN_THREAD_COND_TIMEOUT_MS(250ms)
-- result depends on gp_interconnect_type:
-- * udpifc, "ERROR: fault triggered"
-- * tcp, "ERROR: canceling statement due to statement timeout"
begin; select count(*) from qe_errors_ic; rollback;
ERROR: fault triggered, fault name:'exec_mpp_query_start' fault type:'error' (seg1 slice1 127.0.0.1:6001 pid=69822)
reset statement_timeout;
select gp_inject_fault('exec_mpp_query_start', 'reset', 2);
gp_inject_fault
-----------------
Success:
(1 row)
select gp_inject_fault('exec_mpp_query_start', 'reset', 3);
gp_inject_fault
-----------------
Success:
(1 row)
select gp_inject_fault('exec_mpp_query_start', 'reset', 4);
gp_inject_fault
-----------------
Success:
(1 row)
DROP TABLE qe_errors_ic;