Skip to content
Permalink
Browse files
Add VLE SRF (Set Returning Function) age_vle
This patch contains the age_vle SRF and all of its supporting code.

The age_vle function takes the following input arguments -

    0 - agtype (graph name as an agtype string)
    1 - agtype (start vertex as an agtype vertex)
    2 - agtype (end vertex as an agtype vertex)
    3 - agtype (edge prototype to match as an agtype edge)
                Note: Only the label and properties are used. The
                      rest is ignored.
    4 - agtype lidx (lower range index)
                Note: 0 is not supported but is equivalent to 1.
    5 - agtype uidx (upper range index)
                Note: An AGTV_NULL is appropriate here for an
                      infinite upper bound.
    6 - agtype edge direction (enum) as an integer -

            CYPHER_REL_DIR_NONE = 0,
            CYPHER_REL_DIR_LEFT = -1,
            CYPHER_REL_DIR_RIGHT = 1

    NOTE: The above values for the enum are TEMPORARY and are only
          for testing. They will be removed after VLE integration
          has completed. Using these values directly in any code
          is not recommended.

Included are regression tests for paths and edge matching.
All components should be fully functional.

jrg
  • Loading branch information
jrgemignani committed Sep 2, 2021
1 parent 3b8b0b4 commit 1bb2c0deb2b4bd258bf8ac43820a7644c2dfb962
Showing 12 changed files with 2,386 additions and 62 deletions.
@@ -50,6 +50,7 @@ OBJS = src/backend/age.o \
src/backend/utils/adt/agtype_ops.o \
src/backend/utils/adt/agtype_parser.o \
src/backend/utils/adt/agtype_util.o \
src/backend/utils/adt/agtype_vle.o \
src/backend/utils/adt/cypher_funcs.o \
src/backend/utils/adt/ag_float8_supp.o \
src/backend/utils/adt/graphid.o \
@@ -73,6 +74,7 @@ REGRESS = scan \
cypher_remove \
cypher_delete \
cypher_with \
cypher_vle \
drop

ag_regress_dir = $(srcdir)/regress
@@ -3710,6 +3710,15 @@ STABLE
PARALLEL SAFE
AS 'MODULE_PATHNAME';

CREATE OR REPLACE FUNCTION ag_catalog.age_vle(
IN agtype, IN agtype, IN agtype, IN agtype,
IN agtype, IN agtype, IN agtype,
OUT edges agtype)
RETURNS SETOF agtype
LANGUAGE C
IMMUTABLE
STRICT
AS 'MODULE_PATHNAME';
--
-- End
--
@@ -2219,7 +2219,7 @@ SELECT agtype_access_operator(_agtype_build_vertex('1'::graphid, $$label$$,
(1 row)

SELECT _agtype_build_vertex('1'::graphid, $$label$$, agtype_build_list());
ERROR: agtype_build_vertex() properties argument must be an object
ERROR: _agtype_build_vertex() properties argument must be an object
--Vertex in a map
SELECT agtype_build_map(
'vertex',

Large diffs are not rendered by default.

@@ -0,0 +1,85 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

LOAD 'age';
SET search_path TO ag_catalog;

SELECT create_graph('cypher_vle');

--
-- Create table to hold the start and end vertices to test the SRF
--

CREATE TABLE start_and_end_points (start_vertex agtype, end_vertex agtype);

-- Create a graph to test
SELECT * FROM cypher('cypher_vle', $$CREATE (b:begin)-[:edge {name: 'main edge', number: 1, dangerous: {type: "all", level: "all"}}]->(u1:middle)-[:edge {name: 'main edge', number: 2, dangerous: {type: "all", level: "all"}, packages: [2,4,6]}]->(u2:middle)-[:edge {name: 'main edge', number: 3, dangerous: {type: "all", level: "all"}}]->(u3:middle)-[:edge {name: 'main edge', number: 4, dangerous: {type: "all", level: "all"}}]->(e:end), (u1)-[:self_loop {name: 'self loop', number: 1, dangerous: {type: "all", level: "all"}}]->(u1), (e)-[:self_loop {name: 'self loop', number: 2, dangerous: {type: "all", level: "all"}}]->(e), (b)-[:alternate_edge {name: 'alternate edge', number: 1, packages: [2,4,6], dangerous: {type: "poisons", level: "all"}}]->(u1), (u2)-[:alternate_edge {name: 'alternate edge', number: 2, packages: [2,4,6], dangerous: {type: "poisons", level: "all"}}]->(u3), (u3)-[:alternate_edge {name: 'alternate edge', number: 3, packages: [2,4,6], dangerous: {type: "poisons", level: "all"}}]->(e), (u2)-[:bypass_edge {name: 'bypass edge', number: 1, packages: [1,3,5,7]}]->(e), (e)-[:alternate_edge {name: 'backup edge', number: 1, packages: [1,3,5,7]}]->(u3), (u3)-[:alternate_edge {name: 'backup edge', number: 2, packages: [1,3,5,7]}]->(u2), (u2)-[:bypass_edge {name: 'bypass edge', number: 2, packages: [1,3,5,7], dangerous: {type: "poisons", level: "all"}}]->(b) return b, e $$) AS (b agtype, e agtype);

-- Insert start and end points for graph
INSERT INTO start_and_end_points (SELECT * FROM cypher('cypher_vle', $$MATCH (b:begin)-[:edge]->()-[:edge]->()-[:edge]->()-[:edge]->(e:end) return b, e $$) AS (b agtype, e agtype));

-- Display our points
SELECT * FROM start_and_end_points;

-- Count the total paths from left (start) to right (end) -[]-> should be 400
SELECT count(edges) FROM start_and_end_points, age_vle( '"cypher_vle"'::agtype, start_vertex, end_vertex, '{"id": 1111111111111111, "label": "", "end_id": 2222222222222222, "start_id": 333333333333333, "properties": {}}::edge'::agtype, '1'::agtype, 'null'::agtype, '1'::agtype) group by ctid;

-- Count the total paths from right (end) to left (start) <-[]- should be 2
SELECT count(edges) FROM start_and_end_points, age_vle( '"cypher_vle"'::agtype, start_vertex, end_vertex, '{"id": 1111111111111111, "label": "", "end_id": 2222222222222222, "start_id": 333333333333333, "properties": {}}::edge'::agtype, '1'::agtype, 'null'::agtype, '-1'::agtype) group by ctid;

-- Count the total paths undirectional -[]- should be 7092
SELECT count(edges) FROM start_and_end_points, age_vle( '"cypher_vle"'::agtype, start_vertex, end_vertex, '{"id": 1111111111111111, "label": "", "end_id": 2222222222222222, "start_id": 333333333333333, "properties": {}}::edge'::agtype, '1'::agtype, 'null'::agtype, '0'::agtype) group by ctid;

-- All paths of length 3 -[]-> should be 2
SELECT edges FROM start_and_end_points, age_vle( '"cypher_vle"'::agtype, start_vertex, end_vertex, '{"id": 1111111111111111, "label": "", "end_id": 2222222222222222, "start_id": 333333333333333, "properties": {}}::edge'::agtype, '3'::agtype, '3'::agtype, '1'::agtype);

-- All paths of length 3 <-[]- should be 1
SELECT edges FROM start_and_end_points, age_vle( '"cypher_vle"'::agtype, start_vertex, end_vertex, '{"id": 1111111111111111, "label": "", "end_id": 2222222222222222, "start_id": 333333333333333, "properties": {}}::edge'::agtype, '3'::agtype, '3'::agtype, '-1'::agtype);

-- All paths of length 3 -[]- should be 12
SELECT edges FROM start_and_end_points, age_vle( '"cypher_vle"'::agtype, start_vertex, end_vertex, '{"id": 1111111111111111, "label": "", "end_id": 2222222222222222, "start_id": 333333333333333, "properties": {}}::edge'::agtype, '3'::agtype, '3'::agtype, '0'::agtype);

-- Test edge label matching - should match 1
SELECT edges FROM start_and_end_points, age_vle( '"cypher_vle"'::agtype, start_vertex, end_vertex, '{"id": 1111111111111111, "label": "edge", "end_id": 2222222222222222, "start_id": 333333333333333, "properties": {}}::edge'::agtype, '1'::agtype, 'null'::agtype, '1'::agtype);

-- Test scalar property matching - should match 1
SELECT edges FROM start_and_end_points, age_vle( '"cypher_vle"'::agtype, start_vertex, end_vertex, '{"id": 1111111111111111, "label": "", "end_id": 2222222222222222, "start_id": 333333333333333, "properties": {"name": "main edge"}}::edge'::agtype, '1'::agtype, 'null'::agtype, '1'::agtype);

-- Test object property matching - should match 4
SELECT edges FROM start_and_end_points, age_vle( '"cypher_vle"'::agtype, start_vertex, end_vertex, '{"id": 1111111111111111, "label": "", "end_id": 2222222222222222, "start_id": 333333333333333, "properties": {"dangerous": {"type": "all", "level": "all"}}}::edge'::agtype, '1'::agtype, 'null'::agtype, '1'::agtype);

-- Test array property matching - should match 2
SELECT edges FROM start_and_end_points, age_vle( '"cypher_vle"'::agtype, start_vertex, end_vertex, '{"id": 1111111111111111, "label": "", "end_id": 2222222222222222, "start_id": 333333333333333, "properties": {"packages": [1,3,5,7]}}::edge'::agtype, '1'::agtype, 'null'::agtype, '0'::agtype);

-- Test array property matching - should match 1
SELECT edges FROM start_and_end_points, age_vle( '"cypher_vle"'::agtype, start_vertex, end_vertex, '{"id": 1111111111111111, "label": "", "end_id": 2222222222222222, "start_id": 333333333333333, "properties": {"packages": [2,4,6]}}::edge'::agtype, '1'::agtype, 'null'::agtype, '0'::agtype);

-- Test object property matching - should match 1
SELECT edges FROM start_and_end_points, age_vle( '"cypher_vle"'::agtype, start_vertex, end_vertex, '{"id": 1111111111111111, "label": "", "end_id": 2222222222222222, "start_id": 333333333333333, "properties": {"dangerous": {"type": "poisons", "level": "all"}}}::edge'::agtype, '1'::agtype, 'null'::agtype, '0'::agtype);

-- Clean up
--

DROP TABLE start_and_end_points;

SELECT drop_graph('cypher_vle', true);

--
-- End
--
@@ -1566,7 +1566,8 @@ reserved_keyword:
*/

safe_keywords:
AND
AND { $$ = pnstrdup($1, 3); }
| ANALYZE { $$ = pnstrdup($1, 7); }
| AS { $$ = pnstrdup($1, 2); }
| ASC { $$ = pnstrdup($1, 3); }
| ASCENDING { $$ = pnstrdup($1, 9); }
@@ -1583,6 +1584,7 @@ safe_keywords:
| ELSE { $$ = pnstrdup($1, 4); }
| ENDS { $$ = pnstrdup($1, 4); }
| EXISTS { $$ = pnstrdup($1, 6); }
| EXPLAIN { $$ = pnstrdup($1, 7); }
| IN { $$ = pnstrdup($1, 2); }
| IS { $$ = pnstrdup($1, 2); }
| LIMIT { $$ = pnstrdup($1, 6); }
@@ -1597,6 +1599,7 @@ safe_keywords:
| STARTS { $$ = pnstrdup($1, 6); }
| THEN { $$ = pnstrdup($1, 4); }
| WHEN { $$ = pnstrdup($1, 4); }
| VERBOSE { $$ = pnstrdup($1, 7); }
| WHERE { $$ = pnstrdup($1, 5); }
| WITH { $$ = pnstrdup($1, 4); }
;

0 comments on commit 1bb2c0d

Please sign in to comment.