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+
39093917static 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 ;
0 commit comments