diff --git a/README.md b/README.md index 4053a72..0627daa 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ go install github.com/GoogleCloudPlatform/protoc-gen-bq-schema@latest ``` ## Usage - protoc --bq-schema\_out=path/to/outdir \[--bq-schema_opt=single-message\] foo.proto + protoc --bq-schema\_out=path/to/outdir \[--bq-schema_opt=single-message,use-json-names\] foo.proto `protoc` and `protoc-gen-bq-schema` commands must be found in $PATH. @@ -72,6 +72,9 @@ The message `foo.Baz` is ignored because it doesn't have option `gen_bq_schema.b `protoc --bq-schema_out=. --bq-schema_opt=single-message single_message.proto` will generate a file named `foo/single_message.schema`. The message `foo.Baz` is also ignored because it is not the first message in the file. +`protoc --bq-schema_out=. --bq-schema_opt=use-json-names foo.proto` will generate a schema whose fields are named using `json_name`. +This is equivalent to tagging every message as `use_json_names = true` and provided for convenience. + ### Support for PolicyTags `protoc-gen-bq-schema` now supports [policyTags](https://cloud.google.com/bigquery/docs/column-level-security-intro). diff --git a/pkg/converter/convert.go b/pkg/converter/convert.go index 3f26b27..730eee8 100644 --- a/pkg/converter/convert.go +++ b/pkg/converter/convert.go @@ -60,6 +60,8 @@ var ( descriptor.FieldDescriptorProto_LABEL_REQUIRED: "REQUIRED", descriptor.FieldDescriptorProto_LABEL_REPEATED: "REPEATED", } + + globallyUseJsonNames = false ) // Field describes the schema of a field in BigQuery. @@ -118,7 +120,7 @@ func convertField( field := &Field{ Name: desc.GetName(), } - if msgOpts.GetUseJsonNames() && desc.GetJsonName() != "" { + if (msgOpts.GetUseJsonNames() || globallyUseJsonNames) && desc.GetJsonName() != "" { field.Name = desc.GetJsonName() } @@ -385,7 +387,21 @@ func handleSingleMessageOpt(file *descriptor.FileDescriptorProto, requestParam s }) } +// handleUseJsonNamesOpt handles --bq-schema_opt=use-json-names in protoc params. +// providing that param tells protoc-gen-bq-schema to always use a field's json_name +// as the corresponding BigQuery column name. +// it is equivalent to setting the option use_json_name as true to every message. +func handleUseJsonNamesOpt(requestParam string) { + if !strings.Contains(requestParam, "use-json-names") { + return + } + + globallyUseJsonNames = true +} + func Convert(req *plugin.CodeGeneratorRequest) (*plugin.CodeGeneratorResponse, error) { + handleUseJsonNamesOpt(req.GetParameter()) + generateTargets := make(map[string]bool) for _, file := range req.GetFileToGenerate() { generateTargets[file] = true diff --git a/pkg/converter/plugin_test.go b/pkg/converter/plugin_test.go index e388a7d..40dba9a 100644 --- a/pkg/converter/plugin_test.go +++ b/pkg/converter/plugin_test.go @@ -504,3 +504,37 @@ func TestExtraFields(t *testing.T) { ]`, }) } + +func TestUseJsonNamesOpt(t *testing.T) { + option := "use-json-names" + testConvert(t, ` + file_to_generate: "foo.proto" + proto_file < + name: "foo.proto" + package: "example_package.nested" + message_type < + name: "FooProto" + field < name: "str" number: 1 type: TYPE_STRING label: LABEL_OPTIONAL json_name: "someJsonSpecificName" > + field < + name: "nested_message" number: 2 type: TYPE_MESSAGE label: LABEL_OPTIONAL + type_name: ".example_package.nested.FooProto.Nested" json_name: "nestedMessage" + > + nested_type < + name: "Nested" + field < name: "some_field" number: 1 type: TYPE_STRING label: LABEL_OPTIONAL json_name: "someField" > + > + options < [gen_bq_schema.bigquery_opts] > + > + > + `, + map[string]string{ + "example_package/nested/foo_table.schema": `[ + { "name": "someJsonSpecificName", "type": "STRING", "mode": "NULLABLE" }, + { + "name": "nestedMessage", "type": "RECORD", "mode": "NULLABLE", + "fields": [{ "name": "someField", "type": "STRING", "mode": "NULLABLE" }] + } + ]`, + }, + func(request *plugin.CodeGeneratorRequest) { request.Parameter = &option }) +}