2266 lines
62 KiB
Plaintext
2266 lines
62 KiB
Plaintext
create database pl_test_funcion DBCOMPATIBILITY 'pg';
|
|
\c pl_test_funcion;
|
|
create schema distribute_function;
|
|
set current_schema = distribute_function;
|
|
select nls_initcap('hello word');
|
|
nls_initcap
|
|
-------------
|
|
Hello Word
|
|
(1 row)
|
|
|
|
select nls_initcap('журнал журнал');--俄语
|
|
nls_initcap
|
|
---------------
|
|
Журнал Журнал
|
|
(1 row)
|
|
|
|
SELECT nls_initcap('el gato negro');--西班牙语
|
|
nls_initcap
|
|
---------------
|
|
El Gato Negro
|
|
(1 row)
|
|
|
|
SELECT nls_initcap('o gato preto');--葡萄牙语
|
|
nls_initcap
|
|
--------------
|
|
O Gato Preto
|
|
(1 row)
|
|
|
|
SELECT nls_initcap('HELLO ß world', 'NLS_SORT = XGERMAN'); --第二个参数不支持。
|
|
NOTICE: The second parameter of this function will not take effect.
|
|
CONTEXT: referenced column: nls_initcap
|
|
nls_initcap
|
|
---------------
|
|
Hello ß World
|
|
(1 row)
|
|
|
|
select nls_initcap('hello word'); --3个空格
|
|
nls_initcap
|
|
--------------
|
|
Hello Word
|
|
(1 row)
|
|
|
|
select nls_initcap('hello word'); --2个tab键等作为分隔符
|
|
nls_initcap
|
|
-------------------
|
|
Hello Word
|
|
(1 row)
|
|
|
|
select nls_initcap('hello *** &&& ()()() 你好啦 word'); --中间有其他非英文字母,或者中文等
|
|
nls_initcap
|
|
----------------------------------------
|
|
Hello *** &&& ()()() 你好啦 Word
|
|
(1 row)
|
|
|
|
SELECT nls_initcap('o gato preto','o gato preto','o gato preto');--报错
|
|
ERROR: function nls_initcap(unknown, unknown, unknown) does not exist
|
|
LINE 1: SELECT nls_initcap('o gato preto','o gato preto','o gato pre...
|
|
^
|
|
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
|
|
CONTEXT: referenced column: nls_initcap
|
|
create table function_table_01(f1 int, f2 float, f3 text);
|
|
insert into function_table_01 values(1,2.0,'abcde'),(2,4.0,'abcde'),(3,5.0,'affde');
|
|
insert into function_table_01 values(4,7.0,'aeede'),(5,1.0,'facde'),(6,3.0,'affde');
|
|
analyze function_table_01;
|
|
CREATE OR REPLACE FUNCTION test_function_immutable RETURNS BIGINT AS
|
|
$body$
|
|
BEGIN
|
|
RETURN 3;
|
|
END;
|
|
$body$
|
|
LANGUAGE 'plpgsql'
|
|
IMMUTABLE
|
|
CALLED ON NULL INPUT
|
|
SECURITY INVOKER
|
|
COST 100;
|
|
explain (verbose, costs off) select * from test_function_immutable();
|
|
QUERY PLAN
|
|
------------------------------------------
|
|
Function Scan on test_function_immutable
|
|
Output: test_function_immutable
|
|
Function Call: 3::bigint
|
|
(3 rows)
|
|
|
|
select * from test_function_immutable();
|
|
test_function_immutable
|
|
-------------------------
|
|
3
|
|
(1 row)
|
|
|
|
CREATE VIEW functionview AS SELECT f1,f2,left(f3,test_function_immutable()::INT) f3 FROM function_table_01;
|
|
--targetlist
|
|
explain (verbose, costs off) select f1,left(f3,test_function_immutable()::INT) from function_table_01 order by 1 limit 3;
|
|
QUERY PLAN
|
|
---------------------------------------------------------------
|
|
Limit
|
|
Output: f1, ("left"(f3, 3))
|
|
-> Sort
|
|
Output: f1, ("left"(f3, 3))
|
|
Sort Key: function_table_01.f1
|
|
-> Seq Scan on distribute_function.function_table_01
|
|
Output: f1, "left"(f3, 3)
|
|
(7 rows)
|
|
|
|
select f1,left(f3,test_function_immutable()::INT) from function_table_01 order by 1 limit 3;
|
|
f1 | left
|
|
----+------
|
|
1 | abc
|
|
2 | abc
|
|
3 | aff
|
|
(3 rows)
|
|
|
|
--fromQual
|
|
explain (verbose, costs off) select * from function_table_01 where f1 = test_function_immutable();
|
|
QUERY PLAN
|
|
---------------------------------------------------
|
|
Seq Scan on distribute_function.function_table_01
|
|
Output: f1, f2, f3
|
|
Filter: (function_table_01.f1 = 3::bigint)
|
|
(3 rows)
|
|
|
|
select * from function_table_01 where f1 = test_function_immutable();
|
|
f1 | f2 | f3
|
|
----+----+-------
|
|
3 | 5 | affde
|
|
(1 row)
|
|
|
|
--sortClause
|
|
explain (verbose, costs off) select f1,f3 from function_table_01 order by left(f3,test_function_immutable()::INT) limit 3;
|
|
QUERY PLAN
|
|
---------------------------------------------------------------
|
|
Limit
|
|
Output: f1, f3, ("left"(f3, 3))
|
|
-> Sort
|
|
Output: f1, f3, ("left"(f3, 3))
|
|
Sort Key: ("left"(function_table_01.f3, 3))
|
|
-> Seq Scan on distribute_function.function_table_01
|
|
Output: f1, f3, "left"(f3, 3)
|
|
(7 rows)
|
|
|
|
select f1,f3 from function_table_01 order by left(f3,test_function_immutable()::INT), f1 limit 3;
|
|
f1 | f3
|
|
----+-------
|
|
1 | abcde
|
|
2 | abcde
|
|
4 | aeede
|
|
(3 rows)
|
|
|
|
--groupClause
|
|
explain (verbose, costs off) select avg(f2),left(f3,test_function_immutable()::INT) from function_table_01 group by 2 order by 1;
|
|
QUERY PLAN
|
|
---------------------------------------------------------------
|
|
Sort
|
|
Output: (avg(f2)), ("left"(f3, 3))
|
|
Sort Key: (avg(function_table_01.f2))
|
|
-> HashAggregate
|
|
Output: avg(f2), ("left"(f3, 3))
|
|
Group By Key: "left"(function_table_01.f3, 3)
|
|
-> Seq Scan on distribute_function.function_table_01
|
|
Output: "left"(f3, 3), f2
|
|
(8 rows)
|
|
|
|
select avg(f2),left(f3,test_function_immutable()::INT) from function_table_01 group by 2 order by 1;
|
|
avg | left
|
|
-----+------
|
|
1 | fac
|
|
3 | abc
|
|
4 | aff
|
|
7 | aee
|
|
(4 rows)
|
|
|
|
--havingClause
|
|
explain (verbose, costs off) select avg(f2) fa,f3 from function_table_01 group by f3 having avg(f2)>test_function_immutable() order by 1;
|
|
QUERY PLAN
|
|
-------------------------------------------------------------------
|
|
Sort
|
|
Output: (avg(f2)), f3
|
|
Sort Key: (avg(function_table_01.f2))
|
|
-> HashAggregate
|
|
Output: avg(f2), f3
|
|
Group By Key: function_table_01.f3
|
|
Filter: (avg(function_table_01.f2) > 3::double precision)
|
|
-> Seq Scan on distribute_function.function_table_01
|
|
Output: f3, f2
|
|
(9 rows)
|
|
|
|
select avg(f2) fa,f3 from function_table_01 group by f3 having avg(f2)>test_function_immutable() order by 1;
|
|
fa | f3
|
|
----+-------
|
|
4 | affde
|
|
7 | aeede
|
|
(2 rows)
|
|
|
|
--limitClause && offsetClause
|
|
explain (verbose, costs off) select * from function_table_01 order by 1 limit test_function_immutable() offset test_function_immutable();
|
|
QUERY PLAN
|
|
---------------------------------------------------------------
|
|
Limit
|
|
Output: f1, f2, f3
|
|
-> Sort
|
|
Output: f1, f2, f3
|
|
Sort Key: function_table_01.f1
|
|
-> Seq Scan on distribute_function.function_table_01
|
|
Output: f1, f2, f3
|
|
(7 rows)
|
|
|
|
select * from function_table_01 order by 1 limit test_function_immutable() offset test_function_immutable();
|
|
f1 | f2 | f3
|
|
----+----+-------
|
|
4 | 7 | aeede
|
|
5 | 1 | facde
|
|
6 | 3 | affde
|
|
(3 rows)
|
|
|
|
explain (verbose, costs off) select avg(f2),left(f3,test_function_immutable()::INT) from function_table_01 group by 2 having avg(f2)>test_function_immutable() order by 1 limit test_function_immutable() offset test_function_immutable()-2;
|
|
QUERY PLAN
|
|
-------------------------------------------------------------------------
|
|
Limit
|
|
Output: (avg(f2)), ("left"(f3, 3))
|
|
-> Sort
|
|
Output: (avg(f2)), ("left"(f3, 3))
|
|
Sort Key: (avg(function_table_01.f2))
|
|
-> HashAggregate
|
|
Output: avg(f2), ("left"(f3, 3))
|
|
Group By Key: "left"(function_table_01.f3, 3)
|
|
Filter: (avg(function_table_01.f2) > 3::double precision)
|
|
-> Seq Scan on distribute_function.function_table_01
|
|
Output: "left"(f3, 3), f2
|
|
(11 rows)
|
|
|
|
select avg(f2),left(f3,test_function_immutable()::INT) from function_table_01 group by 2 having avg(f2)>test_function_immutable() order by 1 limit test_function_immutable() offset test_function_immutable()-2;
|
|
avg | left
|
|
-----+------
|
|
7 | aee
|
|
(1 row)
|
|
|
|
CREATE OR REPLACE FUNCTION test_function_volatile RETURNS BIGINT AS
|
|
$body$
|
|
DECLARE
|
|
cnt BIGINT;
|
|
cnt2 BIGINT;
|
|
BEGIN
|
|
SELECT count(*) INTO cnt FROM(select * from functionview limit 3);
|
|
SELECT count(*) INTO cnt2 from function_table_01;
|
|
RETURN (cnt+cnt2/2)/2;
|
|
END;
|
|
$body$
|
|
LANGUAGE 'plpgsql'
|
|
VOLATILE
|
|
CALLED ON NULL INPUT
|
|
SECURITY INVOKER
|
|
COST 100;
|
|
explain (verbose on, costs off) select * from test_function_volatile();
|
|
QUERY PLAN
|
|
-------------------------------------------------------------
|
|
Function Scan on distribute_function.test_function_volatile
|
|
Output: test_function_volatile
|
|
Function Call: test_function_volatile()
|
|
(3 rows)
|
|
|
|
select * from test_function_volatile();
|
|
test_function_volatile
|
|
------------------------
|
|
3
|
|
(1 row)
|
|
|
|
explain (verbose on, costs off) select test_function_volatile();
|
|
QUERY PLAN
|
|
------------------------------------
|
|
Result
|
|
Output: test_function_volatile()
|
|
(2 rows)
|
|
|
|
select test_function_volatile();
|
|
test_function_volatile
|
|
------------------------
|
|
3
|
|
(1 row)
|
|
|
|
--targetlist
|
|
select f1,left(f3,test_function_volatile()::INT) from function_table_01 order by 1 limit 3;
|
|
f1 | left
|
|
----+------
|
|
1 | abc
|
|
2 | abc
|
|
3 | aff
|
|
(3 rows)
|
|
|
|
--fromQual
|
|
select * from function_table_01 where f1 = test_function_volatile();
|
|
f1 | f2 | f3
|
|
----+----+-------
|
|
3 | 5 | affde
|
|
(1 row)
|
|
|
|
--sortClause
|
|
select f1,f3 from function_table_01 order by left(f3,test_function_volatile()::INT) limit 3;
|
|
f1 | f3
|
|
----+-------
|
|
1 | abcde
|
|
2 | abcde
|
|
4 | aeede
|
|
(3 rows)
|
|
|
|
--groupClause
|
|
select avg(f2),left(f3,test_function_volatile()::INT) from function_table_01 group by 2 order by 1;
|
|
avg | left
|
|
-----+------
|
|
1 | fac
|
|
3 | abc
|
|
4 | aff
|
|
7 | aee
|
|
(4 rows)
|
|
|
|
--havingClause
|
|
select avg(f2) fa,f3 from function_table_01 group by f3 having avg(f2)>test_function_volatile() order by 1;
|
|
fa | f3
|
|
----+-------
|
|
4 | affde
|
|
7 | aeede
|
|
(2 rows)
|
|
|
|
--limitClause && offsetClause
|
|
select * from function_table_01 order by 1 limit test_function_volatile() offset test_function_volatile();
|
|
f1 | f2 | f3
|
|
----+----+-------
|
|
4 | 7 | aeede
|
|
5 | 1 | facde
|
|
6 | 3 | affde
|
|
(3 rows)
|
|
|
|
select avg(f2),left(f3,test_function_volatile()::INT) from function_table_01 group by 2 having avg(f2)>test_function_volatile() order by 1 limit test_function_volatile() offset test_function_volatile()-2;
|
|
avg | left
|
|
-----+------
|
|
7 | aee
|
|
(1 row)
|
|
|
|
drop function test_function_volatile;
|
|
drop view functionview;
|
|
drop function test_function_immutable;
|
|
drop table function_table_01;
|
|
drop schema distribute_function;
|
|
reset current_schema;
|
|
create table distribute_function_t1(a int, b int) /*distribute by hash(a)*/;
|
|
create table distribute_function_t2(a int, b int) /*distribute by replication*/;
|
|
explain (verbose on, costs off) select * from distribute_function_t1, generate_series(1, 1, 5);
|
|
QUERY PLAN
|
|
-----------------------------------------------------------------------------------------------
|
|
Nested Loop
|
|
Output: distribute_function_t1.a, distribute_function_t1.b, generate_series.generate_series
|
|
-> Function Scan on pg_catalog.generate_series
|
|
Output: generate_series.generate_series
|
|
Function Call: generate_series(1, 1, 5)
|
|
-> Materialize
|
|
Output: distribute_function_t1.a, distribute_function_t1.b
|
|
-> Seq Scan on public.distribute_function_t1
|
|
Output: distribute_function_t1.a, distribute_function_t1.b
|
|
(9 rows)
|
|
|
|
explain (verbose on, costs off) select * from distribute_function_t1, generate_series(1, 1, 5);
|
|
QUERY PLAN
|
|
-----------------------------------------------------------------------------------------------
|
|
Nested Loop
|
|
Output: distribute_function_t1.a, distribute_function_t1.b, generate_series.generate_series
|
|
-> Function Scan on pg_catalog.generate_series
|
|
Output: generate_series.generate_series
|
|
Function Call: generate_series(1, 1, 5)
|
|
-> Materialize
|
|
Output: distribute_function_t1.a, distribute_function_t1.b
|
|
-> Seq Scan on public.distribute_function_t1
|
|
Output: distribute_function_t1.a, distribute_function_t1.b
|
|
(9 rows)
|
|
|
|
drop table distribute_function_t1;
|
|
drop table distribute_function_t2;
|
|
--object inside procedure be searched and new table/view/etc be created in. This is to adapt behaviar of Ora.
|
|
create schema dist_func1;
|
|
create schema dist_func2;
|
|
create or replace function func_create_columnar_partition_table_176_xkey_xpart(part integer) returns boolean as $$ declare
|
|
sql_temp text;
|
|
begin
|
|
sql_temp := 'create table create_columnar_table_176_xkey_'||part||'part ( c_smallint smallint not null,c_double_precision double precision,c_time_without_time_zone time without time zone null,c_time_with_time_zone time with time zone,c_integer integer default 23423,c_bigint bigint default 923423432,c_decimal decimal(19) default 923423423,c_real real,c_numeric numeric(18,12) null,c_varchar varchar(19),c_char char(57) null,c_timestamp_with_timezone timestamp with time zone,c_char2 char default ''0'',c_text text null,c_varchar2 varchar2(20),c_timestamp_without_timezone timestamp without time zone,c_date date,c_varchar22 varchar2(11621),c_numeric2 numeric null) /*distribute by hash(c_decimal)*/;';
|
|
execute immediate sql_temp;
|
|
return true;
|
|
end;
|
|
$$ language plpgsql;
|
|
create or replace function dist_func1.func_create_columnar_partition_table_176_xkey_xpart(part integer) returns boolean as $$ declare
|
|
sql_temp text;
|
|
begin
|
|
sql_temp := 'create table create_columnar_table_176_xkey_'||part||'part ( c_smallint smallint not null,c_double_precision double precision,c_time_without_time_zone time without time zone null,c_time_with_time_zone time with time zone,c_integer integer default 23423,c_bigint bigint default 923423432,c_decimal decimal(19) default 923423423,c_real real,c_numeric numeric(18,12) null,c_varchar varchar(19),c_char char(57) null,c_timestamp_with_timezone timestamp with time zone,c_char2 char default ''0'',c_text text null,c_varchar2 varchar2(20),c_timestamp_without_timezone timestamp without time zone,c_date date,c_varchar22 varchar2(11621),c_numeric2 numeric null) /*distribute by hash(c_decimal);*/';
|
|
execute immediate sql_temp;
|
|
return true;
|
|
end;
|
|
$$ language plpgsql;
|
|
call dist_func1.func_create_columnar_partition_table_176_xkey_xpart(1);
|
|
func_create_columnar_partition_table_176_xkey_xpart
|
|
-----------------------------------------------------
|
|
t
|
|
(1 row)
|
|
|
|
set search_path to dist_func1;
|
|
call public.func_create_columnar_partition_table_176_xkey_xpart(2);
|
|
func_create_columnar_partition_table_176_xkey_xpart
|
|
-----------------------------------------------------
|
|
t
|
|
(1 row)
|
|
|
|
call func_create_columnar_partition_table_176_xkey_xpart(3);
|
|
func_create_columnar_partition_table_176_xkey_xpart
|
|
-----------------------------------------------------
|
|
t
|
|
(1 row)
|
|
|
|
set search_path to dist_func3;
|
|
call public.func_create_columnar_partition_table_176_xkey_xpart(4);
|
|
func_create_columnar_partition_table_176_xkey_xpart
|
|
-----------------------------------------------------
|
|
t
|
|
(1 row)
|
|
|
|
call dist_func1.func_create_columnar_partition_table_176_xkey_xpart(5);
|
|
func_create_columnar_partition_table_176_xkey_xpart
|
|
-----------------------------------------------------
|
|
t
|
|
(1 row)
|
|
|
|
create or replace function dist_func1.test1(part int) returns boolean as $$ declare
|
|
sql_temp text;
|
|
begin
|
|
sql_temp := 'set search_path to dist_func2;';
|
|
execute immediate sql_temp;
|
|
sql_temp := 'create table create_columnar_table_176_xkey_'||part||'part ( c_smallint smallint not null,c_double_precision double precision,c_time_without_time_zone time without time zone null,c_time_with_time_zone time with time zone,c_integer integer default 23423,c_bigint bigint default 923423432,c_decimal decimal(19) default 923423423,c_real real,c_numeric numeric(18,12) null,c_varchar varchar(19),c_char char(57) null,c_timestamp_with_timezone timestamp with time zone,c_char2 char default ''0'',c_text text null,c_varchar2 varchar2(20),c_timestamp_without_timezone timestamp without time zone,c_date date,c_varchar22 varchar2(11621),c_numeric2 numeric null) /*distribute by hash(c_decimal)*/;';
|
|
execute immediate sql_temp;
|
|
return true;
|
|
end;
|
|
$$ language plpgsql;
|
|
call dist_func1.test1(6);
|
|
test1
|
|
-------
|
|
t
|
|
(1 row)
|
|
|
|
select schemaname, tablename from pg_tables where tablename like 'create_columnar_table_176_xkey_%' order by tablename;
|
|
schemaname | tablename
|
|
------------+--------------------------------------
|
|
dist_func1 | create_columnar_table_176_xkey_1part
|
|
public | create_columnar_table_176_xkey_2part
|
|
dist_func1 | create_columnar_table_176_xkey_3part
|
|
public | create_columnar_table_176_xkey_4part
|
|
dist_func1 | create_columnar_table_176_xkey_5part
|
|
dist_func1 | create_columnar_table_176_xkey_6part
|
|
(6 rows)
|
|
|
|
create or replace function dist_func1.multi_call1(a integer) returns int as $$
|
|
declare
|
|
b int;
|
|
begin
|
|
select multi_call2(a) + 1 into b;
|
|
return b;
|
|
end;
|
|
$$ language plpgsql;
|
|
create or replace function dist_func1.multi_call2(a integer) returns int as $$
|
|
declare
|
|
b int;
|
|
begin
|
|
select dist_func2.multi_call3(a) + 1 into b;
|
|
return b;
|
|
end;
|
|
$$ language plpgsql;
|
|
create or replace function dist_func2.multi_call3(a integer) returns int as $$
|
|
declare
|
|
b int;
|
|
begin
|
|
select multi_call4() + 1 into b;
|
|
return b;
|
|
end;
|
|
$$ language plpgsql;
|
|
create or replace function dist_func2.multi_call4() returns int as $$
|
|
declare
|
|
b int;
|
|
begin
|
|
return 1;
|
|
end;
|
|
$$ language plpgsql;
|
|
call dist_func1.multi_call1(1);
|
|
multi_call1
|
|
-------------
|
|
4
|
|
(1 row)
|
|
|
|
-- Test cross-schema
|
|
-- search_path public, procedure sche1, row table distribute by hash
|
|
create schema sche1;
|
|
set search_path=sche1;
|
|
create or replace function fun_001() returns void as $$
|
|
declare
|
|
begin
|
|
create table schema_tbl_001(a int) ;
|
|
insert into schema_tbl_001 values(1);
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
set search_path=public;
|
|
select sche1.fun_001();
|
|
fun_001
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select * from sche1.schema_tbl_001;
|
|
a
|
|
---
|
|
1
|
|
(1 row)
|
|
|
|
select count(*) from pg_class where relname='schema_tbl_001';
|
|
count
|
|
-------
|
|
1
|
|
(1 row)
|
|
|
|
drop schema sche1 cascade;
|
|
NOTICE: drop cascades to 2 other objects
|
|
DETAIL: drop cascades to function sche1.fun_001()
|
|
drop cascades to table sche1.schema_tbl_001
|
|
-- search_path sche1, procedure public, row unlogged table distribute by hash
|
|
create schema sche1;
|
|
set search_path=public;
|
|
create or replace function fun_001() returns void as $$
|
|
declare
|
|
begin
|
|
create unlogged table schema_tbl_001(a int) ;
|
|
insert into schema_tbl_001 values(1);
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
set search_path=sche1;
|
|
select public.fun_001();
|
|
fun_001
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select * from schema_tbl_001;
|
|
ERROR: relation "schema_tbl_001" does not exist on datanode1
|
|
LINE 1: select * from schema_tbl_001;
|
|
^
|
|
select * from public.schema_tbl_001;
|
|
a
|
|
---
|
|
1
|
|
(1 row)
|
|
|
|
drop function public.fun_001;
|
|
drop schema sche1 cascade;
|
|
drop table public.schema_tbl_001;
|
|
reset search_path;
|
|
-- search_path sche1, procedure sche2, row partition table
|
|
create schema sche1;
|
|
create schema sche2;
|
|
set search_path=sche2;
|
|
create or replace function fun_001() returns void as $$
|
|
declare
|
|
begin
|
|
create table schema_tbl_001(a int) partition by range(a) (partition p1 values less than(10), partition p2 values less than(20), partition p3 values less than(maxvalue));
|
|
insert into schema_tbl_001 values(1),(10),(20),(100);
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
set search_path=sche1;
|
|
select sche2.fun_001();
|
|
fun_001
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select * from sche2.schema_tbl_001 order by a;
|
|
a
|
|
-----
|
|
1
|
|
10
|
|
20
|
|
100
|
|
(4 rows)
|
|
|
|
drop schema sche1 cascade;
|
|
drop schema sche2 cascade;
|
|
NOTICE: drop cascades to 2 other objects
|
|
DETAIL: drop cascades to function sche2.fun_001()
|
|
drop cascades to table sche2.schema_tbl_001
|
|
reset search_path;
|
|
-- search_path sche1, procedure sche2, table sche3, row table distribute by replication
|
|
create schema sche1;
|
|
create schema sche2;
|
|
create schema sche3;
|
|
set search_path=sche2;
|
|
create or replace function fun_001() returns void as $$
|
|
declare
|
|
begin
|
|
create table sche3.schema_tbl_001(a int) /*distribute by replication*/;
|
|
insert into sche3.schema_tbl_001 values(1);
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
set search_path=sche1;
|
|
select sche2.fun_001();
|
|
fun_001
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select * from sche2.schema_tbl_001;
|
|
ERROR: relation "sche2.schema_tbl_001" does not exist on datanode1
|
|
LINE 1: select * from sche2.schema_tbl_001;
|
|
^
|
|
select * from sche3.schema_tbl_001;
|
|
a
|
|
---
|
|
1
|
|
(1 row)
|
|
|
|
drop schema sche1 cascade;
|
|
drop schema sche2 cascade;
|
|
NOTICE: drop cascades to function sche2.fun_001()
|
|
drop schema sche3 cascade;
|
|
NOTICE: drop cascades to table sche3.schema_tbl_001
|
|
reset search_path;
|
|
-- set search_path/current_schema inside procedure is invalid
|
|
-- test set search_path
|
|
create schema sche1;
|
|
create schema sche2;
|
|
set search_path=sche2;
|
|
create or replace function fun_001() returns void as $$
|
|
declare
|
|
begin
|
|
set search_path=sche1;
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
reset search_path;
|
|
show search_path;
|
|
search_path
|
|
----------------
|
|
"$user",public
|
|
(1 row)
|
|
|
|
select sche2.fun_001();
|
|
fun_001
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
show search_path;
|
|
search_path
|
|
----------------
|
|
"$user",public
|
|
(1 row)
|
|
|
|
-- test set current_schema
|
|
set search_path=sche2;
|
|
create or replace function fun_002() returns void as $$
|
|
declare
|
|
begin
|
|
set current_schema=sche1;
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
reset current_schema;
|
|
show current_schema;
|
|
current_schema
|
|
----------------
|
|
"$user",public
|
|
(1 row)
|
|
|
|
select sche2.fun_002();
|
|
fun_002
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
show current_schema;
|
|
current_schema
|
|
----------------
|
|
"$user",public
|
|
(1 row)
|
|
|
|
-- test reset search_path
|
|
set search_path=sche2;
|
|
create or replace function fun_003() returns void as $$
|
|
declare
|
|
begin
|
|
reset search_path;
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
show current_schema;
|
|
current_schema
|
|
----------------
|
|
sche2
|
|
(1 row)
|
|
|
|
select sche2.fun_003();
|
|
fun_003
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
show search_path;
|
|
search_path
|
|
-------------
|
|
sche2
|
|
(1 row)
|
|
|
|
-- test set search_path mixed with other operations, column table distribute by hash
|
|
set search_path=sche2;
|
|
create or replace function fun_004() returns void as $$
|
|
declare
|
|
begin
|
|
set search_path=public;
|
|
create table schema_tbl_001(a int) with (orientation = column);
|
|
insert into schema_tbl_001 values(1);
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
set search_path=sche1;
|
|
select sche2.fun_004();
|
|
fun_004
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
show search_path;
|
|
search_path
|
|
-------------
|
|
sche1
|
|
(1 row)
|
|
|
|
select * from public.schema_tbl_001;
|
|
ERROR: relation "public.schema_tbl_001" does not exist on datanode1
|
|
LINE 1: select * from public.schema_tbl_001;
|
|
^
|
|
select * from sche2.schema_tbl_001;
|
|
a
|
|
---
|
|
1
|
|
(1 row)
|
|
|
|
drop schema sche1 cascade;
|
|
drop schema sche2 cascade;
|
|
NOTICE: drop cascades to 5 other objects
|
|
DETAIL: drop cascades to function sche2.fun_001()
|
|
drop cascades to function sche2.fun_002()
|
|
drop cascades to function sche2.fun_003()
|
|
drop cascades to function sche2.fun_004()
|
|
drop cascades to table sche2.schema_tbl_001
|
|
reset search_path;
|
|
-- test multiple schemas with DDL, DML.
|
|
create schema sche1;
|
|
create schema sche2;
|
|
create or replace function sche1.multi_call1(a integer) returns int as $$
|
|
declare
|
|
b int;
|
|
begin
|
|
select multi_call2(a) + 1 into b;
|
|
insert into sche1_tbl values(1);
|
|
return b;
|
|
end;
|
|
$$ language plpgsql;
|
|
create or replace function sche1.multi_call2(a integer) returns int as $$
|
|
declare
|
|
b int;
|
|
begin
|
|
create table sche1_tbl(id int) with (orientation = column) /*distribute by replication*/;
|
|
select sche2.multi_call3(a) + 1 into b;
|
|
insert into sche2.sche2_tbl values(3);
|
|
return b;
|
|
end;
|
|
$$ language plpgsql;
|
|
create or replace function sche2.multi_call3(a integer) returns int as $$
|
|
declare
|
|
b int;
|
|
begin
|
|
select multi_call4() + 1 into b;
|
|
create table sche2_tbl(id int) /*distribute by hash(id)*/;
|
|
insert into sche2_tbl values(2);
|
|
return b;
|
|
end;
|
|
$$ language plpgsql;
|
|
create or replace function sche2.multi_call4() returns int as $$
|
|
declare
|
|
b int;
|
|
begin
|
|
return 1;
|
|
end;
|
|
$$ language plpgsql;
|
|
select sche1.multi_call1(1);
|
|
multi_call1
|
|
-------------
|
|
4
|
|
(1 row)
|
|
|
|
select * from sche1.sche1_tbl order by id;
|
|
id
|
|
----
|
|
1
|
|
(1 row)
|
|
|
|
select * from sche2.sche2_tbl order by id;
|
|
id
|
|
----
|
|
2
|
|
3
|
|
(2 rows)
|
|
|
|
drop schema sche1 cascade;
|
|
NOTICE: drop cascades to 3 other objects
|
|
DETAIL: drop cascades to function sche1.multi_call1(integer)
|
|
drop cascades to function sche1.multi_call2(integer)
|
|
drop cascades to table sche1.sche1_tbl
|
|
drop schema sche2 cascade;
|
|
NOTICE: drop cascades to 3 other objects
|
|
DETAIL: drop cascades to function sche2.multi_call3(integer)
|
|
drop cascades to function sche2.multi_call4()
|
|
drop cascades to table sche2.sche2_tbl
|
|
-- test temp table in subtransaction
|
|
create or replace function fun_002()
|
|
returns int
|
|
AS $$
|
|
DECLARE
|
|
x integer;
|
|
BEGIN
|
|
create temp table fun_tmp(a int) /*distribute by hash(a)*/;
|
|
perform 1 / 0;
|
|
insert into fun_tmp values(2);
|
|
return 2;
|
|
END; $$
|
|
LANGUAGE plpgsql;
|
|
create or replace function fun_003()
|
|
returns int
|
|
AS $$
|
|
DECLARE
|
|
x integer;
|
|
BEGIN
|
|
create temp table fun_tmp(a int) /*distribute by hash(a)*/;
|
|
insert into fun_tmp values(3);
|
|
return 3;
|
|
END; $$
|
|
LANGUAGE plpgsql;
|
|
create or replace function fun_001()
|
|
returns void
|
|
AS $$
|
|
DECLARE
|
|
x integer;
|
|
BEGIN
|
|
BEGIN
|
|
select fun_002() into x;
|
|
insert into fun_tmp values(4);
|
|
exception when others then
|
|
END;
|
|
BEGIN
|
|
select fun_003() into x;
|
|
insert into fun_tmp values(5);
|
|
END;
|
|
insert into fun_tmp values(6);
|
|
END; $$
|
|
LANGUAGE plpgsql;
|
|
call public.fun_001();
|
|
fun_001
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select * from fun_tmp order by 1;
|
|
a
|
|
---
|
|
3
|
|
5
|
|
6
|
|
(3 rows)
|
|
|
|
drop function fun_001;
|
|
drop function fun_002;
|
|
drop function fun_003;
|
|
drop table fun_tmp;
|
|
-- test temp table with exception
|
|
create schema sche1;
|
|
set search_path = sche1;
|
|
create or replace procedure proc_001
|
|
as
|
|
begin
|
|
create table tt1(a int) /*distribute by hash(a)*/;
|
|
begin
|
|
create temp table tablenamelevel (a int, b int) /*distribute by hash(a)*/;
|
|
select substring('abc', 1, -5);
|
|
exception when others then RAISE NOTICE 'others';
|
|
end;
|
|
begin
|
|
create temp table tablenamelevel2 (a int, b int) /*distribute by hash(a)*/;
|
|
begin
|
|
create temp table tablenamelevel3 (a int, b int) /*distribute by hash(a)*/;
|
|
select substring('abc', 1, -5);
|
|
exception when others then RAISE NOTICE 'others';
|
|
insert into tablenamelevel2 values(2,3);
|
|
end;
|
|
exception when others then RAISE NOTICE 'others';
|
|
end;
|
|
begin
|
|
create temp table tablenamelevel4 (a int, b int) /*distribute by hash(a)*/;
|
|
select substring('abc', 1, -5);
|
|
exception when others then RAISE NOTICE 'others';
|
|
end;
|
|
insert into tt1 values(1);
|
|
exception when others then RAISE NOTICE 'others';
|
|
end;
|
|
/
|
|
reset search_path;
|
|
prepare test_cacheplan_pbe as select substring('abc', 1, -5);
|
|
start transaction;
|
|
savepoint sp1;
|
|
create temp table temptable1(a int) /*distribute by hash(a)*/;
|
|
rollback to savepoint sp1;
|
|
create temp table temptable1(a int) /*distribute by hash(a)*/;
|
|
select substring('abc', 1, -5);
|
|
ERROR: negative substring length not allowed
|
|
CONTEXT: referenced column: substring
|
|
rollback to savepoint sp1;
|
|
create temp table temptable1(a int) /*distribute by hash(a)*/;
|
|
execute test_cacheplan_pbe;
|
|
ERROR: negative substring length not allowed
|
|
CONTEXT: referenced column: substring
|
|
rollback to savepoint sp1;
|
|
select sche1.proc_001();
|
|
NOTICE: others
|
|
CONTEXT: referenced column: proc_001
|
|
NOTICE: others
|
|
CONTEXT: referenced column: proc_001
|
|
NOTICE: others
|
|
CONTEXT: referenced column: proc_001
|
|
proc_001
|
|
----------
|
|
|
|
(1 row)
|
|
|
|
end;
|
|
select * from sche1.tt1;
|
|
a
|
|
---
|
|
1
|
|
(1 row)
|
|
|
|
select * from tablenamelevel1;
|
|
ERROR: relation "tablenamelevel1" does not exist on datanode1
|
|
LINE 1: select * from tablenamelevel1;
|
|
^
|
|
select * from tablenamelevel2;
|
|
a | b
|
|
---+---
|
|
2 | 3
|
|
(1 row)
|
|
|
|
select * from tablenamelevel3;
|
|
ERROR: relation "tablenamelevel3" does not exist on datanode1
|
|
LINE 1: select * from tablenamelevel3;
|
|
^
|
|
select * from tablenamelevel4;
|
|
ERROR: relation "tablenamelevel4" does not exist on datanode1
|
|
LINE 1: select * from tablenamelevel4;
|
|
^
|
|
deallocate test_cacheplan_pbe;
|
|
drop table tablenamelevel2;
|
|
drop table sche1.tt1;
|
|
drop schema sche1 cascade;
|
|
NOTICE: drop cascades to function sche1.proc_001()
|
|
reset search_path;
|
|
-- test the table with the same name with a pg_catalog table
|
|
create schema sche1;
|
|
create table sche1.pg_class(id int);
|
|
set search_path=sche1;
|
|
insert into pg_class values(1);
|
|
ERROR: null value in column "relnamespace" violates not-null constraint
|
|
DETAIL: Failing row contains (1, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null).
|
|
select * from sche1.pg_class;
|
|
id
|
|
----
|
|
(0 rows)
|
|
|
|
-- invalid to put pg_catalog behind sche1
|
|
set search_path=sche1, pg_catalog;
|
|
WARNING: It is invalid to set pg_temp or pg_catalog behind other schemas in search path explicitly. The priority order is pg_temp, pg_catalog and other schemas.
|
|
insert into pg_class values(1);
|
|
ERROR: null value in column "relnamespace" violates not-null constraint
|
|
DETAIL: Failing row contains (1, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null).
|
|
select * from sche1.pg_class;
|
|
id
|
|
----
|
|
(0 rows)
|
|
|
|
insert into sche1.pg_class values(1);
|
|
select * from sche1.pg_class;
|
|
id
|
|
----
|
|
1
|
|
(1 row)
|
|
|
|
delete from sche1.pg_class;
|
|
set search_path=sche1;
|
|
create or replace function fun_001() returns void as $$
|
|
declare
|
|
begin
|
|
insert into pg_class values(1);
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
select sche1.fun_001();
|
|
ERROR: null value in column "relnamespace" violates not-null constraint
|
|
DETAIL: Failing row contains (1, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null).
|
|
CONTEXT: SQL statement "insert into pg_class values(1)"
|
|
PL/pgSQL function fun_001() line 4 at SQL statement
|
|
referenced column: fun_001
|
|
select * from sche1.pg_class;
|
|
id
|
|
----
|
|
(0 rows)
|
|
|
|
set search_path=sche1, pg_catalog;
|
|
WARNING: It is invalid to set pg_temp or pg_catalog behind other schemas in search path explicitly. The priority order is pg_temp, pg_catalog and other schemas.
|
|
select sche1.fun_001();
|
|
ERROR: null value in column "relnamespace" violates not-null constraint
|
|
DETAIL: Failing row contains (1, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null).
|
|
CONTEXT: SQL statement "insert into pg_class values(1)"
|
|
PL/pgSQL function fun_001() line 4 at SQL statement
|
|
referenced column: fun_001
|
|
select * from sche1.pg_class;
|
|
id
|
|
----
|
|
(0 rows)
|
|
|
|
create or replace function sche1.fun_002() returns void as $$
|
|
declare
|
|
begin
|
|
insert into sche1.pg_class values(1);
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
select sche1.fun_002();
|
|
fun_002
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select * from sche1.pg_class;
|
|
id
|
|
----
|
|
1
|
|
(1 row)
|
|
|
|
drop schema sche1 cascade;
|
|
NOTICE: drop cascades to 3 other objects
|
|
DETAIL: drop cascades to table sche1.pg_class
|
|
drop cascades to function fun_001()
|
|
drop cascades to function fun_002()
|
|
-- test the table with the same name with a temp table
|
|
create schema sche1;
|
|
create schema sche2;
|
|
set search_path=sche1;
|
|
create or replace function fun_002() returns void as $$
|
|
declare
|
|
begin
|
|
create table schema_tbl_001(a int) with(orientation=column) partition by range(a) (partition p1 values less than(10),partition p2 values less than(20), partition p3 values less than(maxvalue));
|
|
insert into schema_tbl_001 values(10),(20),(100);
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
set search_path=public;
|
|
create or replace function sche1.fun_001() returns void as $$
|
|
declare
|
|
begin
|
|
create temp table schema_tbl_001(a int) with(orientation=column) /*distribute by replication*/;
|
|
insert into schema_tbl_001 values(4);
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
set search_path=sche2;
|
|
select sche1.fun_001();
|
|
fun_001
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select sche1.fun_002();
|
|
fun_002
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
-- always insert into temp table.
|
|
select * from sche1.schema_tbl_001;
|
|
a
|
|
---
|
|
(0 rows)
|
|
|
|
drop schema sche1 cascade;
|
|
NOTICE: drop cascades to 3 other objects
|
|
DETAIL: drop cascades to function sche1.fun_002()
|
|
drop cascades to function sche1.fun_001()
|
|
drop cascades to table sche1.schema_tbl_001
|
|
drop schema sche2 cascade;
|
|
drop table schema_tbl_001;
|
|
reset search_path;
|
|
-- test create table ... as select
|
|
create schema sche1;
|
|
set search_path=sche1;
|
|
create table sche1.schema_tbl_001(a int);
|
|
insert into sche1.schema_tbl_001 values(1),(2);
|
|
create or replace function fun_002() returns void as $$
|
|
declare
|
|
begin
|
|
create table t2 as select * from schema_tbl_001;
|
|
insert into t2 values(3);
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
set search_path=public;
|
|
select sche1.fun_002();
|
|
fun_002
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select * from sche1.t2 order by 1;
|
|
a
|
|
---
|
|
1
|
|
2
|
|
3
|
|
(3 rows)
|
|
|
|
drop schema sche1 cascade;
|
|
NOTICE: drop cascades to 3 other objects
|
|
DETAIL: drop cascades to table sche1.schema_tbl_001
|
|
drop cascades to function sche1.fun_002()
|
|
drop cascades to table sche1.t2
|
|
reset search_path;
|
|
-- test insert into select
|
|
create schema sche1;
|
|
set search_path=sche1;
|
|
create table sche1.schema_tbl_001(a int);
|
|
insert into sche1.schema_tbl_001 values(1),(2);
|
|
create or replace function fun_002() returns void as $$
|
|
declare
|
|
begin
|
|
create table t2(a int);
|
|
insert into t2 select a from schema_tbl_001;
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
set search_path=public;
|
|
select sche1.fun_002();
|
|
fun_002
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select * from sche1.t2 order by 1;
|
|
a
|
|
---
|
|
1
|
|
2
|
|
(2 rows)
|
|
|
|
drop schema sche1 cascade;
|
|
NOTICE: drop cascades to 3 other objects
|
|
DETAIL: drop cascades to table sche1.schema_tbl_001
|
|
drop cascades to function sche1.fun_002()
|
|
drop cascades to table sche1.t2
|
|
reset search_path;
|
|
-- test creating schema inside procedure
|
|
create schema sche1;
|
|
create or replace function sche1.fun1() returns void as $$
|
|
declare
|
|
begin
|
|
create table t1(a int);
|
|
create schema sche2 create table t2(a int);
|
|
insert into t1 values(1);
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
set search_path = public;
|
|
select sche1.fun1();
|
|
fun1
|
|
------
|
|
|
|
(1 row)
|
|
|
|
select * from sche1.t1;
|
|
a
|
|
---
|
|
1
|
|
(1 row)
|
|
|
|
select * from sche2.t2;
|
|
a
|
|
---
|
|
(0 rows)
|
|
|
|
drop schema sche1 cascade;
|
|
NOTICE: drop cascades to 2 other objects
|
|
DETAIL: drop cascades to function sche1.fun1()
|
|
drop cascades to table sche1.t1
|
|
drop schema sche2 cascade;
|
|
NOTICE: drop cascades to table sche2.t2
|
|
reset search_path;
|
|
-- test with grammar
|
|
create schema sche1;
|
|
create schema sche2;
|
|
create table sche1.t1(a int) /*distribute by replication*/;
|
|
set search_path = sche2;
|
|
create or replace function sche1.fun_001()
|
|
returns setof sche1.t1
|
|
AS $$
|
|
DECLARE
|
|
row_data t1%rowtype;
|
|
row_name record;
|
|
query_str text;
|
|
BEGIN
|
|
query_str := 'WITH t AS (
|
|
INSERT INTO t1 VALUES (11),(12),(13) RETURNING *
|
|
)
|
|
SELECT * FROM t order by 1;';
|
|
FOR row_data IN EXECUTE(query_str) LOOP
|
|
return next row_data;
|
|
END LOOP;
|
|
return;
|
|
END; $$
|
|
LANGUAGE 'plpgsql' NOT FENCED;
|
|
select sche1.fun_001();
|
|
fun_001
|
|
---------
|
|
(11)
|
|
(12)
|
|
(13)
|
|
(3 rows)
|
|
|
|
select * from sche1.t1;
|
|
a
|
|
----
|
|
11
|
|
12
|
|
13
|
|
(3 rows)
|
|
|
|
drop schema sche1 cascade;
|
|
NOTICE: drop cascades to 2 other objects
|
|
DETAIL: drop cascades to table sche1.t1
|
|
drop cascades to function sche1.fun_001()
|
|
drop schema sche2 cascade;
|
|
reset search_path;
|
|
-- test cursor
|
|
create schema sche1;
|
|
set search_path = sche1;
|
|
create table schema_tbl_001(a int) /*distribute by replication*/;
|
|
insert into schema_tbl_001 values(1),(2);
|
|
CREATE OR REPLACE PROCEDURE fun_001()
|
|
AS
|
|
DECLARE
|
|
b int;
|
|
CURSOR C1 IS
|
|
SELECT a FROM schema_tbl_001 order by 1;
|
|
BEGIN
|
|
OPEN C1;
|
|
LOOP
|
|
FETCH C1 INTO b;
|
|
EXIT WHEN C1%NOTFOUND;
|
|
END LOOP;
|
|
CLOSE C1;
|
|
END;
|
|
/
|
|
reset search_path;
|
|
select sche1.fun_001();
|
|
fun_001
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
drop schema sche1 cascade;
|
|
NOTICE: drop cascades to 2 other objects
|
|
DETAIL: drop cascades to table sche1.schema_tbl_001
|
|
drop cascades to function sche1.fun_001()
|
|
reset search_path;
|
|
-- test current_schemas()
|
|
set search_path to pg_catalog,public;
|
|
select current_schemas('f');
|
|
current_schemas
|
|
---------------------
|
|
{pg_catalog,public}
|
|
(1 row)
|
|
|
|
set search_path to public,pg_catalog;
|
|
WARNING: It is invalid to set pg_temp or pg_catalog behind other schemas in search path explicitly. The priority order is pg_temp, pg_catalog and other schemas.
|
|
select current_schemas('f');
|
|
current_schemas
|
|
-----------------
|
|
{public}
|
|
(1 row)
|
|
|
|
-- test SUPPORT_BIND_SEARCHPATH
|
|
SET behavior_compat_options = 'bind_procedure_searchpath';
|
|
create schema sche1;
|
|
create schema sche2;
|
|
set search_path = public;
|
|
create table public.bind_t1(a int) /*distribute by hash(a)*/;
|
|
create or replace function sche2.fun_001() returns int as $$
|
|
declare
|
|
begin
|
|
insert into bind_t1 values(2);
|
|
return 2;
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
create or replace function sche1.fun_001() returns int as $$
|
|
declare
|
|
x int;
|
|
begin
|
|
insert into bind_t1 values(1);
|
|
select sche2.fun_001() into x;
|
|
return 1;
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
-- insert into public.bind_t1;
|
|
call sche2.fun_001();
|
|
fun_001
|
|
---------
|
|
2
|
|
(1 row)
|
|
|
|
select * from public.bind_t1;
|
|
a
|
|
---
|
|
2
|
|
(1 row)
|
|
|
|
delete from public.bind_t1;
|
|
-- insert into public.bind_t1;
|
|
call sche1.fun_001();
|
|
fun_001
|
|
---------
|
|
1
|
|
(1 row)
|
|
|
|
select * from public.bind_t1;
|
|
a
|
|
---
|
|
1
|
|
2
|
|
(2 rows)
|
|
|
|
delete from public.bind_t1;
|
|
-- cannot find bind_t1. insert fail.
|
|
set search_path = sche2;
|
|
call sche2.fun_001();
|
|
ERROR: relation "bind_t1" does not exist on datanode1
|
|
LINE 1: insert into bind_t1 values(2)
|
|
^
|
|
QUERY: insert into bind_t1 values(2)
|
|
CONTEXT: PL/pgSQL function fun_001() line 4 at SQL statement
|
|
-- insert into sche1.bind_t1;
|
|
create table sche1.bind_t1(a int) /*distribute by hash(a)*/;
|
|
set search_path = sche1;
|
|
call sche2.fun_001();
|
|
fun_001
|
|
---------
|
|
2
|
|
(1 row)
|
|
|
|
select * from public.bind_t1;
|
|
a
|
|
---
|
|
(0 rows)
|
|
|
|
select * from sche1.bind_t1;
|
|
a
|
|
---
|
|
2
|
|
(1 row)
|
|
|
|
delete from public.bind_t1;
|
|
delete from sche1.bind_t1;
|
|
-- insert into sche1.bind_t1;
|
|
call sche1.fun_001();
|
|
fun_001
|
|
---------
|
|
1
|
|
(1 row)
|
|
|
|
select * from public.bind_t1;
|
|
a
|
|
---
|
|
(0 rows)
|
|
|
|
select * from sche1.bind_t1;
|
|
a
|
|
---
|
|
1
|
|
2
|
|
(2 rows)
|
|
|
|
delete from public.bind_t1;
|
|
delete from sche1.bind_t1;
|
|
-- cannot insert into sche2.bind_t1.
|
|
create table sche2.bind_t1(a int) /*distribute by hash(a)*/;
|
|
call sche2.fun_001();
|
|
fun_001
|
|
---------
|
|
2
|
|
(1 row)
|
|
|
|
select * from public.bind_t1;
|
|
a
|
|
---
|
|
(0 rows)
|
|
|
|
select * from sche1.bind_t1;
|
|
a
|
|
---
|
|
2
|
|
(1 row)
|
|
|
|
select * from sche2.bind_t1;
|
|
a
|
|
---
|
|
(0 rows)
|
|
|
|
-- insert into sche2.bind_t1.
|
|
set search_path = sche2;
|
|
call sche2.fun_001();
|
|
fun_001
|
|
---------
|
|
2
|
|
(1 row)
|
|
|
|
select * from public.bind_t1;
|
|
a
|
|
---
|
|
(0 rows)
|
|
|
|
select * from sche1.bind_t1;
|
|
a
|
|
---
|
|
2
|
|
(1 row)
|
|
|
|
select * from sche2.bind_t1;
|
|
a
|
|
---
|
|
2
|
|
(1 row)
|
|
|
|
delete from public.bind_t1;
|
|
delete from sche1.bind_t1;
|
|
delete from sche2.bind_t1;
|
|
-- insert into sche1.bind_t1 and sche2.bind_t1.
|
|
call sche1.fun_001();
|
|
fun_001
|
|
---------
|
|
1
|
|
(1 row)
|
|
|
|
select * from public.bind_t1;
|
|
a
|
|
---
|
|
(0 rows)
|
|
|
|
select * from sche1.bind_t1;
|
|
a
|
|
---
|
|
1
|
|
(1 row)
|
|
|
|
select * from sche2.bind_t1;
|
|
a
|
|
---
|
|
2
|
|
(1 row)
|
|
|
|
reset search_path;
|
|
drop table public.bind_t1;
|
|
drop table sche1.bind_t1;
|
|
drop table sche2.bind_t1;
|
|
drop schema sche1 cascade;
|
|
NOTICE: drop cascades to function sche1.fun_001()
|
|
drop schema sche2 cascade;
|
|
NOTICE: drop cascades to function sche2.fun_001()
|
|
-- test DDL under SUPPORT_BIND_SEARCHPATH
|
|
create schema sche1;
|
|
create table public.sche_t1(a int, b int);
|
|
insert into public.sche_t1 values(1, 11);
|
|
create or replace procedure sche1.fun_001() as
|
|
begin
|
|
insert into sche_t1 values(2, 12);
|
|
truncate table sche_t1;
|
|
insert into sche_t1 values(3, 13);
|
|
end;
|
|
/
|
|
call sche1.fun_001();
|
|
fun_001
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select * from public.sche_t1;
|
|
a | b
|
|
---+----
|
|
3 | 13
|
|
(1 row)
|
|
|
|
create or replace procedure sche1.fun_001() as
|
|
begin
|
|
alter table sche_t1 add column c char(10);
|
|
insert into sche_t1 values(4, 14, 'hello');
|
|
end;
|
|
/
|
|
call sche1.fun_001();
|
|
fun_001
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select * from public.sche_t1 order by 1,2,3;
|
|
a | b | c
|
|
---+----+------------
|
|
3 | 13 |
|
|
4 | 14 | hello
|
|
(2 rows)
|
|
|
|
drop table public.sche_t1;
|
|
drop schema sche1 cascade;
|
|
NOTICE: drop cascades to function sche1.fun_001()
|
|
reset behavior_compat_options;
|
|
-- test multiple CREATE TABLE AS.
|
|
-- avoid cacheplan CREATE TABLE AS statement as INSERT.
|
|
create schema sche1;
|
|
create table sche1.sche_t1(a int,b varchar);
|
|
insert into sche1.sche_t1 values(1,1);
|
|
create or replace procedure sche1.subpro() as
|
|
begin
|
|
create table test as select * from sche_t1;
|
|
insert into test values(2,2);
|
|
end;
|
|
/
|
|
create or replace procedure sche1.pro() as
|
|
begin
|
|
subpro();
|
|
subpro();
|
|
end;
|
|
/
|
|
call sche1.pro();
|
|
ERROR: relation "test" already exists in schema "sche1"
|
|
DETAIL: creating new table with existing name in the same schema
|
|
CONTEXT: SQL statement "create table test as select * from sche_t1"
|
|
PL/pgSQL function subpro() line 2 at SQL statement
|
|
SQL statement "CALL subpro()"
|
|
PL/pgSQL function sche1.pro() line 3 at PERFORM
|
|
drop schema sche1 cascade;
|
|
NOTICE: drop cascades to 3 other objects
|
|
DETAIL: drop cascades to table sche1.sche_t1
|
|
drop cascades to function sche1.subpro()
|
|
drop cascades to function sche1.pro()
|
|
-- clear option
|
|
reset search_path;
|
|
CREATE OR REPLACE FUNCTION func_increment_sql_1(i int, out result_1 bigint, out result_2 bigint)
|
|
returns SETOF RECORD
|
|
as $$
|
|
begin
|
|
result_1 = i + 1;
|
|
result_2 = i * 10;
|
|
raise notice '%', result_1;
|
|
raise notice '%', result_2;
|
|
return next;
|
|
end;
|
|
$$language plpgsql;
|
|
SELECT func_increment_sql_1(1);
|
|
NOTICE: 2
|
|
CONTEXT: referenced column: func_increment_sql_1
|
|
NOTICE: 10
|
|
CONTEXT: referenced column: func_increment_sql_1
|
|
func_increment_sql_1
|
|
----------------------
|
|
(2,10)
|
|
(1 row)
|
|
|
|
CREATE OR REPLACE FUNCTION func_increment_sql_2(i int, inout result_1 bigint, out result_2 bigint)
|
|
returns SETOF RECORD
|
|
as $$
|
|
begin
|
|
raise notice '%', result_1;
|
|
result_1 = i + 1;
|
|
result_2 = i * 10;
|
|
raise notice '%', result_1;
|
|
raise notice '%', result_2;
|
|
return next;
|
|
end;
|
|
$$language plpgsql;
|
|
--error
|
|
SELECT func_increment_sql_2(1);
|
|
ERROR: function func_increment_sql_2(integer) does not exist
|
|
LINE 1: SELECT func_increment_sql_2(1);
|
|
^
|
|
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
|
|
CONTEXT: referenced column: func_increment_sql_2
|
|
--success
|
|
SELECT func_increment_sql_2(1,2);
|
|
NOTICE: 2
|
|
CONTEXT: referenced column: func_increment_sql_2
|
|
NOTICE: 2
|
|
CONTEXT: referenced column: func_increment_sql_2
|
|
NOTICE: 10
|
|
CONTEXT: referenced column: func_increment_sql_2
|
|
func_increment_sql_2
|
|
----------------------
|
|
(2,10)
|
|
(1 row)
|
|
|
|
CREATE OR REPLACE FUNCTION fun_test_1(i int)
|
|
RETURNS void
|
|
as $$
|
|
begin
|
|
PERFORM func_increment_sql_1(i);
|
|
end;
|
|
$$language plpgsql;
|
|
select fun_test_1(1);
|
|
NOTICE: 2
|
|
CONTEXT: referenced column: func_increment_sql_1
|
|
SQL statement "SELECT func_increment_sql_1(i)"
|
|
PL/pgSQL function fun_test_1(integer) line 3 at PERFORM
|
|
referenced column: fun_test_1
|
|
NOTICE: 10
|
|
CONTEXT: referenced column: func_increment_sql_1
|
|
SQL statement "SELECT func_increment_sql_1(i)"
|
|
PL/pgSQL function fun_test_1(integer) line 3 at PERFORM
|
|
referenced column: fun_test_1
|
|
fun_test_1
|
|
------------
|
|
|
|
(1 row)
|
|
|
|
--error
|
|
CREATE OR REPLACE FUNCTION fun_test_2(i int)
|
|
RETURNS void
|
|
as $$
|
|
begin
|
|
PERFORM func_increment_sql_2(i);
|
|
end;
|
|
$$language plpgsql;
|
|
ERROR: function func_increment_sql_2 has no enough parameters
|
|
CONTEXT: compilation of PL/pgSQL function "fun_test_2" near line 1
|
|
CREATE OR REPLACE FUNCTION fun_test_2(i int)
|
|
RETURNS void
|
|
as $$
|
|
begin
|
|
PERFORM func_increment_sql_2(i,i+1);
|
|
end;
|
|
$$language plpgsql;
|
|
select fun_test_2(1);
|
|
NOTICE: 2
|
|
CONTEXT: referenced column: func_increment_sql_2
|
|
SQL statement "SELECT func_increment_sql_2(i,i+1)"
|
|
PL/pgSQL function fun_test_2(integer) line 3 at PERFORM
|
|
referenced column: fun_test_2
|
|
NOTICE: 2
|
|
CONTEXT: referenced column: func_increment_sql_2
|
|
SQL statement "SELECT func_increment_sql_2(i,i+1)"
|
|
PL/pgSQL function fun_test_2(integer) line 3 at PERFORM
|
|
referenced column: fun_test_2
|
|
NOTICE: 10
|
|
CONTEXT: referenced column: func_increment_sql_2
|
|
SQL statement "SELECT func_increment_sql_2(i,i+1)"
|
|
PL/pgSQL function fun_test_2(integer) line 3 at PERFORM
|
|
referenced column: fun_test_2
|
|
fun_test_2
|
|
------------
|
|
|
|
(1 row)
|
|
|
|
CREATE FUNCTION w_testfun3 (c_int INOUT int DEFAULT 1) RETURNS int AS $$
|
|
BEGIN
|
|
RETURN (c_int);
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
DROP FUNCTION func_increment_sql_1;
|
|
DROP FUNCTION func_increment_sql_2;
|
|
DROP FUNCTION fun_test_1;
|
|
DROP FUNCTION fun_test_2;
|
|
set behavior_compat_options='select_into_return_null';
|
|
create table test_table_030(id int, name text);
|
|
insert into test_table_030 values(1,'a'),(2,'b');
|
|
CREATE OR REPLACE FUNCTION select_into_null_func(canshu varchar(16))
|
|
returns int
|
|
as $$
|
|
DECLARE test_table_030a int;
|
|
begin
|
|
SELECT ID into test_table_030a FROM test_table_030 WHERE NAME = canshu;
|
|
return test_table_030a;
|
|
end; $$ language plpgsql;
|
|
select select_into_null_func('aaa');
|
|
select_into_null_func
|
|
-----------------------
|
|
|
|
(1 row)
|
|
|
|
select select_into_null_func('aaa') is null;
|
|
?column?
|
|
----------
|
|
t
|
|
(1 row)
|
|
|
|
drop table test_table_030;
|
|
drop function select_into_null_func;
|
|
reset behavior_compat_options;
|
|
\c regression;
|
|
drop database IF EXISTS pl_test_funcion;
|
|
-- test create internal functions
|
|
create function fn_void(cstring) returns void language internal as 'int8in';
|
|
select fn_void(null);
|
|
fn_void
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select fn_void('');
|
|
fn_void
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select fn_void('1234');
|
|
fn_void
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select fn_void(1234); -- should error, no function matches
|
|
ERROR: function fn_void(integer) does not exist
|
|
LINE 1: select fn_void(1234);
|
|
^
|
|
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
|
|
CONTEXT: referenced column: fn_void
|
|
drop function fn_void(cstring);
|
|
create function fn_n(cstring) returns int language internal as 'int4in';
|
|
select fn_n(null);
|
|
fn_n
|
|
------
|
|
|
|
(1 row)
|
|
|
|
select fn_n('');
|
|
fn_n
|
|
------
|
|
|
|
(1 row)
|
|
|
|
select fn_n('666');
|
|
fn_n
|
|
------
|
|
666
|
|
(1 row)
|
|
|
|
select fn_n(666); -- should error, no function matches
|
|
ERROR: function fn_n(integer) does not exist
|
|
LINE 1: select fn_n(666);
|
|
^
|
|
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
|
|
CONTEXT: referenced column: fn_n
|
|
select fn_n('666666666666666666666666666666666666666666666666666'); -- out of range
|
|
ERROR: value "666666666666666666666666666666666666666666666666666" is out of range for type integer
|
|
CONTEXT: referenced column: fn_n
|
|
select fn_n('fhdsfhdj'); -- invalid input
|
|
ERROR: invalid input syntax for integer: "fhdsfhdj"
|
|
CONTEXT: referenced column: fn_n
|
|
drop function fn_n(cstring);
|
|
create function fn_n2(int8) returns cstring language internal as 'int8out';
|
|
select fn_n2(0);
|
|
fn_n2
|
|
-------
|
|
0
|
|
(1 row)
|
|
|
|
select fn_n2(1::int2);
|
|
fn_n2
|
|
-------
|
|
1
|
|
(1 row)
|
|
|
|
select fn_n2(1234);
|
|
fn_n2
|
|
-------
|
|
1234
|
|
(1 row)
|
|
|
|
select fn_n2(-1234::int4);
|
|
fn_n2
|
|
-------
|
|
-1234
|
|
(1 row)
|
|
|
|
select fn_n2('1234');
|
|
fn_n2
|
|
-------
|
|
1234
|
|
(1 row)
|
|
|
|
drop function fn_n2(int8);
|
|
create function fn_n3(int8, cstring) returns cstring language internal as 'int8out'; -- exeeded param is ok
|
|
select fn_n3(null, null);
|
|
fn_n3
|
|
-------
|
|
|
|
(1 row)
|
|
|
|
select fn_n3('', '');
|
|
fn_n3
|
|
-------
|
|
|
|
(1 row)
|
|
|
|
select fn_n3(123456789, null);
|
|
fn_n3
|
|
-------
|
|
|
|
(1 row)
|
|
|
|
select fn_n3(12345, ''); -- empty string will be treated as null
|
|
fn_n3
|
|
-------
|
|
|
|
(1 row)
|
|
|
|
select fn_n3(12345, 'rtrgfgf');
|
|
fn_n3
|
|
-------
|
|
12345
|
|
(1 row)
|
|
|
|
drop function fn_n3(int8, cstring);
|
|
create function fn_txt(text) returns cstring as 'textout' language internal;
|
|
select fn_txt(null);
|
|
fn_txt
|
|
--------
|
|
|
|
(1 row)
|
|
|
|
select fn_txt('');
|
|
fn_txt
|
|
--------
|
|
|
|
(1 row)
|
|
|
|
select fn_txt('084329sdjhfdsffdjf');
|
|
fn_txt
|
|
--------------------
|
|
084329sdjhfdsffdjf
|
|
(1 row)
|
|
|
|
select fn_txt('sfiewr0239408497867^&*%&^$%^$*&()&*(&084329sdjhfdsffdjf');
|
|
fn_txt
|
|
---------------------------------------------------------
|
|
sfiewr0239408497867^&*%&^$%^$*&()&*(&084329sdjhfdsffdjf
|
|
(1 row)
|
|
|
|
drop function fn_txt(text);
|
|
create function fn_txt2(text, ot out int) returns cstring as 'textout' language internal;
|
|
select fn_txt2(null);
|
|
fn_txt2
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select fn_txt2('');
|
|
fn_txt2
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select fn_txt2('084329sdjhfdsffdjf');
|
|
fn_txt2
|
|
--------------------
|
|
084329sdjhfdsffdjf
|
|
(1 row)
|
|
|
|
select fn_txt2('sfiewr0239408497867^&*%&^$%^$*&()&*(&084329sdjhfdsffdjf');
|
|
fn_txt2
|
|
---------------------------------------------------------
|
|
sfiewr0239408497867^&*%&^$%^$*&()&*(&084329sdjhfdsffdjf
|
|
(1 row)
|
|
|
|
drop function fn_txt2(text, ot out int);
|
|
create function fn_txt3(text, ot out cstring) as 'textout' language internal;
|
|
select fn_txt3(null);
|
|
fn_txt3
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select fn_txt3('');
|
|
fn_txt3
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select fn_txt3('084329sdjhfdsffdjf');
|
|
fn_txt3
|
|
--------------------
|
|
084329sdjhfdsffdjf
|
|
(1 row)
|
|
|
|
select fn_txt3('sfiewr0239408497867^&*%&^$%^$*&()&*(&084329sdjhfdsffdjf');
|
|
fn_txt3
|
|
---------------------------------------------------------
|
|
sfiewr0239408497867^&*%&^$%^$*&()&*(&084329sdjhfdsffdjf
|
|
(1 row)
|
|
|
|
drop function fn_txt3(text, ot out cstring);
|
|
create function fn_txt4(ot out cstring, text) as 'textout' language internal;
|
|
select fn_txt4(null);
|
|
fn_txt4
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select fn_txt4('');
|
|
fn_txt4
|
|
---------
|
|
|
|
(1 row)
|
|
|
|
select fn_txt4('084329sdjhfdsffdjf');
|
|
fn_txt4
|
|
--------------------
|
|
084329sdjhfdsffdjf
|
|
(1 row)
|
|
|
|
select fn_txt4('sfiewr0239408497867^&*%&^$%^$*&()&*(&084329sdjhfdsffdjf');
|
|
fn_txt4
|
|
---------------------------------------------------------
|
|
sfiewr0239408497867^&*%&^$%^$*&()&*(&084329sdjhfdsffdjf
|
|
(1 row)
|
|
|
|
drop function fn_txt4(ot out cstring, text);
|
|
create function gt(int8, int8) returns bool as 'int8gt' language internal;
|
|
select gt(123, 234);
|
|
gt
|
|
----
|
|
f
|
|
(1 row)
|
|
|
|
select gt(123, 122);
|
|
gt
|
|
----
|
|
t
|
|
(1 row)
|
|
|
|
select gt(123, null);
|
|
gt
|
|
----
|
|
|
|
(1 row)
|
|
|
|
select gt('', null);
|
|
gt
|
|
----
|
|
|
|
(1 row)
|
|
|
|
select gt(null, null);
|
|
gt
|
|
----
|
|
|
|
(1 row)
|
|
|
|
select gt('12', '12');
|
|
gt
|
|
----
|
|
f
|
|
(1 row)
|
|
|
|
select gt('123', '13');
|
|
gt
|
|
----
|
|
t
|
|
(1 row)
|
|
|
|
select gt(123, 234) = int8gt(123, 234) as eq;
|
|
eq
|
|
----
|
|
t
|
|
(1 row)
|
|
|
|
select gt(123, 122) = int8gt(123, 122) as eq;
|
|
eq
|
|
----
|
|
t
|
|
(1 row)
|
|
|
|
select gt(123, null) is null and int8gt(123, null) is null as eq;
|
|
eq
|
|
----
|
|
t
|
|
(1 row)
|
|
|
|
select gt('', null) is null and int8gt('', null) is null as eq;
|
|
eq
|
|
----
|
|
t
|
|
(1 row)
|
|
|
|
select gt(null, null) is null and int8gt(null, null)is null as eq;
|
|
eq
|
|
----
|
|
t
|
|
(1 row)
|
|
|
|
select gt('12', '12') = int8gt('12', '12') as eq;
|
|
eq
|
|
----
|
|
t
|
|
(1 row)
|
|
|
|
select gt('123', '13') = int8gt('123', '13') as eq;
|
|
eq
|
|
----
|
|
t
|
|
(1 row)
|
|
|
|
drop function gt(int8, int8);
|
|
create type circle_tbl_ct;
|
|
create function fn_txt4(text) returns circle_tbl_ct as 'textout' language internal; -- OK
|
|
NOTICE: return type circle_tbl_ct is only a shell
|
|
create function fn_tfn_txt5(text, ot out circle_tbl_ct) as 'textout' language internal; -- OK
|
|
NOTICE: argument type circle_tbl_ct is only a shell
|
|
drop type circle_tbl_ct cascade;
|
|
NOTICE: drop cascades to 2 other objects
|
|
DETAIL: drop cascades to function fn_txt4(text)
|
|
drop cascades to function fn_tfn_txt5(text)
|
|
create function gt(int, int) returns bool as 'int8gt' language internal; -- should error
|
|
ERROR: The 1st input parameter of the function does not match the parameter type of the built-in function
|
|
create function gt(int8, int) returns bool as 'int8gt' language internal; -- should error
|
|
ERROR: The 2nd input parameter of the function does not match the parameter type of the built-in function
|
|
create function fn_p(int, cstring) returns int8 language internal as 'int8in'; -- should error
|
|
ERROR: The 1st input parameter of the function does not match the parameter type of the built-in function
|
|
create function fn_p2(int, cstring) returns int8 language internal as 'int8in'; -- should error
|
|
ERROR: The 1st input parameter of the function does not match the parameter type of the built-in function
|
|
create function fn_r(cstring) returns int language internal as 'int8in'; -- should error
|
|
ERROR: return type mismatch in function declared to return integer
|
|
DETAIL: actual return type is bigint
|
|
create function fn_r(cstring, o out int) language internal as 'int8in'; -- should error
|
|
ERROR: return type mismatch in function declared to return integer
|
|
DETAIL: actual return type is bigint
|
|
create function fn_txt_r(int8) returns text language internal as 'int8out'; -- ERROR: return type cstring
|
|
ERROR: return type mismatch in function declared to return text
|
|
DETAIL: actual return type is cstring
|
|
create function fn_txt_p(cstring) returns cstring as 'textout' language internal; -- error: param is text type
|
|
ERROR: The 1st input parameter of the function does not match the parameter type of the built-in function
|
|
-- test function for custum type
|
|
create type cc1_type;
|
|
create function cc1_in(cstring) returns cc1_type
|
|
strict immutable language internal as 'int8in';
|
|
NOTICE: return type cc1_type is only a shell
|
|
create function cc1_out(cc1_type) returns cstring
|
|
strict immutable language internal as 'int8out';
|
|
NOTICE: argument type cc1_type is only a shell
|
|
create function cc1_in_bad(cstring) returns cc1_type
|
|
strict immutable language internal as 'textin';
|
|
NOTICE: return type cc1_type is only a shell
|
|
create function cc1_out_bad(cc1_type) returns cstring
|
|
strict immutable language internal as 'textout';
|
|
NOTICE: argument type cc1_type is only a shell
|
|
-- should failed: internallength
|
|
create type cc1_type(
|
|
input = cc1_in,
|
|
output = cc1_out
|
|
);
|
|
ERROR: the input function's real return type bigint mismatch the type
|
|
DETAIL: attribute typlen 8 mismatch internallength -1
|
|
-- should failed: internallength
|
|
create type cc1_type(
|
|
internallength = 6,
|
|
input = cc1_in,
|
|
output = cc1_out
|
|
);
|
|
ERROR: the input function's real return type bigint mismatch the type
|
|
DETAIL: attribute typlen 8 mismatch internallength 6
|
|
-- should failed: output
|
|
create type cc1_type(
|
|
internallength = 8,
|
|
passedbyvalue = true,
|
|
alignment = double,
|
|
storage=plain,
|
|
input = cc1_in,
|
|
output = cc1_out_bad
|
|
);
|
|
ERROR: the output function's real parameter type text mismatch the type
|
|
DETAIL: attribute typlen -1 mismatch internallength 8
|
|
-- should failed
|
|
create type cc1_type(
|
|
internallength = 8,
|
|
passedbyvalue = true,
|
|
input = cc1_in,
|
|
output = cc1_out
|
|
);
|
|
ERROR: alignment "i" is invalid for passed-by-value type of size 8
|
|
-- should pass
|
|
create type cc1_type(
|
|
internallength = 8,
|
|
passedbyvalue = true,
|
|
alignment = double,
|
|
input = cc1_in,
|
|
output = cc1_out
|
|
);
|
|
create cast (int8 as cc1_type) with inout;
|
|
select 1234::int8::cc1_type;
|
|
cc1_type
|
|
----------
|
|
1234
|
|
(1 row)
|
|
|
|
-- case 2
|
|
create type cc2_type;
|
|
create function cc2_in(cstring) returns cc2_type
|
|
strict immutable language internal as 'textin';
|
|
NOTICE: return type cc2_type is only a shell
|
|
create function cc2_out(cc2_type) returns cstring
|
|
strict immutable language internal as 'textout';
|
|
NOTICE: argument type cc2_type is only a shell
|
|
create function cc2_out_bad(cc2_type) returns cstring
|
|
strict immutable language internal as 'int8out';
|
|
NOTICE: argument type cc2_type is only a shell
|
|
-- should failed
|
|
create type cc2_type(
|
|
input = cc2_in,
|
|
output = cc2_out_bad
|
|
);
|
|
ERROR: the output function's real parameter type bigint mismatch the type
|
|
DETAIL: attribute typlen 8 mismatch internallength -1
|
|
-- should failed
|
|
create type cc2_type(
|
|
internallength = 8,
|
|
input = cc2_in,
|
|
output = cc2_out_bad
|
|
);
|
|
ERROR: the input function's real return type text mismatch the type
|
|
DETAIL: attribute typlen -1 mismatch internallength 8
|
|
-- passed
|
|
create type cc2_type(
|
|
input = cc2_in,
|
|
output = cc2_out
|
|
);
|
|
select 1234::cc2_type; -- error
|
|
ERROR: cannot cast type integer to cc2_type
|
|
LINE 1: select 1234::cc2_type;
|
|
^
|
|
CONTEXT: referenced column: cc2_type
|
|
select '1234'::cc2_type;
|
|
cc2_type
|
|
----------
|
|
1234
|
|
(1 row)
|
|
|
|
select 'fdsfdfg#@$'::text::cc2_type;
|
|
cc2_type
|
|
------------
|
|
fdsfdfg#@$
|
|
(1 row)
|
|
|
|
drop type cc1_type cascade;
|
|
NOTICE: drop cascades to 5 other objects
|
|
DETAIL: drop cascades to function cc1_in(cstring)
|
|
drop cascades to function cc1_out(cc1_type)
|
|
drop cascades to function cc1_in_bad(cstring)
|
|
drop cascades to function cc1_out_bad(cc1_type)
|
|
drop cascades to cast from bigint to cc1_type
|
|
drop type cc2_type cascade;
|
|
NOTICE: drop cascades to 3 other objects
|
|
DETAIL: drop cascades to function cc2_in(cstring)
|
|
drop cascades to function cc2_out(cc2_type)
|
|
drop cascades to function cc2_out_bad(cc2_type)
|
|
CREATE OR REPLACE PROCEDURE test_debug1 ( IN x INT)
|
|
AS
|
|
BEGIN
|
|
INSERT INTO t1 (a) VALUES (x);
|
|
DELETE FROM t1 WHERE a = x;
|
|
END;
|
|
/
|
|
do $$
|
|
declare
|
|
funcoid bigint;
|
|
begin
|
|
select oid from pg_proc into funcoid where proname = 'test_debug1';
|
|
drop function test_debug1;
|
|
select dbe_pldebugger.turn_on(funcoid);
|
|
end;
|
|
$$;
|
|
--?ERROR: function with oid.*
|
|
CONTEXT: referenced column: turn_on
|
|
SQL statement "select dbe_pldebugger.turn_on(funcoid)"
|
|
PL/pgSQL function inline_code_block line 7 at SQL statement
|
|
drop function test_debug1;
|
|
\c postgres
|
|
alter system set enable_stmt_track=on;
|
|
set log_min_duration_statement=0;
|
|
set track_stmt_stat_level='L1,L1';
|
|
alter system set instr_unique_sql_count = 10000;
|
|
delete from dbe_perf.statement_history;
|
|
CREATE TABLE stmt_hist_t1 ( first_name text, last_name text, job_id int, department_id int,d1 bigint ) ;
|
|
create index stmt_hist_t1_i1 on stmt_hist_t1 (job_id) ;
|
|
create index stmt_hist_t1_i2 on stmt_hist_t1 (department_id) ;
|
|
insert into stmt_hist_t1 (first_name,last_name,job_id,department_id) values('Alice', 'Adams', 2, 1 );
|
|
insert into stmt_hist_t1 (first_name,last_name,job_id,department_id) values('Beatrice', 'Brand', 3, 1);
|
|
CREATE TABLE stmt_hist_t2 ( job_title text, job_id int) ;
|
|
insert into stmt_hist_t2 values( 'Job1', 1 );
|
|
insert into stmt_hist_t2 values( 'Job2', 2 );
|
|
insert into stmt_hist_t2 values( 'Job3', 3 );
|
|
analyze stmt_hist_t1;
|
|
analyze stmt_hist_t2;
|
|
CREATE FUNCTION func_add_sql() RETURNS integer
|
|
AS 'select 3;'
|
|
LANGUAGE SQL
|
|
IMMUTABLE
|
|
RETURNS NULL ON NULL INPUT;
|
|
explain (verbose, costs off) select func_add_sql() from stmt_hist_t2 join stmt_hist_t1 on stmt_hist_t2.job_id = stmt_hist_t1.job_id where stmt_hist_t1.job_id not in (select department_id from stmt_hist_t1 );
|
|
QUERY PLAN
|
|
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
Nested Loop
|
|
Output: 3
|
|
Join Filter: (public.stmt_hist_t1.job_id = stmt_hist_t2.job_id)
|
|
-> Nested Loop Anti Join
|
|
Output: public.stmt_hist_t1.job_id
|
|
Join Filter: ((public.stmt_hist_t1.job_id = public.stmt_hist_t1.department_id) OR (public.stmt_hist_t1.job_id IS NULL) OR (public.stmt_hist_t1.department_id IS NULL))
|
|
-> Seq Scan on public.stmt_hist_t1
|
|
Output: public.stmt_hist_t1.first_name, public.stmt_hist_t1.last_name, public.stmt_hist_t1.job_id, public.stmt_hist_t1.department_id, public.stmt_hist_t1.d1
|
|
-> Materialize
|
|
Output: public.stmt_hist_t1.department_id
|
|
-> Seq Scan on public.stmt_hist_t1
|
|
Output: public.stmt_hist_t1.department_id
|
|
-> Seq Scan on public.stmt_hist_t2
|
|
Output: stmt_hist_t2.job_title, stmt_hist_t2.job_id
|
|
(14 rows)
|
|
|
|
select func_add_sql() from stmt_hist_t2 join stmt_hist_t1 on stmt_hist_t2.job_id = stmt_hist_t1.job_id where stmt_hist_t1.job_id not in (select department_id from stmt_hist_t1 );
|
|
func_add_sql
|
|
--------------
|
|
3
|
|
3
|
|
(2 rows)
|
|
|
|
call pg_sleep(1);
|
|
pg_sleep
|
|
----------
|
|
|
|
(1 row)
|
|
|
|
select query_plan from dbe_perf.statement_history where query ilike '%select func_add_sql() from stmt_hist_t2 join stmt_hist_t1 on stmt_hist_t2.job_id = stmt_hist_t1.job_id where stmt_hist_t1.job_id not in (select department_id from stmt_hist_t1 );%';
|
|
query_plan
|
|
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
Datanode Name: datanode1 +
|
|
Nested Loop (cost=0.00..3.16 rows=1 width=0) +
|
|
Join Filter: (public.stmt_hist_t1.job_id = stmt_hist_t2.job_id) +
|
|
-> Nested Loop Anti Join (cost=0.00..2.10 rows=1 width=4) +
|
|
Join Filter: ((public.stmt_hist_t1.job_id = public.stmt_hist_t1.department_id) OR (public.stmt_hist_t1.job_id IS NULL) OR (public.stmt_hist_t1.department_id IS NULL))+
|
|
-> Seq Scan on stmt_hist_t1 (cost=0.00..1.02 rows=2 width=4) +
|
|
-> Materialize (cost=0.00..1.03 rows=2 width=4) +
|
|
-> Seq Scan on stmt_hist_t1 (cost=0.00..1.02 rows=2 width=4) +
|
|
-> Seq Scan on stmt_hist_t2 (cost=0.00..1.03 rows=3 width=4) +
|
|
+
|
|
|
|
(1 row)
|
|
|
|
drop table stmt_hist_t1, stmt_hist_t2 cascade;
|
|
drop function func_add_sql;
|
|
alter system set enable_stmt_track=off;
|
|
reset log_min_duration_statement;
|
|
reset track_stmt_stat_level;
|
|
alter system set instr_unique_sql_count = 100;
|
|
\c regression
|