Skip to content

Commit 2cb1d48

Browse files
bigquery_table - add support for external_data_configuration.bigtable_options (#10557) (#18181)
[upstream:75e558661607f3241ecf7ac4007716ecc2776e50] Signed-off-by: Modular Magician <magic-modules@google.com>
1 parent 93a6b82 commit 2cb1d48

File tree

3 files changed

+392
-4
lines changed

3 files changed

+392
-4
lines changed

google/services/bigquery/resource_bigquery_table.go

Lines changed: 263 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ func ResourceBigQueryTable() *schema.Resource {
515515
"source_format": {
516516
Type: schema.TypeString,
517517
Optional: true,
518-
Description: ` Please see sourceFormat under ExternalDataConfiguration in Bigquery's public API documentation (https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#externaldataconfiguration) for supported formats. To use "GOOGLE_SHEETS" the scopes must include "googleapis.com/auth/drive.readonly".`,
518+
Description: `Please see sourceFormat under ExternalDataConfiguration in Bigquery's public API documentation (https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#externaldataconfiguration) for supported formats. To use "GOOGLE_SHEETS" the scopes must include "googleapis.com/auth/drive.readonly".`,
519519
ValidateFunc: validation.StringInSlice([]string{
520520
"CSV", "GOOGLE_SHEETS", "NEWLINE_DELIMITED_JSON", "AVRO", "ICEBERG", "DATASTORE_BACKUP", "PARQUET", "ORC", "BIGTABLE",
521521
}, false),
@@ -621,7 +621,7 @@ func ResourceBigQueryTable() *schema.Resource {
621621
Type: schema.TypeList,
622622
Optional: true,
623623
MaxItems: 1,
624-
Description: `Additional properties to set if sourceFormat is set to JSON."`,
624+
Description: `Additional properties to set if sourceFormat is set to JSON.`,
625625
Elem: &schema.Resource{
626626
Schema: map[string]*schema.Schema{
627627
"encoding": {
@@ -642,11 +642,105 @@ func ResourceBigQueryTable() *schema.Resource {
642642
Description: `Load option to be used together with sourceFormat newline-delimited JSON to indicate that a variant of JSON is being loaded. To load newline-delimited GeoJSON, specify GEOJSON (and sourceFormat must be set to NEWLINE_DELIMITED_JSON).`,
643643
},
644644

645+
"bigtable_options": {
646+
Type: schema.TypeList,
647+
Optional: true,
648+
MaxItems: 1,
649+
Description: `Additional options if sourceFormat is set to BIGTABLE.`,
650+
Elem: &schema.Resource{
651+
Schema: map[string]*schema.Schema{
652+
"column_family": {
653+
Type: schema.TypeList,
654+
Optional: true,
655+
Description: `A list of column families to expose in the table schema along with their types. This list restricts the column families that can be referenced in queries and specifies their value types. You can use this list to do type conversions - see the 'type' field for more details. If you leave this list empty, all column families are present in the table schema and their values are read as BYTES. During a query only the column families referenced in that query are read from Bigtable.`,
656+
Elem: &schema.Resource{
657+
Schema: map[string]*schema.Schema{
658+
"column": {
659+
Type: schema.TypeList,
660+
Optional: true,
661+
Description: `A List of columns that should be exposed as individual fields as opposed to a list of (column name, value) pairs. All columns whose qualifier matches a qualifier in this list can be accessed as Other columns can be accessed as a list through column field`,
662+
Elem: &schema.Resource{
663+
Schema: map[string]*schema.Schema{
664+
"qualifier_encoded": {
665+
Type: schema.TypeString,
666+
Optional: true,
667+
Description: `Qualifier of the column. Columns in the parent column family that has this exact qualifier are exposed as . field. If the qualifier is valid UTF-8 string, it can be specified in the qualifierString field. Otherwise, a base-64 encoded value must be set to qualifierEncoded. The column field name is the same as the column qualifier. However, if the qualifier is not a valid BigQuery field identifier i.e. does not match [a-zA-Z][a-zA-Z0-9_]*, a valid identifier must be provided as fieldName.`,
668+
},
669+
"qualifier_string": {
670+
Type: schema.TypeString,
671+
Optional: true,
672+
Description: `Qualifier string.`,
673+
},
674+
"field_name": {
675+
Type: schema.TypeString,
676+
Optional: true,
677+
Description: `If the qualifier is not a valid BigQuery field identifier i.e. does not match [a-zA-Z][a-zA-Z0-9_]*, a valid identifier must be provided as the column field name and is used as field name in queries.`,
678+
},
679+
"type": {
680+
Type: schema.TypeString,
681+
Optional: true,
682+
Description: `The type to convert the value in cells of this column. The values are expected to be encoded using HBase Bytes.toBytes function when using the BINARY encoding value. Following BigQuery types are allowed (case-sensitive): "BYTES", "STRING", "INTEGER", "FLOAT", "BOOLEAN", "JSON", Default type is "BYTES". 'type' can also be set at the column family level. However, the setting at this level takes precedence if 'type' is set at both levels.`,
683+
},
684+
"encoding": {
685+
Type: schema.TypeString,
686+
Optional: true,
687+
Description: `The encoding of the values when the type is not STRING. Acceptable encoding values are: TEXT - indicates values are alphanumeric text strings. BINARY - indicates values are encoded using HBase Bytes.toBytes family of functions. 'encoding' can also be set at the column family level. However, the setting at this level takes precedence if 'encoding' is set at both levels.`,
688+
},
689+
"only_read_latest": {
690+
Type: schema.TypeBool,
691+
Optional: true,
692+
Description: `If this is set, only the latest version of value in this column are exposed. 'onlyReadLatest' can also be set at the column family level. However, the setting at this level takes precedence if 'onlyReadLatest' is set at both levels.`,
693+
},
694+
},
695+
},
696+
},
697+
"family_id": {
698+
Type: schema.TypeString,
699+
Optional: true,
700+
Description: `Identifier of the column family.`,
701+
},
702+
"type": {
703+
Type: schema.TypeString,
704+
Optional: true,
705+
Description: `The type to convert the value in cells of this column family. The values are expected to be encoded using HBase Bytes.toBytes function when using the BINARY encoding value. Following BigQuery types are allowed (case-sensitive): "BYTES", "STRING", "INTEGER", "FLOAT", "BOOLEAN", "JSON". Default type is BYTES. This can be overridden for a specific column by listing that column in 'columns' and specifying a type for it.`,
706+
},
707+
"encoding": {
708+
Type: schema.TypeString,
709+
Optional: true,
710+
Description: `The encoding of the values when the type is not STRING. Acceptable encoding values are: TEXT - indicates values are alphanumeric text strings. BINARY - indicates values are encoded using HBase Bytes.toBytes family of functions. This can be overridden for a specific column by listing that column in 'columns' and specifying an encoding for it.`,
711+
},
712+
"only_read_latest": {
713+
Type: schema.TypeBool,
714+
Optional: true,
715+
Description: `If this is set only the latest version of value are exposed for all columns in this column family. This can be overridden for a specific column by listing that column in 'columns' and specifying a different setting for that column.`,
716+
},
717+
},
718+
},
719+
},
720+
"ignore_unspecified_column_families": {
721+
Type: schema.TypeBool,
722+
Optional: true,
723+
Description: `If field is true, then the column families that are not specified in columnFamilies list are not exposed in the table schema. Otherwise, they are read with BYTES type values. The default value is false.`,
724+
},
725+
"read_rowkey_as_string": {
726+
Type: schema.TypeBool,
727+
Optional: true,
728+
Description: `If field is true, then the rowkey column families will be read and converted to string. Otherwise they are read with BYTES type values and users need to manually cast them with CAST if necessary. The default value is false.`,
729+
},
730+
"output_column_families_as_json": {
731+
Type: schema.TypeBool,
732+
Optional: true,
733+
Description: `If field is true, then each column family will be read as a single JSON column. Otherwise they are read as a repeated cell structure containing timestamp/value tuples. The default value is false.`,
734+
},
735+
},
736+
},
737+
},
738+
645739
"parquet_options": {
646740
Type: schema.TypeList,
647741
Optional: true,
648742
MaxItems: 1,
649-
Description: `Additional properties to set if sourceFormat is set to PARQUET."`,
743+
Description: `Additional properties to set if sourceFormat is set to PARQUET.`,
650744
Elem: &schema.Resource{
651745
Schema: map[string]*schema.Schema{
652746
"enum_as_string": {
@@ -675,7 +769,7 @@ func ResourceBigQueryTable() *schema.Resource {
675769
"range": {
676770
Type: schema.TypeString,
677771
Optional: true,
678-
Description: `Range of a sheet to query from. Only used when non-empty. At least one of range or skip_leading_rows must be set. Typical format: "sheet_name!top_left_cell_id:bottom_right_cell_id" For example: "sheet1!A1:B20"`,
772+
Description: `Range of a sheet to query from. Only used when non-empty. At least one of range or skip_leading_rows must be set. Typical format: "sheet_name!top_left_cell_id:bottom_right_cell_id" For example: "sheet1!A1:B20`,
679773
AtLeastOneOf: []string{
680774
"external_data_configuration.0.google_sheets_options.0.skip_leading_rows",
681775
"external_data_configuration.0.google_sheets_options.0.range",
@@ -1873,6 +1967,9 @@ func expandExternalDataConfiguration(cfg interface{}) (*bigquery.ExternalDataCon
18731967
if v, ok := raw["json_options"]; ok {
18741968
edc.JsonOptions = expandJsonOptions(v)
18751969
}
1970+
if v, ok := raw["bigtable_options"]; ok {
1971+
edc.BigtableOptions = expandBigtableOptions(v)
1972+
}
18761973
if v, ok := raw["google_sheets_options"]; ok {
18771974
edc.GoogleSheetsOptions = expandGoogleSheetsOptions(v)
18781975
}
@@ -1962,6 +2059,10 @@ func flattenExternalDataConfiguration(edc *bigquery.ExternalDataConfiguration) (
19622059
result["json_options"] = flattenJsonOptions(edc.JsonOptions)
19632060
}
19642061

2062+
if edc.BigtableOptions != nil {
2063+
result["bigtable_options"] = flattenBigtableOptions(edc.BigtableOptions)
2064+
}
2065+
19652066
if edc.IgnoreUnknownValues {
19662067
result["ignore_unknown_values"] = edc.IgnoreUnknownValues
19672068
}
@@ -2192,6 +2293,164 @@ func flattenParquetOptions(opts *bigquery.ParquetOptions) []map[string]interface
21922293
return []map[string]interface{}{result}
21932294
}
21942295

2296+
func expandBigtableOptions(configured interface{}) *bigquery.BigtableOptions {
2297+
if len(configured.([]interface{})) == 0 {
2298+
return nil
2299+
}
2300+
2301+
raw := configured.([]interface{})[0].(map[string]interface{})
2302+
opts := &bigquery.BigtableOptions{}
2303+
2304+
crs := []*bigquery.BigtableColumnFamily{}
2305+
if v, ok := raw["column_family"]; ok {
2306+
for _, columnFamily := range v.([]interface{}) {
2307+
crs = append(crs, expandBigtableColumnFamily(columnFamily))
2308+
}
2309+
2310+
if len(crs) > 0 {
2311+
opts.ColumnFamilies = crs
2312+
}
2313+
}
2314+
2315+
if v, ok := raw["ignore_unspecified_column_families"]; ok {
2316+
opts.IgnoreUnspecifiedColumnFamilies = v.(bool)
2317+
}
2318+
2319+
if v, ok := raw["read_rowkey_as_string"]; ok {
2320+
opts.ReadRowkeyAsString = v.(bool)
2321+
}
2322+
2323+
if v, ok := raw["output_column_families_as_json"]; ok {
2324+
opts.OutputColumnFamiliesAsJson = v.(bool)
2325+
}
2326+
2327+
return opts
2328+
}
2329+
2330+
func flattenBigtableOptions(opts *bigquery.BigtableOptions) []map[string]interface{} {
2331+
result := map[string]interface{}{}
2332+
2333+
if opts.ColumnFamilies != nil {
2334+
result["column_family"] = flattenBigtableColumnFamily(opts.ColumnFamilies)
2335+
}
2336+
2337+
if opts.IgnoreUnspecifiedColumnFamilies {
2338+
result["ignore_unspecified_column_families"] = opts.IgnoreUnspecifiedColumnFamilies
2339+
}
2340+
2341+
if opts.ReadRowkeyAsString {
2342+
result["read_rowkey_as_string"] = opts.ReadRowkeyAsString
2343+
}
2344+
2345+
if opts.OutputColumnFamiliesAsJson {
2346+
result["output_column_families_as_json"] = opts.OutputColumnFamiliesAsJson
2347+
}
2348+
2349+
return []map[string]interface{}{result}
2350+
}
2351+
2352+
func expandBigtableColumnFamily(configured interface{}) *bigquery.BigtableColumnFamily {
2353+
raw := configured.(map[string]interface{})
2354+
2355+
opts := &bigquery.BigtableColumnFamily{}
2356+
2357+
crs := []*bigquery.BigtableColumn{}
2358+
if v, ok := raw["column"]; ok {
2359+
for _, column := range v.([]interface{}) {
2360+
crs = append(crs, expandBigtableColumn(column))
2361+
}
2362+
2363+
if len(crs) > 0 {
2364+
opts.Columns = crs
2365+
}
2366+
}
2367+
2368+
if v, ok := raw["family_id"]; ok {
2369+
opts.FamilyId = v.(string)
2370+
}
2371+
2372+
if v, ok := raw["type"]; ok {
2373+
opts.Type = v.(string)
2374+
}
2375+
2376+
if v, ok := raw["encoding"]; ok {
2377+
opts.Encoding = v.(string)
2378+
}
2379+
2380+
if v, ok := raw["only_read_latest"]; ok {
2381+
opts.OnlyReadLatest = v.(bool)
2382+
}
2383+
2384+
return opts
2385+
}
2386+
2387+
func flattenBigtableColumnFamily(edc []*bigquery.BigtableColumnFamily) []map[string]interface{} {
2388+
results := []map[string]interface{}{}
2389+
2390+
for _, fr := range edc {
2391+
result := map[string]interface{}{}
2392+
if fr.Columns != nil {
2393+
result["column"] = flattenBigtableColumn(fr.Columns)
2394+
}
2395+
result["family_id"] = fr.FamilyId
2396+
result["type"] = fr.Type
2397+
result["encoding"] = fr.Encoding
2398+
result["only_read_latest"] = fr.OnlyReadLatest
2399+
results = append(results, result)
2400+
}
2401+
2402+
return results
2403+
}
2404+
2405+
func expandBigtableColumn(configured interface{}) *bigquery.BigtableColumn {
2406+
raw := configured.(map[string]interface{})
2407+
2408+
opts := &bigquery.BigtableColumn{}
2409+
2410+
if v, ok := raw["qualifier_encoded"]; ok {
2411+
opts.QualifierEncoded = v.(string)
2412+
}
2413+
2414+
if v, ok := raw["qualifier_string"]; ok {
2415+
opts.QualifierString = v.(string)
2416+
}
2417+
2418+
if v, ok := raw["field_name"]; ok {
2419+
opts.FieldName = v.(string)
2420+
}
2421+
2422+
if v, ok := raw["type"]; ok {
2423+
opts.Type = v.(string)
2424+
}
2425+
2426+
if v, ok := raw["encoding"]; ok {
2427+
opts.Encoding = v.(string)
2428+
}
2429+
2430+
if v, ok := raw["only_read_latest"]; ok {
2431+
opts.OnlyReadLatest = v.(bool)
2432+
}
2433+
2434+
return opts
2435+
}
2436+
2437+
func flattenBigtableColumn(edc []*bigquery.BigtableColumn) []map[string]interface{} {
2438+
results := []map[string]interface{}{}
2439+
2440+
for _, fr := range edc {
2441+
result := map[string]interface{}{}
2442+
result["qualifier_encoded"] = fr.QualifierEncoded
2443+
result["qualifier_string"] = fr.QualifierString
2444+
result["field_name"] = fr.FieldName
2445+
result["type"] = fr.Type
2446+
result["encoding"] = fr.Encoding
2447+
result["only_read_latest"] = fr.OnlyReadLatest
2448+
results = append(results, result)
2449+
}
2450+
2451+
return results
2452+
}
2453+
21952454
func expandJsonOptions(configured interface{}) *bigquery.JsonOptions {
21962455
if len(configured.([]interface{})) == 0 {
21972456
return nil

0 commit comments

Comments
 (0)