Skip to content

Commit de7b191

Browse files
Promote external catalog table options and foreign type info and definition to google_bigquery_table GA (#13607) (#22302)
[upstream:9c4203d9badc4a950c68ccdf93bcaa279cf6b57b] Signed-off-by: Modular Magician <[email protected]>
1 parent 7a641b8 commit de7b191

File tree

4 files changed

+544
-60
lines changed

4 files changed

+544
-60
lines changed

.changelog/13607.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
bigquery: added `external_catalog_table_options` and `schema_foreign_type_info` fields to `google_bigquery_table` resource (GA)
3+
```

google/services/bigquery/resource_bigquery_table.go

Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,13 @@ func jsonCompareWithMapKeyOverride(key string, a, b interface{}, compareMapKeyVa
9797
for subKey := range objectB {
9898
unionOfKeys[subKey] = true
9999
}
100+
101+
// Disregard "type" and "fields" if "foreignTypeDefinition" is present since they may have been modified by the server.
102+
if _, ok := unionOfKeys["foreignTypeDefinition"]; ok {
103+
delete(unionOfKeys, "type")
104+
delete(unionOfKeys, "fields")
105+
}
106+
100107
for subKey := range unionOfKeys {
101108
eq := compareMapKeyVal(subKey, objectA, objectB)
102109
if !eq {
@@ -324,6 +331,13 @@ func resourceBigQueryTableSchemaIsChangeable(old, new interface{}, isExternalTab
324331
for key := range objectNew {
325332
unionOfKeys[key] = true
326333
}
334+
335+
// Disregard "type" and "fields" if "foreignTypeDefinition" is present since they may have been modified by the server.
336+
if _, ok := unionOfKeys["foreignTypeDefinition"]; ok {
337+
delete(unionOfKeys, "type")
338+
delete(unionOfKeys, "fields")
339+
}
340+
327341
for key := range unionOfKeys {
328342
valOld := objectOld[key]
329343
valNew := objectNew[key]
@@ -994,6 +1008,24 @@ func ResourceBigQueryTable() *schema.Resource {
9941008
DiffSuppressFunc: bigQueryTableSchemaDiffSuppress,
9951009
Description: `A JSON schema for the table.`,
9961010
},
1011+
// SchemaForeignTypeInfo: [Optional] Specifies metadata of the foreign data type definition in field schema.
1012+
"schema_foreign_type_info": {
1013+
Type: schema.TypeList,
1014+
Optional: true,
1015+
ForceNew: true,
1016+
MaxItems: 1,
1017+
Description: "Specifies metadata of the foreign data type definition in field schema.",
1018+
Elem: &schema.Resource{
1019+
Schema: map[string]*schema.Schema{
1020+
// TypeSystem: [Required] Specifies the system which defines the foreign data type.
1021+
"type_system": {
1022+
Type: schema.TypeString,
1023+
Required: true,
1024+
Description: `Specifies the system which defines the foreign data type.`,
1025+
},
1026+
},
1027+
},
1028+
},
9971029
// View: [Optional] If specified, configures this table as a view.
9981030
"view": {
9991031
Type: schema.TypeList,
@@ -1459,6 +1491,90 @@ func ResourceBigQueryTable() *schema.Resource {
14591491
Elem: &schema.Schema{Type: schema.TypeString},
14601492
Description: `The tags attached to this table. Tag keys are globally unique. Tag key is expected to be in the namespaced format, for example "123456789012/environment" where 123456789012 is the ID of the parent organization or project resource for this tag key. Tag value is expected to be the short name, for example "Production".`,
14611493
},
1494+
// ExternalCatalogTableOptions: [Optional] Options defining open source compatible table.
1495+
"external_catalog_table_options": {
1496+
Type: schema.TypeList,
1497+
Optional: true,
1498+
MaxItems: 1,
1499+
Description: `Options defining open source compatible table.`,
1500+
Elem: &schema.Resource{
1501+
Schema: map[string]*schema.Schema{
1502+
// Parameters: [Optional] The parameters of the table.
1503+
"parameters": {
1504+
Type: schema.TypeMap,
1505+
Optional: true,
1506+
Elem: &schema.Schema{Type: schema.TypeString},
1507+
Description: `A map of key value pairs defining the parameters and properties of the open source table. Corresponds with hive meta store table parameters. Maximum size of 4Mib.`,
1508+
},
1509+
// StorageDescriptor: [Optional] A storage descriptor containing information about the physical storage of this table.
1510+
"storage_descriptor": {
1511+
Type: schema.TypeList,
1512+
Optional: true,
1513+
MaxItems: 1,
1514+
Description: `A storage descriptor containing information about the physical storage of this table.`,
1515+
Elem: &schema.Resource{
1516+
Schema: map[string]*schema.Schema{
1517+
// LocationUri: [Optional] The physical location of the table (e.g. 'gs://spark-dataproc-data/pangea-data/case_sensitive/' or 'gs://spark-dataproc-data/pangea-data/*'). The maximum length is 2056 bytes.
1518+
"location_uri": {
1519+
Type: schema.TypeString,
1520+
Optional: true,
1521+
Description: `The physical location of the table (e.g. 'gs://spark-dataproc-data/pangea-data/case_sensitive/' or 'gs://spark-dataproc-data/pangea-data/*'). The maximum length is 2056 bytes.`,
1522+
},
1523+
// InputFormat: [Optional] Specifies the fully qualified class name of the InputFormat (e.g. "org.apache.hadoop.hive.ql.io.orc.OrcInputFormat"). The maximum length is 128 characters.
1524+
"input_format": {
1525+
Type: schema.TypeString,
1526+
Optional: true,
1527+
Description: `Specifies the fully qualified class name of the InputFormat (e.g. "org.apache.hadoop.hive.ql.io.orc.OrcInputFormat"). The maximum length is 128 characters.`,
1528+
},
1529+
// OutputFormat: [Optional] Specifies the fully qualified class name of the OutputFormat (e.g. "org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat"). The maximum length is 128 characters.
1530+
"output_format": {
1531+
Type: schema.TypeString,
1532+
Optional: true,
1533+
Description: `Specifies the fully qualified class name of the OutputFormat (e.g. "org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat"). The maximum length is 128 characters.`,
1534+
},
1535+
// SerdeInfo: [Optional] Serializer and deserializer information.
1536+
"serde_info": {
1537+
Type: schema.TypeList,
1538+
Optional: true,
1539+
MaxItems: 1,
1540+
Description: `Serializer and deserializer information.`,
1541+
Elem: &schema.Resource{
1542+
Schema: map[string]*schema.Schema{
1543+
// Name: [Optional] Name of the SerDe. The maximum length is 256 characters.
1544+
"name": {
1545+
Type: schema.TypeString,
1546+
Optional: true,
1547+
Description: `Name of the SerDe. The maximum length is 256 characters.`,
1548+
},
1549+
// SerializationLibrary: [Required] Specifies a fully-qualified class name of the serialization library that is responsible for the translation of data between table representation and the underlying low-level input and output format structures. The maximum length is 256 characters.
1550+
"serialization_library": {
1551+
Type: schema.TypeString,
1552+
Required: true,
1553+
Description: `Specifies a fully-qualified class name of the serialization library that is responsible for the translation of data between table representation and the underlying low-level input and output format structures. The maximum length is 256 characters.`,
1554+
},
1555+
// Parameters: [Optional] Key-value pairs that define the initialization parameters for the serialization library. Maximum size 10 Kib.
1556+
"parameters": {
1557+
Type: schema.TypeMap,
1558+
Optional: true,
1559+
Elem: &schema.Schema{Type: schema.TypeString},
1560+
Description: `Key-value pairs that define the initialization parameters for the serialization library. Maximum size 10 Kib.`,
1561+
},
1562+
},
1563+
},
1564+
},
1565+
},
1566+
},
1567+
},
1568+
// ConnectionId: [Optional] The connection specifying the credentials to be used to read external storage, such as Azure Blob, Cloud Storage, or S3. The connection is needed to read the open source table from BigQuery Engine. The connection_id can have the form `<project_id>.<location_id>.<connection_id>` or `projects/<project_id>/locations/<location_id>/connections/<connection_id>`.
1569+
"connection_id": {
1570+
Type: schema.TypeString,
1571+
Optional: true,
1572+
DiffSuppressFunc: bigQueryTableConnectionIdSuppress,
1573+
Description: `The connection specifying the credentials to be used to read external storage, such as Azure Blob, Cloud Storage, or S3. The connection is needed to read the open source table from BigQuery Engine. The connection_id can have the form <project_id>.<location_id>.<connection_id> or projects/<project_id>/locations/<location_id>/connections/<connection_id>.`,
1574+
},
1575+
},
1576+
},
1577+
},
14621578
},
14631579
UseJSONNumber: true,
14641580
}
@@ -1547,6 +1663,13 @@ func resourceTable(d *schema.ResourceData, meta interface{}) (*bigquery.Table, e
15471663
}
15481664
table.Schema = schema
15491665
}
1666+
1667+
if v, ok := d.GetOk("schema_foreign_type_info"); ok {
1668+
if table.Schema != nil {
1669+
table.Schema.ForeignTypeInfo = expandForeignTypeInfo(v)
1670+
}
1671+
}
1672+
15501673
if v, ok := d.GetOk("time_partitioning"); ok {
15511674
table.TimePartitioning = expandTimePartitioning(v)
15521675
}
@@ -1581,6 +1704,11 @@ func resourceTable(d *schema.ResourceData, meta interface{}) (*bigquery.Table, e
15811704
}
15821705

15831706
table.ResourceTags = tpgresource.ExpandStringMap(d, "resource_tags")
1707+
1708+
if v, ok := d.GetOk("external_catalog_table_options"); ok {
1709+
table.ExternalCatalogTableOptions = expandExternalCatalogTableOptions(v)
1710+
}
1711+
15841712
return table, nil
15851713
}
15861714

@@ -1848,6 +1976,12 @@ func resourceBigQueryTableRead(d *schema.ResourceData, meta interface{}) error {
18481976
if err := d.Set("schema", schema); err != nil {
18491977
return fmt.Errorf("Error setting schema: %s", err)
18501978
}
1979+
if res.Schema.ForeignTypeInfo != nil {
1980+
foreignTypeInfo := flattenForeignTypeInfo(res.Schema.ForeignTypeInfo)
1981+
if err := d.Set("schema_foreign_type_info", foreignTypeInfo); err != nil {
1982+
return fmt.Errorf("Error setting schema_foreign_type_info: %s", err)
1983+
}
1984+
}
18511985
}
18521986

18531987
if res.View != nil {
@@ -1902,6 +2036,15 @@ func resourceBigQueryTableRead(d *schema.ResourceData, meta interface{}) error {
19022036
return fmt.Errorf("Error setting table replication info: %s", err)
19032037
}
19042038
}
2039+
2040+
if res.ExternalCatalogTableOptions != nil {
2041+
externalCatalogTableOptions := flattenExternalCatalogTableOptions(res.ExternalCatalogTableOptions)
2042+
2043+
if err := d.Set("external_catalog_table_options", externalCatalogTableOptions); err != nil {
2044+
return fmt.Errorf("Error setting external_catalog_table_options: %s", err)
2045+
}
2046+
}
2047+
19052048
return nil
19062049
}
19072050

@@ -2648,6 +2791,31 @@ func schemaHasRequiredFields(schema *bigquery.TableSchema) bool {
26482791
}
26492792
return false
26502793
}
2794+
2795+
func expandForeignTypeInfo(configured interface{}) *bigquery.ForeignTypeInfo {
2796+
if len(configured.([]interface{})) == 0 {
2797+
return nil
2798+
}
2799+
2800+
raw := configured.([]interface{})[0].(map[string]interface{})
2801+
fti := &bigquery.ForeignTypeInfo{}
2802+
2803+
if v, ok := raw["type_system"]; ok {
2804+
fti.TypeSystem = v.(string)
2805+
}
2806+
2807+
return fti
2808+
}
2809+
2810+
func flattenForeignTypeInfo(fti *bigquery.ForeignTypeInfo) []map[string]interface{} {
2811+
if fti == nil {
2812+
return nil
2813+
}
2814+
2815+
result := map[string]interface{}{"type_system": fti.TypeSystem}
2816+
return []map[string]interface{}{result}
2817+
}
2818+
26512819
func expandTimePartitioning(configured interface{}) *bigquery.TimePartitioning {
26522820
raw := configured.([]interface{})[0].(map[string]interface{})
26532821
tp := &bigquery.TimePartitioning{Type: raw["type"].(string)}
@@ -3053,6 +3221,154 @@ func flattenTableReplicationInfo(tableReplicationInfo map[string]interface{}) []
30533221

30543222
return []map[string]interface{}{result}
30553223
}
3224+
3225+
func expandExternalCatalogTableOptions(configured interface{}) *bigquery.ExternalCatalogTableOptions {
3226+
if len(configured.([]interface{})) == 0 {
3227+
return nil
3228+
}
3229+
3230+
raw := configured.([]interface{})[0].(map[string]interface{})
3231+
ecto := &bigquery.ExternalCatalogTableOptions{}
3232+
3233+
if v, ok := raw["parameters"]; ok {
3234+
parameters := map[string]string{}
3235+
3236+
for k, v := range v.(map[string]interface{}) {
3237+
parameters[k] = v.(string)
3238+
}
3239+
3240+
ecto.Parameters = parameters
3241+
}
3242+
3243+
if v, ok := raw["storage_descriptor"]; ok {
3244+
ecto.StorageDescriptor = expandStorageDescriptor(v)
3245+
}
3246+
3247+
if v, ok := raw["connection_id"]; ok {
3248+
ecto.ConnectionId = v.(string)
3249+
}
3250+
3251+
return ecto
3252+
}
3253+
3254+
func flattenExternalCatalogTableOptions(ecto *bigquery.ExternalCatalogTableOptions) []map[string]interface{} {
3255+
if ecto == nil {
3256+
return nil
3257+
}
3258+
3259+
result := map[string]interface{}{}
3260+
3261+
if ecto.Parameters != nil {
3262+
result["parameters"] = ecto.Parameters
3263+
}
3264+
3265+
if ecto.StorageDescriptor != nil {
3266+
result["storage_descriptor"] = flattenStorageDescriptor(ecto.StorageDescriptor)
3267+
}
3268+
3269+
if ecto.ConnectionId != "" {
3270+
result["connection_id"] = ecto.ConnectionId
3271+
}
3272+
3273+
return []map[string]interface{}{result}
3274+
}
3275+
3276+
func expandStorageDescriptor(configured interface{}) *bigquery.StorageDescriptor {
3277+
if len(configured.([]interface{})) == 0 {
3278+
return nil
3279+
}
3280+
3281+
raw := configured.([]interface{})[0].(map[string]interface{})
3282+
sd := &bigquery.StorageDescriptor{}
3283+
3284+
if v, ok := raw["location_uri"]; ok {
3285+
sd.LocationUri = v.(string)
3286+
}
3287+
3288+
if v, ok := raw["input_format"]; ok {
3289+
sd.InputFormat = v.(string)
3290+
}
3291+
3292+
if v, ok := raw["output_format"]; ok {
3293+
sd.OutputFormat = v.(string)
3294+
}
3295+
3296+
if v, ok := raw["serde_info"]; ok {
3297+
sd.SerdeInfo = expandSerDeInfo(v)
3298+
}
3299+
3300+
return sd
3301+
}
3302+
3303+
func flattenStorageDescriptor(sd *bigquery.StorageDescriptor) []map[string]interface{} {
3304+
if sd == nil {
3305+
return nil
3306+
}
3307+
3308+
result := map[string]interface{}{}
3309+
3310+
if sd.LocationUri != "" {
3311+
result["location_uri"] = sd.LocationUri
3312+
}
3313+
3314+
if sd.InputFormat != "" {
3315+
result["input_format"] = sd.InputFormat
3316+
}
3317+
3318+
if sd.OutputFormat != "" {
3319+
result["output_format"] = sd.OutputFormat
3320+
}
3321+
3322+
if sd.SerdeInfo != nil {
3323+
result["serde_info"] = flattenSerDeInfo(sd.SerdeInfo)
3324+
}
3325+
3326+
return []map[string]interface{}{result}
3327+
}
3328+
3329+
func expandSerDeInfo(configured interface{}) *bigquery.SerDeInfo {
3330+
if len(configured.([]interface{})) == 0 {
3331+
return nil
3332+
}
3333+
3334+
raw := configured.([]interface{})[0].(map[string]interface{})
3335+
si := &bigquery.SerDeInfo{SerializationLibrary: raw["serialization_library"].(string)}
3336+
3337+
if v, ok := raw["name"]; ok {
3338+
si.Name = v.(string)
3339+
}
3340+
3341+
if v, ok := raw["parameters"]; ok {
3342+
parameters := map[string]string{}
3343+
3344+
for k, v := range v.(map[string]interface{}) {
3345+
parameters[k] = v.(string)
3346+
}
3347+
3348+
si.Parameters = parameters
3349+
}
3350+
3351+
return si
3352+
}
3353+
3354+
func flattenSerDeInfo(si *bigquery.SerDeInfo) []map[string]interface{} {
3355+
if si == nil {
3356+
return nil
3357+
}
3358+
3359+
result := map[string]interface{}{"serialization_library": si.SerializationLibrary}
3360+
3361+
if si.Name != "" {
3362+
result["name"] = si.Name
3363+
}
3364+
3365+
if si.Parameters != nil {
3366+
result["parameters"] = si.Parameters
3367+
}
3368+
3369+
return []map[string]interface{}{result}
3370+
}
3371+
30563372
func resourceBigQueryTableImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
30573373
config := meta.(*transport_tpg.Config)
30583374
if err := tpgresource.ParseImportId([]string{

0 commit comments

Comments
 (0)