我一直致力于用最新版本的Postgres(REL_16_BETA
版本)更新Apache AGE。我面临的一个主要问题是,代码被重写以更新权限检查,现在一些查询返回ERROR: invalid perminfoindex <rte->perminfoindex> in RTE with relid <rte->relid>
。这是由于具有perminfoindex = 0
和relid
的一个RTEs包含值而发生的。
AGE允许我们在Postgres中执行openCypher命令,这样它就可以创建一个包含节点和边的图。创建了两个主表:_ag_label_vertex
和_ag_label_edge
的三个不同的数据类型。它们都将是我们创建的每个其他顶点/边标签的父标签表。
当我们执行一个简单的MATCH
查询来查找所有带有v
标签的节点时:
SELECT * FROM cypher('cypher_set', $$
MATCH (n:v)
RETURN n
$$) AS (node agtype);
字符串
在add_rtes_to_flat_rtable()
函数中,它进入一个循环,我们可以看到root->parse->rtable
中存储的RTEs:
// I've simplified what every RTE shows.
root->parse->rtable
[
(rtekind = RTE_SUBQUERY, relid = 0, perminfoindex = 0),
(rtekind = RTE_SUBQUERY, relid = 0, perminfoindex = 0),
(rtekind = RTE_SUBQUERY, relid = 0, perminfoindex = 0),
(rtekind = RTE_RELATION, relid = 16991, perminfoindex = 1)
]
型
但是使用一个简单的SET
子句执行查询:
SELECT * FROM cypher('cypher_set', $$
MATCH (n)
SET n.i = 3
$$) AS (a agtype);
型
具有非空值的RTE_RELATION
类型和relid
的其中一个RTE具有perminfoindex = 0
root->parse->rtable
[
(rtekind = RTE_SUBQUERY, relid = 0, perminfoindex = 0),
(rtekind = RTE_RELATION, relid = 16971, perminfoindex = 1),
(rtekind = RTE_RELATION, relid = 16971, perminfoindex = 1),
(rtekind = RTE_RELATION, relid = 16991, perminfoindex = 0)
]
型
我们可以看到relid = 16991
与子顶点标签相关,relid = 16971
与父顶点标签相关:
SELECT to_regclass('cypher_set._ag_label_vertex')::oid;
to_regclass
-------------
16971
SELECT to_regclass('cypher_set.v')::oid;
to_regclass
-------------
16991
型
通过进一步检查AGE的代码,在执行SET
查询后,它进入transform_cypher_clause_as_subquery()
函数,ParseNamespaceItem
具有以下值:
{p_names = 0x1205638, p_rte = 0x11edb70, p_rtindex = 1, p_perminfo = 0x7f7f7f7f7f7f7f7f,
p_nscolumns = 0x1205848, p_rel_visible = true, p_cols_visible = true, p_lateral_only = false,
p_lateral_ok = true}
型pnsi->p_rte
:
{type = T_RangeTblEntry, rtekind = RTE_SUBQUERY, relid = 0, relkind = 0 '\000', rellockmode = 0,
tablesample = 0x0, perminfoindex = 0, subquery = 0x11ed710, security_barrier = false,
jointype = JOIN_INNER, joinmergedcols = 0, joinaliasvars = 0x0, joinleftcols = 0x0, joinrightcols = 0x0,
join_using_alias = 0x0, functions = 0x0, funcordinality = false, tablefunc = 0x0, values_lists = 0x0,
ctename = 0x0, ctelevelsup = 0, self_reference = false, coltypes = 0x0, coltypmods = 0x0,
colcollations = 0x0, enrname = 0x0, enrtuples = 0, alias = 0x12055f0, eref = 0x1205638, lateral = false,
inh = false, inFromCl = true, securityQuals = 0x0}
型
然后调用addNSItemToQuery(pstate, pnsi, true, false, true);
。此函数将给定的nsitem/RTE作为顶级条目添加到pstate的连接列表和/或名称空间列表中。我一直在想,这样添加nsitem/RTE是否不会导致此错误?
同样在handle_prev_clause
中,它有下面一行,这将把所有rte的属性添加到当前查询的targetlist中,同样,我不确定这是否是导致问题的原因,因为rte的relid是0:
query->targetList = expandNSItemAttrs(pstate, pnsi, 0, true, -1);
型
如果有人知道更多关于它,我会很感激任何形式的回答或帮助。
1条答案
按热度按时间cuxqih211#
首先,我要感谢Amit Langote和Tom Lane在这件事上帮助我。我已经发送了一些emails到pgsql黑客关于这个问题,他们帮助我展示了可能的错误。
当我们使用AGE执行
SET
查询时,代码的执行会经过GetResultRTEPermissionInfo()
并检查relinfo->ri_RootResultRelInfo
。这个变量指向nil。正因为如此,Postgres将解释为ResultRelInfo
必须仅为过滤触发器而创建,并且关系不会被插入。实际上,我们想触发第一个if语句字符串
因此,它最终会有错误的索引并指向错误的RTE,从而触发
getRTEPermissionInfo()
中的错误。