The Perl Advent Calendar needs more articles for 2022. Submit your idea today!

NAME

Neo4j::Driver::Transaction - Logical container for an atomic unit of work

VERSION

version 0.27

SYNOPSIS

 use Neo4j::Driver;
 $session = Neo4j::Driver->new->basic_auth(...)->session;
 
 # Commit
 $tx = $session->begin_transaction;
 $node_id = $tx->run(
   'CREATE (p:Person) RETURN id(p)'
 )->single->get;
 $tx->run(
   'MATCH (p) WHERE id(p) = {id} SET p.name = {name}',
   {id => $node_id, name => 'Douglas'}
 );
 $tx->commit;
 
 # Rollback
 $tx = $session->begin_transaction;
 $tx->run('CREATE (a:Universal:Answer {value:42})');
 $tx->rollback;

DESCRIPTION

Logical container for an atomic unit of work that is either committed in its entirety or is rolled back on failure. A driver Transaction object corresponds to a server transaction.

Statements may be run lazily. Most of the time, you will not notice this, because the driver automatically waits for statements to complete at specific points to fulfill its contracts. If you require execution of a statement to have completed, you need to use the Result, for example by calling one of the methods fetch(), list() or summary().

METHODS

Neo4j::Driver::Transaction implements the following methods.

commit

 $transaction->commit;

Commits the transaction and returns the result.

After committing the transaction is closed and can no longer be used.

is_open

 $bool = $transaction->is_open;

Report whether this transaction is still open, which means commit or rollback has not happened and the transaction has not timed out.

Bolt transactions by default have no timeout, while the default dbms.rest.transaction.idle_timeout for HTTP transactions is 60 seconds.

rollback

 $transaction->rollback;

Rollbacks the transaction.

After rolling back the transaction is closed and can no longer be used.

run

 $result = $transaction->run($query, %params);

Run a statement and return the Result. This method takes an optional set of parameters that will be injected into the Cypher statement by Neo4j. Using parameters is highly encouraged: It helps avoid dangerous Cypher injection attacks and improves database performance as Neo4j can re-use query plans more often.

Parameters are given as Perl hashref. Alternatively, they may be given as a hash / balanced list.

 # all of these are semantically equal
 $result = $transaction->run('...', {key => 'value'});
 $result = $transaction->run('...',  key => 'value' );
 %hash = (key => 'value');
 $result = $transaction->run('...', \%hash);
 $result = $transaction->run('...',  %hash);

When used as parameters, Perl values are converted to Neo4j types as shown in the following example:

 $parameters = {
   number =>  0 + $scalar,
   string => '' . $scalar,
   true   => \1,
   false  => \0,
   null   => undef,
   list   => [ ],
   map    => { },
 };

A Perl scalar may internally be represented as a number or a string (see "Scalar values" in perldata). Perl usually auto-converts one into the other based on the context in which the scalar is used. However, Perl cannot know the context of a Neo4j query parameter, because queries are just opaque strings to Perl. Most often your scalars will already have the correct internal flavour. A typical example for a situation in which this is not the case are numbers parsed out of strings using regular expressions. If necessary, you can force conversion of such values into the correct type using unary coercions as shown in the example above.

Running empty queries is supported. They yield an empty result (having zero records). With HTTP connections, the empty result is retrieved from the server, which resets the transaction timeout. This feature may also be used to test the connection to the server. For Bolt connections, the empty result is generated locally in the driver.

 $result = $transaction->run;

Queries are usually strings, but may also be REST::Neo4p::Query or Neo4j::Cypher::Abstract objects. Such objects are automatically converted to strings before they are sent to the Neo4j server.

 $transaction->run( REST::Neo4p::Query->new('RETURN 42') );
 $transaction->run( Neo4j::Cypher::Abstract->new->return(42) );

ERROR HANDLING

This driver always reports all errors using die(). Error messages received from the Neo4j server are passed on as-is.

Statement errors occur when the statement is executed on the server. This may not necessarily have happened by the time run() returns. If you use try to handle errors, make sure you use the Result within the try block, for example by calling one of the methods fetch(), list() or summary().

Transactions are rolled back and closed automatically if the Neo4j server encounters an error when running a query. However, if an internal error occurs in the driver or in one of its supporting modules, explicit transactions remain open.

Typically, no particular handling of error conditions is required. But if you wrap your transaction in a try (or eval) block, you intend to continue using the same session even after an error condition, and you want to be absolutely sure the session is in a defined state, you can roll back a failed transaction manually:

 use Try::Tiny;
 $tx = $session->begin_transaction;
 try {
   ...;
   $tx->commit;
 }
 catch {
   say "Database error: $_";
   ...;
   $tx->rollback if $tx->is_open;
 };
 # at this point, $session is safe to use

EXPERIMENTAL FEATURES

Neo4j::Driver::Transaction implements the following experimental features. These are subject to unannounced modification or removal in future versions. Expect your code to break if you depend upon these features.

Execute multiple statements at once

 @statements = (
   [ 'RETURN 42' ],
   [ 'RETURN {value}', value => 'forty-two' ],
 );
 @results = $transaction->_run_multiple(@statements);
 foreach $result ( @results ) {
   say $result->single->get;
 }

The Neo4j HTTP API supports executing multiple statements within a single HTTP request. This driver exposes this feature to the client. It is only available on HTTP connections.

This feature might eventually be used to implement lazy statement execution for this driver. The private _run_multiple() method which makes using this feature explicit is expected to remain available at least until that time. See also "USE OF INTERNAL APIS" in Neo4j::Driver::Net.

Disable obtaining query statistics

 $transaction = $session->begin_transaction;
 $transaction->{return_stats} = 0;
 $result = $transaction->run('...');

Since version 0.13, this driver requests query statistics from the Neo4j server by default. When using HTTP, this behaviour can be disabled. Doing so might provide a very minor performance increase.

The ability to disable the statistics may be removed in future.

Return results in graph format

 $session = $driver->config( jolt => 0 )->session;
 $transaction = $session->begin_transaction;
 $transaction->{return_graph} = 1;
 $records = $transaction->run('...')->list;
 for $record ( @$records ) {
   $graph_data = $record->{graph};
   ...
 }

The Neo4j HTTP JSON API supports a "graph" results data format. This feature is only available when Jolt is disabled, which is not recommended. The return_graph option will most likely be removed entirely in future versions, as requesting the "graph" result is also possible by using a custom networking module; see Neo4j::Driver::Net.

SEE ALSO

AUTHOR

Arne Johannessen <ajnn@cpan.org>

COPYRIGHT AND LICENSE

This software is Copyright (c) 2016-2021 by Arne Johannessen.

This is free software, licensed under:

  The Artistic License 2.0 (GPL Compatible)