diff --git a/src/postgres/src/test/regress/expected/yb_pg_misc.out b/src/postgres/src/test/regress/expected/yb_pg_misc.out index 95996b7ae44e..8567a47a72a1 100644 --- a/src/postgres/src/test/regress/expected/yb_pg_misc.out +++ b/src/postgres/src/test/regress/expected/yb_pg_misc.out @@ -7,24 +7,85 @@ \getenv libdir PG_LIBDIR \getenv dlsuffix PG_DLSUFFIX \set regresslib :libdir '/regress' :dlsuffix --- TODO requires 'INHERITS' which is not supported. CREATE FUNCTION overpaid(emp) RETURNS bool AS :'regresslib' - LANGUAGE C STRICT; + LANGUAGE C STRICT; -- YB: fails because creating emp requires unsupported INHERITS ERROR: type emp does not exist CREATE FUNCTION reverse_name(name) RETURNS name AS :'regresslib' LANGUAGE C STRICT; +-- +-- BTREE +-- +UPDATE onek + SET unique1 = onek.unique1 + 1; +UPDATE onek + SET unique1 = onek.unique1 - 1; +-- +-- BTREE partial +-- +-- UPDATE onek2 +-- SET unique1 = onek2.unique1 + 1; +--UPDATE onek2 +-- SET unique1 = onek2.unique1 - 1; +-- +-- BTREE shutting out non-functional updates +-- +-- the following two tests seem to take a long time on some +-- systems. This non-func update stuff needs to be examined +-- more closely. - jolly (2/22/96) +-- SELECT two, stringu1, ten, string4 INTO TABLE tmp FROM onek; +UPDATE tmp + SET stringu1 = reverse_name(onek.stringu1) + FROM onek + WHERE onek.stringu1 = 'JBAAAA' and + onek.stringu1 = tmp.stringu1; +UPDATE tmp + SET stringu1 = reverse_name(onek2.stringu1) + FROM onek2 + WHERE onek2.stringu1 = 'JCAAAA' and + onek2.stringu1 = tmp.stringu1; +DROP TABLE tmp; +--UPDATE person* +-- SET age = age + 1; +--UPDATE person* +-- SET age = age + 3 +-- WHERE name = 'linda'; +-- +-- copy +-- \set filename :abs_builddir '/results/onek.data' COPY onek TO :'filename'; --- YB note: create YB table instead of temp table to exercise YB tables. -CREATE TABLE onek_copy (LIKE onek); +CREATE TABLE onek_copy (LIKE onek); -- YB: create YB table instead of temp table to exercise YB tables COPY onek_copy FROM :'filename'; +SELECT * FROM onek EXCEPT ALL SELECT * FROM onek_copy; + unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 +---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- +(0 rows) + +SELECT * FROM onek_copy EXCEPT ALL SELECT * FROM onek; + unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 +---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- +(0 rows) + +\set filename :abs_builddir '/results/stud_emp.data' +COPY BINARY stud_emp TO :'filename'; +ERROR: relation "stud_emp" does not exist +/* YB: uncomment when stud_emp is available (needs INHERITS) +CREATE TEMP TABLE stud_emp_copy (LIKE stud_emp); + +COPY BINARY stud_emp_copy FROM :'filename'; + +SELECT * FROM stud_emp_copy; +*/ -- YB +-- +-- test data for postquel functions +-- CREATE TABLE hobbies_r ( name text, person text @@ -33,6 +94,22 @@ CREATE TABLE equipment_r ( name text, hobby text ); +INSERT INTO hobbies_r (name, person) + SELECT 'posthacking', p.name + FROM person* p + WHERE p.name = 'mike' or p.name = 'jeff'; +INSERT INTO hobbies_r (name, person) + SELECT 'basketball', p.name + FROM person p + WHERE p.name = 'joe' or p.name = 'sally'; +INSERT INTO hobbies_r (name) VALUES ('skywalking'); +INSERT INTO equipment_r (name, hobby) VALUES ('advil', 'posthacking'); +INSERT INTO equipment_r (name, hobby) VALUES ('peet''s coffee', 'posthacking'); +INSERT INTO equipment_r (name, hobby) VALUES ('hightops', 'basketball'); +INSERT INTO equipment_r (name, hobby) VALUES ('guts', 'skywalking'); +-- +-- postquel functions +-- CREATE FUNCTION hobbies(person) RETURNS setof hobbies_r AS 'select * from hobbies_r where person = $1.name' @@ -79,6 +156,143 @@ CREATE FUNCTION equipment_named_ambiguous_2b(hobby text) RETURNS setof equipment_r AS 'select * from equipment_r where equipment_r.hobby = hobby' LANGUAGE SQL; --- YB note: mimic natural discard of temp tables for tables that have been --- converted from temp tables in the upstream PG to YB tables here. -DROP TABLE onek_copy; +-- +-- mike does post_hacking, +-- joe and sally play basketball, and +-- everyone else does nothing. +-- +SELECT p.name, name(p.hobbies) FROM ONLY person p ORDER BY 2 DESC, 1; -- YB: add ordering + name | name +-------+------------- + mike | posthacking + joe | basketball + sally | basketball +(3 rows) + +/* YB: uncomment when person's descendant tables such as stud_emp are supported +-- +-- as above, but jeff also does post_hacking. +-- +SELECT p.name, name(p.hobbies) FROM person* p; + +-- +-- the next two queries demonstrate how functions generate bogus duplicates. +-- this is a "feature" .. +-- +SELECT DISTINCT hobbies_r.name, name(hobbies_r.equipment) FROM hobbies_r + ORDER BY 1,2; + +SELECT hobbies_r.name, (hobbies_r.equipment).name FROM hobbies_r; + +-- +-- mike needs advil and peet's coffee, +-- joe and sally need hightops, and +-- everyone else is fine. +-- +SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM ONLY person p; + +-- +-- as above, but jeff needs advil and peet's coffee as well. +-- +SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM person* p; + +-- +-- just like the last two, but make sure that the target list fixup and +-- unflattening is being done correctly. +-- +SELECT name(equipment(p.hobbies)), p.name, name(p.hobbies) FROM ONLY person p; + +SELECT (p.hobbies).equipment.name, p.name, name(p.hobbies) FROM person* p; + +SELECT (p.hobbies).equipment.name, name(p.hobbies), p.name FROM ONLY person p; + +SELECT name(equipment(p.hobbies)), name(p.hobbies), p.name FROM person* p; +*/ -- YB +SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer'))); + name +------ + guts +(1 row) + +SELECT name(equipment(hobby_construct_named(text 'skywalking', text 'mer'))); + name +------ + guts +(1 row) + +SELECT name(equipment_named(hobby_construct_named(text 'skywalking', text 'mer'))); + name +------ + guts +(1 row) + +SELECT name(equipment_named_ambiguous_1a(hobby_construct_named(text 'skywalking', text 'mer'))); + name +------ + guts +(1 row) + +SELECT name(equipment_named_ambiguous_1b(hobby_construct_named(text 'skywalking', text 'mer'))); + name +------ + guts +(1 row) + +SELECT name(equipment_named_ambiguous_1c(hobby_construct_named(text 'skywalking', text 'mer'))); + name +------ + guts +(1 row) + +SELECT name(equipment_named_ambiguous_2a(text 'skywalking')); + name +------ + guts +(1 row) + +SELECT name(equipment_named_ambiguous_2b(text 'skywalking')) ORDER BY substr(name(equipment_named_ambiguous_2b(text 'skywalking')), 2, 1); -- YB: add ordering + name +--------------- + advil + peet's coffee + hightops + guts +(4 rows) + +/* YB: output sometimes gives joe, sometimes sally +SELECT hobbies_by_name('basketball'); +*/ -- YB +SELECT name, overpaid(emp.*) FROM emp; +ERROR: relation "emp" does not exist +LINE 4: SELECT name, overpaid(emp.*) FROM emp; + ^ +-- +-- Try a few cases with SQL-spec row constructor expressions +-- +SELECT * FROM equipment(ROW('skywalking', 'mer')); + name | hobby +------+------------ + guts | skywalking +(1 row) + +SELECT name(equipment(ROW('skywalking', 'mer'))); + name +------ + guts +(1 row) + +/* YB: uncomment when person's descendant tables such as stud_emp are supported +SELECT *, name(equipment(h.*)) FROM hobbies_r h; + +SELECT *, (equipment(CAST((h.*) AS hobbies_r))).name FROM hobbies_r h; +*/ -- YB +-- +-- functional joins +-- +-- +-- instance rules +-- +-- +-- rewrite rules +-- +DROP TABLE onek_copy; -- YB: mimic natural discard of temp tables for tables that have been converted from temp tables in the upstream PG to YB tables here diff --git a/src/postgres/src/test/regress/expected/yb_pg_misc_functions.out b/src/postgres/src/test/regress/expected/yb_pg_misc_functions.out index f888dc25e7f4..6edd15415f6b 100644 --- a/src/postgres/src/test/regress/expected/yb_pg_misc_functions.out +++ b/src/postgres/src/test/regress/expected/yb_pg_misc_functions.out @@ -2,6 +2,280 @@ \getenv libdir PG_LIBDIR \getenv dlsuffix PG_DLSUFFIX \set regresslib :libdir '/regress' :dlsuffix +-- +-- num_nulls() +-- +SELECT num_nonnulls(NULL); + num_nonnulls +-------------- + 0 +(1 row) + +SELECT num_nonnulls('1'); + num_nonnulls +-------------- + 1 +(1 row) + +SELECT num_nonnulls(NULL::text); + num_nonnulls +-------------- + 0 +(1 row) + +SELECT num_nonnulls(NULL::text, NULL::int); + num_nonnulls +-------------- + 0 +(1 row) + +SELECT num_nonnulls(1, 2, NULL::text, NULL::point, '', int8 '9', 1.0 / NULL); + num_nonnulls +-------------- + 4 +(1 row) + +SELECT num_nonnulls(VARIADIC '{1,2,NULL,3}'::int[]); + num_nonnulls +-------------- + 3 +(1 row) + +SELECT num_nonnulls(VARIADIC '{"1","2","3","4"}'::text[]); + num_nonnulls +-------------- + 4 +(1 row) + +SELECT num_nonnulls(VARIADIC ARRAY(SELECT CASE WHEN i <> 40 THEN i END FROM generate_series(1, 100) i)); + num_nonnulls +-------------- + 99 +(1 row) + +SELECT num_nulls(NULL); + num_nulls +----------- + 1 +(1 row) + +SELECT num_nulls('1'); + num_nulls +----------- + 0 +(1 row) + +SELECT num_nulls(NULL::text); + num_nulls +----------- + 1 +(1 row) + +SELECT num_nulls(NULL::text, NULL::int); + num_nulls +----------- + 2 +(1 row) + +SELECT num_nulls(1, 2, NULL::text, NULL::point, '', int8 '9', 1.0 / NULL); + num_nulls +----------- + 3 +(1 row) + +SELECT num_nulls(VARIADIC '{1,2,NULL,3}'::int[]); + num_nulls +----------- + 1 +(1 row) + +SELECT num_nulls(VARIADIC '{"1","2","3","4"}'::text[]); + num_nulls +----------- + 0 +(1 row) + +SELECT num_nulls(VARIADIC ARRAY(SELECT CASE WHEN i <> 40 THEN i END FROM generate_series(1, 100) i)); + num_nulls +----------- + 1 +(1 row) + +-- special cases +SELECT num_nonnulls(VARIADIC NULL::text[]); + num_nonnulls +-------------- + +(1 row) + +SELECT num_nonnulls(VARIADIC '{}'::int[]); + num_nonnulls +-------------- + 0 +(1 row) + +SELECT num_nulls(VARIADIC NULL::text[]); + num_nulls +----------- + +(1 row) + +SELECT num_nulls(VARIADIC '{}'::int[]); + num_nulls +----------- + 0 +(1 row) + +-- should fail, one or more arguments is required +SELECT num_nonnulls(); +ERROR: function num_nonnulls() does not exist +LINE 1: SELECT num_nonnulls(); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +SELECT num_nulls(); +ERROR: function num_nulls() does not exist +LINE 1: SELECT num_nulls(); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +-- +-- canonicalize_path() +-- +CREATE FUNCTION test_canonicalize_path(text) + RETURNS text + AS :'regresslib' + LANGUAGE C STRICT IMMUTABLE; +SELECT test_canonicalize_path('/'); + test_canonicalize_path +------------------------ + / +(1 row) + +SELECT test_canonicalize_path('/./abc/def/'); + test_canonicalize_path +------------------------ + /abc/def +(1 row) + +SELECT test_canonicalize_path('/./../abc/def'); + test_canonicalize_path +------------------------ + /abc/def +(1 row) + +SELECT test_canonicalize_path('/./../../abc/def/'); + test_canonicalize_path +------------------------ + /abc/def +(1 row) + +SELECT test_canonicalize_path('/abc/.././def/ghi'); + test_canonicalize_path +------------------------ + /def/ghi +(1 row) + +SELECT test_canonicalize_path('/abc/./../def/ghi//'); + test_canonicalize_path +------------------------ + /def/ghi +(1 row) + +SELECT test_canonicalize_path('/abc/def/../..'); + test_canonicalize_path +------------------------ + / +(1 row) + +SELECT test_canonicalize_path('/abc/def/../../..'); + test_canonicalize_path +------------------------ + / +(1 row) + +SELECT test_canonicalize_path('/abc/def/../../../../ghi/jkl'); + test_canonicalize_path +------------------------ + /ghi/jkl +(1 row) + +SELECT test_canonicalize_path('.'); + test_canonicalize_path +------------------------ + . +(1 row) + +SELECT test_canonicalize_path('./'); + test_canonicalize_path +------------------------ + . +(1 row) + +SELECT test_canonicalize_path('./abc/..'); + test_canonicalize_path +------------------------ + . +(1 row) + +SELECT test_canonicalize_path('abc/../'); + test_canonicalize_path +------------------------ + . +(1 row) + +SELECT test_canonicalize_path('abc/../def'); + test_canonicalize_path +------------------------ + def +(1 row) + +SELECT test_canonicalize_path('..'); + test_canonicalize_path +------------------------ + .. +(1 row) + +SELECT test_canonicalize_path('../abc/def'); + test_canonicalize_path +------------------------ + ../abc/def +(1 row) + +SELECT test_canonicalize_path('../abc/..'); + test_canonicalize_path +------------------------ + .. +(1 row) + +SELECT test_canonicalize_path('../abc/../def'); + test_canonicalize_path +------------------------ + ../def +(1 row) + +SELECT test_canonicalize_path('../abc/../../def/ghi'); + test_canonicalize_path +------------------------ + ../../def/ghi +(1 row) + +SELECT test_canonicalize_path('./abc/./def/.'); + test_canonicalize_path +------------------------ + abc/def +(1 row) + +SELECT test_canonicalize_path('./abc/././def/.'); + test_canonicalize_path +------------------------ + abc/def +(1 row) + +SELECT test_canonicalize_path('./abc/./def/.././ghi/../../../jkl/mno'); + test_canonicalize_path +------------------------ + ../jkl/mno +(1 row) + -- -- pg_log_backend_memory_contexts() -- @@ -16,7 +290,244 @@ SELECT pg_log_backend_memory_contexts(pg_backend_pid()); t (1 row) +SELECT pg_log_backend_memory_contexts(pid) FROM pg_stat_activity + WHERE backend_type = 'checkpointer'; + pg_log_backend_memory_contexts +-------------------------------- + t +(1 row) + +CREATE ROLE regress_log_memory; +SELECT has_function_privilege('regress_log_memory', + 'pg_log_backend_memory_contexts(integer)', 'EXECUTE'); -- no + has_function_privilege +------------------------ + f +(1 row) + +GRANT EXECUTE ON FUNCTION pg_log_backend_memory_contexts(integer) + TO regress_log_memory; +SELECT has_function_privilege('regress_log_memory', + 'pg_log_backend_memory_contexts(integer)', 'EXECUTE'); -- yes + has_function_privilege +------------------------ + t +(1 row) + +SET ROLE regress_log_memory; +SELECT pg_log_backend_memory_contexts(pg_backend_pid()); + pg_log_backend_memory_contexts +-------------------------------- + t +(1 row) + +RESET ROLE; +REVOKE EXECUTE ON FUNCTION pg_log_backend_memory_contexts(integer) + FROM regress_log_memory; +DROP ROLE regress_log_memory; +-- +-- Test some built-in SRFs +-- +-- The outputs of these are variable, so we can't just print their results +-- directly, but we can at least verify that the code doesn't fail. +-- +select setting as segsize +from pg_settings where name = 'wal_segment_size' +\gset +select count(*) > 0 as ok from pg_ls_waldir(); + ok +---- + t +(1 row) + +-- Test ProjectSet as well as FunctionScan +select count(*) > 0 as ok from (select pg_ls_waldir()) ss; + ok +---- + t +(1 row) + +-- Test not-run-to-completion cases. +select * from pg_ls_waldir() limit 0; + name | size | modification +------+------+-------------- +(0 rows) + +select count(*) > 0 as ok from (select * from pg_ls_waldir() limit 1) ss; + ok +---- + t +(1 row) + +select (w).size = :segsize as ok +from (select pg_ls_waldir() w) ss where length((w).name) = 24 limit 1; + ok +---- + t +(1 row) + +select count(*) >= 0 as ok from pg_ls_archive_statusdir(); + ok +---- + t +(1 row) + +select * from (select pg_ls_dir('.') a) a where a = 'base' limit 1; + a +------ + base +(1 row) + +-- Test missing_ok (second argument) +select pg_ls_dir('does not exist', false, false); -- error +ERROR: could not open directory "does not exist": No such file or directory +select pg_ls_dir('does not exist', true, false); -- ok + pg_ls_dir +----------- +(0 rows) + +-- Test include_dot_dirs (third argument) +select count(*) = 1 as dot_found + from pg_ls_dir('.', false, true) as ls where ls = '.'; + dot_found +----------- + t +(1 row) + +select count(*) = 1 as dot_found + from pg_ls_dir('.', false, false) as ls where ls = '.'; + dot_found +----------- + f +(1 row) + +select * from (select (pg_timezone_names()).name) ptn where name='UTC' limit 1; + name +------ + UTC +(1 row) + +select count(*) > 0 from + (select pg_tablespace_databases(oid) as pts from pg_tablespace + where spcname = 'pg_default') pts + join pg_database db on pts.pts = db.oid; + ?column? +---------- + t +(1 row) + +-- +-- Test replication slot directory functions +-- +CREATE ROLE regress_slot_dir_funcs; +-- Not available by default. +SELECT has_function_privilege('regress_slot_dir_funcs', + 'pg_ls_logicalsnapdir()', 'EXECUTE'); + has_function_privilege +------------------------ + f +(1 row) + +SELECT has_function_privilege('regress_slot_dir_funcs', + 'pg_ls_logicalmapdir()', 'EXECUTE'); + has_function_privilege +------------------------ + f +(1 row) + +SELECT has_function_privilege('regress_slot_dir_funcs', + 'pg_ls_replslotdir(text)', 'EXECUTE'); + has_function_privilege +------------------------ + f +(1 row) + +GRANT pg_monitor TO regress_slot_dir_funcs; +-- Role is now part of pg_monitor, so these are available. +SELECT has_function_privilege('regress_slot_dir_funcs', + 'pg_ls_logicalsnapdir()', 'EXECUTE'); + has_function_privilege +------------------------ + t +(1 row) + +SELECT has_function_privilege('regress_slot_dir_funcs', + 'pg_ls_logicalmapdir()', 'EXECUTE'); + has_function_privilege +------------------------ + t +(1 row) + +SELECT has_function_privilege('regress_slot_dir_funcs', + 'pg_ls_replslotdir(text)', 'EXECUTE'); + has_function_privilege +------------------------ + t +(1 row) + +DROP ROLE regress_slot_dir_funcs; +-- +-- Test adding a support function to a subject function +-- +CREATE FUNCTION my_int_eq(int, int) RETURNS bool + LANGUAGE internal STRICT IMMUTABLE PARALLEL SAFE + AS $$int4eq$$; +-- By default, planner does not think that's selective +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 a JOIN tenk1 b ON a.unique1 = b.unique1 +WHERE my_int_eq(a.unique2, 42); -- YB: output's a and b are flipped + QUERY PLAN +---------------------------------------- + Hash Join + Hash Cond: (a.unique1 = b.unique1) + -> Seq Scan on tenk1 a + Filter: my_int_eq(unique2, 42) + -> Hash + -> Seq Scan on tenk1 b +(6 rows) + +-- With support function that knows it's int4eq, we get a different plan CREATE FUNCTION test_support_func(internal) RETURNS internal AS :'regresslib', 'test_support_func' LANGUAGE C STRICT; +ALTER FUNCTION my_int_eq(int, int) SUPPORT test_support_func; +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 a JOIN tenk1 b ON a.unique1 = b.unique1 +WHERE my_int_eq(a.unique2, 42); -- YB: TODO: investigate why NestLoop is still higher cost + QUERY PLAN +---------------------------------------- + Hash Join + Hash Cond: (a.unique1 = b.unique1) + -> Seq Scan on tenk1 a + Filter: my_int_eq(unique2, 42) + -> Hash + -> Seq Scan on tenk1 b +(6 rows) + +-- Also test non-default rowcount estimate +CREATE FUNCTION my_gen_series(int, int) RETURNS SETOF integer + LANGUAGE internal STRICT IMMUTABLE PARALLEL SAFE + AS $$generate_series_int4$$ + SUPPORT test_support_func; +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 a JOIN my_gen_series(1,1000) g ON a.unique1 = g; + QUERY PLAN +---------------------------------------- + Hash Join + Hash Cond: (g.g = a.unique1) + -> Function Scan on my_gen_series g + -> Hash + -> Seq Scan on tenk1 a +(5 rows) + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 a JOIN my_gen_series(1,10) g ON a.unique1 = g; + QUERY PLAN +---------------------------------------------------------------------- + YB Batched Nested Loop Join + Join Filter: (a.unique1 = g.g) + -> Function Scan on my_gen_series g + -> Index Scan using tenk1_unique1 on tenk1 a + Index Cond: (unique1 = ANY (ARRAY[g.g, $1, $2, ..., $1023])) +(5 rows) diff --git a/src/postgres/src/test/regress/expected/yb_pg_prepare.out b/src/postgres/src/test/regress/expected/yb_pg_prepare.out index d28781dda734..c55f32425e60 100644 --- a/src/postgres/src/test/regress/expected/yb_pg_prepare.out +++ b/src/postgres/src/test/regress/expected/yb_pg_prepare.out @@ -64,28 +64,108 @@ EXECUTE q2('postgres'); postgres | f | t (1 row) +PREPARE q3(text, int, float, boolean, smallint) AS + SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR + ten = $3::bigint OR true = $4 OR odd = $5::int) + ORDER BY unique1; +EXECUTE q3('AAAAxx', 5::smallint, 10.5::float, false, 4::bigint); + unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 +---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- + 2 | 2716 | 0 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 4 | 5 | CAAAAA | MAEAAA | AAAAxx + 102 | 612 | 0 | 2 | 2 | 2 | 2 | 102 | 102 | 102 | 102 | 4 | 5 | YDAAAA | OXAAAA | AAAAxx + 802 | 2908 | 0 | 2 | 2 | 2 | 2 | 802 | 802 | 802 | 802 | 4 | 5 | WEAAAA | WHEAAA | AAAAxx + 902 | 1104 | 0 | 2 | 2 | 2 | 2 | 902 | 902 | 902 | 902 | 4 | 5 | SIAAAA | MQBAAA | AAAAxx + 1002 | 2580 | 0 | 2 | 2 | 2 | 2 | 2 | 1002 | 1002 | 1002 | 4 | 5 | OMAAAA | GVDAAA | AAAAxx + 1602 | 8148 | 0 | 2 | 2 | 2 | 2 | 602 | 1602 | 1602 | 1602 | 4 | 5 | QJAAAA | KBMAAA | AAAAxx + 1702 | 7940 | 0 | 2 | 2 | 2 | 2 | 702 | 1702 | 1702 | 1702 | 4 | 5 | MNAAAA | KTLAAA | AAAAxx + 2102 | 6184 | 0 | 2 | 2 | 2 | 2 | 102 | 102 | 2102 | 2102 | 4 | 5 | WCAAAA | WDJAAA | AAAAxx + 2202 | 8028 | 0 | 2 | 2 | 2 | 2 | 202 | 202 | 2202 | 2202 | 4 | 5 | SGAAAA | UWLAAA | AAAAxx + 2302 | 7112 | 0 | 2 | 2 | 2 | 2 | 302 | 302 | 2302 | 2302 | 4 | 5 | OKAAAA | ONKAAA | AAAAxx + 2902 | 6816 | 0 | 2 | 2 | 2 | 2 | 902 | 902 | 2902 | 2902 | 4 | 5 | QHAAAA | ECKAAA | AAAAxx + 3202 | 7128 | 0 | 2 | 2 | 2 | 2 | 202 | 1202 | 3202 | 3202 | 4 | 5 | ETAAAA | EOKAAA | AAAAxx + 3902 | 9224 | 0 | 2 | 2 | 2 | 2 | 902 | 1902 | 3902 | 3902 | 4 | 5 | CUAAAA | UQNAAA | AAAAxx + 4102 | 7676 | 0 | 2 | 2 | 2 | 2 | 102 | 102 | 4102 | 4102 | 4 | 5 | UBAAAA | GJLAAA | AAAAxx + 4202 | 6628 | 0 | 2 | 2 | 2 | 2 | 202 | 202 | 4202 | 4202 | 4 | 5 | QFAAAA | YUJAAA | AAAAxx + 4502 | 412 | 0 | 2 | 2 | 2 | 2 | 502 | 502 | 4502 | 4502 | 4 | 5 | ERAAAA | WPAAAA | AAAAxx + 4702 | 2520 | 0 | 2 | 2 | 2 | 2 | 702 | 702 | 4702 | 4702 | 4 | 5 | WYAAAA | YSDAAA | AAAAxx + 4902 | 1600 | 0 | 2 | 2 | 2 | 2 | 902 | 902 | 4902 | 4902 | 4 | 5 | OGAAAA | OJCAAA | AAAAxx + 5602 | 8796 | 0 | 2 | 2 | 2 | 2 | 602 | 1602 | 602 | 5602 | 4 | 5 | MHAAAA | IANAAA | AAAAxx + 6002 | 8932 | 0 | 2 | 2 | 2 | 2 | 2 | 2 | 1002 | 6002 | 4 | 5 | WWAAAA | OFNAAA | AAAAxx + 6402 | 3808 | 0 | 2 | 2 | 2 | 2 | 402 | 402 | 1402 | 6402 | 4 | 5 | GMAAAA | MQFAAA | AAAAxx + 7602 | 1040 | 0 | 2 | 2 | 2 | 2 | 602 | 1602 | 2602 | 7602 | 4 | 5 | KGAAAA | AOBAAA | AAAAxx + 7802 | 7508 | 0 | 2 | 2 | 2 | 2 | 802 | 1802 | 2802 | 7802 | 4 | 5 | COAAAA | UCLAAA | AAAAxx + 8002 | 9980 | 0 | 2 | 2 | 2 | 2 | 2 | 2 | 3002 | 8002 | 4 | 5 | UVAAAA | WTOAAA | AAAAxx + 8302 | 7800 | 0 | 2 | 2 | 2 | 2 | 302 | 302 | 3302 | 8302 | 4 | 5 | IHAAAA | AOLAAA | AAAAxx + 8402 | 5708 | 0 | 2 | 2 | 2 | 2 | 402 | 402 | 3402 | 8402 | 4 | 5 | ELAAAA | OLIAAA | AAAAxx + 8602 | 5440 | 0 | 2 | 2 | 2 | 2 | 602 | 602 | 3602 | 8602 | 4 | 5 | WSAAAA | GBIAAA | AAAAxx + 9502 | 1812 | 0 | 2 | 2 | 2 | 2 | 502 | 1502 | 4502 | 9502 | 4 | 5 | MBAAAA | SRCAAA | AAAAxx + 9602 | 9972 | 0 | 2 | 2 | 2 | 2 | 602 | 1602 | 4602 | 9602 | 4 | 5 | IFAAAA | OTOAAA | AAAAxx +(29 rows) + +-- too few params +EXECUTE q3('bool'); +ERROR: wrong number of parameters for prepared statement "q3" +DETAIL: Expected 5 parameters but got 1. +-- too many params +EXECUTE q3('bytea', 5::smallint, 10.5::float, false, 4::bigint, true); +ERROR: wrong number of parameters for prepared statement "q3" +DETAIL: Expected 5 parameters but got 6. +-- wrong param types +EXECUTE q3(5::smallint, 10.5::float, false, 4::bigint, 'bytea'); +ERROR: parameter $3 of type boolean cannot be coerced to the expected type double precision +LINE 1: EXECUTE q3(5::smallint, 10.5::float, false, 4::bigint, 'byte... + ^ +HINT: You will need to rewrite or cast the expression. -- invalid type -PREPARE q3(nonexistenttype) AS SELECT $1; +PREPARE q4(nonexistenttype) AS SELECT $1; ERROR: type "nonexistenttype" does not exist -LINE 1: PREPARE q3(nonexistenttype) AS SELECT $1; +LINE 1: PREPARE q4(nonexistenttype) AS SELECT $1; ^ +-- create table as execute +PREPARE q5(int, text) AS + SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2 + ORDER BY unique1; +CREATE TEMPORARY TABLE q5_prep_results AS EXECUTE q5(200, 'DTAAAA'); +ERROR: CREATE TABLE AS EXECUTE not supported yet +LINE 1: CREATE TEMPORARY TABLE q5_prep_results AS EXECUTE q5(200, 'D... + ^ +HINT: Please report the issue on https://github.com/YugaByte/yugabyte-db/issues +/* YB: uncomment when above CREATE TABLE AS EXECUTE is supported +SELECT * FROM q5_prep_results; +CREATE TEMPORARY TABLE q5_prep_nodata AS EXECUTE q5(200, 'DTAAAA') + WITH NO DATA; +SELECT * FROM q5_prep_nodata; +*/ -- YB +SELECT 1; -- YB: add intermediate dummy query to avoid comments from polluting the below select from pg_prepared_statements + ?column? +---------- + 1 +(1 row) + -- unknown or unspecified parameter types: should succeed -PREPARE q4 AS - SELECT * FROM pg_database WHERE oid = $1 AND datname = $2; -PREPARE q5(unknown) AS - SELECT * FROM pg_namespace WHERE nspname = $1; +PREPARE q6 AS + SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2; +PREPARE q7(unknown) AS + SELECT * FROM road WHERE thepath = $1; SELECT name, statement, parameter_types FROM pg_prepared_statements ORDER BY name; - name | statement | parameter_types -------+----------------------------------------------------------------+----------------- - q2 | PREPARE q2(text) AS +| {text} - | SELECT datname, datistemplate, datallowconn +| - | FROM pg_database WHERE datname = $1; | - q4 | PREPARE q4 AS +| {oid,name} - | SELECT * FROM pg_database WHERE oid = $1 AND datname = $2; | - q5 | PREPARE q5(unknown) AS +| {name} - | SELECT * FROM pg_namespace WHERE nspname = $1; | -(3 rows) + name | statement | parameter_types +------+------------------------------------------------------------------+---------------------------------------------------- + q2 | PREPARE q2(text) AS +| {text} + | SELECT datname, datistemplate, datallowconn +| + | FROM pg_database WHERE datname = $1; | + q3 | PREPARE q3(text, int, float, boolean, smallint) AS +| {text,integer,"double precision",boolean,smallint} + | SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR+| + | ten = $3::bigint OR true = $4 OR odd = $5::int) +| + | ORDER BY unique1; | + q5 | PREPARE q5(int, text) AS +| {integer,text} + | SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2 +| + | ORDER BY unique1; | + q6 | PREPARE q6 AS +| {integer,name} + | SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2; | + q7 | PREPARE q7(unknown) AS +| {path} + | SELECT * FROM road WHERE thepath = $1; | +(5 rows) -- test DEALLOCATE ALL; DEALLOCATE ALL; diff --git a/src/postgres/src/test/regress/sql/yb_pg_misc.sql b/src/postgres/src/test/regress/sql/yb_pg_misc.sql index 2982f2bd69fe..ce33a0066749 100644 --- a/src/postgres/src/test/regress/sql/yb_pg_misc.sql +++ b/src/postgres/src/test/regress/sql/yb_pg_misc.sql @@ -10,29 +10,95 @@ \set regresslib :libdir '/regress' :dlsuffix --- TODO requires 'INHERITS' which is not supported. CREATE FUNCTION overpaid(emp) RETURNS bool AS :'regresslib' - LANGUAGE C STRICT; + LANGUAGE C STRICT; -- YB: fails because creating emp requires unsupported INHERITS CREATE FUNCTION reverse_name(name) RETURNS name AS :'regresslib' LANGUAGE C STRICT; +-- +-- BTREE +-- +UPDATE onek + SET unique1 = onek.unique1 + 1; + +UPDATE onek + SET unique1 = onek.unique1 - 1; + +-- +-- BTREE partial +-- +-- UPDATE onek2 +-- SET unique1 = onek2.unique1 + 1; + +--UPDATE onek2 +-- SET unique1 = onek2.unique1 - 1; + +-- +-- BTREE shutting out non-functional updates +-- +-- the following two tests seem to take a long time on some +-- systems. This non-func update stuff needs to be examined +-- more closely. - jolly (2/22/96) +-- SELECT two, stringu1, ten, string4 INTO TABLE tmp FROM onek; +UPDATE tmp + SET stringu1 = reverse_name(onek.stringu1) + FROM onek + WHERE onek.stringu1 = 'JBAAAA' and + onek.stringu1 = tmp.stringu1; + +UPDATE tmp + SET stringu1 = reverse_name(onek2.stringu1) + FROM onek2 + WHERE onek2.stringu1 = 'JCAAAA' and + onek2.stringu1 = tmp.stringu1; + +DROP TABLE tmp; + +--UPDATE person* +-- SET age = age + 1; + +--UPDATE person* +-- SET age = age + 3 +-- WHERE name = 'linda'; + +-- +-- copy +-- \set filename :abs_builddir '/results/onek.data' COPY onek TO :'filename'; --- YB note: create YB table instead of temp table to exercise YB tables. -CREATE TABLE onek_copy (LIKE onek); +CREATE TABLE onek_copy (LIKE onek); -- YB: create YB table instead of temp table to exercise YB tables COPY onek_copy FROM :'filename'; +SELECT * FROM onek EXCEPT ALL SELECT * FROM onek_copy; + +SELECT * FROM onek_copy EXCEPT ALL SELECT * FROM onek; + +\set filename :abs_builddir '/results/stud_emp.data' +COPY BINARY stud_emp TO :'filename'; + +/* YB: uncomment when stud_emp is available (needs INHERITS) +CREATE TEMP TABLE stud_emp_copy (LIKE stud_emp); + +COPY BINARY stud_emp_copy FROM :'filename'; + +SELECT * FROM stud_emp_copy; +*/ -- YB + +-- +-- test data for postquel functions +-- + CREATE TABLE hobbies_r ( name text, person text @@ -43,6 +109,30 @@ CREATE TABLE equipment_r ( hobby text ); +INSERT INTO hobbies_r (name, person) + SELECT 'posthacking', p.name + FROM person* p + WHERE p.name = 'mike' or p.name = 'jeff'; + +INSERT INTO hobbies_r (name, person) + SELECT 'basketball', p.name + FROM person p + WHERE p.name = 'joe' or p.name = 'sally'; + +INSERT INTO hobbies_r (name) VALUES ('skywalking'); + +INSERT INTO equipment_r (name, hobby) VALUES ('advil', 'posthacking'); + +INSERT INTO equipment_r (name, hobby) VALUES ('peet''s coffee', 'posthacking'); + +INSERT INTO equipment_r (name, hobby) VALUES ('hightops', 'basketball'); + +INSERT INTO equipment_r (name, hobby) VALUES ('guts', 'skywalking'); + +-- +-- postquel functions +-- + CREATE FUNCTION hobbies(person) RETURNS setof hobbies_r AS 'select * from hobbies_r where person = $1.name' @@ -98,6 +188,97 @@ CREATE FUNCTION equipment_named_ambiguous_2b(hobby text) AS 'select * from equipment_r where equipment_r.hobby = hobby' LANGUAGE SQL; --- YB note: mimic natural discard of temp tables for tables that have been --- converted from temp tables in the upstream PG to YB tables here. -DROP TABLE onek_copy; +-- +-- mike does post_hacking, +-- joe and sally play basketball, and +-- everyone else does nothing. +-- +SELECT p.name, name(p.hobbies) FROM ONLY person p ORDER BY 2 DESC, 1; -- YB: add ordering + +/* YB: uncomment when person's descendant tables such as stud_emp are supported +-- +-- as above, but jeff also does post_hacking. +-- +SELECT p.name, name(p.hobbies) FROM person* p; + +-- +-- the next two queries demonstrate how functions generate bogus duplicates. +-- this is a "feature" .. +-- +SELECT DISTINCT hobbies_r.name, name(hobbies_r.equipment) FROM hobbies_r + ORDER BY 1,2; + +SELECT hobbies_r.name, (hobbies_r.equipment).name FROM hobbies_r; + +-- +-- mike needs advil and peet's coffee, +-- joe and sally need hightops, and +-- everyone else is fine. +-- +SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM ONLY person p; + +-- +-- as above, but jeff needs advil and peet's coffee as well. +-- +SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM person* p; + +-- +-- just like the last two, but make sure that the target list fixup and +-- unflattening is being done correctly. +-- +SELECT name(equipment(p.hobbies)), p.name, name(p.hobbies) FROM ONLY person p; + +SELECT (p.hobbies).equipment.name, p.name, name(p.hobbies) FROM person* p; + +SELECT (p.hobbies).equipment.name, name(p.hobbies), p.name FROM ONLY person p; + +SELECT name(equipment(p.hobbies)), name(p.hobbies), p.name FROM person* p; +*/ -- YB + +SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer'))); + +SELECT name(equipment(hobby_construct_named(text 'skywalking', text 'mer'))); + +SELECT name(equipment_named(hobby_construct_named(text 'skywalking', text 'mer'))); + +SELECT name(equipment_named_ambiguous_1a(hobby_construct_named(text 'skywalking', text 'mer'))); + +SELECT name(equipment_named_ambiguous_1b(hobby_construct_named(text 'skywalking', text 'mer'))); + +SELECT name(equipment_named_ambiguous_1c(hobby_construct_named(text 'skywalking', text 'mer'))); + +SELECT name(equipment_named_ambiguous_2a(text 'skywalking')); + +SELECT name(equipment_named_ambiguous_2b(text 'skywalking')) ORDER BY substr(name(equipment_named_ambiguous_2b(text 'skywalking')), 2, 1); -- YB: add ordering + +/* YB: output sometimes gives joe, sometimes sally +SELECT hobbies_by_name('basketball'); +*/ -- YB + +SELECT name, overpaid(emp.*) FROM emp; + +-- +-- Try a few cases with SQL-spec row constructor expressions +-- +SELECT * FROM equipment(ROW('skywalking', 'mer')); + +SELECT name(equipment(ROW('skywalking', 'mer'))); + +/* YB: uncomment when person's descendant tables such as stud_emp are supported +SELECT *, name(equipment(h.*)) FROM hobbies_r h; + +SELECT *, (equipment(CAST((h.*) AS hobbies_r))).name FROM hobbies_r h; +*/ -- YB + +-- +-- functional joins +-- + +-- +-- instance rules +-- + +-- +-- rewrite rules +-- +DROP TABLE onek_copy; -- YB: mimic natural discard of temp tables for tables that have been converted from temp tables in the upstream PG to YB tables here diff --git a/src/postgres/src/test/regress/sql/yb_pg_misc_functions.sql b/src/postgres/src/test/regress/sql/yb_pg_misc_functions.sql index 3fadd8737729..e43dd31c588e 100644 --- a/src/postgres/src/test/regress/sql/yb_pg_misc_functions.sql +++ b/src/postgres/src/test/regress/sql/yb_pg_misc_functions.sql @@ -4,6 +4,70 @@ \set regresslib :libdir '/regress' :dlsuffix +-- +-- num_nulls() +-- + +SELECT num_nonnulls(NULL); +SELECT num_nonnulls('1'); +SELECT num_nonnulls(NULL::text); +SELECT num_nonnulls(NULL::text, NULL::int); +SELECT num_nonnulls(1, 2, NULL::text, NULL::point, '', int8 '9', 1.0 / NULL); +SELECT num_nonnulls(VARIADIC '{1,2,NULL,3}'::int[]); +SELECT num_nonnulls(VARIADIC '{"1","2","3","4"}'::text[]); +SELECT num_nonnulls(VARIADIC ARRAY(SELECT CASE WHEN i <> 40 THEN i END FROM generate_series(1, 100) i)); + +SELECT num_nulls(NULL); +SELECT num_nulls('1'); +SELECT num_nulls(NULL::text); +SELECT num_nulls(NULL::text, NULL::int); +SELECT num_nulls(1, 2, NULL::text, NULL::point, '', int8 '9', 1.0 / NULL); +SELECT num_nulls(VARIADIC '{1,2,NULL,3}'::int[]); +SELECT num_nulls(VARIADIC '{"1","2","3","4"}'::text[]); +SELECT num_nulls(VARIADIC ARRAY(SELECT CASE WHEN i <> 40 THEN i END FROM generate_series(1, 100) i)); + +-- special cases +SELECT num_nonnulls(VARIADIC NULL::text[]); +SELECT num_nonnulls(VARIADIC '{}'::int[]); +SELECT num_nulls(VARIADIC NULL::text[]); +SELECT num_nulls(VARIADIC '{}'::int[]); + +-- should fail, one or more arguments is required +SELECT num_nonnulls(); +SELECT num_nulls(); + +-- +-- canonicalize_path() +-- + +CREATE FUNCTION test_canonicalize_path(text) + RETURNS text + AS :'regresslib' + LANGUAGE C STRICT IMMUTABLE; + +SELECT test_canonicalize_path('/'); +SELECT test_canonicalize_path('/./abc/def/'); +SELECT test_canonicalize_path('/./../abc/def'); +SELECT test_canonicalize_path('/./../../abc/def/'); +SELECT test_canonicalize_path('/abc/.././def/ghi'); +SELECT test_canonicalize_path('/abc/./../def/ghi//'); +SELECT test_canonicalize_path('/abc/def/../..'); +SELECT test_canonicalize_path('/abc/def/../../..'); +SELECT test_canonicalize_path('/abc/def/../../../../ghi/jkl'); +SELECT test_canonicalize_path('.'); +SELECT test_canonicalize_path('./'); +SELECT test_canonicalize_path('./abc/..'); +SELECT test_canonicalize_path('abc/../'); +SELECT test_canonicalize_path('abc/../def'); +SELECT test_canonicalize_path('..'); +SELECT test_canonicalize_path('../abc/def'); +SELECT test_canonicalize_path('../abc/..'); +SELECT test_canonicalize_path('../abc/../def'); +SELECT test_canonicalize_path('../abc/../../def/ghi'); +SELECT test_canonicalize_path('./abc/./def/.'); +SELECT test_canonicalize_path('./abc/././def/.'); +SELECT test_canonicalize_path('./abc/./def/.././ghi/../../../jkl/mno'); + -- -- pg_log_backend_memory_contexts() -- @@ -15,7 +79,121 @@ SELECT pg_log_backend_memory_contexts(pg_backend_pid()); +SELECT pg_log_backend_memory_contexts(pid) FROM pg_stat_activity + WHERE backend_type = 'checkpointer'; + +CREATE ROLE regress_log_memory; + +SELECT has_function_privilege('regress_log_memory', + 'pg_log_backend_memory_contexts(integer)', 'EXECUTE'); -- no + +GRANT EXECUTE ON FUNCTION pg_log_backend_memory_contexts(integer) + TO regress_log_memory; + +SELECT has_function_privilege('regress_log_memory', + 'pg_log_backend_memory_contexts(integer)', 'EXECUTE'); -- yes + +SET ROLE regress_log_memory; +SELECT pg_log_backend_memory_contexts(pg_backend_pid()); +RESET ROLE; + +REVOKE EXECUTE ON FUNCTION pg_log_backend_memory_contexts(integer) + FROM regress_log_memory; + +DROP ROLE regress_log_memory; + +-- +-- Test some built-in SRFs +-- +-- The outputs of these are variable, so we can't just print their results +-- directly, but we can at least verify that the code doesn't fail. +-- +select setting as segsize +from pg_settings where name = 'wal_segment_size' +\gset + +select count(*) > 0 as ok from pg_ls_waldir(); +-- Test ProjectSet as well as FunctionScan +select count(*) > 0 as ok from (select pg_ls_waldir()) ss; +-- Test not-run-to-completion cases. +select * from pg_ls_waldir() limit 0; +select count(*) > 0 as ok from (select * from pg_ls_waldir() limit 1) ss; +select (w).size = :segsize as ok +from (select pg_ls_waldir() w) ss where length((w).name) = 24 limit 1; + +select count(*) >= 0 as ok from pg_ls_archive_statusdir(); + +select * from (select pg_ls_dir('.') a) a where a = 'base' limit 1; +-- Test missing_ok (second argument) +select pg_ls_dir('does not exist', false, false); -- error +select pg_ls_dir('does not exist', true, false); -- ok +-- Test include_dot_dirs (third argument) +select count(*) = 1 as dot_found + from pg_ls_dir('.', false, true) as ls where ls = '.'; +select count(*) = 1 as dot_found + from pg_ls_dir('.', false, false) as ls where ls = '.'; + +select * from (select (pg_timezone_names()).name) ptn where name='UTC' limit 1; + +select count(*) > 0 from + (select pg_tablespace_databases(oid) as pts from pg_tablespace + where spcname = 'pg_default') pts + join pg_database db on pts.pts = db.oid; + +-- +-- Test replication slot directory functions +-- +CREATE ROLE regress_slot_dir_funcs; +-- Not available by default. +SELECT has_function_privilege('regress_slot_dir_funcs', + 'pg_ls_logicalsnapdir()', 'EXECUTE'); +SELECT has_function_privilege('regress_slot_dir_funcs', + 'pg_ls_logicalmapdir()', 'EXECUTE'); +SELECT has_function_privilege('regress_slot_dir_funcs', + 'pg_ls_replslotdir(text)', 'EXECUTE'); +GRANT pg_monitor TO regress_slot_dir_funcs; +-- Role is now part of pg_monitor, so these are available. +SELECT has_function_privilege('regress_slot_dir_funcs', + 'pg_ls_logicalsnapdir()', 'EXECUTE'); +SELECT has_function_privilege('regress_slot_dir_funcs', + 'pg_ls_logicalmapdir()', 'EXECUTE'); +SELECT has_function_privilege('regress_slot_dir_funcs', + 'pg_ls_replslotdir(text)', 'EXECUTE'); +DROP ROLE regress_slot_dir_funcs; + +-- +-- Test adding a support function to a subject function +-- + +CREATE FUNCTION my_int_eq(int, int) RETURNS bool + LANGUAGE internal STRICT IMMUTABLE PARALLEL SAFE + AS $$int4eq$$; + +-- By default, planner does not think that's selective +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 a JOIN tenk1 b ON a.unique1 = b.unique1 +WHERE my_int_eq(a.unique2, 42); -- YB: output's a and b are flipped + +-- With support function that knows it's int4eq, we get a different plan CREATE FUNCTION test_support_func(internal) RETURNS internal AS :'regresslib', 'test_support_func' LANGUAGE C STRICT; + +ALTER FUNCTION my_int_eq(int, int) SUPPORT test_support_func; + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 a JOIN tenk1 b ON a.unique1 = b.unique1 +WHERE my_int_eq(a.unique2, 42); -- YB: TODO: investigate why NestLoop is still higher cost + +-- Also test non-default rowcount estimate +CREATE FUNCTION my_gen_series(int, int) RETURNS SETOF integer + LANGUAGE internal STRICT IMMUTABLE PARALLEL SAFE + AS $$generate_series_int4$$ + SUPPORT test_support_func; + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 a JOIN my_gen_series(1,1000) g ON a.unique1 = g; + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 a JOIN my_gen_series(1,10) g ON a.unique1 = g; diff --git a/src/postgres/src/test/regress/sql/yb_pg_prepare.sql b/src/postgres/src/test/regress/sql/yb_pg_prepare.sql index 34d7350b3cc1..3f0fc64da685 100644 --- a/src/postgres/src/test/regress/sql/yb_pg_prepare.sql +++ b/src/postgres/src/test/regress/sql/yb_pg_prepare.sql @@ -36,14 +36,43 @@ PREPARE q2(text) AS EXECUTE q2('postgres'); +PREPARE q3(text, int, float, boolean, smallint) AS + SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR + ten = $3::bigint OR true = $4 OR odd = $5::int) + ORDER BY unique1; + +EXECUTE q3('AAAAxx', 5::smallint, 10.5::float, false, 4::bigint); + +-- too few params +EXECUTE q3('bool'); + +-- too many params +EXECUTE q3('bytea', 5::smallint, 10.5::float, false, 4::bigint, true); + +-- wrong param types +EXECUTE q3(5::smallint, 10.5::float, false, 4::bigint, 'bytea'); + -- invalid type -PREPARE q3(nonexistenttype) AS SELECT $1; +PREPARE q4(nonexistenttype) AS SELECT $1; + +-- create table as execute +PREPARE q5(int, text) AS + SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2 + ORDER BY unique1; +CREATE TEMPORARY TABLE q5_prep_results AS EXECUTE q5(200, 'DTAAAA'); +/* YB: uncomment when above CREATE TABLE AS EXECUTE is supported +SELECT * FROM q5_prep_results; +CREATE TEMPORARY TABLE q5_prep_nodata AS EXECUTE q5(200, 'DTAAAA') + WITH NO DATA; +SELECT * FROM q5_prep_nodata; +*/ -- YB +SELECT 1; -- YB: add intermediate dummy query to avoid comments from polluting the below select from pg_prepared_statements -- unknown or unspecified parameter types: should succeed -PREPARE q4 AS - SELECT * FROM pg_database WHERE oid = $1 AND datname = $2; -PREPARE q5(unknown) AS - SELECT * FROM pg_namespace WHERE nspname = $1; +PREPARE q6 AS + SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2; +PREPARE q7(unknown) AS + SELECT * FROM road WHERE thepath = $1; SELECT name, statement, parameter_types FROM pg_prepared_statements ORDER BY name; diff --git a/src/postgres/src/test/regress/yb_pg_misc_independent_serial_schedule b/src/postgres/src/test/regress/yb_pg_misc_independent_serial_schedule index 3a927b775a15..c052dc0b6cfc 100644 --- a/src/postgres/src/test/regress/yb_pg_misc_independent_serial_schedule +++ b/src/postgres/src/test/regress/yb_pg_misc_independent_serial_schedule @@ -17,11 +17,8 @@ test: yb_pg_lock test: yb_pg_drop_operator test: yb_pg_alter_generic test: yb_pg_alter_operator -test: yb_pg_misc test: yb_pg_dbsize -test: yb_pg_misc_functions test: yb_pg_indirect_toast -test: yb_pg_prepare test: yb_pg_conversion test: yb_pg_truncate test: yb_pg_sequence diff --git a/src/postgres/src/test/regress/yb_pg_misc_serial_schedule b/src/postgres/src/test/regress/yb_pg_misc_serial_schedule index 495b9ec0dfb0..794eb4a442dc 100644 --- a/src/postgres/src/test/regress/yb_pg_misc_serial_schedule +++ b/src/postgres/src/test/regress/yb_pg_misc_serial_schedule @@ -5,7 +5,8 @@ # This includes miscellaneous tests that are not yet characterized to a proper testsuite. Unlike # yb_pg_misc_independent_serial_schedule, the tests in this schedule have dependencies. #################################################################################################### -# Dependency for yb_pg_create_index, yb_pg_errors, yb_pg_with +# Dependency for yb_pg_create_index, yb_pg_errors, yb_pg_misc, +# yb_pg_misc_functions, yb_pg_prepare, yb_pg_with test: yb_pg_test_setup # Dependency for yb_pg_create_operator @@ -19,4 +20,7 @@ test: yb_pg_create_operator test: yb_pg_create_index test: yb_pg_create_am test: yb_pg_errors +test: yb_pg_misc +test: yb_pg_misc_functions +test: yb_pg_prepare test: yb_pg_with