英文:
RTE (RangeTblEntry) Replacement with PNSI (ParseNamespaceItem) in make_edge_expr function
问题
目前,我正在与一个团队合作,该团队正在将Apache AGE源代码中的RTE替换为PNSI,以使版本在代码方面变得统一。
我已经检查了Apache AGE用于PostgreSQL v12的代码,其中包含一个我打算改变的函数,使其与v13上的函数类似。
这是AGE_PG13上函数的定义:
static Node *make_vertex_expr(cypher_parsestate *cpstate,
ParseNamespaceItem *pnsi,
char *label);
而AGE_PG12上的函数定义如下:
static Node *make_vertex_expr(cypher_parsestate *cpstate, RangeTblEntry *rte,
char *label);
我们可以注意到参数RangeTblEntry *rte和ParseNamespaceItem *pnsi发生了变化,这是我的目标。
我已经更新了所有需要在函数中进行的更改。
对于不了解的人:PNSI是RTE的容器,因此RTE是PNSI的属性,这使我们感到放心,如果我们已经替换了每个使用RTE的必要部分为PNSI->RTE。
以下是AGE_PG12上发生的更改:
更改 @src/backend/parser/cypher_clause.c
@@ -4574,20 +4575,22 @@ static Expr *transform_cypher_node(cypher_parsestate *cpstate,
label_range_var = makeRangeVar(schema_name, rel_name, -1);
alias = makeAlias(node->name, NIL);
-
- rte = addRangeTableEntry(pstate, label_range_var, alias,
+ pnsi = malloc(sizeof(ParseNamespaceItem));
+ pnsi->p_rte = addRangeTableEntry(pstate, label_range_var, alias,
label_range_var->inh, true);
+
+ Assert(pnsi != NULL);
/*
* relation is visible (r.a in expression works) but attributes in the
* relation are not visible (a in expression doesn't work)
*/
- addRTEtoQuery(pstate, rte, true, true, true);
+ addRTEtoQuery(pstate, pnsi->p_rte, true, true, true);
resno = pstate->p_next_resno++;
if (valid_label)
{
- expr = (Expr *)make_vertex_expr(cpstate, rte, node->label);
+ expr = (Expr *)make_vertex_expr(cpstate, pnsi, node->label);
}
else
{
@@ -4650,7 +4653,7 @@ static Node *make_edge_expr(cypher_parsestate *cpstate, RangeTblEntry *rte,
return (Node *)func_expr;
}
-static Node *make_vertex_expr(cypher_parsestate *cpstate, RangeTblEntry *rte,
+static Node *make_vertex_expr(cypher_parsestate *cpstate, ParseNamespaceItem *pnsi,
char *label)
{
@@ -4666,7 +4669,7 @@ static Node *make_vertex_expr(cypher_parsestate *cpstate, RangeTblEntry *rte,
func_oid = get_ag_func_oid("_agtype_build_vertex", 3, GRAPHIDOID,
CSTRINGOID, AGTYPEOID);
- id = scanRTEForColumn(pstate, rte, AG_VERTEX_COLNAME_ID, -1, 0, NULL);
+ id = scanRTEForColumn(pstate, pnsi->p_rte, AG_VERTEX_COLNAME_ID, -1, 0, NULL);
@@ -4682,9 +4685,8 @@ static Node *make_vertex_expr(cypher_parsestate *cpstate, RangeTblEntry *rte,
InvalidOid, COERCE_EXPLICIT_CALL);
label_name_func_expr->location = -1;
- props = scanRTEForColumn(pstate, rte, AG_VERTEX_COLNAME_PROPERTIES, -1, 0,
+ props = scanRTEForColumn(pstate, pnsi->p_rte, AG_VERTEX_COLNAME_PROPERTIES, -1, 0,
NULL);
问题出在这里:我看到这是一种内存浪费,因为对于每个使用RTE的单个实例,我都需要用PNSI的分配内存来替换它(而PNSI更大)。是否有更有效的方法可以实现我的目标?
参考
英文:
Currently I am working as a part of a team which is working on replacing the RTE from apache-age source code to PNSI so that the versions became or unified in terms of the code wise.
I have checked the code which is being used at Apache AGE for PostgreSQL v12 and it contains a function that I am targeting to change it like wise that one on v13.
That is the definition of the function at AGE_PG13
static Node *make_vertex_expr(cypher_parsestate *cpstate,
ParseNamespaceItem *pnsi,
char *label);
And that what is was on AGE_PG12
static Node *make_vertex_expr(cypher_parsestate *cpstate, RangeTblEntry *rte,
char *label);
We can notice here the change happens in the parameter *RangeTblEntry rte, and *ParseNamespaceItem pnsi That's my goal
I have updated all of the changes that is required within the functions.
For those who are not aware: PNSI is a container of RTE so that RTE is property of PNSI which make us feels it's okay if we have replaced every needed part which uses RTE to PNSI->RTE.
Here is the changes happened on AGE_PG12
changes @src/backend/parser/cypher_clause.c
@@ -4574,20 +4575,22 @@ static Expr *transform_cypher_node(cypher_parsestate *cpstate,
label_range_var = makeRangeVar(schema_name, rel_name, -1);
alias = makeAlias(node->name, NIL);
-
- rte = addRangeTableEntry(pstate, label_range_var, alias,
+ pnsi = malloc(sizeof(ParseNamespaceItem));
+ pnsi->p_rte = addRangeTableEntry(pstate, label_range_var, alias,
label_range_var->inh, true);
+
+ Assert(pnsi != NULL);
/*
* relation is visible (r.a in expression works) but attributes in the
* relation are not visible (a in expression doesn't work)
*/
- addRTEtoQuery(pstate, rte, true, true, true);
+ addRTEtoQuery(pstate, pnsi->p_rte, true, true, true);
resno = pstate->p_next_resno++;
if (valid_label)
{
- expr = (Expr *)make_vertex_expr(cpstate, rte, node->label);
+ expr = (Expr *)make_vertex_expr(cpstate, pnsi, node->label);
}
else
{
@@ -4650,7 +4653,7 @@ static Node *make_edge_expr(cypher_parsestate *cpstate, RangeTblEntry *rte,
return (Node *)func_expr;
}
-static Node *make_vertex_expr(cypher_parsestate *cpstate, RangeTblEntry *rte,
+static Node *make_vertex_expr(cypher_parsestate *cpstate, ParseNamespaceItem *pnsi,
char *label)
{
@@ -4666,7 +4669,7 @@ static Node *make_vertex_expr(cypher_parsestate *cpstate, RangeTblEntry *rte,
func_oid = get_ag_func_oid("_agtype_build_vertex", 3, GRAPHIDOID,
CSTRINGOID, AGTYPEOID);
- id = scanRTEForColumn(pstate, rte, AG_VERTEX_COLNAME_ID, -1, 0, NULL);
+ id = scanRTEForColumn(pstate, pnsi->p_rte, AG_VERTEX_COLNAME_ID, -1, 0, NULL);
@@ -4682,9 +4685,8 @@ static Node *make_vertex_expr(cypher_parsestate *cpstate, RangeTblEntry *rte,
InvalidOid, COERCE_EXPLICIT_CALL);
label_name_func_expr->location = -1;
- props = scanRTEForColumn(pstate, rte, AG_VERTEX_COLNAME_PROPERTIES, -1, 0,
+ props = scanRTEForColumn(pstate, pnsi->p_rte, AG_VERTEX_COLNAME_PROPERTIES, -1, 0,
NULL);
The questions comes here; I am seeing that is a waste of memory because for every single instance where RTE was being used I will need to replace it with an allocated memory with size of PNSI (which is larger) to be able to use RTE within that PNSI? Is there any another way efficient that I can follow to achieve my goal?
References
答案1
得分: 2
你不需要在 PostgreSQL 函数中使用 malloc()
。PostgreSQL 在 C 的基础上构建了自己的内存管理系统。因此,你应该在适当的内存上下文中使用 palloc()
分配内存,它将在适当的时候(语句或事务结束时)自动释放。
关于是否使用 ParseNamespaceItem
是一个需要与编写 Apache AGE 的人讨论的问题。
英文:
You don't malloc()
in a PostgreSQL function. PostgreSQL has built its own memory management system on top of C. So you should palloc()
the memory in the appropriate memory context, and it will be freed automatically at the appropriate time (when the statement or the transaction ends).
If using a ParseNamespaceItem
is a good idea or not is a question you have to discuss with the people who wrote Apache AGE.
答案2
得分: 0
关于此事,我们决定不继续进行此替换,因为这将脱离上下文。由于Postgresql 12的AGE依赖于Postgresql 12的API和支持的函数,而Postgresql 13中包含的函数在版本12中不完全受支持,因此在版本12上很难像在版本13上那样进行替换,因为在版本13中新增了一些函数,这些函数对于版本12来说是必要的,以成功进行此替换。
英文:
Regarding this we have decided not to move forward with this replacement as it will be out of context. As AGE of Postgresql 12 depends on the Postgresql 12 api and the supported functions which are included on Postgresql 13 are not fully supported in version 12 so that the replacement that happened on v13 is not easily can be done on v12 because there are some functions are newly added on v13 those needed for v12 to make this replacement successfully
答案3
得分: 0
是的,您说得对,PNSI 需要比 RTE 更多的内存开销,但是您可以利用 PNSI 中的 指针 来最小化内存分配。
在使用 指针 时,您只需要通过指针引用每个实例的 PNSI。使用这种技术,您可以在需要的任何地方指向并使用 PNSI。
英文:
Yes, you are right that PNSI requires more memory overhead than RTE but you can make use of pointers with PNSI to minimize the memory allocation.
While using pointers, you just need to refer to PNSI through a pointer for every instance. With this technique, you can point and use PNSI wherever you need for instances.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论