MR::Tarantool::Box(3pm) | User Contributed Perl Documentation | MR::Tarantool::Box(3pm) |
MR::Tarantool::Box - A driver for an efficient Tarantool/Box NoSQL in-memory storage.
my $box = MR::Tarantool::Box->new({ servers => "127.0.0.1:33013", name => "My Box", # mostly used for debug purposes spaces => [ { indexes => [ { index_name => 'idx1', keys => [0], }, { index_name => 'idx2', keys => [1,2], }, ], space => 1, # space id, as set in Tarantool/Box config name => "primary", # self-descriptive space-id format => "QqLlSsCc&$", # pack()-compatible, Qq must be supported by perl itself, # & stands for byte-string, $ stands for utf8 string. default_index => 'idx1', fields => [qw/ id f2 field3 f4 f5 f6 f7 f8 misc_string /], # turn each tuple into hash, field names according to format }, { #... } ], default_space => "primary", timeout => 1.0, # seconds retry => 3, debug => 9, # output to STDERR some debugging info raise => 0, # don't raise an exception in case of error }); my $bool = $box->Insert(1, 2,3, 4,5,6,7,8,"asdf") or die $box->ErrorStr; my $bool = $box->Insert(2, 2,4, 4,5,6,7,8,"asdf",{space => "primary"}) or die $box->ErrorStr; my $tuple = $box->Insert(3, 3,3, 4,5,6,7,8,"asdf",{want_inserted_tuple => 1}) or die $box->ErrorStr; # Select by single-field key my $tuple = $box->Select(1); # scalar context - scalar result: $tuple my @tuples = $box->Select(1,2,3); # list context - list result: ($tuple, $tuple, ...) my $tuples = $box->Select([1,2,3],{space => "primary", use_index => "idx1"}); # arrayref result: [$tuple, $tuple, ...] # Select by multi-field key my $tuples = $box->Select([[2,3]],{use_index => "idx2"}); # by full key my $tuples = $box->Select([[2]] ,{use_index => "idx2"}); # by partial key my $bool = $box->UpdateMulti(1,[ f4 => add => 3 ]); my $bool = $box->UpdateMulti(2,[ f4 => add => 3 ],{space => "primary"}); my $tuple = $box->UpdateMulti(3,[ f4 => add => 3 ],{want_updated_tuple => 1}); my $bool = $box->Delete(1); my $tuple = $box->Delete(2, {want_deleted_tuple => 1});
new
my $box = $class->new(\%args);
%args:
$coderef = sub { my ($space_id, $resultset) = @_; $_ = { FieldName1 => $_->[0], FieldName2 => $_->[1], ... } for @$resultset; };
Sometimes we need short timeout for select's and long timeout for critical update's, because in case of timeout we don't know if the update has succeeded. For the same reason we can't retry update operation.
So increasing "timeout" and setting "retry => 1" for updates lowers possibility of such situations (but, of course, does not exclude them at all), and guarantees that we don't do the same more then once.
This is also limited by "retry"/"select_retry" (depending on query type).
Error
Last error code, or 'fail' for some network reason, oftenly a timeout.
$box->Insert(@tuple) or die sprintf "Error %X", $box->Error; # die "Error 202"
ErrorStr
Last error code and description in a single string.
$box->Insert(@tuple) or die $box->ErrorStr; # die "Error 00000202: Illegal Parameters"
Call
Call a stored procedure. Returns an arrayref of the result tuple(s) upon success.
my $results = $box->Call('stored_procedure_name', \@procedure_params, \%options) or die $box->ErrorStr; # Call failed my $result_tuple = @$results && $results->[0] or warn "Call succeeded, but returned nothing";
Add, Insert, Replace
$box->Add(@tuple) or die $box->ErrorStr; # only store a new tuple $box->Replace(@tuple, { space => "secondary" }); # only store an existing tuple $box->Insert(@tuple, { space => "main" }); # store anyway
Insert a @tuple into the storage into $options{space} or "default_space" space. All of them return "true" upon success.
All of them have the same parameters:
The difference between them is the behaviour concerning tuple with the same primary key:
Select
Select tuple(s) from storage
my $key = $id; my $key = [ $firstname, $lastname ]; my @keys = ($key, ...); my $tuple = $box->Select($key) or $box->Error && die $box->ErrorStr; my $tuple = $box->Select($key, \%options) or $box->Error && die $box->ErrorStr; my @tuples = $box->Select(@keys) or $box->Error && die $box->ErrorStr; my @tuples = $box->Select(@keys, \%options) or $box->Error && die $box->ErrorStr; my $tuples = $box->Select(\@keys) or die $box->ErrorStr; my $tuples = $box->Select(\@keys, \%options) or die $box->ErrorStr;
Contextual behaviour:
Other notes:
Delete
Delete tuple from storage. Return false upon error.
my $n_deleted = $box->Delete($key) or die $box->ErrorStr; my $n_deleted = $box->Delete($key, \%options) or die $box->ErrorStr; warn "Nothing was deleted" unless int $n_deleted; my $deleted_tuple_set = $box->Delete($key, { want_deleted_tuples => 1 }) or die $box->ErrorStr; warn "Nothing was deleted" unless @$deleted_tuple_set;
UpdateMulti
Apply several update operations to a tuple.
my @op = ([ f1 => add => 10 ], [ f1 => and => 0xFF], [ f2 => set => time() ], [ misc_string => cutend => 3 ]); my $n_updated = $box->UpdateMulti($key, @op) or die $box->ErrorStr; my $n_updated = $box->UpdateMulti($key, @op, \%options) or die $box->ErrorStr; warn "Nothing was updated" unless int $n_updated; my $updated_tuple_set = $box->UpdateMulti($key, @op, { want_result => 1 }) or die $box->ErrorStr; warn "Nothing was updated" unless @$updated_tuple_set;
Different fields can be updated at one shot. The same field can be updated more than once. All update operations are done atomically. Returns false upon error.
"Insert, UpdateMulti, Select, Delete, Call" methods can be given the following options:
"Select" methods can be given the following options:
You should handle timeouts and retries manually (using select() call for example). Usage example:
my $continuation = $box->Select(13,{ return_fh => 1 }); ok $continuation, "select/continuation"; my $rin = ''; vec($rin,$continuation->{fh}->fileno,1) = 1; my $ein = $rin; ok 0 <= select($rin,undef,$ein,2), "select/continuation/select"; my $res = $continuation->{continue}->(); use Data::Dumper; is_deeply $res, [13, 'some_email@test.mail.ru', 1, 2, 3, 4, '123456789'], "select/continuation/result";
If "format" given to "new", or "unpack_format" given to "Call" ends with a star ("*") long tuple is enabled. Last field or group of fields of "format" represent variable-length tail of the tuple. "long_fields" option given to "new" will fold the tail into array of hashes.
$box->Insert(1,"2",3); #1 $box->Insert(3,"2",3,4,5); #2 $box->Insert(5,"2",3,4,5,6,7); #3
If we set up
format => "L&CL*", fields => [qw/ a b c d /], # d is the folding field here # no long_fields - no folding into hash
we'll get:
$result = $box->Select([1,2,3,4,5]); $result = [ { a => 1, b => "2", c => 3, d => [] }, #1 { a => 3, b => "2", c => 3, d => [4,5] }, #2 { a => 5, b => "2", c => 3, d => [4,5,6,7] }, #3 ];
And if we set up
format => "L&C(LL)*", fields => [qw/ a b c d /], # d is the folding field here long_fields => [qw/ d1 d2 /],
we'll get:
$result = [ { a => 1, b => "2", c => 3, d => [] }, #1 { a => 3, b => "2", c => 3, d => [{d1=>4, d2=>5}] }, #2 { a => 5, b => "2", c => 3, d => [{d1=>4, d2=>5}, {d1=>6, d2=>7}] }, #3 ];
"UpdateMulti" can be given a field number in several ways:
$box->UpdateMulti(5, [ 5 => set => $val ]) #3: set 6 to $val
$box->UpdateMulti(5, [ [1,0] => set => $val ]) #3: set 6 to $val $box->UpdateMulti(5, [ [1,'d1'] => set => $val ]) #3: set 6 to $val
Utf8 strings are supported very simply. When pushing any data to tarantool (with any query, read or write), the utf8 flag is set off, so all data is pushed as bytestring. When reading response, for fields marked a dollar sign "$" (see "new") (including such in "LongTuple" tail) utf8 flag is set on. That's all. Validity is on your own.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
2020-07-21 | perl v5.30.3 |