bitnine-oss / agensgraph

AgensGraph, a transactional graph database based on PostgreSQL
http://www.agensgraph.org
Other
1.33k stars 148 forks source link

User defined functions limited to one graph_path? #507

Closed pebbe closed 2 years ago

pebbe commented 4 years ago

In PostgreSQL I can write a function and in works on all datasets. Not so in AgensGraph, when you use match in the function.

  1. set graph_path
  2. create a function
  3. do a match query using the function, this works
  4. switch to another graph_path
  5. run same query, this won't work
  6. create the function again, won't work, function already defined
  7. remove function
  8. create function
  9. do a match query using the function, this works
    1. switch back to first graph_path
    2. run match query again, it doesn't work, function needs to be removed and created again

So it looks like when you create a function, and use a match, then that match is linked to the current graph_path.

For illustration, here are the function and the query using the function, though you'd need the dataset, of course.

CREATE FUNCTION is_np(obj json) RETURNS bool AS $$
DECLARE
  sentid text;
  id integer;
  i record;
  retval bool := false;
BEGIN
  sentid := obj #>> '{properties, sentid}';
  id := obj #>> '{properties, id}';
  FOR i IN 
    match (x:nw{sentid: sentid, id: id})<-[r:rel]-()
    optional match (x)-[r2:rel]->(x2)
    with x, x2, r, r2
    where (x.cat is not null and x.cat = 'np')
       or (x.lcat is not null and x.lcat = 'np' and not r.rel in ['hd','mwp'])
       or (x.pt is not null and x.pt = 'n' and r.rel != 'hd')
       or (x.pt is not null and x.pt = 'vnw' and x.pdtype is not null and x.pdtype = 'pron' and r.rel != 'hd')
       or (x.cat is not null and x.cat = 'mwu' and r.rel in ['su','obj1','obj2','app'])
       or (x.cat is not null and x.cat = 'conj'
           and x2 is not null
           and ((x2.cat is not null and x2.cat = 'np')
             or (x2.lcat is not null and x2.lcat = 'np' and not r2.rel in ['hd','mwp'])
             or (x2.pt is not null and x2.pt = 'n' and r2.rel != 'hd')
             or (x2.pt is not null and x2.pt = 'vnw' and x2.pdtype is not null and x2.pdtype = 'pron' and r2.rel != 'hd')
             or (x2.cat is not null and x2.cat = 'mwu' and r2.rel in ['su','obj1','obj2','app'])))
    return 1
    limit 1
  LOOP
    retval := true;
  END LOOP;
  RETURN retval;
END;
$$ LANGUAGE plpgsql;

select count(distinct(sentid)), count(sentid)
from (
  match (w:word{pt:'adj', graad:'comp'})<-[:rel{rel:'hd'}]-()-[:rel{rel:'obcomp'}]->()-[:rel{rel:'body'}]->(x)
  where is_np(to_json(x))
  return distinct w.sentid, w.id
) as foo;
emotionbug commented 2 years ago

I cannot reproduce this issue. close it until responding. :(

-- github issue #507
CREATE (x:v1 {id: 'v1'})<-[r:rel]-();
MATCH (x:v1)
CREATE (x)-[r2:rel]->(x2);
CREATE FUNCTION udf_cypher_results() RETURNS RECORD AS $$
DECLARE
    ret RECORD;
BEGIN
    MATCH (x:v1 {id: 'v1'})<-[r:rel]-()
    OPTIONAL MATCH (x)-[r2:rel]->(x2)
    return x, r, x2, r2 INTO ret;
    RETURN ret;
END;
$$ LANGUAGE plpgsql;
SELECT udf_cypher_results();
                                    udf_cypher_results                                    
------------------------------------------------------------------------------------------
 ("v1[6.1]{""id"": ""v1""}","rel[7.1][1.1,6.1]{}",ag_vertex[1.2]{},"rel[7.2][6.1,1.2]{}")
(1 row)

CREATE GRAPH udf_temp;
SET GRAPH_PATH to udf_temp;
SELECT udf_cypher_results();
ERROR:  vertex label "v1" does not exist
CONTEXT:  SQL statement "MATCH (x:v1 {id: 'v1'})<-[r:rel]-()
    OPTIONAL MATCH (x)-[r2:rel]->(x2)
    return x, r, x2, r2"
PL/pgSQL function udf_cypher_results() line 5 at SQL statement
DROP GRAPH udf_temp CASCADE;
NOTICE:  drop cascades to 3 other objects
DETAIL:  drop cascades to sequence udf_temp.ag_label_seq
drop cascades to vlabel ag_vertex
drop cascades to elabel ag_edge