Merge branch 'master' of gitee.com:opengauss/openGauss-server into helper
This commit is contained in:
@ -70,6 +70,7 @@
|
||||
|
||||
THR_LOCAL bool skip_read_extern_fields = false;
|
||||
|
||||
#define IS_DATANODE_BUT_NOT_SINGLENODE (IS_PGXC_DATANODE && !IS_SINGLE_NODE)
|
||||
/*
|
||||
* Macros to simplify reading of different kinds of fields. Use these
|
||||
* wherever possible to reduce the chance for silly typos. Note that these
|
||||
@ -401,24 +402,27 @@ THR_LOCAL bool skip_read_extern_fields = false;
|
||||
token = pg_strtok(&length); /* skip :fldname */ \
|
||||
local_node->fldname = _readBitmapset()
|
||||
|
||||
#define READ_TYPEINFO_FIELD(fldname) \
|
||||
do { \
|
||||
if (local_node->fldname >= FirstBootstrapObjectId) { \
|
||||
IF_EXIST(exprtypename) \
|
||||
{ \
|
||||
char* exprtypename = NULL; \
|
||||
char* exprtypenamespace = NULL; \
|
||||
token = pg_strtok(&length); \
|
||||
token = pg_strtok(&length); \
|
||||
exprtypename = nullable_string(token, length); \
|
||||
token = pg_strtok(&length); \
|
||||
token = pg_strtok(&length); \
|
||||
exprtypenamespace = nullable_string(token, length); \
|
||||
local_node->fldname = get_typeoid(get_namespace_oid(exprtypenamespace, false), exprtypename); \
|
||||
pfree_ext(exprtypename); \
|
||||
pfree_ext(exprtypenamespace); \
|
||||
} \
|
||||
} \
|
||||
#define READ_TYPEINFO_FIELD(fldname) \
|
||||
do { \
|
||||
if (local_node->fldname >= FirstBootstrapObjectId) { \
|
||||
IF_EXIST(exprtypename) \
|
||||
{ \
|
||||
char* exprtypename = NULL; \
|
||||
char* exprtypenamespace = NULL; \
|
||||
token = pg_strtok(&length); \
|
||||
token = pg_strtok(&length); \
|
||||
exprtypename = nullable_string(token, length); \
|
||||
token = pg_strtok(&length); \
|
||||
token = pg_strtok(&length); \
|
||||
exprtypenamespace = nullable_string(token, length); \
|
||||
/* No need to reset field on CN or singlenode, keep pg_strtok() for forward compatibility */ \
|
||||
if (IS_DATANODE_BUT_NOT_SINGLENODE) { \
|
||||
local_node->fldname = get_typeoid(get_namespace_oid(exprtypenamespace, false), exprtypename); \
|
||||
} \
|
||||
pfree_ext(exprtypename); \
|
||||
pfree_ext(exprtypenamespace); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define READ_TYPEINFO(typePtr) \
|
||||
@ -493,9 +497,30 @@ THR_LOCAL bool skip_read_extern_fields = false;
|
||||
token = pg_strtok(&length); \
|
||||
token = pg_strtok(&length); \
|
||||
funcnamespace = nullable_string(token, length); \
|
||||
if (IS_PGXC_DATANODE && !skip_read_extern_fields) { \
|
||||
local_node->fldname = \
|
||||
get_func_oid(funcname, get_namespace_oid(funcnamespace, false), (Expr*)local_node); \
|
||||
bool notfound = false; \
|
||||
if (IS_DATANODE_BUT_NOT_SINGLENODE && !skip_read_extern_fields) { \
|
||||
Oid funcoid = InvalidOid; \
|
||||
do { \
|
||||
Oid nspid = get_namespace_oid(funcnamespace, true); \
|
||||
if (!OidIsValid(nspid)) { \
|
||||
notfound = true; \
|
||||
break; \
|
||||
} \
|
||||
funcoid = get_func_oid(funcname, nspid, (Expr*)local_node); \
|
||||
} while (0); \
|
||||
if (notfound || !OidIsValid(funcoid)) { \
|
||||
ereport(ERROR, \
|
||||
(errmodule(MOD_OPT), errcode(ERRCODE_UNDEFINED_OBJECT), \
|
||||
errmsg("Cannot identify function %s.%s while deserializing field.", \
|
||||
funcname, funcnamespace), \
|
||||
errdetail("Function with oid %u or its namespace may be renamed", \
|
||||
local_node->fldname), \
|
||||
errhint("Please rebuild column defalt expression, views etc. that are" \
|
||||
" related to this renamed object."), \
|
||||
errcause("Object renamed after recorded as nodetree."), \
|
||||
erraction("Rebuild relevant object."))); \
|
||||
} \
|
||||
local_node->fldname = funcoid; \
|
||||
} \
|
||||
pfree_ext(funcname); \
|
||||
pfree_ext(funcnamespace); \
|
||||
@ -525,7 +550,7 @@ THR_LOCAL bool skip_read_extern_fields = false;
|
||||
token = pg_strtok(&length); \
|
||||
token = pg_strtok(&length); \
|
||||
oprrightname = nullable_string(token, length); \
|
||||
if (IS_PGXC_DATANODE) { \
|
||||
if (IS_DATANODE_BUT_NOT_SINGLENODE) { \
|
||||
namespaceId = get_namespace_oid(opnamespace, false); \
|
||||
oprleft = get_typeoid(namespaceId, oprleftname); \
|
||||
oprright = oprleft; \
|
||||
@ -568,7 +593,7 @@ THR_LOCAL bool skip_read_extern_fields = false;
|
||||
token = pg_strtok(&length); \
|
||||
token = pg_strtok(&length); \
|
||||
oprrightname = nullable_string(token, length); \
|
||||
if (IS_PGXC_DATANODE) { \
|
||||
if (IS_DATANODE_BUT_NOT_SINGLENODE) { \
|
||||
namespaceId = get_namespace_oid(opnamespace, false); \
|
||||
oprleft = get_typeoid(namespaceId, oprleftname); \
|
||||
oprright = oprleft; \
|
||||
@ -2126,14 +2151,21 @@ static FuncExpr* _readFuncExpr(void)
|
||||
ereport(ERROR, (errcode(ERRCODE_UNEXPECTED_NULL_VALUE), errmsg("NULL seqNamespace for nextval()")));
|
||||
}
|
||||
|
||||
if (!IS_PGXC_COORDINATOR && !skip_read_extern_fields) {
|
||||
Oid seqid = get_valid_relname_relid(seqNamespace, seqName);
|
||||
if (IS_DATANODE_BUT_NOT_SINGLENODE && !skip_read_extern_fields) {
|
||||
|
||||
Oid seqid = get_valid_relname_relid(seqNamespace, seqName, true);
|
||||
Const* firstArg = (Const*)linitial(local_node->args);
|
||||
if (OidIsValid(seqid)) {
|
||||
Const* firstArg = (Const*)linitial(local_node->args);
|
||||
if (firstArg != NULL) {
|
||||
firstArg->constvalue = ObjectIdGetDatum(seqid);
|
||||
}
|
||||
} else {
|
||||
ereport(ERROR, (errmodule(MOD_OPT), errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("Cannot identify sequence %s.%s while deserializing field.", seqNamespace, seqName),
|
||||
errdetail("Sequence with oid %u or its namespace may be renamed",
|
||||
DatumGetObjectId(firstArg->constvalue)),
|
||||
errhint("Please rebuild column defalt expression, views etc. that are related to this sequence"),
|
||||
errcause("Object renamed after recorded as nodetree."), erraction("Rebuild relevant object.")));
|
||||
}
|
||||
}
|
||||
pfree_ext(seqName);
|
||||
|
||||
7
src/common/backend/utils/cache/lsyscache.cpp
vendored
7
src/common/backend/utils/cache/lsyscache.cpp
vendored
@ -1723,7 +1723,7 @@ char* get_relname_relid_extend(
|
||||
extern bool StreamTopConsumerAmI();
|
||||
|
||||
/* same as get_relname_relid except we check for cache invalidation here */
|
||||
Oid get_valid_relname_relid(const char* relnamespace, const char* relname)
|
||||
Oid get_valid_relname_relid(const char* relnamespace, const char* relname, bool nsp_missing_ok)
|
||||
{
|
||||
Oid nspid = InvalidOid;
|
||||
Oid oldnspid = InvalidOid;
|
||||
@ -1747,7 +1747,10 @@ Oid get_valid_relname_relid(const char* relnamespace, const char* relname)
|
||||
if (EnableLocalSysCache()) {
|
||||
thrd_inval_count = t_thrd.lsc_cxt.lsc->inval_cxt.SIMCounter;
|
||||
}
|
||||
nspid = get_namespace_oid(relnamespace, false);
|
||||
nspid = get_namespace_oid(relnamespace, nsp_missing_ok);
|
||||
if (!OidIsValid(nspid)) {
|
||||
return InvalidOid;
|
||||
}
|
||||
relid = get_relname_relid(relname, nspid);
|
||||
/*
|
||||
* In bootstrap processing mode, we don't bother with locking
|
||||
|
||||
@ -1181,6 +1181,17 @@ static Node* pull_up_simple_subquery(PlannerInfo* root, Node* jtnode, RangeTblEn
|
||||
return jtnode;
|
||||
}
|
||||
|
||||
/*
|
||||
* We must flatten any join alias Vars in the subquery's targetlist,
|
||||
* because pulling up the subquery's subqueries might have changed their
|
||||
* expansions into arbitrary expressions, which could affect
|
||||
* pullup_replace_vars' decisions about whether PlaceHolderVar wrappers
|
||||
* are needed for tlist entries. (Likely it'd be better to do
|
||||
* flatten_join_alias_vars on the whole query tree at some earlier stage,
|
||||
* maybe even in the rewriter; but for now let's just fix this case here.)
|
||||
*/
|
||||
subquery->targetList = (List *) flatten_join_alias_vars(subroot, (Node *) subquery->targetList);
|
||||
|
||||
/*
|
||||
* Adjust level-0 varnos in subquery so that we can append its rangetable
|
||||
* to upper query's. We have to fix the subquery's append_rel_list as
|
||||
|
||||
@ -213,7 +213,7 @@ extern bool check_rel_is_partitioned(Oid relid);
|
||||
extern Oid partid_get_parentid(Oid partid);
|
||||
extern bool is_not_strict_agg(Oid funcOid);
|
||||
extern bool is_pgxc_class_table(Oid tableoid);
|
||||
extern Oid get_valid_relname_relid(const char* relnamespace, const char* relname);
|
||||
extern Oid get_valid_relname_relid(const char* relnamespace, const char* relname, bool nsp_missing_ok = false);
|
||||
extern bool get_func_iswindow(Oid funcid);
|
||||
extern char get_func_prokind(Oid funcid);
|
||||
extern char get_typecategory(Oid typid);
|
||||
|
||||
116
src/test/regress/expected/deserialize_func.out
Normal file
116
src/test/regress/expected/deserialize_func.out
Normal file
@ -0,0 +1,116 @@
|
||||
create schema deserialize_func1;
|
||||
set current_schema = deserialize_func1;
|
||||
create sequence test_seq;
|
||||
create or replace function test_func() return int
|
||||
as
|
||||
begin
|
||||
return 1;
|
||||
end;
|
||||
/
|
||||
create table t1(key int, id int default nextval('test_seq'));
|
||||
create table t2(key int, id int default test_func());
|
||||
select * from pg_get_tabledef('deserialize_func1.t1');
|
||||
pg_get_tabledef
|
||||
------------------------------------------------------
|
||||
SET search_path = deserialize_func1; +
|
||||
CREATE TABLE t1 ( +
|
||||
key integer, +
|
||||
id integer DEFAULT nextval('test_seq'::regclass)+
|
||||
) +
|
||||
WITH (orientation=row, compression=no);
|
||||
(1 row)
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func1.t2');
|
||||
pg_get_tabledef
|
||||
-----------------------------------------
|
||||
SET search_path = deserialize_func1; +
|
||||
CREATE TABLE t2 ( +
|
||||
key integer, +
|
||||
id integer DEFAULT test_func() +
|
||||
) +
|
||||
WITH (orientation=row, compression=no);
|
||||
(1 row)
|
||||
|
||||
alter schema deserialize_func1 rename to deserialize_func2;
|
||||
select * from pg_get_tabledef('deserialize_func2.t1');
|
||||
pg_get_tabledef
|
||||
------------------------------------------------------------------------
|
||||
SET search_path = deserialize_func2; +
|
||||
CREATE TABLE t1 ( +
|
||||
key integer, +
|
||||
id integer DEFAULT nextval('deserialize_func2.test_seq'::regclass)+
|
||||
) +
|
||||
WITH (orientation=row, compression=no);
|
||||
(1 row)
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func2.t2');
|
||||
pg_get_tabledef
|
||||
------------------------------------------------------
|
||||
SET search_path = deserialize_func2; +
|
||||
CREATE TABLE t2 ( +
|
||||
key integer, +
|
||||
id integer DEFAULT deserialize_func2.test_func()+
|
||||
) +
|
||||
WITH (orientation=row, compression=no);
|
||||
(1 row)
|
||||
|
||||
alter table deserialize_func2.t1 alter column id drop default;
|
||||
alter table deserialize_func2.t1 alter column id set default nextval('deserialize_func2.test_seq');
|
||||
select * from pg_get_tabledef('deserialize_func2.t1');
|
||||
pg_get_tabledef
|
||||
------------------------------------------------------------------------
|
||||
SET search_path = deserialize_func2; +
|
||||
CREATE TABLE t1 ( +
|
||||
key integer, +
|
||||
id integer DEFAULT nextval('deserialize_func2.test_seq'::regclass)+
|
||||
) +
|
||||
WITH (orientation=row, compression=no);
|
||||
(1 row)
|
||||
|
||||
alter table deserialize_func2.t2 alter column id drop default;
|
||||
alter table deserialize_func2.t2 alter column id set default deserialize_func2.test_func();
|
||||
select * from pg_get_tabledef('deserialize_func2.t2');
|
||||
pg_get_tabledef
|
||||
------------------------------------------------------
|
||||
SET search_path = deserialize_func2; +
|
||||
CREATE TABLE t2 ( +
|
||||
key integer, +
|
||||
id integer DEFAULT deserialize_func2.test_func()+
|
||||
) +
|
||||
WITH (orientation=row, compression=no);
|
||||
(1 row)
|
||||
|
||||
set current_schema = deserialize_func2;
|
||||
create type type1 as (a int);
|
||||
create view v1 as select '(1)'::type1;
|
||||
alter type type1 rename to type2;
|
||||
select pg_get_viewdef('v1');
|
||||
pg_get_viewdef
|
||||
-------------------------------
|
||||
SELECT '(1)'::type2 AS type1;
|
||||
(1 row)
|
||||
|
||||
drop view v1 cascade;
|
||||
create table atest12 as select x as a, 10001-x as b from generate_series(1, 10000) x;
|
||||
create function func1(integer, integer) returns boolean as $$begin return $1 < $2; end $$ language plpgsql immutable;
|
||||
create operator <<< (procedure=func1, leftarg=integer, rightarg=integer, restrict=scalarltsel);
|
||||
create view atest12v as select * from atest12 where b <<< 5;
|
||||
select pg_get_viewdef('atest12v');
|
||||
pg_get_viewdef
|
||||
-------------------------------------------------
|
||||
SELECT * FROM atest12 WHERE (atest12.b <<< 5);
|
||||
(1 row)
|
||||
|
||||
drop schema if exists deserialize_func1 cascade;
|
||||
NOTICE: schema "deserialize_func1" does not exist, skipping
|
||||
drop schema if exists deserialize_func2 cascade;
|
||||
NOTICE: drop cascades to 9 other objects
|
||||
DETAIL: drop cascades to sequence test_seq
|
||||
drop cascades to function test_func()
|
||||
drop cascades to table t1
|
||||
drop cascades to table t2
|
||||
drop cascades to type type2
|
||||
drop cascades to table atest12
|
||||
drop cascades to function func1(integer,integer)
|
||||
drop cascades to operator <<<(integer,integer)
|
||||
drop cascades to view atest12v
|
||||
55
src/test/regress/expected/join_test_alias.out
Normal file
55
src/test/regress/expected/join_test_alias.out
Normal file
@ -0,0 +1,55 @@
|
||||
CREATE TABLE t11 (
|
||||
sec_code character(6) NOT NULL,
|
||||
issue_type character(3) NOT NULL
|
||||
);
|
||||
CREATE TABLE t22 (
|
||||
company_code character(6) NOT NULL,
|
||||
list_profit_flag character(1) NOT NULL
|
||||
);
|
||||
CREATE TABLE t33 (
|
||||
company_code character(6) NOT NULL,
|
||||
issue_flag character(6) NOT NULL
|
||||
);
|
||||
insert into t11 values(1,'S04');
|
||||
insert into t22 values(1,'Y');
|
||||
insert into t33 values(1,'1');
|
||||
insert into t33 values(2,'2');
|
||||
select
|
||||
T5.issue_type
|
||||
,T6.is_type
|
||||
from
|
||||
(
|
||||
select T1.sec_code
|
||||
,issue_type
|
||||
--,case when list_profit_flag='Y' then '是' else '否' end as list_profit_flag
|
||||
from
|
||||
(
|
||||
select sec_code
|
||||
,case when issue_type in ('S04','S05','S06','S09') then '增发'
|
||||
when issue_type in ('S01','S02') then '首发'
|
||||
else '其他' end as issue_type
|
||||
from t11
|
||||
)T1
|
||||
left join
|
||||
(
|
||||
select list_profit_flag
|
||||
,company_code
|
||||
from t22
|
||||
)T2
|
||||
on T1.sec_code=T2.company_code
|
||||
)T5
|
||||
full join
|
||||
(
|
||||
SELECT CASE
|
||||
WHEN issue_flag = ANY (ARRAY['1'::bpchar, '3'::bpchar, '11'::bpchar]) THEN '首发'::text
|
||||
ELSE '增发'::text
|
||||
END AS is_type from t33
|
||||
)T6
|
||||
on T5.issue_type=T6.is_type
|
||||
;
|
||||
issue_type | is_type
|
||||
------------+---------
|
||||
增发 | 增发
|
||||
| 首发
|
||||
(2 rows)
|
||||
|
||||
@ -25,7 +25,7 @@ test: pldeveloper_gs_source
|
||||
test: index_advisor
|
||||
test: pl_debugger_server pl_debugger_client
|
||||
test: update_for_wait_s1 update_for_wait_s2
|
||||
test: plan_hint plan_hint_set plan_hint_no_expand plan_hint_iud null_test_opt
|
||||
test: plan_hint plan_hint_set plan_hint_no_expand plan_hint_iud null_test_opt deserialize_func
|
||||
test: large_sequence int16 gs_dump_sequence
|
||||
test: gs_dump_tableof
|
||||
test: analyze_commands
|
||||
@ -917,3 +917,4 @@ test: gs_global_config_audit
|
||||
test: detail
|
||||
test: gs_dump_encrypt
|
||||
test: composite_datum_record
|
||||
test: join_test_alias
|
||||
|
||||
@ -5238,7 +5238,7 @@ static void check_global_variables()
|
||||
}
|
||||
}
|
||||
|
||||
#define BASE_PGXC_LIKE_MACRO_NUM 1401
|
||||
#define BASE_PGXC_LIKE_MACRO_NUM 1402
|
||||
static void check_pgxc_like_macros()
|
||||
{
|
||||
#ifdef BUILD_BY_CMAKE
|
||||
|
||||
63
src/test/regress/sql/deserialize_func.sql
Normal file
63
src/test/regress/sql/deserialize_func.sql
Normal file
@ -0,0 +1,63 @@
|
||||
create schema deserialize_func1;
|
||||
set current_schema = deserialize_func1;
|
||||
|
||||
create sequence test_seq;
|
||||
|
||||
create or replace function test_func() return int
|
||||
as
|
||||
begin
|
||||
return 1;
|
||||
end;
|
||||
/
|
||||
|
||||
create table t1(key int, id int default nextval('test_seq'));
|
||||
|
||||
create table t2(key int, id int default test_func());
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func1.t1');
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func1.t2');
|
||||
|
||||
alter schema deserialize_func1 rename to deserialize_func2;
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func2.t1');
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func2.t2');
|
||||
|
||||
alter table deserialize_func2.t1 alter column id drop default;
|
||||
|
||||
alter table deserialize_func2.t1 alter column id set default nextval('deserialize_func2.test_seq');
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func2.t1');
|
||||
|
||||
alter table deserialize_func2.t2 alter column id drop default;
|
||||
|
||||
alter table deserialize_func2.t2 alter column id set default deserialize_func2.test_func();
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func2.t2');
|
||||
|
||||
set current_schema = deserialize_func2;
|
||||
|
||||
create type type1 as (a int);
|
||||
|
||||
create view v1 as select '(1)'::type1;
|
||||
|
||||
alter type type1 rename to type2;
|
||||
|
||||
select pg_get_viewdef('v1');
|
||||
|
||||
drop view v1 cascade;
|
||||
|
||||
create table atest12 as select x as a, 10001-x as b from generate_series(1, 10000) x;
|
||||
|
||||
create function func1(integer, integer) returns boolean as $$begin return $1 < $2; end $$ language plpgsql immutable;
|
||||
|
||||
create operator <<< (procedure=func1, leftarg=integer, rightarg=integer, restrict=scalarltsel);
|
||||
|
||||
create view atest12v as select * from atest12 where b <<< 5;
|
||||
|
||||
select pg_get_viewdef('atest12v');
|
||||
|
||||
drop schema if exists deserialize_func1 cascade;
|
||||
|
||||
drop schema if exists deserialize_func2 cascade;
|
||||
53
src/test/regress/sql/join_test_alias.sql
Normal file
53
src/test/regress/sql/join_test_alias.sql
Normal file
@ -0,0 +1,53 @@
|
||||
CREATE TABLE t11 (
|
||||
sec_code character(6) NOT NULL,
|
||||
issue_type character(3) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE t22 (
|
||||
company_code character(6) NOT NULL,
|
||||
list_profit_flag character(1) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE t33 (
|
||||
company_code character(6) NOT NULL,
|
||||
issue_flag character(6) NOT NULL
|
||||
);
|
||||
|
||||
insert into t11 values(1,'S04');
|
||||
insert into t22 values(1,'Y');
|
||||
insert into t33 values(1,'1');
|
||||
insert into t33 values(2,'2');
|
||||
|
||||
select
|
||||
T5.issue_type
|
||||
,T6.is_type
|
||||
from
|
||||
(
|
||||
select T1.sec_code
|
||||
,issue_type
|
||||
--,case when list_profit_flag='Y' then '是' else '否' end as list_profit_flag
|
||||
from
|
||||
(
|
||||
select sec_code
|
||||
,case when issue_type in ('S04','S05','S06','S09') then '增发'
|
||||
when issue_type in ('S01','S02') then '首发'
|
||||
else '其他' end as issue_type
|
||||
from t11
|
||||
)T1
|
||||
left join
|
||||
(
|
||||
select list_profit_flag
|
||||
,company_code
|
||||
from t22
|
||||
)T2
|
||||
on T1.sec_code=T2.company_code
|
||||
)T5
|
||||
full join
|
||||
(
|
||||
SELECT CASE
|
||||
WHEN issue_flag = ANY (ARRAY['1'::bpchar, '3'::bpchar, '11'::bpchar]) THEN '首发'::text
|
||||
ELSE '增发'::text
|
||||
END AS is_type from t33
|
||||
)T6
|
||||
on T5.issue_type=T6.is_type
|
||||
;
|
||||
Reference in New Issue
Block a user