google-cloud-bigquery 1.31.0 → 1.32.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,945 @@
1
+ # Copyright 2021 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ require "google/apis/bigquery_v2"
17
+ require "base64"
18
+ require "google/cloud/bigquery/external/bigtable_source/column"
19
+
20
+ module Google
21
+ module Cloud
22
+ module Bigquery
23
+ module External
24
+ class BigtableSource < External::DataSource
25
+ ##
26
+ # # BigtableSource::ColumnFamily
27
+ #
28
+ # A Bigtable column family used to expose in the table schema along
29
+ # with its types and columns.
30
+ #
31
+ # @example
32
+ # require "google/cloud/bigquery"
33
+ #
34
+ # bigquery = Google::Cloud::Bigquery.new
35
+ #
36
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
37
+ # bigtable_table = bigquery.external bigtable_url do |bt|
38
+ # bt.rowkey_as_string = true
39
+ # bt.add_family "user" do |u|
40
+ # u.add_string "name"
41
+ # u.add_string "email"
42
+ # u.add_integer "age"
43
+ # u.add_boolean "active"
44
+ # end
45
+ # end
46
+ #
47
+ # data = bigquery.query "SELECT * FROM my_ext_table",
48
+ # external: { my_ext_table: bigtable_table }
49
+ #
50
+ # # Iterate over the first page of results
51
+ # data.each do |row|
52
+ # puts row[:name]
53
+ # end
54
+ # # Retrieve the next page of results
55
+ # data = data.next if data.next?
56
+ #
57
+ class ColumnFamily
58
+ ##
59
+ # @private Create an empty BigtableSource::ColumnFamily object.
60
+ def initialize
61
+ @gapi = Google::Apis::BigqueryV2::BigtableColumnFamily.new
62
+ @columns = []
63
+ end
64
+
65
+ ##
66
+ # The encoding of the values when the type is not `STRING`.
67
+ #
68
+ # @return [String]
69
+ #
70
+ # @example
71
+ # require "google/cloud/bigquery"
72
+ #
73
+ # bigquery = Google::Cloud::Bigquery.new
74
+ #
75
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
76
+ # bigtable_table = bigquery.external bigtable_url do |bt|
77
+ # bt.add_family "user" do |u|
78
+ # u.encoding = "UTF-8"
79
+ # end
80
+ # end
81
+ #
82
+ # bigtable_table.families[0].encoding #=> "UTF-8"
83
+ #
84
+ def encoding
85
+ @gapi.encoding
86
+ end
87
+
88
+ ##
89
+ # Set the encoding of the values when the type is not `STRING`.
90
+ # Acceptable encoding values are:
91
+ #
92
+ # * `TEXT` - indicates values are alphanumeric text strings.
93
+ # * `BINARY` - indicates values are encoded using HBase
94
+ # `Bytes.toBytes` family of functions. This can be overridden on a
95
+ # column.
96
+ #
97
+ # @param [String] new_encoding New encoding value
98
+ #
99
+ # @example
100
+ # require "google/cloud/bigquery"
101
+ #
102
+ # bigquery = Google::Cloud::Bigquery.new
103
+ #
104
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
105
+ # bigtable_table = bigquery.external bigtable_url do |bt|
106
+ # bt.add_family "user" do |u|
107
+ # u.encoding = "UTF-8"
108
+ # end
109
+ # end
110
+ #
111
+ # bigtable_table.families[0].encoding #=> "UTF-8"
112
+ #
113
+ def encoding= new_encoding
114
+ frozen_check!
115
+ @gapi.encoding = new_encoding
116
+ end
117
+
118
+ ##
119
+ # Identifier of the column family.
120
+ #
121
+ # @return [String]
122
+ #
123
+ # @example
124
+ # require "google/cloud/bigquery"
125
+ #
126
+ # bigquery = Google::Cloud::Bigquery.new
127
+ #
128
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
129
+ # bigtable_table = bigquery.external bigtable_url do |bt|
130
+ # bt.add_family "user"
131
+ # end
132
+ #
133
+ # bigtable_table.families[0].family_id #=> "user"
134
+ #
135
+ def family_id
136
+ @gapi.family_id
137
+ end
138
+
139
+ ##
140
+ # Set the identifier of the column family.
141
+ #
142
+ # @param [String] new_family_id New family_id value
143
+ #
144
+ # @example
145
+ # require "google/cloud/bigquery"
146
+ #
147
+ # bigquery = Google::Cloud::Bigquery.new
148
+ #
149
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
150
+ # bigtable_table = bigquery.external bigtable_url do |bt|
151
+ # bt.add_family "user"
152
+ # end
153
+ #
154
+ # bigtable_table.families[0].family_id #=> "user"
155
+ # bigtable_table.families[0].family_id = "User"
156
+ # bigtable_table.families[0].family_id #=> "User"
157
+ #
158
+ def family_id= new_family_id
159
+ frozen_check!
160
+ @gapi.family_id = new_family_id
161
+ end
162
+
163
+ ##
164
+ # Whether only the latest version of value are exposed for all
165
+ # columns in this column family.
166
+ #
167
+ # @return [Boolean]
168
+ #
169
+ # @example
170
+ # require "google/cloud/bigquery"
171
+ #
172
+ # bigquery = Google::Cloud::Bigquery.new
173
+ #
174
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
175
+ # bigtable_table = bigquery.external bigtable_url do |bt|
176
+ # bt.add_family "user" do |u|
177
+ # u.latest = true
178
+ # end
179
+ # end
180
+ #
181
+ # bigtable_table.families[0].latest #=> true
182
+ #
183
+ def latest
184
+ @gapi.only_read_latest
185
+ end
186
+
187
+ ##
188
+ # Set whether only the latest version of value are exposed for all
189
+ # columns in this column family.
190
+ #
191
+ # @param [Boolean] new_latest New latest value
192
+ #
193
+ # @example
194
+ # require "google/cloud/bigquery"
195
+ #
196
+ # bigquery = Google::Cloud::Bigquery.new
197
+ #
198
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
199
+ # bigtable_table = bigquery.external bigtable_url do |bt|
200
+ # bt.add_family "user" do |u|
201
+ # u.latest = true
202
+ # end
203
+ # end
204
+ #
205
+ # bigtable_table.families[0].latest #=> true
206
+ #
207
+ def latest= new_latest
208
+ frozen_check!
209
+ @gapi.only_read_latest = new_latest
210
+ end
211
+
212
+ ##
213
+ # The type to convert the value in cells of this column family. The
214
+ # values are expected to be encoded using HBase `Bytes.toBytes`
215
+ # function when using the `BINARY` encoding value. The following
216
+ # BigQuery types are allowed:
217
+ #
218
+ # * `BYTES`
219
+ # * `STRING`
220
+ # * `INTEGER`
221
+ # * `FLOAT`
222
+ # * `BOOLEAN`
223
+ #
224
+ # Default type is `BYTES`. This can be overridden on a column.
225
+ #
226
+ # @return [String]
227
+ #
228
+ # @example
229
+ # require "google/cloud/bigquery"
230
+ #
231
+ # bigquery = Google::Cloud::Bigquery.new
232
+ #
233
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
234
+ # bigtable_table = bigquery.external bigtable_url do |bt|
235
+ # bt.add_family "user" do |u|
236
+ # u.type = "STRING"
237
+ # end
238
+ # end
239
+ #
240
+ # bigtable_table.families[0].type #=> "STRING"
241
+ #
242
+ def type
243
+ @gapi.type
244
+ end
245
+
246
+ ##
247
+ # Set the type to convert the value in cells of this column family.
248
+ # The values are expected to be encoded using HBase `Bytes.toBytes`
249
+ # function when using the `BINARY` encoding value. The following
250
+ # BigQuery types are allowed:
251
+ #
252
+ # * `BYTES`
253
+ # * `STRING`
254
+ # * `INTEGER`
255
+ # * `FLOAT`
256
+ # * `BOOLEAN`
257
+ #
258
+ # Default type is `BYTES`. This can be overridden on a column.
259
+ #
260
+ # @param [String] new_type New type value
261
+ #
262
+ # @example
263
+ # require "google/cloud/bigquery"
264
+ #
265
+ # bigquery = Google::Cloud::Bigquery.new
266
+ #
267
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
268
+ # bigtable_table = bigquery.external bigtable_url do |bt|
269
+ # bt.add_family "user" do |u|
270
+ # u.type = "STRING"
271
+ # end
272
+ # end
273
+ #
274
+ # bigtable_table.families[0].type #=> "STRING"
275
+ #
276
+ def type= new_type
277
+ frozen_check!
278
+ @gapi.type = new_type
279
+ end
280
+
281
+ ##
282
+ # Lists of columns that should be exposed as individual fields.
283
+ #
284
+ # @return [Array<BigtableSource::Column>]
285
+ #
286
+ # @example
287
+ # require "google/cloud/bigquery"
288
+ #
289
+ # bigquery = Google::Cloud::Bigquery.new
290
+ #
291
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
292
+ # bigtable_table = bigquery.external bigtable_url do |bt|
293
+ # bt.rowkey_as_string = true
294
+ # bt.add_family "user" do |u|
295
+ # u.add_string "name"
296
+ # u.add_string "email"
297
+ # u.add_integer "age"
298
+ # u.add_boolean "active"
299
+ # end
300
+ # end
301
+ #
302
+ # bigtable_table.families[0].columns.count #=> 4
303
+ #
304
+ def columns
305
+ @columns
306
+ end
307
+
308
+ ##
309
+ # Add a column to the column family to expose in the table schema
310
+ # along with its types.
311
+ #
312
+ # @param [String] qualifier Qualifier of the column. See
313
+ # {BigtableSource::Column#qualifier}.
314
+ # @param [String] as A valid identifier to be used as the column
315
+ # field name if the qualifier is not a valid BigQuery field
316
+ # identifier (i.e. does not match `[a-zA-Z][a-zA-Z0-9_]*`). See
317
+ # {BigtableSource::Column#field_name}.
318
+ # @param [String] type The type to convert the value in cells of
319
+ # this column. See {BigtableSource::Column#type}. The following
320
+ # BigQuery types are allowed:
321
+ #
322
+ # * `BYTES`
323
+ # * `STRING`
324
+ # * `INTEGER`
325
+ # * `FLOAT`
326
+ # * `BOOLEAN`
327
+ #
328
+ # @yield [column] a block for setting the column
329
+ # @yieldparam [BigtableSource::Column] column the column object
330
+ #
331
+ # @return [Array<BigtableSource::Column>]
332
+ #
333
+ # @example
334
+ # require "google/cloud/bigquery"
335
+ #
336
+ # bigquery = Google::Cloud::Bigquery.new
337
+ #
338
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
339
+ # bigtable_table = bigquery.external bigtable_url do |bt|
340
+ # bt.rowkey_as_string = true
341
+ # bt.add_family "user" do |u|
342
+ # u.add_column "name", type: "STRING"
343
+ # end
344
+ # end
345
+ #
346
+ def add_column qualifier, as: nil, type: nil
347
+ frozen_check!
348
+ col = BigtableSource::Column.new
349
+ col.qualifier = qualifier
350
+ col.field_name = as if as
351
+ col.type = type if type
352
+ yield col if block_given?
353
+ @columns << col
354
+ col
355
+ end
356
+
357
+ ##
358
+ # Add a column to the column family to expose in the table schema
359
+ # that is specified as the `BYTES` type.
360
+ #
361
+ # @param [String] qualifier Qualifier of the column. See
362
+ # {BigtableSource::Column#qualifier}.
363
+ # @param [String] as A valid identifier to be used as the column
364
+ # field name if the qualifier is not a valid BigQuery field
365
+ # identifier (i.e. does not match `[a-zA-Z][a-zA-Z0-9_]*`). See
366
+ # {BigtableSource::Column#field_name}.
367
+ #
368
+ # @yield [column] a block for setting the column
369
+ # @yieldparam [BigtableSource::Column] column the column object
370
+ #
371
+ # @return [Array<BigtableSource::Column>]
372
+ #
373
+ # @example
374
+ # require "google/cloud/bigquery"
375
+ #
376
+ # bigquery = Google::Cloud::Bigquery.new
377
+ #
378
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
379
+ # bigtable_table = bigquery.external bigtable_url do |bt|
380
+ # bt.rowkey_as_string = true
381
+ # bt.add_family "user" do |u|
382
+ # u.add_bytes "avatar"
383
+ # end
384
+ # end
385
+ #
386
+ def add_bytes qualifier, as: nil
387
+ col = add_column qualifier, as: as, type: "BYTES"
388
+ yield col if block_given?
389
+ col
390
+ end
391
+
392
+ ##
393
+ # Add a column to the column family to expose in the table schema
394
+ # that is specified as the `STRING` type.
395
+ #
396
+ # @param [String] qualifier Qualifier of the column. See
397
+ # {BigtableSource::Column#qualifier}.
398
+ # @param [String] as A valid identifier to be used as the column
399
+ # field name if the qualifier is not a valid BigQuery field
400
+ # identifier (i.e. does not match `[a-zA-Z][a-zA-Z0-9_]*`). See
401
+ # {BigtableSource::Column#field_name}.
402
+ #
403
+ # @yield [column] a block for setting the column
404
+ # @yieldparam [BigtableSource::Column] column the column object
405
+ #
406
+ # @return [Array<BigtableSource::Column>]
407
+ #
408
+ # @example
409
+ # require "google/cloud/bigquery"
410
+ #
411
+ # bigquery = Google::Cloud::Bigquery.new
412
+ #
413
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
414
+ # bigtable_table = bigquery.external bigtable_url do |bt|
415
+ # bt.rowkey_as_string = true
416
+ # bt.add_family "user" do |u|
417
+ # u.add_string "name"
418
+ # end
419
+ # end
420
+ #
421
+ def add_string qualifier, as: nil
422
+ col = add_column qualifier, as: as, type: "STRING"
423
+ yield col if block_given?
424
+ col
425
+ end
426
+
427
+ ##
428
+ # Add a column to the column family to expose in the table schema
429
+ # that is specified as the `INTEGER` type.
430
+ #
431
+ # @param [String] qualifier Qualifier of the column. See
432
+ # {BigtableSource::Column#qualifier}.
433
+ # @param [String] as A valid identifier to be used as the column
434
+ # field name if the qualifier is not a valid BigQuery field
435
+ # identifier (i.e. does not match `[a-zA-Z][a-zA-Z0-9_]*`). See
436
+ # {BigtableSource::Column#field_name}.
437
+ #
438
+ # @yield [column] a block for setting the column
439
+ # @yieldparam [BigtableSource::Column] column the column object
440
+ #
441
+ # @return [Array<BigtableSource::Column>]
442
+ #
443
+ # @example
444
+ # require "google/cloud/bigquery"
445
+ #
446
+ # bigquery = Google::Cloud::Bigquery.new
447
+ #
448
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
449
+ # bigtable_table = bigquery.external bigtable_url do |bt|
450
+ # bt.rowkey_as_string = true
451
+ # bt.add_family "user" do |u|
452
+ # u.add_integer "age"
453
+ # end
454
+ # end
455
+ #
456
+ def add_integer qualifier, as: nil
457
+ col = add_column qualifier, as: as, type: "INTEGER"
458
+ yield col if block_given?
459
+ col
460
+ end
461
+
462
+ ##
463
+ # Add a column to the column family to expose in the table schema
464
+ # that is specified as the `FLOAT` type.
465
+ #
466
+ # @param [String] qualifier Qualifier of the column. See
467
+ # {BigtableSource::Column#qualifier}.
468
+ # @param [String] as A valid identifier to be used as the column
469
+ # field name if the qualifier is not a valid BigQuery field
470
+ # identifier (i.e. does not match `[a-zA-Z][a-zA-Z0-9_]*`). See
471
+ # {BigtableSource::Column#field_name}.
472
+ #
473
+ # @yield [column] a block for setting the column
474
+ # @yieldparam [BigtableSource::Column] column the column object
475
+ #
476
+ # @return [Array<BigtableSource::Column>]
477
+ #
478
+ # @example
479
+ # require "google/cloud/bigquery"
480
+ #
481
+ # bigquery = Google::Cloud::Bigquery.new
482
+ #
483
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
484
+ # bigtable_table = bigquery.external bigtable_url do |bt|
485
+ # bt.rowkey_as_string = true
486
+ # bt.add_family "user" do |u|
487
+ # u.add_float "score"
488
+ # end
489
+ # end
490
+ #
491
+ def add_float qualifier, as: nil
492
+ col = add_column qualifier, as: as, type: "FLOAT"
493
+ yield col if block_given?
494
+ col
495
+ end
496
+
497
+ ##
498
+ # Add a column to the column family to expose in the table schema
499
+ # that is specified as the `BOOLEAN` type.
500
+ #
501
+ # @param [String] qualifier Qualifier of the column. See
502
+ # {BigtableSource::Column#qualifier}.
503
+ # @param [String] as A valid identifier to be used as the column
504
+ # field name if the qualifier is not a valid BigQuery field
505
+ # identifier (i.e. does not match `[a-zA-Z][a-zA-Z0-9_]*`). See
506
+ # {BigtableSource::Column#field_name}.
507
+ #
508
+ # @yield [column] a block for setting the column
509
+ # @yieldparam [BigtableSource::Column] column the column object
510
+ #
511
+ # @return [Array<BigtableSource::Column>]
512
+ #
513
+ # @example
514
+ # require "google/cloud/bigquery"
515
+ #
516
+ # bigquery = Google::Cloud::Bigquery.new
517
+ #
518
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
519
+ # bigtable_table = bigquery.external bigtable_url do |bt|
520
+ # bt.rowkey_as_string = true
521
+ # bt.add_family "user" do |u|
522
+ # u.add_boolean "active"
523
+ # end
524
+ # end
525
+ #
526
+ def add_boolean qualifier, as: nil
527
+ col = add_column qualifier, as: as, type: "BOOLEAN"
528
+ yield col if block_given?
529
+ col
530
+ end
531
+
532
+ ##
533
+ # @private Google API Client object.
534
+ def to_gapi
535
+ @gapi.columns = @columns.map(&:to_gapi)
536
+ @gapi
537
+ end
538
+
539
+ ##
540
+ # @private Google API Client object.
541
+ def self.from_gapi gapi
542
+ new_fam = new
543
+ new_fam.instance_variable_set :@gapi, gapi
544
+ columns = Array(gapi.columns).map { |col_gapi| BigtableSource::Column.from_gapi col_gapi }
545
+ new_fam.instance_variable_set :@columns, columns
546
+ new_fam
547
+ end
548
+
549
+ ##
550
+ # @private
551
+ def freeze
552
+ @columns.map(&:freeze!)
553
+ @columns.freeze!
554
+ super
555
+ end
556
+
557
+ protected
558
+
559
+ def frozen_check!
560
+ return unless frozen?
561
+ raise ArgumentError, "Cannot modify external data source when frozen"
562
+ end
563
+ end
564
+
565
+ ##
566
+ # # BigtableSource::Column
567
+ #
568
+ # A Bigtable column to expose in the table schema along with its
569
+ # types.
570
+ #
571
+ # @example
572
+ # require "google/cloud/bigquery"
573
+ #
574
+ # bigquery = Google::Cloud::Bigquery.new
575
+ #
576
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
577
+ # bigtable_table = bigquery.external bigtable_url do |bt|
578
+ # bt.rowkey_as_string = true
579
+ # bt.add_family "user" do |u|
580
+ # u.add_string "name"
581
+ # u.add_string "email"
582
+ # u.add_integer "age"
583
+ # u.add_boolean "active"
584
+ # end
585
+ # end
586
+ #
587
+ # data = bigquery.query "SELECT * FROM my_ext_table",
588
+ # external: { my_ext_table: bigtable_table }
589
+ #
590
+ # # Iterate over the first page of results
591
+ # data.each do |row|
592
+ # puts row[:name]
593
+ # end
594
+ # # Retrieve the next page of results
595
+ # data = data.next if data.next?
596
+ #
597
+ class Column
598
+ ##
599
+ # @private Create an empty BigtableSource::Column object.
600
+ def initialize
601
+ @gapi = Google::Apis::BigqueryV2::BigtableColumn.new
602
+ end
603
+
604
+ ##
605
+ # Qualifier of the column. Columns in the parent column family that
606
+ # has this exact qualifier are exposed as `.` field. If the
607
+ # qualifier is valid UTF-8 string, it will be represented as a UTF-8
608
+ # string. Otherwise, it will represented as a ASCII-8BIT string.
609
+ #
610
+ # If the qualifier is not a valid BigQuery field identifier (does
611
+ # not match `[a-zA-Z][a-zA-Z0-9_]*`) a valid identifier must be
612
+ # provided as `field_name`.
613
+ #
614
+ # @return [String]
615
+ #
616
+ # @example
617
+ # require "google/cloud/bigquery"
618
+ #
619
+ # bigquery = Google::Cloud::Bigquery.new
620
+ #
621
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
622
+ # bigtable_table = bigquery.external bigtable_url do |bt|
623
+ # bt.add_family "user" do |u|
624
+ # u.add_string "name" do |col|
625
+ # col.qualifier # "user"
626
+ # col.qualifier = "User"
627
+ # col.qualifier # "User"
628
+ # end
629
+ # end
630
+ # end
631
+ #
632
+ def qualifier
633
+ @gapi.qualifier_string || Base64.strict_decode64(@gapi.qualifier_encoded.to_s)
634
+ end
635
+
636
+ ##
637
+ # Set the qualifier of the column. Columns in the parent column
638
+ # family that has this exact qualifier are exposed as `.` field.
639
+ # Values that are valid UTF-8 strings will be treated as such. All
640
+ # other values will be treated as `BINARY`.
641
+ #
642
+ # @param [String] new_qualifier New qualifier value
643
+ #
644
+ # @example
645
+ # require "google/cloud/bigquery"
646
+ #
647
+ # bigquery = Google::Cloud::Bigquery.new
648
+ #
649
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
650
+ # bigtable_table = bigquery.external bigtable_url do |bt|
651
+ # bt.add_family "user" do |u|
652
+ # u.add_string "name" do |col|
653
+ # col.qualifier # "user"
654
+ # col.qualifier = "User"
655
+ # col.qualifier # "User"
656
+ # end
657
+ # end
658
+ # end
659
+ #
660
+ def qualifier= new_qualifier
661
+ frozen_check!
662
+ raise ArgumentError if new_qualifier.nil?
663
+
664
+ utf8_qualifier = new_qualifier.encode Encoding::UTF_8
665
+ if utf8_qualifier.valid_encoding?
666
+ @gapi.qualifier_string = utf8_qualifier
667
+ if @gapi.instance_variables.include? :@qualifier_encoded
668
+ @gapi.remove_instance_variable :@qualifier_encoded
669
+ end
670
+ else
671
+ @gapi.qualifier_encoded = Base64.strict_encode64 new_qualifier
672
+ if @gapi.instance_variables.include? :@qualifier_string
673
+ @gapi.remove_instance_variable :@qualifier_string
674
+ end
675
+ end
676
+ rescue EncodingError
677
+ @gapi.qualifier_encoded = Base64.strict_encode64 new_qualifier
678
+ @gapi.remove_instance_variable :@qualifier_string if @gapi.instance_variables.include? :@qualifier_string
679
+ end
680
+
681
+ ##
682
+ # The encoding of the values when the type is not `STRING`.
683
+ #
684
+ # @return [String]
685
+ #
686
+ # @example
687
+ # require "google/cloud/bigquery"
688
+ #
689
+ # bigquery = Google::Cloud::Bigquery.new
690
+ #
691
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
692
+ # bigtable_table = bigquery.external bigtable_url do |bt|
693
+ # bt.add_family "user" do |u|
694
+ # u.add_bytes "name" do |col|
695
+ # col.encoding = "TEXT"
696
+ # col.encoding # "TEXT"
697
+ # end
698
+ # end
699
+ # end
700
+ #
701
+ def encoding
702
+ @gapi.encoding
703
+ end
704
+
705
+ ##
706
+ # Set the encoding of the values when the type is not `STRING`.
707
+ # Acceptable encoding values are:
708
+ #
709
+ # * `TEXT` - indicates values are alphanumeric text strings.
710
+ # * `BINARY` - indicates values are encoded using HBase
711
+ # `Bytes.toBytes` family of functions. This can be overridden on a
712
+ # column.
713
+ #
714
+ # @param [String] new_encoding New encoding value
715
+ #
716
+ # @example
717
+ # require "google/cloud/bigquery"
718
+ #
719
+ # bigquery = Google::Cloud::Bigquery.new
720
+ #
721
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
722
+ # bigtable_table = bigquery.external bigtable_url do |bt|
723
+ # bt.add_family "user" do |u|
724
+ # u.add_bytes "name" do |col|
725
+ # col.encoding = "TEXT"
726
+ # col.encoding # "TEXT"
727
+ # end
728
+ # end
729
+ # end
730
+ #
731
+ def encoding= new_encoding
732
+ frozen_check!
733
+ @gapi.encoding = new_encoding
734
+ end
735
+
736
+ ##
737
+ # If the qualifier is not a valid BigQuery field identifier (does
738
+ # not match `[a-zA-Z][a-zA-Z0-9_]*`) a valid identifier must be
739
+ # provided as the column field name and is used as field name in
740
+ # queries.
741
+ #
742
+ # @return [String]
743
+ #
744
+ # @example
745
+ # require "google/cloud/bigquery"
746
+ #
747
+ # bigquery = Google::Cloud::Bigquery.new
748
+ #
749
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
750
+ # bigtable_table = bigquery.external bigtable_url do |bt|
751
+ # bt.add_family "user" do |u|
752
+ # u.add_string "001_name", as: "user" do |col|
753
+ # col.field_name # "user"
754
+ # col.field_name = "User"
755
+ # col.field_name # "User"
756
+ # end
757
+ # end
758
+ # end
759
+ #
760
+ def field_name
761
+ @gapi.field_name
762
+ end
763
+
764
+ ##
765
+ # Sets the identifier to be used as the column field name in queries
766
+ # when the qualifier is not a valid BigQuery field identifier (does
767
+ # not match `[a-zA-Z][a-zA-Z0-9_]*`).
768
+ #
769
+ # @param [String] new_field_name New field_name value
770
+ #
771
+ # @example
772
+ # require "google/cloud/bigquery"
773
+ #
774
+ # bigquery = Google::Cloud::Bigquery.new
775
+ #
776
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
777
+ # bigtable_table = bigquery.external bigtable_url do |bt|
778
+ # bt.add_family "user" do |u|
779
+ # u.add_string "001_name", as: "user" do |col|
780
+ # col.field_name # "user"
781
+ # col.field_name = "User"
782
+ # col.field_name # "User"
783
+ # end
784
+ # end
785
+ # end
786
+ #
787
+ def field_name= new_field_name
788
+ frozen_check!
789
+ @gapi.field_name = new_field_name
790
+ end
791
+
792
+ ##
793
+ # Whether only the latest version of value in this column are
794
+ # exposed. Can also be set at the column family level. However, this
795
+ # value takes precedence when set at both levels.
796
+ #
797
+ # @return [Boolean]
798
+ #
799
+ # @example
800
+ # require "google/cloud/bigquery"
801
+ #
802
+ # bigquery = Google::Cloud::Bigquery.new
803
+ #
804
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
805
+ # bigtable_table = bigquery.external bigtable_url do |bt|
806
+ # bt.add_family "user" do |u|
807
+ # u.add_string "name" do |col|
808
+ # col.latest = true
809
+ # col.latest # true
810
+ # end
811
+ # end
812
+ # end
813
+ #
814
+ def latest
815
+ @gapi.only_read_latest
816
+ end
817
+
818
+ ##
819
+ # Set whether only the latest version of value in this column are
820
+ # exposed. Can also be set at the column family level. However, this
821
+ # value takes precedence when set at both levels.
822
+ #
823
+ # @param [Boolean] new_latest New latest value
824
+ #
825
+ # @example
826
+ # require "google/cloud/bigquery"
827
+ #
828
+ # bigquery = Google::Cloud::Bigquery.new
829
+ #
830
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
831
+ # bigtable_table = bigquery.external bigtable_url do |bt|
832
+ # bt.add_family "user" do |u|
833
+ # u.add_string "name" do |col|
834
+ # col.latest = true
835
+ # col.latest # true
836
+ # end
837
+ # end
838
+ # end
839
+ #
840
+ def latest= new_latest
841
+ frozen_check!
842
+ @gapi.only_read_latest = new_latest
843
+ end
844
+
845
+ ##
846
+ # The type to convert the value in cells of this column. The values
847
+ # are expected to be encoded using HBase `Bytes.toBytes` function
848
+ # when using the `BINARY` encoding value. The following BigQuery
849
+ # types are allowed:
850
+ #
851
+ # * `BYTES`
852
+ # * `STRING`
853
+ # * `INTEGER`
854
+ # * `FLOAT`
855
+ # * `BOOLEAN`
856
+ #
857
+ # Default type is `BYTES`. Can also be set at the column family
858
+ # level. However, this value takes precedence when set at both
859
+ # levels.
860
+ #
861
+ # @return [String]
862
+ #
863
+ # @example
864
+ # require "google/cloud/bigquery"
865
+ #
866
+ # bigquery = Google::Cloud::Bigquery.new
867
+ #
868
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
869
+ # bigtable_table = bigquery.external bigtable_url do |bt|
870
+ # bt.add_family "user" do |u|
871
+ # u.add_string "name" do |col|
872
+ # col.type # "STRING"
873
+ # end
874
+ # end
875
+ # end
876
+ #
877
+ def type
878
+ @gapi.type
879
+ end
880
+
881
+ ##
882
+ # Set the type to convert the value in cells of this column. The
883
+ # values are expected to be encoded using HBase `Bytes.toBytes`
884
+ # function when using the `BINARY` encoding value. The following
885
+ # BigQuery types are allowed:
886
+ #
887
+ # * `BYTES`
888
+ # * `STRING`
889
+ # * `INTEGER`
890
+ # * `FLOAT`
891
+ # * `BOOLEAN`
892
+ #
893
+ # Default type is `BYTES`. Can also be set at the column family
894
+ # level. However, this value takes precedence when set at both
895
+ # levels.
896
+ #
897
+ # @param [String] new_type New type value
898
+ #
899
+ # @example
900
+ # require "google/cloud/bigquery"
901
+ #
902
+ # bigquery = Google::Cloud::Bigquery.new
903
+ #
904
+ # bigtable_url = "https://googleapis.com/bigtable/projects/..."
905
+ # bigtable_table = bigquery.external bigtable_url do |bt|
906
+ # bt.add_family "user" do |u|
907
+ # u.add_string "name" do |col|
908
+ # col.type # "STRING"
909
+ # col.type = "BYTES"
910
+ # col.type # "BYTES"
911
+ # end
912
+ # end
913
+ # end
914
+ #
915
+ def type= new_type
916
+ frozen_check!
917
+ @gapi.type = new_type
918
+ end
919
+
920
+ ##
921
+ # @private Google API Client object.
922
+ def to_gapi
923
+ @gapi
924
+ end
925
+
926
+ ##
927
+ # @private Google API Client object.
928
+ def self.from_gapi gapi
929
+ new_col = new
930
+ new_col.instance_variable_set :@gapi, gapi
931
+ new_col
932
+ end
933
+
934
+ protected
935
+
936
+ def frozen_check!
937
+ return unless frozen?
938
+ raise ArgumentError, "Cannot modify external data source when frozen"
939
+ end
940
+ end
941
+ end
942
+ end
943
+ end
944
+ end
945
+ end