DBIO-PostgreSQL-Age

 view release on metacpan or  search on metacpan

share/skills/dbio-postgresql-age/SKILL.md  view on Meta::CPAN

If extension not installed:

```perl
$storage->dbh->do('CREATE EXTENSION IF NOT EXISTS age');
```

## Graph Lifecycle

```perl
$storage->create_graph('social');
$storage->drop_graph('social', 1);   # 1 = cascade
```

Graph names must be plain PG identifiers (validated by `cypher()`):

```
valid:   social, app_graph_1
invalid: app-graph, public.social, "graph name"
```

## Running Cypher

```perl
my $rows = $storage->cypher($graph, $query, \@result_columns, \%params);
```

Every result column is declared `agtype`. Returns arrayref of hashrefs.

```perl
my $rows = $storage->cypher(
  'social',
  q{ MATCH (p:Person) RETURN p.name, p.age },
  [qw(name age)],
);

for my $row (@$rows) {
  say "$row->{name} is $row->{age}";
}
```

## Vertices

AGE requires every `cypher()` to RETURN at least one column, so CREATE returns a stub.

```perl
$storage->cypher(
  'social',
  q{
    CREATE (:Person {name: $name, age: $age})
    RETURN 1
  },
  ['ok'],
  { name => 'Alice', age => 30 },
);
```

Always parameterise user input — never interpolate.

## Edges

Match endpoints first, then create. Can combine create + create in one query.

```perl
$storage->cypher(
  'social',
  q{
    MATCH (a:Person {name: $from}), (b:Person {name: $to})
    CREATE (a)-[:KNOWS {since: $since}]->(b)
    RETURN 1
  },
  ['ok'],
  { from => 'Alice', to => 'Bob', since => 2020 },
);
```

## Querying

```perl
my $rows = $storage->cypher(
  'social',
  q{
    MATCH (a:Person)-[r:KNOWS]->(b:Person)
    RETURN a.name, b.name, r.since
  },
  [qw(person friend since)],
);
```

## agtype Results

`cypher()` returns `agtype` as strings via DBI. Scalar strings often come back quoted.

```perl
sub ag_string {
  my ($value) = @_;
  return undef unless defined $value;
  $value =~ s/\A"//;
  $value =~ s/"\z//;
  return $value;
}
```

JSON-like agtype values → use `JSON::MaybeXS`:

```perl
use JSON::MaybeXS qw(decode_json);

my $rows = $storage->cypher(
  'social',
  q{ MATCH (p:Person {name: $name}) RETURN p {.name, .age} },
  ['person'],
  { name => 'Alice' },
);

my $person = decode_json($rows->[0]{person});
```

Full vertices/edges/paths may include graph annotations in text form. Prefer projected maps:

```perl
$storage->cypher('social', q{



( run in 1.106 second using v1.01-cache-2.11-cpan-c966e8aa7e8 )