File Coverage

blib/lib/Google/BigQuery.pm
Criterion Covered Total %
statement 12 14 85.7
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 17 19 89.4


line stmt bran cond sub pod time code
1             package Google::BigQuery;
2 1     1   770 use 5.010001;
  1         4  
3 1     1   5 use strict;
  1         1  
  1         19  
4 1     1   4 use warnings;
  1         9  
  1         43  
5              
6             our $VERSION = "1.02";
7              
8 1     1   41542 use Class::Load qw(load_class);
  1         397663  
  1         62  
9 1     1   425 use Crypt::OpenSSL::PKCS12;
  0            
  0            
10             use JSON qw(decode_json encode_json);
11             use JSON::WebToken;
12             use LWP::UserAgent;
13              
14             sub create {
15             my (%args) = @_;
16              
17             my $version = $args{version} // 'v2';
18             my $class = 'Google::BigQuery::' . ucfirst($version);
19              
20             if (load_class($class)) {
21             return $class->new(%args);
22             } else {
23             die "Can't load class: $class";
24             }
25             }
26              
27             sub new {
28             my ($class, %args) = @_;
29              
30             die "undefined client_eamil" if !defined $args{client_email};
31             die "undefined private_key_file" if !defined $args{private_key_file};
32             die "not found private_key_file" if !-f $args{private_key_file};
33              
34             my $self = bless { %args }, $class;
35              
36             $self->{GOOGLE_API_TOKEN_URI} = 'https://accounts.google.com/o/oauth2/token';
37             $self->{GOOGLE_API_GRANT_TYPE} = 'urn:ietf:params:oauth:grant-type:jwt-bearer';
38              
39             if ($self->{private_key_file} =~ /\.json$/) {
40             open my $in, "<", $self->{private_key_file} or die "can't open $self->{private_key_file} : $!";
41             my $private_key_json = decode_json(join('', <$in>));
42             close $in;
43             $self->{private_key} = $private_key_json->{private_key};
44             } elsif ($self->{private_key_file} =~ /\.p12$/) {
45             my $password = "notasecret";
46             my $pkcs12 = Crypt::OpenSSL::PKCS12->new_from_file($self->{private_key_file});
47             $self->{private_key} = $pkcs12->private_key($password);
48             } else {
49             die "invalid private_key_file format";
50             }
51              
52             $self->_auth;
53             $self->_set_rest_description;
54              
55             return $self;
56             }
57              
58             sub DESTROY {
59             }
60              
61             sub _auth {
62             my ($self) = @_;
63              
64             $self->{scope} //= [qw(https://www.googleapis.com/auth/bigquery)];
65             $self->{exp} = time + 3600;
66             $self->{iat} = time;
67             $self->{ua} = LWP::UserAgent->new;
68              
69             my $claim = {
70             iss => $self->{client_email},
71             scope => join(" ", @{$self->{scope}}),
72             aud => $self->{GOOGLE_API_TOKEN_URI},
73             exp => $self->{exp},
74             iat => $self->{iat},
75             };
76              
77             my $jwt = JSON::WebToken::encode_jwt($claim, $self->{private_key}, 'RS256', { type => 'JWT' });
78              
79             my $response = $self->{ua}->post(
80             $self->{GOOGLE_API_TOKEN_URI},
81             { grant_type => $self->{GOOGLE_API_GRANT_TYPE}, assertion => $jwt }
82             );
83              
84             if ($response->is_success) {
85             $self->{access_token} = decode_json($response->decoded_content);
86             } else {
87             my $error = decode_json($response->decoded_content);
88             die $error->{error};
89             }
90             }
91              
92             sub _set_rest_description {
93             my ($self) = @_;
94             my $response = $self->{ua}->get($self->{GOOGLE_BIGQUERY_REST_DESCRIPTION});
95             $self->{rest_description} = decode_json($response->decoded_content);
96             }
97              
98             sub use_project {
99             my ($self, $project_id) = @_;
100             $self->{project_id} = $project_id // return;
101             }
102              
103             sub use_dataset {
104             my ($self, $dataset_id) = @_;
105             $self->{dataset_id} = $dataset_id // return;
106             }
107              
108             sub create_dataset {
109             my ($self, %args) = @_;
110              
111             my $project_id = $args{project_id} // $self->{project_id};
112             my $dataset_id = $args{dataset_id} // $self->{dataset_id};
113              
114             unless ($project_id) {
115             warn "no project\n";
116             return 0;
117             }
118             unless ($dataset_id) {
119             warn "no dataset\n";
120             return 0;
121             }
122              
123             my $content = {
124             datasetReference => {
125             projectId => $project_id,
126             datasetId => $dataset_id
127             }
128             };
129              
130             # option
131             $content->{access} = $args{access} if defined $args{access};
132             $content->{description} = $args{description} if defined $args{description};
133             $content->{friendlyName} = $args{friendlyName} if defined $args{friendlyName};
134              
135             my $response = $self->request(
136             resource => 'datasets',
137             method => 'insert',
138             project_id => $project_id,
139             dataset_id => $dataset_id,
140             content => $content,
141             );
142             $self->{response} = $response;
143              
144             if (defined $response->{error}) {
145             warn $response->{error}{message};
146             return 0;
147             } else {
148             return 1;
149             }
150             }
151              
152             sub drop_dataset {
153             my ($self, %args) = @_;
154              
155             my $project_id = $args{project_id} // $self->{project_id};
156             my $dataset_id = $args{dataset_id};
157              
158             unless ($project_id) {
159             warn "no project\n";
160             return 0;
161             }
162             unless ($dataset_id) {
163             warn "no dataset\n";
164             return 0;
165             }
166              
167             # option
168             my $query_string = {};
169             if (defined $args{deleteContents}) {
170             $query_string->{deleteContents} = $args{deleteContents} ? 'true' : 'false';
171             }
172              
173             my $response = $self->request(
174             resource => 'datasets',
175             method => 'delete',
176             project_id => $project_id,
177             dataset_id => $dataset_id,
178             query_string => $query_string,
179             );
180             $self->{response} = $response;
181              
182             if (defined $response->{error}) {
183             warn $response->{error}{message};
184             return 0;
185             } else {
186             return 1;
187             }
188             }
189              
190             sub show_datasets {
191             my ($self, %args) = @_;
192              
193             my $project_id = $args{project_id} // $self->{project_id};
194              
195             unless ($project_id) {
196             warn "no project\n";
197             return undef;
198             }
199              
200             # option
201             my $query_string = {};
202             if (defined $args{all}) {
203             $query_string->{all} = $args{all} ? 'true' : 'false';
204             }
205             $query_string->{maxResults} = $args{maxResults} if defined $args{maxResults};
206             $query_string->{pageToken} = $args{pageToken} if defined $args{pageToken};
207              
208             my $response = $self->request(
209             resource => 'datasets',
210             method => 'list',
211             project_id => $project_id,
212             query_string => $query_string,
213             );
214             $self->{response} = $response;
215              
216             if (defined $response->{error}) {
217             warn $response->{error}{message};
218             return undef;
219             }
220              
221             my @ret = ();
222             foreach my $dataset (@{$response->{datasets}}) {
223             push @ret, $dataset->{datasetReference}{datasetId};
224             }
225              
226             return @ret;
227             }
228              
229             sub desc_dataset {
230             my ($self, %args) = @_;
231              
232             my $project_id = $args{project_id} // $self->{project_id};
233             my $dataset_id = $args{dataset_id} // $self->{dataset_id};
234              
235             unless ($project_id) {
236             warn "no project\n";
237             return 0;
238             }
239             unless ($dataset_id) {
240             warn "no dataset\n";
241             return 0;
242             }
243              
244             my $response = $self->request(
245             resource => 'datasets',
246             method => 'get',
247             project_id => $project_id,
248             dataset_id => $dataset_id,
249             );
250             $self->{response} = $response;
251              
252             if (defined $response->{error}) {
253             warn $response->{error}{message};
254             return undef;
255             } else {
256             return $response;
257             }
258             }
259              
260             sub create_table {
261             my ($self, %args) = @_;
262              
263             my $project_id = $args{project_id} // $self->{project_id};
264             my $dataset_id = $args{dataset_id} // $self->{dataset_id};
265             my $table_id = $args{table_id};
266              
267             unless ($project_id) {
268             warn "no project\n";
269             return 0;
270             }
271             unless ($dataset_id) {
272             warn "no dataset\n";
273             return 0;
274             }
275             unless ($table_id) {
276             warn "no table\n";
277             return 0;
278             }
279              
280             my $content = {
281             tableReference => {
282             projectId => $project_id,
283             datasetId => $dataset_id,
284             tableId => $table_id
285             },
286             };
287              
288             # option
289             $content->{description} = $args{description} if defined $args{description};
290             $content->{expirationTime} = $args{expirationTime} if defined $args{expirationTime};
291             $content->{friendlyName} = $args{friendlyName} if defined $args{friendlyName};
292             $content->{schema}{fields} = $args{schema} if defined $args{schema};
293             $content->{view}{query} = $args{view} if defined $args{view};
294              
295             my $response = $self->request(
296             resource => 'tables',
297             method => 'insert',
298             project_id => $project_id,
299             dataset_id => $dataset_id,
300             table_id => $table_id,
301             content => $content,
302             );
303             $self->{response} = $response;
304              
305             if (defined $response->{error}) {
306             warn $response->{error}{message};
307             return 0;
308             } elsif (defined $args{schema} && !defined $response->{schema}) {
309             warn "no create schema";
310             return 0;
311             } else {
312             return 1;
313             }
314             }
315              
316             sub drop_table {
317             my ($self, %args) = @_;
318              
319             my $project_id = $args{project_id} // $self->{project_id};
320             my $dataset_id = $args{dataset_id} // $self->{dataset_id};
321             my $table_id = $args{table_id};
322              
323             unless ($project_id) {
324             warn "no project\n";
325             return 0;
326             }
327             unless ($dataset_id) {
328             warn "no dataset\n";
329             return 0;
330             }
331             unless ($table_id) {
332             warn "no table\n";
333             return 0;
334             }
335              
336             my $response = $self->request(
337             resource => 'tables',
338             method => 'delete',
339             project_id => $project_id,
340             dataset_id => $dataset_id,
341             table_id => $table_id
342             );
343             $self->{response} = $response;
344              
345             if (defined $response->{error}) {
346             warn $response->{error}{message};
347             return 0;
348             } else {
349             return 1;
350             }
351             }
352              
353             sub show_tables {
354             my ($self, %args) = @_;
355              
356             my $project_id = $args{project_id} // $self->{project_id};
357             my $dataset_id = $args{dataset_id} // $self->{dataset_id};
358              
359             unless ($project_id) {
360             warn "no project\n";
361             return undef;
362             }
363             unless ($dataset_id) {
364             warn "no dataset\n";
365             return undef;
366             }
367              
368             # option
369             my $query_string = {};
370             $query_string->{maxResults} = $args{maxResults} if defined $args{maxResults};
371             $query_string->{pageToken} = $args{pageToken} if defined $args{pageToken};
372              
373             my $response = $self->request(
374             resource => 'tables',
375             method => 'list',
376             project_id => $project_id,
377             dataset_id => $dataset_id,
378             query_string => $query_string,
379             );
380             $self->{response} = $response;
381              
382             if (defined $response->{error}) {
383             warn $response->{error}{message};
384             return undef;
385             }
386              
387             my @ret = ();
388             foreach my $table (@{$response->{tables}}) {
389             push @ret, $table->{tableReference}{tableId};
390             }
391              
392             return @ret;
393             }
394              
395             sub desc_table {
396             my ($self, %args) = @_;
397              
398             my $project_id = $args{project_id} // $self->{project_id};
399             my $dataset_id = $args{dataset_id} // $self->{dataset_id};
400             my $table_id = $args{table_id};
401              
402             unless ($project_id) {
403             warn "no project\n";
404             return 0;
405             }
406             unless ($dataset_id) {
407             warn "no dataset\n";
408             return 0;
409             }
410             unless ($table_id) {
411             warn "no table\n";
412             return 0;
413             }
414              
415             my $response = $self->request(
416             resource => 'tables',
417             method => 'get',
418             project_id => $project_id,
419             dataset_id => $dataset_id,
420             table_id => $table_id,
421             );
422             $self->{response} = $response;
423              
424             if (defined $response->{error}) {
425             warn $response->{error}{message};
426             return undef;
427             } else {
428             return $response;
429             }
430             }
431              
432             sub load {
433             my ($self, %args) = @_;
434              
435             my $project_id = $args{project_id} // $self->{project_id};
436             my $dataset_id = $args{dataset_id} // $self->{dataset_id};
437             my $table_id = $args{table_id};
438             my $data = $args{data};
439             my $async = $args{async} // 0;
440              
441             unless ($project_id) {
442             warn "no project\n";
443             return 0;
444             }
445             unless ($dataset_id) {
446             warn "no dataset\n";
447             return 0;
448             }
449             unless ($table_id) {
450             warn "no table\n";
451             return 0;
452             }
453             unless ($data) {
454             warn "no data\n";
455             return 0;
456             }
457              
458             my $content = {
459             configuration => {
460             load => {
461             destinationTable => {
462             projectId => $project_id,
463             datasetId => $dataset_id,
464             tableId => $table_id,
465             }
466             }
467             }
468             };
469              
470             if (ref($data) =~ /ARRAY/) {
471             $content->{configuration}{load}{sourceUris} = $data;
472             } elsif ($data =~ /^gs:\/\//) {
473             $content->{configuration}{load}{sourceUris} = [($data)];
474             }
475              
476             my $suffix;
477             if (defined $content->{configuration}{load}{sourceUris}) {
478             $suffix = $1 if $content->{configuration}{load}{sourceUris}[0] =~ /\.(tsv|csv|json)(?:\.gz)?$/i;
479             } else {
480             $suffix = $1 if $data =~ /\.(tsv|csv|json)(?:\.gz)?$/i;
481             }
482              
483             if (defined $suffix) {
484             my $source_format;
485             my $field_delimiter;
486             if ($suffix =~ /^tsv$/i) {
487             $field_delimiter = "\t";
488             } elsif ($suffix =~ /^json$/i) {
489             $source_format = "NEWLINE_DELIMITED_JSON";
490             }
491             $content->{configuration}{load}{sourceFormat} = $source_format if defined $source_format;
492             $content->{configuration}{load}{fieldDelimiter} = $field_delimiter if defined $field_delimiter;
493             }
494              
495             # load options
496             if (defined $args{allowJaggedRows}) {
497             $content->{configuration}{load}{allowJaggedRows} = $args{allowJaggedRows} ? 'true' : 'false';
498             }
499             if (defined $args{allowQuotedNewlines}) {
500             $content->{configuration}{load}{allowQuotedNewlines} = $args{allowQuotedNewlines} ? 'true' : 'false';
501             }
502             $content->{configuration}{load}{createDisposition} = $args{createDisposition} if defined $args{createDisposition};
503             $content->{configuration}{load}{encoding} = $args{encoding} if defined $args{encoding};
504             $content->{configuration}{load}{fieldDelimiter} = $args{fieldDelimiter} if defined $args{fieldDelimiter};
505             if (defined $args{ignoreUnknownValues}) {
506             $content->{configuration}{load}{ignoreUnknownValues} = $args{ignoreUnknownValues} ? 'true' : 'false';
507             }
508             $content->{configuration}{load}{maxBadRecords} = $args{maxBadRecords} if defined $args{maxBadRecords};
509             $content->{configuration}{load}{quote} = $args{quote} if defined $args{quote};
510             $content->{configuration}{load}{schema}{fields} = $args{schema} if defined $args{schema};
511             $content->{configuration}{load}{skipLeadingRows} = $args{skipLeadingRows} if defined $args{skipLeadingRows};
512             $content->{configuration}{load}{sourceFormat} = $args{sourceFormat} if defined $args{sourceFormat};
513             $content->{configuration}{load}{sourceUris} = $args{sourceUris} if defined $args{sourceUris};
514             $content->{configuration}{load}{writeDisposition} = $args{writeDisposition} if defined $args{writeDisposition};
515              
516             my $response = $self->request(
517             resource => 'jobs',
518             method => 'insert',
519             project_id => $project_id,
520             dataset_id => $dataset_id,
521             talbe_id => $table_id,
522             content => $content,
523             data => $data,
524             async => $async
525             );
526             $self->{response} = $response;
527              
528             if (defined $response->{error}) {
529             warn $response->{error}{message};
530             return 0;
531             } elsif ($async) {
532             # return job_id if async is true.
533             return $response->{jobReference}{jobId};
534             } elsif ($response->{status}{state} eq 'DONE') {
535             if (defined $response->{status}{errors}) {
536             foreach my $error (@{$response->{status}{errors}}) {
537             warn encode_json($error), "\n";
538             }
539             return 0;
540             } else {
541             return 1;
542             }
543             } else {
544             return 0;
545             }
546             }
547              
548             sub insert {
549             my ($self, %args) = @_;
550              
551             my $project_id = $args{project_id} // $self->{project_id};
552             my $dataset_id = $args{dataset_id} // $self->{dataset_id};
553             my $table_id = $args{table_id};
554             my $values = $args{values};
555              
556             unless ($project_id) {
557             warn "no project\n";
558             return 0;
559             }
560             unless ($dataset_id) {
561             warn "no dataset\n";
562             return 0;
563             }
564             unless ($table_id) {
565             warn "no table\n";
566             return 0;
567             }
568             unless ($values) {
569             warn "no values\n";
570             return 0;
571             }
572              
573             my $rows = [];
574             foreach my $value (@$values) {
575             push @$rows, { json => $value };
576             }
577              
578             my $response = $self->request(
579             resource => 'tabledata',
580             method => 'insertAll',
581             project_id => $project_id,
582             dataset_id => $dataset_id,
583             table_id => $table_id,
584             content => {
585             rows => $rows
586             }
587             );
588             $self->{response} = $response;
589              
590             if (defined $response->{error}) {
591             warn $response->{error}{message};
592             return 0;
593             } elsif (defined $response->{insertErrors}) {
594             foreach my $error (@{$response->{insertErrors}}) {
595             warn encode_json($error), "\n";
596             }
597             return 0;
598             } else {
599             return 1;
600             }
601             }
602              
603             sub selectrow_array {
604             my ($self, %args) = @_;
605              
606             my $query = $args{query};
607             my $project_id = $args{project_id} // $self->{project_id};
608             my $dataset_id = $args{dataset_id} // $self->{dataset_id};
609              
610             unless ($query) {
611             warn "no query\n";
612             return 0;
613             }
614             unless ($project_id) {
615             warn "no project\n";
616             return 0;
617             }
618              
619             my $content = {
620             query => $query,
621             };
622              
623             # option
624             if (defined $dataset_id) {
625             $content->{defaultDataset}{projectId} = $project_id;
626             $content->{defaultDataset}{datasetId} = $dataset_id;
627             }
628             $content->{maxResults} = $args{maxResults} if defined $args{maxResults};
629             $content->{timeoutMs} = $args{timeoutMs} if defined $args{timeoutMs};
630             if (defined $args{dryRun}) {
631             $content->{dryRun} = $args{dryRun} ? 'true' : 'false';
632             }
633             if (defined $args{useQueryCache}) {
634             $content->{useQueryCache} = $args{useQueryCache} ? 'true' : 'false';
635             }
636              
637             my $response = $self->request(
638             resource => 'jobs',
639             method => 'query',
640             content => $content
641             );
642             $self->{response} = $response;
643              
644             if (defined $response->{error}) {
645             warn $response->{error}{message};
646             return 0;
647             }
648              
649             my @ret = ();
650             foreach my $field (@{$response->{rows}[0]{f}}) {
651             push @ret, $field->{v};
652             }
653              
654             return @ret;
655             }
656              
657             sub selectall_arrayref {
658             my ($self, %args) = @_;
659              
660             my $query = $args{query};
661             my $project_id = $args{project_id} // $self->{project_id};
662             my $dataset_id = $args{dataset_id} // $self->{dataset_id};
663              
664             unless ($query) {
665             warn "no query\n";
666             return 0;
667             }
668             unless ($project_id) {
669             warn "no project\n";
670             return 0;
671             }
672              
673             my $content = {
674             query => $query,
675             };
676              
677             # option
678             if (defined $dataset_id) {
679             $content->{defaultDataset}{projectId} = $project_id;
680             $content->{defaultDataset}{datasetId} = $dataset_id;
681             }
682             $content->{maxResults} = $args{maxResults} if defined $args{maxResults};
683             $content->{timeoutMs} = $args{timeoutMs} if defined $args{timeoutMs};
684             if (defined $args{dryRun}) {
685             $content->{dryRun} = $args{dryRun} ? 'true' : 'false';
686             }
687             if (defined $args{useQueryCache}) {
688             $content->{useQueryCache} = $args{useQueryCache} ? 'true' : 'false';
689             }
690              
691             my $response = $self->request(
692             resource => 'jobs',
693             method => 'query',
694             content => $content
695             );
696             $self->{response} = $response;
697              
698             if (defined $response->{error}) {
699             warn $response->{error}{message};
700             return 0;
701             }
702              
703             my $ret = [];
704             foreach my $rows (@{$response->{rows}}) {
705             my $row = [];
706             foreach my $field (@{$rows->{f}}) {
707             push @$row, $field->{v};
708             }
709             push @$ret, $row;
710             }
711              
712             return $ret;
713             }
714              
715             sub is_exists_dataset {
716             my ($self, %args) = @_;
717              
718             my $project_id = $args{project_id} // $self->{project_id};
719             my $dataset_id = $args{dataset_id} // $self->{dataset_id};
720              
721             unless ($project_id) {
722             warn "no project\n";
723             return 0;
724             }
725             unless ($dataset_id) {
726             warn "no dataset\n";
727             return 0;
728             }
729              
730             my $response = $self->request(
731             resource => 'datasets',
732             method => 'get',
733             project_id => $project_id,
734             dataset_id => $dataset_id
735             );
736             $self->{response} = $response;
737              
738             if (defined $response->{error}) {
739             #warn $response->{error}{message};
740             return 0;
741             } else {
742             return 1;
743             }
744             }
745              
746             sub is_exists_table {
747             my ($self, %args) = @_;
748              
749             my $project_id = $args{project_id} // $self->{project_id};
750             my $dataset_id = $args{dataset_id} // $self->{dataset_id};
751             my $table_id = $args{table_id};
752              
753             unless ($project_id) {
754             warn "no project\n";
755             return 0;
756             }
757             unless ($dataset_id) {
758             warn "no dataset\n";
759             return 0;
760             }
761             unless ($table_id) {
762             warn "no table\n";
763             return 0;
764             }
765              
766             my $response = $self->request(
767             resource => 'tables',
768             method => 'get',
769             project_id => $project_id,
770             dataset_id => $dataset_id,
771             table_id => $table_id
772             );
773             $self->{response} = $response;
774              
775             if (defined $response->{error}) {
776             #warn $response->{error}{message};
777             return 0;
778             } else {
779             return 1;
780             }
781             }
782              
783             sub extract {
784             my ($self, %args) = @_;
785              
786             my $project_id = $args{project_id} // $self->{project_id};
787             my $dataset_id = $args{dataset_id} // $self->{dataset_id};
788             my $table_id = $args{table_id};
789             my $data = $args{data};
790              
791             unless ($project_id) {
792             warn "no project\n";
793             return 0;
794             }
795             unless ($dataset_id) {
796             warn "no dataset\n";
797             return 0;
798             }
799             unless ($table_id) {
800             warn "no table\n";
801             return 0;
802             }
803             unless ($data) {
804             warn "no data\n";
805             return 0;
806             }
807              
808             my $content = {
809             configuration => {
810             extract => {
811             sourceTable => {
812             projectId => $project_id,
813             datasetId => $dataset_id,
814             tableId => $table_id,
815             }
816             }
817             }
818             };
819              
820             if (ref($data) =~ /ARRAY/) {
821             $content->{configuration}{extract}{destinationUris} = $data;
822             } elsif ($data =~ /^gs:\/\//) {
823             $content->{configuration}{extract}{destinationUris} = [($data)];
824             } else {
825             $content->{configuration}{extract}{destinationUris} = [('')];
826             }
827              
828             my $suffix;
829             my $compression;
830             if (defined $content->{configuration}{extract}{destinationUris}) {
831             $suffix = $1 if $content->{configuration}{extract}{destinationUris}[0] =~ /\.(tsv|csv|json|avro)(?:\.gz)?$/i;
832             $compression = 'GZIP' if $content->{configuration}{extract}{destinationUris}[0] =~ /\.gz$/i;
833             }
834              
835             if (defined $suffix) {
836             my $destination_format;
837             my $field_delimiter;
838             if ($suffix =~ /^tsv$/i) {
839             $field_delimiter = "\t";
840             } elsif ($suffix =~ /^json$/i) {
841             $destination_format = "NEWLINE_DELIMITED_JSON";
842             } elsif ($suffix =~ /^avro$/) {
843             $destination_format = "AVRO";
844             }
845             $content->{configuration}{extract}{destinationFormat} = $destination_format if defined $destination_format;
846             $content->{configuration}{extract}{fieldDelimiter} = $field_delimiter if defined $field_delimiter;
847             }
848             $content->{configuration}{extract}{compression} = $compression if defined $compression;
849              
850             # extract options
851             $content->{configuration}{extract}{compression} = $args{compression} if defined $args{compression};
852             $content->{configuration}{extract}{destinationFormat} = $args{destinationFormat} if defined $args{destinationFormat};
853             $content->{configuration}{extract}{destinationUris} = $args{destinationUris} if defined $args{destinationUris};
854             $content->{configuration}{extract}{fieldDelimiter} = $args{fieldDelimiter} if defined $args{fieldDelimiter};
855             if (defined $args{printHeader}) {
856             $content->{configuration}{extract}{printHeader} = $args{printHeader} ? 'true' : 'false';
857             }
858              
859             my $response = $self->request(
860             resource => 'jobs',
861             method => 'insert',
862             project_id => $project_id,
863             dataset_id => $dataset_id,
864             talbe_id => $table_id,
865             content => $content,
866             data => $data
867             );
868             $self->{response} = $response;
869              
870             if (defined $response->{error}) {
871             warn $response->{error}{message};
872             return 0;
873             } elsif ($response->{status}{state} eq 'DONE') {
874             if (defined $response->{status}{errors}) {
875             foreach my $error (@{$response->{status}{errors}}) {
876             warn encode_json($error), "\n";
877             }
878             return 0;
879             } else {
880             return 1;
881             }
882             } else {
883             return 0;
884             }
885             }
886              
887             sub get_nextPageToken {
888             my $self = shift;
889              
890             if (defined $self->{response}{nextPageToken}) {
891             return $self->{response}{nextPageToken};
892             } else {
893             return undef;
894             }
895             }
896              
897             1;
898             __END__