File Coverage

blib/lib/PawsX/DynamoDB/DocumentClient.pm
Criterion Covered Total %
statement 30 64 46.8
branch 10 14 71.4
condition 15 23 65.2
subroutine 6 15 40.0
pod 9 9 100.0
total 70 125 56.0


line stmt bran cond sub pod time code
1             package PawsX::DynamoDB::DocumentClient;
2              
3 1     1   1013131 use strict;
  1         3  
  1         27  
4 1     1   24 use 5.008_005;
  1         4  
5              
6 1     1   5 use Module::Runtime qw(require_module);
  1         2  
  1         7  
7 1     1   82 use Scalar::Util qw(blessed);
  1         2  
  1         48  
8 1     1   6 use Paws;
  1         2  
  1         457  
9              
10             our $VERSION = '0.04';
11              
12             sub new {
13 5     5 1 17964 my ($class, %args) = @_;
14 5   100     38 my $region = $args{region} || $ENV{AWS_DEFAULT_REGION};
15 5         13 my $paws = $args{paws};
16 5         13 my $dynamodb = $args{dynamodb};
17              
18 5 50 33     33 if ($paws && !(blessed($paws) && $paws->isa('Paws'))) {
      66        
19 0         0 die "paws must be a Paws object";
20             }
21              
22 5 50 33     33 if ($dynamodb && !(blessed($dynamodb) && $dynamodb->isa('Paws::DynamoDB'))) {
      66        
23 0         0 die "dynamodb must be a Paws::DynamoDB object";
24             }
25              
26 5 100 100     29 if (!$region && $paws) {
27 1         24 $region = $paws->config->region;
28             }
29              
30 5 100 100     57 if (!($dynamodb || $region)) {
31 1         14 die "unable to determine region, and no dynamodb object provided";
32             }
33              
34 4 100       16 if (!$paws) {
35 3         34 $paws = Paws->new(config => { region => $region});
36             }
37              
38 4 100       5467 if (!$dynamodb) {
39 3         17 $dynamodb = $paws->service('DynamoDB');
40             }
41              
42 4         493594 my $self = {
43             paws => $paws,
44             dynamodb => $dynamodb,
45             };
46              
47 4         30 return bless $self, $class;
48             }
49              
50             sub batch_get {
51 0     0 1   my ($self, %args) = @_;
52 0           my $command_class = 'PawsX::DynamoDB::DocumentClient::BatchGet';
53 0           $self->_run_command($command_class, %args);
54             }
55              
56             sub batch_write {
57 0     0 1   my ($self, %args) = @_;
58 0           my $command_class = 'PawsX::DynamoDB::DocumentClient::BatchWrite';
59 0           $self->_run_command($command_class, %args);
60             }
61              
62             sub delete {
63 0     0 1   my ($self, %args) = @_;
64 0           my $command_class = 'PawsX::DynamoDB::DocumentClient::Delete';
65 0           $self->_run_command($command_class, %args);
66             }
67              
68             sub get {
69 0     0 1   my ($self, %args) = @_;
70 0           my $command_class = 'PawsX::DynamoDB::DocumentClient::Get';
71 0           $self->_run_command($command_class, %args);
72             }
73              
74             sub put {
75 0     0 1   my ($self, %args) = @_;
76 0           my $command_class = 'PawsX::DynamoDB::DocumentClient::Put';
77 0           $self->_run_command($command_class, %args);
78             }
79              
80             sub query {
81 0     0 1   my ($self, %args) = @_;
82 0           my $command_class = 'PawsX::DynamoDB::DocumentClient::Query';
83 0           $self->_run_command($command_class, %args);
84             }
85              
86             sub scan {
87 0     0 1   my ($self, %args) = @_;
88 0           my $command_class = 'PawsX::DynamoDB::DocumentClient::Scan';
89 0           $self->_run_command($command_class, %args);
90             }
91              
92             sub update {
93 0     0 1   my ($self, %args) = @_;
94 0           my $command_class = 'PawsX::DynamoDB::DocumentClient::Update';
95 0           $self->_run_command($command_class, %args);
96             }
97              
98             sub _run_command {
99 0     0     my ($self, $command_class, %args) = @_;
100 0   0       my $return_paws_output = delete $args{return_paws_output} || 0;
101              
102 0           require_module($command_class);
103              
104 0           my $service = $self->{dynamodb};
105 0           my %service_args = $command_class->transform_arguments(%args);
106 0           my $output = $command_class->run_service_command($service, %service_args);
107              
108 0 0         return $output if $return_paws_output;
109 0           return $command_class->transform_output($output);
110             }
111              
112             1;
113             __END__
114              
115             =encoding utf-8
116              
117             =head1 NAME
118              
119             PawsX::DynamoDB::DocumentClient - a simplified way of working with AWS DynamoDB items that uses Paws under the hood.
120              
121             =head1 SYNOPSIS
122              
123             use PawsX::DynamoDB::DocumentClient;
124              
125             my $dynamodb = PawsX::DynamoDB::DocumentClient->new();
126              
127             $dynamodb->put(
128             TableName => 'users',
129             Item => {
130             user_id => 24,
131             email => 'bob@example.com',
132             roles => ['admin', 'finance'],
133             },
134             );
135              
136             my $user = $dynamodb->get(
137             TableName => 'users',
138             Key => {
139             user_id => 24,
140             },
141             );
142              
143             =head1 DESCRIPTION
144              
145             Paws (in this author's opinion) is the best and most up-to-date way of working with AWS. However, reading and writing DynamoDB items via Paws' low-level API calls can involve a lot of busy work formatting your data structures to include DynamoDB types.
146              
147             This module simplifies some DynamoDB operations by automatically converting back and forth between simpler Perl data structures and the request/response data structures used by Paws.
148              
149             For more information about how types are mananged, see L<Net::Amazon::DynamoDB::Marshaler>.
150              
151             This module is based on a similar class in the L<AWS JavaScript SDK|http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html>.
152              
153             =head2 outputs
154              
155             By default, the methods below return plain values (or nothing) that make normal use cases simpler, as opposed to the output objects that Paws generates. For example, get() returns a hashref of the item's data, as opposed to a L<Paws::DynamoDB::GetItemOutput> object.
156              
157             For use cases where you need more extensive output data, every method supports a return_paws_output flag, which will return the Paws object instead.
158              
159             my $item = $dynamodb->get(
160             TableName => 'users',
161             Key => {
162             user_id => 1000,
163             },
164             );
165             # $item looks like { user_id => 1000, email => 'foo@bar.com', ... }
166              
167             my $output = $dynamodb->get(
168             TableName => 'users',
169             Key => {
170             user_id => 1000,
171             },
172             return_paws_output => 1,
173             );
174             # $output isa Paws::DynamoDB::GetItemOutput
175              
176             =head1 METHODS
177              
178             =head2 new
179              
180             my $dynamodb = PawsX::DynamoDB::DocumentClient->new(
181             region => 'us-east-1',
182             );
183              
184             This class method returns a new PawsX::DynamoDB::DocumentClient object. It accepts the following parameters:
185              
186             =head3 paws
187              
188             A Paws object to use to create the Paws::DynamoDB service object. Optional. Available in case you need to custom configuration of Paws (e.g. authentication).
189              
190             =head3 dynamodb
191              
192             Alternatively, you can provide a Paws::DynamoDB service object directly if you have one. Optional. If given, the 'paws' parameter will be ignored.
193              
194             =head3 region
195              
196             The AWS region to use when creating the Paws::DynamoDB service object. If not specified, will try to grab from the AWS_DEFAULT_REGION environment variable. Will be ignored if the object is constructed with a dynamodb object, or with a paws object that has a region configured.
197              
198             If the constructor can't figure out what region to use, an error will be thrown.
199              
200             =head2 batch_get
201              
202             my $result = $dynamodb->batch_get(
203             RequestItems => {
204             $table_name => {
205             Keys => [
206             { user_id => 1000 },
207             { user_id => 1001 },
208             ],
209             },
210             },
211             );
212              
213             Returns the attributes of one or more items from one or more tables by delegating to L<Paws::DynamoDB::BatchGetItem>.
214              
215             The following arguments are marshalled: values in 'RequestItems.$table_name.Keys'.
216              
217             By default (return_paws_output not set), returns a hashref that looks like:
218              
219             {
220             responses => {
221             $table_name => [
222             {...} # unmarshalled item
223             ...
224             ],
225             },
226             unprocessed_keys => {
227             $table_name => {
228             Keys => [
229             { ... }, # unmarshalled key
230             ...
231             ],
232             ProjectionExpression => '...',
233             ConsistentRead => $boolean,
234             }
235             }
236             }
237              
238             unprocessed_keys can be fed back into a new call to batch_get(). See L<Paws::DynamoDB::BatchGetItemOutput> for more infomation.
239              
240             =head2 batch_write
241              
242             my $result = $dynamodb->batch_write(
243             RequestItems => {
244             $table_name => [
245             {
246             PutRequest => {
247             Item => {
248             user_id => 1000,
249             email => 'jdoe@example.com',
250             },
251             },
252             },
253             {
254             DeleteRequest => {
255             Key => {
256             user_id => 1001,
257             },
258             },
259             },
260             ],
261             },
262             );
263              
264             Puts or deletes multiple items in one or more tables by delegating to L<Paws::DynamoDB::BatchWriteItem>.
265              
266             The following arguments are marshalled: Items in PutRequests, Keys in DeleteRequests.
267              
268             By default (return_paws_output not set), returns a hashref of unprocessed items, in the same format as the RequestItems parameters. The unprocessed items are meant to be fed back into a new call to batch_write(). See L<Paws::DynamoDB::BatchWriteItemOutput> for more information.
269              
270             =head2 delete
271              
272             my $result = $dynamodb->delete(
273             TableName => 'users',
274             Key => {
275             user_id => 1001,
276             },
277             );
278              
279             Deletes a single item in a table by primary key by delegating to L<Paws::DynamoDB::DeleteItem>.
280              
281             The following arguments are marshalled: 'ExpressionAttributeValues', 'Key'.
282              
283             By default (return_paws_output not set), returns undef, unless the 'ReturnValues' argument was set to 'ALL_OLD', in which case an unmarshalled hashref of how the item looked prior to deletion is returned.
284              
285             =head2 get
286              
287             my $result = $dynamodb->get(
288             TableName => 'users',
289             Key => {
290             user_id => 1000,
291             },
292             );
293              
294             Returns a set of attributes for the item with the given primary key by delegating to L<Paws::DynamoDB::GetItem>.
295              
296             The following arguments are marshalled: 'Key'.
297              
298             By default (return_paws_output not set), returns the fetched item as an unmarshalled hashref, or undef if the item was not found.
299              
300             =head2 put
301              
302             my $result = $dynamodb->put(
303             TableName => 'users',
304             Item => {
305             user_id => 1000,
306             email => 'jdoe@example.com',
307             tags => ['foo', 'bar', 'baz'],
308             },
309             );
310              
311             Creates a new item, or replaces an old item with a new item by delegating to L<Paws::DynamoDB::PutItem>.
312              
313             The following arguments are marshalled: 'ExpressionAttributeValues', 'Item'.
314              
315             By default (return_paws_output not set), returns undef. If 'ReturnValues' is set to 'ALL_OLD', returns an unmarshalled hashref of the item as it appeared before the put.
316              
317             =head2 query
318              
319             my $result = $dynamodb->query(
320             TableName => 'users',
321             IndexName => 'company_id',
322             KeyConditionExpression => 'company_id = :company_id',
323             ExpressionAttributeValues => {
324             ':company_id' => 25,
325             },
326             );
327              
328             Directly access items from a table by primary key or a secondary index by delegating to L<Paws::DynamoDB::Query>.
329              
330             The following arguments are marshalled: 'ExclusiveStartKey', 'ExpressionAttributeValues'.
331              
332             By default (return_paws_output not set), returns a hashref that looks like:
333              
334             {
335             items => [
336             { ... }, # unmarshalled item
337             ...
338             ],
339             last_evaluated_key => {
340             ... # unmarshalled key
341             },
342             count => $count,
343             }
344              
345             last_evaluated_key has a value if the query has more items to fetch. It can be used for the 'ExclusiveStartKey' value for a subsequent query.
346              
347             =head2 scan
348              
349             my $result = $dynamodb->scan(
350             TableName => 'users',
351             FilterExpression => 'first_name = :first_name',
352             ExpressionAttributeValues => {
353             ':first_name' => 'John',
354             },
355             );
356              
357             Returns one or more items and item attributes by accessing every item in a table or a secondary index by delegating to L<Paws::DynamoDB::Scan>.
358              
359             The following arguments are marshalled: 'ExclusiveStartKey', 'ExpressionAttributeValues'.
360              
361             Returns the same hashref as returned by query().
362              
363             =head2 update
364              
365             my $result = $dynamodb->update(
366             TableName => 'users',
367             Key: {
368             user_id => 1000,
369             },
370             UpdateExpression: 'SET status = :new_status',
371             ExpressionAttributeValues => {
372             ':new_status' => 'active',
373             },
374             );
375              
376             Edits an existing item's attributes, or adds a new item to the table if it does not already exist by delegating to L<Paws::DynamoDB::UpdateItem>.
377              
378             The following arguments are marshalled: 'ExpressionAttributeValues', 'Key'.
379              
380             By default (return_paws_output not set), returns undef. If 'ReturnValues' is set to something other than 'NONE', returns an unmarshalled hashref of the item as it appeared before the put.
381              
382             =head1 AUTHOR
383              
384             Steve Caldwell E<lt>scaldwell@gmail.comE<gt>
385              
386             =head1 COPYRIGHT
387              
388             Copyright 2017- Steve Caldwell
389              
390             =head1 LICENSE
391              
392             This library is free software; you can redistribute it and/or modify
393             it under the same terms as Perl itself.
394              
395             =head1 SEE ALSO
396              
397             =over 4
398              
399             =item L<Paws>
400              
401             =item L<Paws::DynamoDB>
402              
403             =item L<Net::Amazon::DynamoDB::Marshaler>
404              
405             =item L<DocumentClient|http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html> in the AWS JavaScript SDK.
406              
407             =back
408              
409             =head1 ACKNOWLEDGEMENTS
410              
411             Thanks to L<Campus Explorer|http://www.campusexplorer.com>, who allowed me to release this code as open source.
412              
413             Thanks to Jose Luis Martinez Torres (JLMARTIN), for suggestions (and for Paws!).
414              
415             =cut