| /* |
| * |
| * 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; |
| |
| -- 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; |
| |
| -- 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); |
| |
| -- 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; |
| |
| -- 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); |
| |
| -- 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; |
| |
| 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; |
| |
| -- 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; |
| 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; |
| FETCH 20 FROM c2; |
| FETCH 20 FROM c3; |
| FETCH 20 FROM c4; |
| |
| 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); |
| |
| -- 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); |
| |
| -- 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); |
| |
| -- 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); |
| |
| -- 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); |
| |
| -- 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; |
| 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; |
| |
| -- Paramter range |
| SET gp_interconnect_snd_queue_depth TO -1; -- ERROR |
| SET gp_interconnect_snd_queue_depth TO 0; -- ERROR |
| SET gp_interconnect_snd_queue_depth TO 4097; -- ERROR |
| SET gp_interconnect_queue_depth TO -1; -- ERROR |
| SET gp_interconnect_queue_depth TO 0; -- ERROR |
| SET gp_interconnect_queue_depth TO 4097; -- ERROR |
| |
| -- 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; |
| --end_ignore |
| create table ic_test_1 as select i as c1, i as c2 from generate_series(1, 100000) i; |
| begin; |
| declare ic_test_cursor_c1 cursor for select * from ic_test_1; |
| select gp_inject_fault('interconnect_stop_ack_is_lost', 'reset', 1); |
| select gp_inject_fault('interconnect_stop_ack_is_lost', 'skip', 1); |
| 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); |
| SELECT * FROM a; |
| SELECT gp_inject_fault('interconnect_setup_palloc', 'reset', 1); |
| |
| -- The same, but the fault happens while dispatching an Init Plan. |
| SELECT gp_inject_fault('interconnect_setup_palloc', 'error', 1); |
| SELECT * FROM generate_series(1, 5) g WHERE g < (SELECT max(a.j) FROM a); |
| SELECT gp_inject_fault('interconnect_setup_palloc', 'reset', 1); |
| |
| 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); |
| SELECT gp_inject_fault('interconnect_setup_palloc', 'error', 2); |
| SELECT * FROM test_ic_error t1, test_ic_error t2 where t1.a=t2.b; |
| SELECT gp_inject_fault('interconnect_setup_palloc', 'reset', 2); |
| 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; |
| DROP TABLE recursive_table_ic; |
| |
| -- Test QD can notice the errors in QEs for initplan |
| CREATE TABLE qe_errors_ic (a INT, b INT); |
| 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); |
| |
| -- 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; |
| FETCH ALL FROM qe_errors_cursor; |
| --end_ignore |
| select 1; |
| 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); |
| select gp_inject_fault('exec_mpp_query_start', 'error', 3); |
| select gp_inject_fault('exec_mpp_query_start', 'sleep', '', '', '', 1, 1, 10, 4); |
| |
| 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; |
| reset statement_timeout; |
| |
| select gp_inject_fault('exec_mpp_query_start', 'reset', 2); |
| select gp_inject_fault('exec_mpp_query_start', 'reset', 3); |
| select gp_inject_fault('exec_mpp_query_start', 'reset', 4); |
| |
| DROP TABLE qe_errors_ic; |