!1726 修复视图中包含自定义操作符时,获取视图定义失败的问题

Merge pull request !1726 from pengjiong/logical_core
This commit is contained in:
opengauss-bot 2022-05-13 09:11:34 +00:00 committed by Gitee
commit 6c5898646e
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
7 changed files with 245 additions and 31 deletions

View File

@ -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);

View File

@ -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

View File

@ -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);

View 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

View File

@ -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

View File

@ -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

View 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;