blob: d9eb2bf8fe108a7fed0fd173baa837ad07aba5f0 [file] [log] [blame]
SET datestyle = "ISO, DMY";
-- Test heuristic to resolve unknown-type literals when there are ambiguous
-- functions, added in PostgreSQL commit 1a8b9fb549.
create function ambigargfunc(a int4, b int4) returns text as $$ select 'int variant chosen'::text $$ language sql;
create function ambigargfunc(a int4, b timestamp) returns text as $$ select 'timestamp variant chosen'::text $$ language sql;
select ambigargfunc(1,'2');
drop table if exists test;
create table test (a integer, b integer) distributed by (a);
insert into test select a, a%25 from generate_series(1,100) a;
select greatest(a,b) from test order by a;
select least(a,b) from test order by a;
CREATE OR REPLACE FUNCTION add_em(integer, integer) RETURNS integer AS $$ SELECT $1 + $2; $$ LANGUAGE SQL;
SELECT add_em(75, 25) AS answer;
SELECT add_em(25, 75, 100) AS answer;
CREATE or replace FUNCTION add_em(integer, integer) RETURNS integer AS $$ SELECT $12 + $20; $$ LANGUAGE SQL;
CREATE or replace FUNCTION add_em(integer, integer) RETURNS integer AS $$ SELECT $1 + $2 + $3; $$ LANGUAGE SQL;
CREATE or replace FUNCTION add_em(integer, integer, integer) RETURNS integer AS $$ SELECT $1 + $2; $$ LANGUAGE SQL;
SELECT add_em(25, 75, 100) AS answer;
SELECT add_em(25, 75) AS answer;
SELECT add_em(25) AS answer;
create table bank_ac(acno int, name char(20), balance numeric) distributed by (acno);
insert into bank_ac values(1,'anne',1000);
insert into bank_ac values(3,'chinni',3000);
insert into bank_ac values(4,'dany',4000);
insert into bank_ac values(5,'eric',5000);
insert into bank_ac values(6,'frank',6000);
create or replace function ac_debit1(int,numeric) returns integer AS ' update bank_ac set balance = balance - $2 where acno=$1; select 1;' language sql;
select ac_debit1(2,100);
create or replace function ac_debit(int,numeric) returns numeric as 'UPDATE bank_ac set balance = balance - $2 where acno = $1; select balance from bank_ac where acno = $1;' language sql;
select ac_debit(4, 500);
select * from bank_ac order by acno;
create or replace function ac_credit(int,numeric) returns numeric as 'UPDATE bank_ac set balance = balance + $2 where acno = $1; select balance from bank_ac where acno = $1;' language sql;
select ac_credit(2, 800);
create or replace function ac_delete(int) returns int AS 'delete from bank_ac where acno=$1;' language sql;
create or replace function ac_delete(int) returns int AS 'delete from bank_ac where acno=$1; select 1;' language sql;
select ac_delete(1);
select * from bank_ac where acno = 1;
create table emp_fun(name text, salary numeric, age integer, cubicle point) distributed by (name);
insert into emp_fun values ( 'apple',1000,23,'(1,1)');
insert into emp_fun values ( 'bill',2000,25,'(1,2)');
insert into emp_fun values ( 'cathy',3000,22,'(2,1)');
insert into emp_fun values ( 'drill',3400,45,'(2,2)');
create or replace function increment(emp_fun) returns numeric as ' select $1.salary*2 as salary; ' language sql;
select * from emp_fun order by name;
select name, increment(emp_fun) as new_sal from emp_fun where emp_fun.name='bill';
select name, increment(emp_fun.*) AS new_sal from emp_fun where emp_fun.cubicle ~= point '(2,1)';
select name, increment(ROW(name,salary*1.1,age,cubicle)) AS new_sal from emp_fun order by name;
create or replace function new_emp_fun() returns emp_fun as $$ select text 'henry' AS name, 1000.0 AS salary, 25 AS age, point '(2,2)' AS cubicle; $$ language sql;
select new_emp_fun();
create or replace function new_emp_fun() returns emp_fun AS $$ select ROW('henry',1000.0,25,'(2,2)')::emp_fun; $$ language sql;
select new_emp_fun();
select * from new_emp_fun();
select (new_emp_fun()).name;
select new_emp_fun().name;
select name(new_emp_fun());
create or replace function get_emp_name(emp_fun) returns text AS $$ select $1.name; $$language sql;
select get_emp_name(new_emp_fun());
create or replace function add_num2(IN x int, IN y int, OUT sum int) AS 'select $1+$2' language sql;
select add_num2(25,35);
create or replace function add_num2(IN x int, IN y int) AS 'select $1+$2' language sql;
create or replace function add_num(IN x int, IN y int, OUT sum int, OUT product int) AS 'select $1+$2, $1*$2' language sql;
select add_num(4,5);
create or replace function add_num(x int, y int, sum int, product int) returns integer AS 'select $1+$2, $1*$2;' language sql;
create type sum_prod AS (sum int, product int);
create or replace function num_add_prod(int,int) returns sum_prod AS 'select $1 + $2, $1*$2' language sql;
select num_add_prod(10,12);
create or replace function add_inout(IN x int, INOUT y int) AS 'select $1+$2' language sql;
select add_inout(4,8);
create table tab_sour(tabid int, tabsubid int, tabname text) distributed by (tabid);
insert into tab_sour values(1,1,'joe');
insert into tab_sour values(1,2,'ed');
insert into tab_sour values(2,1,'mary');
select * from tab_sour;
create or replace function get_tab(int) returns tab_sour AS $$ select * from tab_sour where tabid=$1; $$ language sql;
select *, upper(tabname) from get_tab(1) as t1;
create or replace function set_tab(int) returns SETOF tab_sour as $$ select * from tab_sour where tabid=$1; $$ language sql;
select * from set_tab(1) as new_tab;
create table fun_tree(name text, parent text) distributed by (name);
insert into fun_tree values('grand_parent','');
insert into fun_tree values('parent1','grand_parent');
insert into fun_tree values('parent2','grand_parent');
insert into fun_tree values('parent3','grand_parent');
insert into fun_tree values('child1','parent1');
insert into fun_tree values('child2','parent1');
insert into fun_tree values('child3','parent2');
insert into fun_tree values('child4','parent3');
select * from fun_tree;
create or replace function child_list(text) returns SETOF text AS $$ select name FROM fun_tree where parent =$1 order by name $$ language sql;
select child_list('grand_parent');
select name, child_list(name) from fun_tree;
create or replace function fun_array(anyelement,anyelement) returns anyarray AS $$ select array[$1,$2]; $$ language sql;
select fun_array(25,50) as intarray, fun_array('abc'::text, 'bcf') AS textarray;
select fun_array(25,50) as intarray, fun_array('abc', 'bcf') AS textarray;
create or replace function fun_is_greater(anyelement,anyelement) returns boolean AS $$ select $1 > $2 $$ language sql;
select fun_is_greater(3,5);
select fun_is_greater(7,5);
create or replace function invalid_func() returns anyelement as $$ select 1; $$ language sql;
create or replace function fun_dup(f1 anyelement, OUT f2 anyelement, OUT f3 anyarray) AS 'select $1, array[$1,$1]' language sql;
select * from fun_dup(22);
select current_database();
select current_schema();
select current_schemas(true);
select current_schemas(false);
select current_setting('datestyle');
SELECT round(4, 2);
SELECT round(4, 0);
SELECT round(4, -1);
SELECT round(4);
SELECT round(4, 1+1);
SELECT round(CAST (4 AS numeric), 4);
SELECT round(4.0, 4);
SELECT round(0.998, 2);
SELECT substr('1234', 3);
SELECT substr(varchar '1234', 3);
SELECT substr(CAST (varchar '1234' AS text), 3);
SELECT substr(CAST (varchar '1234' AS text), 3);
SELECT substr(1234, 3);
SELECT substr(CAST (1234 AS text), 3);
select * from generate_series(2,4);
select * from generate_series(5,1,-2);
select * from generate_series(4,3);
select date '2007-12-11' + s.a as dates from generate_series(0,14,7) as s(a);
CREATE or REPLACE FUNCTION add_one (integer) RETURNS integer AS '
BEGIN
RETURN $1 + 1;
END;
' LANGUAGE 'plpgsql';
select add_one(4);
CREATE or REPLACE FUNCTION concat_text (text, text) RETURNS text AS '
BEGIN
RETURN $1 || $2;
END;
' LANGUAGE 'plpgsql';
select concat_text('Cloud','berry');
CREATE or REPLACE FUNCTION sales_tax(subtotal real) RETURNS real AS $$
BEGIN
RETURN subtotal * 0.06;
END;
$$ LANGUAGE plpgsql;
select sales_tax(30);
CREATE or REPLACE FUNCTION sales_tax_new(real) RETURNS real AS $$
DECLARE
subtotal ALIAS FOR $1;
BEGIN
RETURN subtotal * 0.06;
END;
$$ LANGUAGE plpgsql;
select sales_tax_new(40.68);
CREATE or REPLACE FUNCTION instr(varchar, integer) RETURNS integer AS $$
DECLARE
v_string ALIAS FOR $1;
index ALIAS FOR $2;
BEGIN
RETURN index+10;
END;
$$ LANGUAGE plpgsql;
select instr('next',3);
CREATE or REPLACE FUNCTION instr(varchar, integer) RETURNS integer AS $$
DECLARE
v_string ALIAS FOR $1;
index ALIAS FOR $2;
BEGIN
RETURN index*10;
END;
$$ LANGUAGE plpgsql;
CREATE or REPLACE FUNCTION sales_tax(subtotal real, OUT tax real) AS $$
BEGIN
tax := subtotal * 0.06;
END;
$$ LANGUAGE plpgsql;
select sales_tax(30);
CREATE or REPLACE FUNCTION sum_n_product(x int, y int, OUT sum int, OUT prod int) AS $$
BEGIN
sum := x + y;
prod := x * y;
END;
$$ LANGUAGE plpgsql;
select sum_n_product(12,10);
CREATE or REPLACE FUNCTION add_three_values(v1 anyelement, v2 anyelement, v3 anyelement) RETURNS anyelement AS $$
DECLARE
result ALIAS FOR $0;
BEGIN
result := v1 + v2 + v3;
RETURN result;
END;
$$ LANGUAGE plpgsql;
select add_three_values(1,2,3);
CREATE or REPLACE FUNCTION add_three_values(v1 anyelement, v2 anyelement, v3 anyelement, OUT sum anyelement) AS $$
BEGIN
sum := v1 + v2 + v3;
END;
$$ LANGUAGE plpgsql;
select add_three_values(1,2,3);
create table logtable(a text,b text) distributed by (a);
CREATE or REPLACE FUNCTION logfunc1(logtxt text) RETURNS timestamp AS $$
BEGIN
INSERT INTO logtable VALUES (logtxt, '2007-12-12 10:00:00.000000');
RETURN '2007-12-12 10:00:00.000000';
END;
$$ LANGUAGE plpgsql;
select logfunc1('firstrow');
select * from logtable;
CREATE or REPLACE FUNCTION logfunc2(logtxt text) RETURNS timestamp AS $$
DECLARE
curtime timestamp;
BEGIN
curtime := '2007-12-12 10:00:00.000000';
INSERT INTO logtable VALUES (logtxt, curtime);
RETURN curtime;
END;
$$ LANGUAGE plpgsql;
select logfunc2('gpdb');
CREATE TABLE db (a INT PRIMARY KEY, b TEXT);
CREATE or REPLACE FUNCTION merge_db(key INT, data TEXT) RETURNS VOID AS $$
BEGIN
LOOP
UPDATE db SET b = data WHERE a = key;
IF found THEN
RETURN;
END IF;
BEGIN
INSERT INTO db(a,b) VALUES (key, data);
RETURN;
EXCEPTION WHEN unique_violation THEN
END;
END LOOP;
END;
$$ LANGUAGE plpgsql;
SELECT merge_db(1, 'david');
SELECT merge_db(1, 'dennis');
CREATE OR REPLACE FUNCTION fib_fun (num integer) RETURNS integer AS $$
BEGIN
IF num < 2 THEN
RETURN num;
END IF;
RETURN fib_fun(num - 2) + fib_fun(num - 1);
END;
$$ LANGUAGE plpgsql;
select fib_fun(8);
CREATE OR REPLACE FUNCTION fib_fast(fib_for integer) RETURNS integer AS $$
DECLARE
ret integer := 0;
nxt integer := 1;
tmp integer;
BEGIN
FOR num IN 1..fib_for LOOP
tmp := ret; ret := nxt; nxt := tmp + nxt;
END LOOP;
RETURN ret;
END;
$$ LANGUAGE plpgsql;
select fib_fast(4);
CREATE OR REPLACE FUNCTION set_int (lim INTEGER) RETURNS SETOF INTEGER AS $$
BEGIN
FOR x in 1..lim LOOP
RETURN NEXT x;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
SELECT * FROM set_int(10);
CREATE OR REPLACE FUNCTION set_tab1() RETURNS SETOF INTEGER AS $$
DECLARE
tab_rec RECORD;
BEGIN
FOR tab_rec IN SELECT * FROM tab_sour LOOP
RETURN NEXT tab_rec.tabid;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
SELECT * FROM set_tab1();
CREATE OR REPLACE FUNCTION set_tab2() RETURNS SETOF tab_sour AS $$
DECLARE
tab_rec RECORD;
BEGIN
FOR tab_rec IN SELECT * FROM tab_sour LOOP
RETURN NEXT tab_rec;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
SELECT * FROM set_tab2();
CREATE OR REPLACE FUNCTION ref_tab1(tab_cur refcursor) RETURNS refcursor AS $$
BEGIN
OPEN tab_cur FOR SELECT * FROM tab_sour;
RETURN tab_cur;
END;
$$ LANGUAGE plpgsql;
drop function add_em(integer,integer);
drop function add_em(integer,integer,integer);
drop function add_num(x integer, y integer, OUT sum integer, OUT product integer);
drop type sum_prod cascade;
drop table bank_ac;
drop table emp_fun cascade;
drop table tab_sour cascade;
drop table fun_tree;
drop table logtable;
drop table db;
create table stress_source as select a from generate_series(1,100) a;
create table stress_table (a int primary key, b int);
create or replace function stress_test() returns text as $body$
declare
mycounter record;
begin
truncate stress_table;
for mycounter in select a from stress_source order by 1 loop
insert into stress_table values(mycounter.a, mycounter.a * 10000);
end loop;
for mycounter in select a from stress_source order by 1 loop
update stress_table set b = b + mycounter.a where a = mycounter.a;
end loop;
return 'ok';
end;
$body$ language plpgsql volatile strict;
select stress_test();
select stress_test();
create function bad_ddl() returns void as $body$
begin
create table junk_table(a int);
drop table junk_table;
end;
$body$ language plpgsql volatile;
select bad_ddl();
select bad_ddl();
create or replace function bad_ddl() returns void as $body$
begin
execute 'create table junk_table(a int)';
execute 'drop table junk_table';
end;
$body$ language plpgsql volatile;
select bad_ddl();
drop function bad_ddl();
SET check_function_bodies TO OFF;
CREATE FUNCTION bad_syntax_func() RETURNS INTEGER AS '
BEGIN
RTRN 0;
END;'
LANGUAGE 'plpgsql';
SELECT bad_syntax_func();
SELECT * from bad_syntax_func();
DROP FUNCTION bad_syntax_func();
RESET check_function_bodies;
CREATE FUNCTION bad_syntax_func() RETURNS INTEGER AS '
BEGIN
RTRN 0;
END;'
LANGUAGE 'plpgsql';
CREATE AGGREGATE agg_point_add1 (
basetype=point,
SFUNC=point_add,
STYPE=point
);
create table agg_point_tbl (p point);
insert into agg_point_tbl values (POINT(3,5));
insert into agg_point_tbl values (POINT(30,50));
select ' ' as "Expect (33,55)", agg_point_add1(p) from agg_point_tbl;
CREATE AGGREGATE agg_point_add2 (
basetype=point,
SFUNC=point_add,
STYPE=point,
INITCOND='(25, 47)'
);
select '' as "Expect (58,102)", agg_point_add2(p) from agg_point_tbl;
create aggregate numeric_sum (
basetype=numeric,
SFUNC=numeric_add,
STYPE=numeric
);
create table agg_numeric_tbl(num numeric) distributed by (num);
insert into agg_numeric_tbl VALUES(30);
insert into agg_numeric_tbl VALUES(-20);
select '' as ten, numeric_sum(num) from agg_numeric_tbl;
drop aggregate numeric_sum(numeric);
create aggregate numeric_sum_plus_fifty (
basetype=numeric,
SFUNC=numeric_add,
STYPE=numeric,
INITCOND='50'
);
select '' as sixty, numeric_sum_plus_fifty(num) from agg_numeric_tbl;
drop aggregate numeric_sum_plus_fifty(numeric);
drop table stress_source;
drop table stress_table;
drop aggregate agg_point_add1(point);
drop table agg_point_tbl;
drop aggregate agg_point_add2(point);
drop table agg_numeric_tbl;
--
-- Test for an old bug, where numeric trunc() scribbled on its input.
--
do $$
declare
n numeric;
begin
n = repeat('9', 1) || '.12';
raise notice 'n: %', n;
raise notice 't: %', trunc(n,1);
raise notice 'n: %', n;
end;
$$;
create table invalid_name (name text) distributed replicated;
create table candidate (name text, parent_name text) distributed by (name);
create or replace function is_invalid_name (aname text) returns boolean language sql as $$ select aname in (select name from invalid_name)$$;
create table tst_valid_name (a text) distributed randomly;
create table tst_invalid_name (a text) distributed randomly;
insert into invalid_name (name) values ('tst_invalid_name');
insert into candidate(name, parent_name) values ('tst_valid_name', 'tst_invalid_name');
select a.name as a_name,
a.parent_name as a_parent_name,
b.name as b_name,
b.parent_name as b_parent_name
from candidate a
full join (select c.relname as name,
'tst_invalid_name' as parent_name
from pg_class c
where c.relname like 'tst%' and
not is_invalid_name(c.relname)) b
on a.name = b.name and
a.parent_name = b.parent_name
order by 1,2,3,4;