Skip to content

Commit 135f20f

Browse files
committed
Move MATCH and MERGE label matching to LTree
In the label redesign, we are going to need to completely change the logic to resolve which tables to use for a label. This is the first step to moving MATCH and MERGE to the new system.
1 parent f8be576 commit 135f20f

10 files changed

Lines changed: 127 additions & 64 deletions

File tree

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ REGRESS = new_cypher \
118118

119119
srcdir=`pwd`
120120
POSTGIS_DIR ?= postgis_dir
121-
121+
PG_LIBS += -ltree
122122
.PHONY:all
123123

124124
all: postgraph--0.1.0.sql
@@ -135,7 +135,7 @@ GEN_KEYWORDLIST = $(PERL) -I ./tools/ ./tools/gen_keywordlist.pl
135135
GEN_KEYWORDLIST_DEPS = ./tools/gen_keywordlist.pl tools/PerfectHash.pm
136136

137137
ag_include_dir = $(srcdir)/src/include
138-
PG_CPPFLAGS = -w -I$(ag_include_dir) -I$(ag_include_dir)/parser -I$(POSTGIS_DIR) -I$(POSTGIS_DIR)/liblwgeom
138+
PG_CPPFLAGS = -w -I$(ag_include_dir) -I$(ag_include_dir)/parser -I$(POSTGIS_DIR) -I$(POSTGIS_DIR)/liblwgeom -I/home/josh/postgres/contrib/ltree
139139
PG_LDFLAGS = -lgeos_c
140140
SHLIB_LINK= $(POSTGIS_DIR)/liblwgeom/.libs/liblwgeom.a -Wl,--no-as-needed -Wl,-l:postgis-3.so -Wl,-l:ltree.so
141141

sql/postgraph.sql.in

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ CREATE TABLE ag_label (
6565
id label_id,
6666
kind label_kind,
6767
relation regclass NOT NULL,
68-
label_path public.ltree NOT NULL,
68+
label_path public.ltree NULL,
6969
CONSTRAINT fk_graph_oid FOREIGN KEY(graph) REFERENCES ag_graph(graphid)
7070
);
7171

@@ -85,6 +85,10 @@ CREATE UNIQUE INDEX ag_label_path_graph_index
8585
ON ag_label
8686
USING btree (label_path, graph);
8787

88+
CREATE INDEX ag_label_ltree_index
89+
ON ag_label
90+
USING gist (label_path public.gist_ltree_ops);
91+
8892
CREATE TABLE session_graph_use (
8993
pid oid not null,
9094
graph_oid oid not null

src/backend/catalog/ag_label.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
#include "utils/rel.h"
3838
#include "utils/relcache.h"
3939

40+
#include "ltree.h"
41+
4042
#include "catalog/ag_graph.h"
4143
#include "catalog/ag_label.h"
4244
#include "commands/label_commands.h"
@@ -50,7 +52,7 @@ PG_FUNCTION_INFO_V1(ltree_addltree);
5052
// INSERT INTO CATALOG_SCHEMA.ag_label
5153
// VALUES (label_name, label_graph, label_id, label_kind, label_relation)
5254
void insert_label(const char *label_name, Oid graph_oid, int32 label_id,
53-
char label_kind, Oid label_relation)
55+
char label_kind, Oid label_relation, const char *ltree)
5456
{
5557
NameData label_name_data;
5658
Datum values[Natts_ag_label + 1];
@@ -85,7 +87,15 @@ void insert_label(const char *label_name, Oid graph_oid, int32 label_id,
8587

8688
values[Anum_ag_label_relation - 1] = ObjectIdGetDatum(label_relation);
8789
nulls[Anum_ag_label_relation - 1] = false;
88-
90+
/*
91+
if (ltree == NULL) {
92+
values[Anum_ag_label_label_path - 1] = NULL;
93+
nulls[Anum_ag_label_label_path - 1] = false;
94+
} else {
95+
values[Anum_ag_label_label_path - 1] = DirectFunctionCall1(ltree_in, CStringGetDatum(ltree));
96+
nulls[Anum_ag_label_label_path - 1] = true;
97+
}*/
98+
8999
if (strcmp(label_name, "_ag_label_vertex") == 0 || strcmp(label_name, "_ag_label_edge") == 0) {
90100
values[5] = DirectFunctionCall1(ltree_in, CStringGetDatum(label_name));
91101
nulls[5] = false;
@@ -100,7 +110,6 @@ void insert_label(const char *label_name, Oid graph_oid, int32 label_id,
100110
DirectFunctionCall1(ltree_in, CStringGetDatum("_ag_label_edge")),
101111
DirectFunctionCall1(ltree_in, CStringGetDatum(label_name)));
102112
nulls[5] = false;
103-
104113
}
105114

106115

src/backend/commands/graph_commands.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ Datum create_graph_if_not_exists(PG_FUNCTION_ARGS)
8787

8888
//Create the default label tables
8989
graph = graph_name->data;
90-
create_label(graph, AG_DEFAULT_LABEL_VERTEX, LABEL_TYPE_VERTEX, NIL);
91-
create_label(graph, AG_DEFAULT_LABEL_EDGE, LABEL_TYPE_EDGE, NIL);
90+
create_label(graph, AG_DEFAULT_LABEL_VERTEX, LABEL_TYPE_VERTEX, NIL, NULL);
91+
create_label(graph, AG_DEFAULT_LABEL_EDGE, LABEL_TYPE_EDGE, NIL, NULL);
9292

9393
ereport(NOTICE,
9494
(errmsg("graph \"%s\" has been created", NameStr(*graph_name))));
@@ -208,8 +208,8 @@ Datum create_graph(PG_FUNCTION_ARGS)
208208

209209
//Create the default label tables
210210
graph = graph_name_str;//graph_name->data;
211-
create_label(graph, AG_DEFAULT_LABEL_VERTEX, LABEL_TYPE_VERTEX, NIL);
212-
create_label(graph, AG_DEFAULT_LABEL_EDGE, LABEL_TYPE_EDGE, NIL);
211+
create_label(graph, AG_DEFAULT_LABEL_VERTEX, LABEL_TYPE_VERTEX, NIL, NULL);
212+
create_label(graph, AG_DEFAULT_LABEL_EDGE, LABEL_TYPE_EDGE, NIL, NULL);
213213

214214
ereport(NOTICE,
215215
(errmsg("graph \"%s\" has been created", graph_name_str)));

src/backend/commands/label_commands.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ Datum create_vlabel(PG_FUNCTION_ARGS)
167167

168168
parent = list_make1(rv);
169169

170-
create_label(graph, label, LABEL_TYPE_VERTEX, parent);
170+
create_label(graph, label, LABEL_TYPE_VERTEX, parent, NULL);
171171

172172
ereport(NOTICE,
173173
(errmsg("VLabel \"%s\" has been created", NameStr(*label_name))));
@@ -246,7 +246,7 @@ Datum create_elabel(PG_FUNCTION_ARGS)
246246
rv = get_label_range_var(graph, graph_oid, AG_DEFAULT_LABEL_EDGE);
247247

248248
parent = list_make1(rv);
249-
create_label(graph, label, LABEL_TYPE_EDGE, parent);
249+
create_label(graph, label, LABEL_TYPE_EDGE, parent, NULL);
250250

251251
ereport(NOTICE,
252252
(errmsg("ELabel \"%s\" has been created", NameStr(*label_name))));
@@ -539,7 +539,7 @@ Datum create_property_index(PG_FUNCTION_ARGS)
539539
* CATALOG_SCHEMA.ag_label.
540540
*/
541541
void create_label(char *graph_name, char *label_name, char label_type,
542-
List *parents)
542+
List *parents, char *ltree)
543543
{
544544
graph_cache_data *cache_data;
545545
Oid graph_oid;
@@ -585,7 +585,7 @@ void create_label(char *graph_name, char *label_name, char label_type,
585585
// get a new "id" for the new label
586586
label_id = get_new_label_id(graph_oid, nsp_id);
587587

588-
insert_label(label_name, graph_oid, label_id, label_type, relation_id);
588+
insert_label(label_name, graph_oid, label_id, label_type, relation_id, NULL);
589589

590590
CommandCounterIncrement();
591591
}

src/backend/parser/cypher_clause.c

Lines changed: 92 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,3 @@
1-
/*
2-
* For PostgreSQL Database Management System:
3-
* (formerly known as Postgres, then as Postgres95)
4-
*
5-
* Portions Copyright (c) 1996-2010, The PostgreSQL Global Development Group
6-
*
7-
* Portions Copyright (c) 1994, The Regents of the University of California
8-
*
9-
* Permission to use, copy, modify, and distribute this software and its documentation for any purpose,
10-
* without fee, and without a written agreement is hereby granted, provided that the above copyright notice
11-
* and this paragraph and the following two paragraphs appear in all copies.
12-
*
13-
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT,
14-
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
15-
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
16-
* OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17-
*
18-
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19-
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20-
*
21-
* THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA
22-
* HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23-
*/
24-
251
#include "postgraph.h"
262

273
#include "access/nbtree.h"
@@ -3906,6 +3882,38 @@ static char *make_endid_alias(char *var_name) {
39063882
return str;
39073883
}
39083884

3885+
3886+
static char *make_lquery_string(char *var_name) {
3887+
return var_name;
3888+
char *str = palloc0(strlen(var_name) + 8);
3889+
3890+
str[0] = '.';
3891+
str[0] = '*';
3892+
str[1] = '\0';
3893+
3894+
return str;
3895+
/*
3896+
str[1] = '.';
3897+
str[0] = '*';
3898+
3899+
int i = 0;
3900+
for (; i < strlen(var_name); i++)
3901+
str[i + 2] = var_name[i];
3902+
3903+
str[i + 3] = '.';
3904+
str[i + 4] = '*';
3905+
str[i + 5] = '\0';
3906+
3907+
return str;
3908+
*/
3909+
}
3910+
3911+
//ltree
3912+
#include "ltree.h"
3913+
3914+
3915+
PG_FUNCTION_INFO_V1(lquery_in);
3916+
39093917
static Expr *transform_cypher_node(cypher_parsestate *cpstate, cypher_node *node, List **target_list, bool output_node) {
39103918
ParseState *pstate = (ParseState *)cpstate;
39113919
char *schema_name;
@@ -3916,9 +3924,11 @@ static Expr *transform_cypher_node(cypher_parsestate *cpstate, cypher_node *node
39163924
TargetEntry *te;
39173925
Expr *expr;
39183926
ParseNamespaceItem *pnsi;
3927+
bool is_default_label = false;
39193928

3920-
if (!node->label) {
3929+
if (!node->label || !strcmp(node->label, AG_DEFAULT_LABEL_VERTEX)) {
39213930
node->label = AG_DEFAULT_LABEL_VERTEX;
3931+
is_default_label = true;
39223932
} else {
39233933
label_cache_data *lcd = search_label_name_graph_cache(node->label, cpstate->graph_oid);
39243934

@@ -3927,7 +3937,7 @@ static Expr *transform_cypher_node(cypher_parsestate *cpstate, cypher_node *node
39273937
errmsg("label %s does not exists", node->label),
39283938
parser_errposition(pstate, node->location)));
39293939

3930-
if (lcd->kind != LABEL_KIND_VERTEX)
3940+
if (lcd->kind != LABEL_KIND_VERTEX)
39313941
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
39323942
errmsg("label %s is for edges, not vertices", node->label),
39333943
parser_errposition(pstate, node->location)));
@@ -3948,30 +3958,65 @@ static Expr *transform_cypher_node(cypher_parsestate *cpstate, cypher_node *node
39483958
transform_entity *entity = find_transform_entity(cpstate, node->name, ENT_VERTEX);
39493959
if (entity)
39503960
return entity->expr;
3951-
}
3952-
else {
3953-
te = findTarget(*target_list, node->name);
3954-
expr = colNameToVar(pstate, node->name, false, node->location);
3961+
} else {
3962+
te = findTarget(*target_list, node->name);
3963+
expr = colNameToVar(pstate, node->name, false, node->location);
39553964

3956-
if (expr)
3957-
return (Expr*)expr;
3965+
if (expr)
3966+
return (Expr*)expr;
39583967

3959-
if (te != NULL) {
3960-
transform_entity *entity = find_variable(cpstate, node->name);
3961-
if (entity != NULL && (entity->type != ENT_VERTEX || !IS_DEFAULT_LABEL_VERTEX(node->label) || node->props))
3962-
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3963-
errmsg("variable %s already exists", node->name),
3964-
parser_errposition(pstate, node->location)));
3968+
if (te != NULL) {
3969+
transform_entity *entity = find_variable(cpstate, node->name);
3970+
if (entity != NULL && (entity->type != ENT_VERTEX || !IS_DEFAULT_LABEL_VERTEX(node->label) || node->props))
3971+
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3972+
errmsg("variable %s already exists", node->name),
3973+
parser_errposition(pstate, node->location)));
39653974

3966-
return te->expr;
3967-
}
3975+
return te->expr;
3976+
}
39683977
}
39693978
} else {
39703979
node->name = get_next_default_alias(cpstate);
39713980
}
39723981

39733982
schema_name = get_graph_namespace_name(cpstate->graph_name);
3974-
rel_name = get_label_relation_name(node->label, cpstate->graph_oid);
3983+
3984+
3985+
Datum label_lquery;
3986+
if (is_default_label)
3987+
label_lquery = DirectFunctionCall1(ltree_in, CStringGetDatum(node->label));
3988+
else
3989+
label_lquery = DirectFunctionCall2(ltree_addltree,
3990+
DirectFunctionCall1(ltree_in, CStringGetDatum(AG_DEFAULT_LABEL_VERTEX)),
3991+
DirectFunctionCall1(ltree_in, CStringGetDatum(node->label)));
3992+
3993+
int ltq_query_args[2];
3994+
ltq_query_args[0] = LookupTypeNameOid(pstate, makeTypeNameFromNameList(list_make2(makeString("public"), makeString("ltree"))), false);
3995+
ltq_query_args[1] = LookupTypeNameOid(pstate, makeTypeNameFromNameList(list_make2(makeString("public"), makeString("ltree"))), false);
3996+
3997+
Oid ltree_contains_oid = LookupFuncName(list_make2(makeString("public"), makeString("ltree_risparent")), 2, &ltq_query_args, false);
3998+
3999+
ScanKeyData scan_keys[1];
4000+
ScanKeyInit(&scan_keys[0], Anum_ag_label_label_path, BTEqualStrategyNumber, ltree_contains_oid, label_lquery);
4001+
4002+
Relation label_catalog = table_open(ag_label_relation_id(), AccessShareLock);
4003+
SysScanDesc scan_desc = systable_beginscan(label_catalog, ag_label_label_index_id(), true, NULL, 1, scan_keys);
4004+
4005+
HeapTuple tuple = systable_getnext(scan_desc);
4006+
4007+
if (!HeapTupleIsValid(tuple))
4008+
ereport(ERROR,
4009+
(errcode(ERRCODE_UNDEFINED_SCHEMA),
4010+
errmsg("not found %s", node->label)));
4011+
4012+
bool is_null;
4013+
rel_name = heap_getattr(tuple, Anum_ag_label_name, RelationGetDescr(label_catalog), &is_null);
4014+
4015+
4016+
systable_endscan(scan_desc);
4017+
table_close(label_catalog, AccessShareLock);
4018+
4019+
//rel_name = get_label_relation_name(node->label, cpstate->graph_oid);
39754020
label_range_var = makeRangeVar(schema_name, rel_name, -1);
39764021
alias = makeAlias(node->name, NIL);
39774022

@@ -3990,7 +4035,7 @@ static Expr *transform_cypher_node(cypher_parsestate *cpstate, cypher_node *node
39904035

39914036
// id field
39924037
Node *id = scanNSItemForColumn(pstate, pnsi, 0, AG_VERTEX_COLNAME_ID, -1);
3993-
resno = pstate->p_next_resno++;
4038+
resno = pstate->p_next_resno++;
39944039

39954040
te = makeTargetEntry(id, resno, make_id_alias(node->name), false);
39964041
*target_list = lappend(*target_list, te);
@@ -3999,7 +4044,7 @@ static Expr *transform_cypher_node(cypher_parsestate *cpstate, cypher_node *node
39994044
* properties field
40004045
*/
40014046
Node *props = scanNSItemForColumn(pstate, pnsi, 0, AG_VERTEX_COLNAME_PROPERTIES, -1);
4002-
resno = pstate->p_next_resno++;
4047+
resno = pstate->p_next_resno++;
40034048

40044049
te = makeTargetEntry(props, resno, make_property_alias(node->name), false);
40054050
*target_list = lappend(*target_list, te);
@@ -4271,7 +4316,7 @@ static cypher_target_node * transform_create_cypher_edge(cypher_parsestate *cpst
42714316

42724317
parent = list_make1(rv);
42734318

4274-
create_label(cpstate->graph_name, edge->label, LABEL_TYPE_EDGE, parent);
4319+
create_label(cpstate->graph_name, edge->label, LABEL_TYPE_EDGE, parent, NULL);
42754320
}
42764321

42774322
// lock the relation of the label
@@ -4505,7 +4550,7 @@ static cypher_target_node *transform_create_cypher_new_node(cypher_parsestate *c
45054550

45064551
parent = list_make1(rv);
45074552

4508-
create_label(cpstate->graph_name, node->label, LABEL_TYPE_VERTEX, parent);
4553+
create_label(cpstate->graph_name, node->label, LABEL_TYPE_VERTEX, parent, NULL);
45094554
}
45104555

45114556
rel->flags = CYPHER_TARGET_NODE_FLAG_INSERT;
@@ -5278,7 +5323,7 @@ static cypher_target_node * transform_merge_cypher_edge(cypher_parsestate *cpsta
52785323
parent = list_make1(rv);
52795324

52805325
// create the label
5281-
create_label(cpstate->graph_name, edge->label, LABEL_TYPE_EDGE, parent);
5326+
create_label(cpstate->graph_name, edge->label, LABEL_TYPE_EDGE, parent, NULL);
52825327
}
52835328

52845329
// lock the relation of the label
@@ -5355,7 +5400,7 @@ static cypher_target_node *transform_merge_cypher_node(cypher_parsestate *cpstat
53555400
parent = list_make1(rv);
53565401

53575402
// create the label
5358-
create_label(cpstate->graph_name, node->label, LABEL_TYPE_VERTEX, parent);
5403+
create_label(cpstate->graph_name, node->label, LABEL_TYPE_VERTEX, parent, NULL);
53595404
}
53605405

53615406
rel->flags |= CYPHER_TARGET_NODE_FLAG_INSERT;

src/include/catalog/ag_label.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,16 @@
6060
ag_relation_id("ag_label_graph_oid_index", "index")
6161
#define ag_label_relation_index_id() \
6262
ag_relation_id("ag_label_relation_index", "index")
63+
#define ag_label_label_index_id() \
64+
ag_relation_id("ag_label_ltree_index", "index")
6365

6466
#define LABEL_ID_SEQ_NAME "_label_id_seq"
6567

6668
#define LABEL_KIND_VERTEX 'v'
6769
#define LABEL_KIND_EDGE 'e'
6870

6971
void insert_label(const char *label_name, Oid graph_oid, int32 label_id,
70-
char label_kind, Oid label_relation);
72+
char label_kind, Oid label_relation, const char *ltree);
7173
void delete_label(Oid relation);
7274

7375
int32 get_label_id(const char *label_name, Oid graph_oid);

src/include/commands/label_commands.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,6 @@
5555
(IS_DEFAULT_LABEL_EDGE(x) || IS_DEFAULT_LABEL_VERTEX(x))
5656

5757
void create_label(char *graph_name, char *label_name, char label_type,
58-
List *parents);
58+
List *parents, char *ltree);
5959

6060
#endif

src/include/utils/ag_cache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ typedef struct label_cache_data
4141
int32 id;
4242
char kind;
4343
Oid relation;
44-
// ltree *label_tree;
44+
ltree *label_tree;
4545
} label_cache_data;
4646

4747
// callers of these functions must not modify the returned struct

0 commit comments

Comments
 (0)