diff --git a/materialize-boilerplate/.snapshots/TestValidate b/materialize-boilerplate/.snapshots/TestValidate index 6bffc518c3..8ec86ec92e 100644 --- a/materialize-boilerplate/.snapshots/TestValidate +++ b/materialize-boilerplate/.snapshots/TestValidate @@ -139,6 +139,7 @@ table already exists with incompatible proposed spec: new materialization with ambiguous fields: {"Field":"FIRSTBADFIELD","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'FIRSTBADFIELD' would be materialized as 'firstbadfield', which is ambiguous with fields [firstBadField,firstbadfield]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} {"Field":"SECONDBADFIELD","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'SECONDBADFIELD' would be materialized as 'secondbadfield', which is ambiguous with fields [secondBadField,secondbadfield]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} +{"Field":"THIRDBADFIELD","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'THIRDBADFIELD' would be materialized as 'thirdbadfield', which is ambiguous with fields [tHiRdBaDfIeLd,thirdBadField,thirdbadfield]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} {"Field":"_meta/flow_truncated","Type":3,"TypeString":"LOCATION_RECOMMENDED","Reason":"The projection has a single scalar type"} {"Field":"firstBadField","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'firstBadField' would be materialized as 'firstbadfield', which is ambiguous with fields [FIRSTBADFIELD,firstbadfield]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} {"Field":"firstbadfield","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'firstbadfield' would be materialized as 'firstbadfield', which is ambiguous with fields [FIRSTBADFIELD,firstBadField]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} @@ -148,10 +149,14 @@ new materialization with ambiguous fields: {"Field":"key","Type":2,"TypeString":"LOCATION_REQUIRED","Reason":"All Locations that are part of the collections key are required"} {"Field":"secondBadField","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'secondBadField' would be materialized as 'secondbadfield', which is ambiguous with fields [SECONDBADFIELD,secondbadfield]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} {"Field":"secondbadfield","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'secondbadfield' would be materialized as 'secondbadfield', which is ambiguous with fields [SECONDBADFIELD,secondBadField]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} +{"Field":"tHiRdBaDfIeLd","Type":3,"TypeString":"LOCATION_RECOMMENDED","Reason":"The projection has a single scalar type"} +{"Field":"thirdBadField","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'thirdBadField' would be materialized as 'thirdbadfield', which is ambiguous with fields [THIRDBADFIELD,tHiRdBaDfIeLd,thirdbadfield]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} +{"Field":"thirdbadfield","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'thirdbadfield' would be materialized as 'thirdbadfield', which is ambiguous with fields [THIRDBADFIELD,tHiRdBaDfIeLd,thirdBadField]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} table already exists with a column for an ambiguous field for a new materialization: {"Field":"FIRSTBADFIELD","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'FIRSTBADFIELD' would be materialized as 'firstbadfield', which is ambiguous with fields [firstBadField,firstbadfield]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} {"Field":"SECONDBADFIELD","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'SECONDBADFIELD' would be materialized as 'secondbadfield', which is ambiguous with fields [secondBadField,secondbadfield]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} +{"Field":"THIRDBADFIELD","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'THIRDBADFIELD' would be materialized as 'thirdbadfield', which is ambiguous with fields [tHiRdBaDfIeLd,thirdBadField,thirdbadfield]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} {"Field":"_meta/flow_truncated","Type":3,"TypeString":"LOCATION_RECOMMENDED","Reason":"The projection has a single scalar type"} {"Field":"firstBadField","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'firstBadField' would be materialized as 'firstbadfield', which is ambiguous with fields [FIRSTBADFIELD,firstbadfield]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} {"Field":"firstbadfield","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'firstbadfield' would be materialized as 'firstbadfield', which is ambiguous with fields [FIRSTBADFIELD,firstBadField]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} @@ -161,10 +166,14 @@ table already exists with a column for an ambiguous field for a new materializat {"Field":"key","Type":1,"TypeString":"FIELD_REQUIRED","Reason":"This field is a key in the current materialization"} {"Field":"secondBadField","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'secondBadField' would be materialized as 'secondbadfield', which is ambiguous with fields [SECONDBADFIELD,secondbadfield]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} {"Field":"secondbadfield","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'secondbadfield' would be materialized as 'secondbadfield', which is ambiguous with fields [SECONDBADFIELD,secondBadField]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} +{"Field":"tHiRdBaDfIeLd","Type":3,"TypeString":"LOCATION_RECOMMENDED","Reason":"The projection has a single scalar type"} +{"Field":"thirdBadField","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'thirdBadField' would be materialized as 'thirdbadfield', which is ambiguous with fields [THIRDBADFIELD,tHiRdBaDfIeLd,thirdbadfield]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} +{"Field":"thirdbadfield","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'thirdbadfield' would be materialized as 'thirdbadfield', which is ambiguous with fields [THIRDBADFIELD,tHiRdBaDfIeLd,thirdBadField]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} update an existing materialization with ambiguous fields: {"Field":"FIRSTBADFIELD","Type":5,"TypeString":"FIELD_FORBIDDEN","Reason":"Flow collection field 'FIRSTBADFIELD' is ambiguous with fields already being materialized as 'firstbadfield' in the destination. Consider using an alternate, unambiguous projection of this field to allow it to be materialized"} {"Field":"SECONDBADFIELD","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'SECONDBADFIELD' would be materialized as 'secondbadfield', which is ambiguous with fields [secondBadField,secondbadfield]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} +{"Field":"THIRDBADFIELD","Type":5,"TypeString":"FIELD_FORBIDDEN","Reason":"Flow collection field 'THIRDBADFIELD' is ambiguous with fields already being materialized as 'thirdbadfield' in the destination. Consider using an alternate, unambiguous projection of this field to allow it to be materialized"} {"Field":"_meta/flow_truncated","Type":3,"TypeString":"LOCATION_RECOMMENDED","Reason":"The projection has a single scalar type"} {"Field":"firstBadField","Type":3,"TypeString":"LOCATION_RECOMMENDED","Reason":"This location is part of the current materialization"} {"Field":"firstbadfield","Type":5,"TypeString":"FIELD_FORBIDDEN","Reason":"Flow collection field 'firstbadfield' is ambiguous with fields already being materialized as 'firstbadfield' in the destination. Consider using an alternate, unambiguous projection of this field to allow it to be materialized"} @@ -174,6 +183,9 @@ update an existing materialization with ambiguous fields: {"Field":"key","Type":1,"TypeString":"FIELD_REQUIRED","Reason":"This field is a key in the current materialization"} {"Field":"secondBadField","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'secondBadField' would be materialized as 'secondbadfield', which is ambiguous with fields [SECONDBADFIELD,secondbadfield]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} {"Field":"secondbadfield","Type":4,"TypeString":"FIELD_OPTIONAL","Reason":"Flow collection field 'secondbadfield' would be materialized as 'secondbadfield', which is ambiguous with fields [SECONDBADFIELD,secondBadField]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields"} +{"Field":"tHiRdBaDfIeLd","Type":5,"TypeString":"FIELD_FORBIDDEN","Reason":"Flow collection field 'tHiRdBaDfIeLd' is ambiguous with fields already being materialized as 'thirdbadfield' in the destination. Consider using an alternate, unambiguous projection of this field to allow it to be materialized"} +{"Field":"thirdBadField","Type":5,"TypeString":"FIELD_FORBIDDEN","Reason":"Flow collection field 'thirdBadField' is ambiguous with fields already being materialized as 'thirdbadfield' in the destination. Consider using an alternate, unambiguous projection of this field to allow it to be materialized"} +{"Field":"thirdbadfield","Type":3,"TypeString":"LOCATION_RECOMMENDED","Reason":"This location is part of the current materialization"} field names over the length limit are forbidden: {"Field":"_meta/flow_truncated","Type":3,"TypeString":"LOCATION_RECOMMENDED","Reason":"The projection has a single scalar type"} diff --git a/materialize-boilerplate/testdata/apply/generated_specs/add-new-binding.flow.proto b/materialize-boilerplate/testdata/apply/generated_specs/add-new-binding.flow.proto index 4879c5438e..d94dd5829d 100644 Binary files a/materialize-boilerplate/testdata/apply/generated_specs/add-new-binding.flow.proto and b/materialize-boilerplate/testdata/apply/generated_specs/add-new-binding.flow.proto differ diff --git a/materialize-boilerplate/testdata/apply/generated_specs/add-new-required.flow.proto b/materialize-boilerplate/testdata/apply/generated_specs/add-new-required.flow.proto index 69eec594bf..e3248d3b61 100644 Binary files a/materialize-boilerplate/testdata/apply/generated_specs/add-new-required.flow.proto and b/materialize-boilerplate/testdata/apply/generated_specs/add-new-required.flow.proto differ diff --git a/materialize-boilerplate/testdata/apply/generated_specs/base.flow.proto b/materialize-boilerplate/testdata/apply/generated_specs/base.flow.proto index 962438c08e..cacc7f2d21 100644 Binary files a/materialize-boilerplate/testdata/apply/generated_specs/base.flow.proto and b/materialize-boilerplate/testdata/apply/generated_specs/base.flow.proto differ diff --git a/materialize-boilerplate/testdata/apply/generated_specs/make-nullable.flow.proto b/materialize-boilerplate/testdata/apply/generated_specs/make-nullable.flow.proto index 5dbdec4f2c..23d67e1ad5 100644 Binary files a/materialize-boilerplate/testdata/apply/generated_specs/make-nullable.flow.proto and b/materialize-boilerplate/testdata/apply/generated_specs/make-nullable.flow.proto differ diff --git a/materialize-boilerplate/testdata/apply/generated_specs/remove-required.flow.proto b/materialize-boilerplate/testdata/apply/generated_specs/remove-required.flow.proto index 03a497b679..bb67a33f31 100644 Binary files a/materialize-boilerplate/testdata/apply/generated_specs/remove-required.flow.proto and b/materialize-boilerplate/testdata/apply/generated_specs/remove-required.flow.proto differ diff --git a/materialize-boilerplate/testdata/apply/generated_specs/replace-original-binding.flow.proto b/materialize-boilerplate/testdata/apply/generated_specs/replace-original-binding.flow.proto index 8fb3723495..80a9c3a0bd 100644 Binary files a/materialize-boilerplate/testdata/apply/generated_specs/replace-original-binding.flow.proto and b/materialize-boilerplate/testdata/apply/generated_specs/replace-original-binding.flow.proto differ diff --git a/materialize-boilerplate/testdata/generate-spec-proto.sh b/materialize-boilerplate/testdata/generate-spec-proto.sh index ce37ae1013..6051b5f493 100755 --- a/materialize-boilerplate/testdata/generate-spec-proto.sh +++ b/materialize-boilerplate/testdata/generate-spec-proto.sh @@ -33,4 +33,10 @@ flowctl raw build \ --db-path ${TEMP_DIR}/build.db \ --source $1 +errors=$(sqlite3 ${TEMP_DIR}/build.db "select * from errors") +if [[ -n "$errors" ]]; then + echo "$errors" >&2 + exit 1 +fi + sqlite3 ${TEMP_DIR}/build.db "select writefile('${OUTPUT}', spec) from built_materializations;" diff --git a/materialize-boilerplate/testdata/validate/ambiguous-fields.flow.yaml b/materialize-boilerplate/testdata/validate/ambiguous-fields.flow.yaml index 028bfaa261..93dbb5aba9 100644 --- a/materialize-boilerplate/testdata/validate/ambiguous-fields.flow.yaml +++ b/materialize-boilerplate/testdata/validate/ambiguous-fields.flow.yaml @@ -11,7 +11,12 @@ collections: secondBadField: { type: string } secondbadfield: { type: string } SECONDBADFIELD: { type: string } + thirdBadField: { type: string } + thirdbadfield: { type: string } + THIRDBADFIELD: { type: string } required: [key] + projections: + tHiRdBaDfIeLd: /THIRDBADFIELD key: [/key] materializations: @@ -29,3 +34,4 @@ materializations: key: {} goodField: {} firstBadField: {} + thirdbadfield: {} # Note: not the explicit projection diff --git a/materialize-boilerplate/testdata/validate/generated_specs/alternate-root.flow.proto b/materialize-boilerplate/testdata/validate/generated_specs/alternate-root.flow.proto index 0548b31a6f..0a700a0587 100644 Binary files a/materialize-boilerplate/testdata/validate/generated_specs/alternate-root.flow.proto and b/materialize-boilerplate/testdata/validate/generated_specs/alternate-root.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate/generated_specs/ambiguous-fields.flow.proto b/materialize-boilerplate/testdata/validate/generated_specs/ambiguous-fields.flow.proto index 7cb5578817..2c550663ef 100644 Binary files a/materialize-boilerplate/testdata/validate/generated_specs/ambiguous-fields.flow.proto and b/materialize-boilerplate/testdata/validate/generated_specs/ambiguous-fields.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate/generated_specs/base.flow.proto b/materialize-boilerplate/testdata/validate/generated_specs/base.flow.proto index 3f9641b409..4699e640bc 100644 Binary files a/materialize-boilerplate/testdata/validate/generated_specs/base.flow.proto and b/materialize-boilerplate/testdata/validate/generated_specs/base.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate/generated_specs/fewer-fields.flow.proto b/materialize-boilerplate/testdata/validate/generated_specs/fewer-fields.flow.proto index 886c9d63f8..e053caf97d 100644 Binary files a/materialize-boilerplate/testdata/validate/generated_specs/fewer-fields.flow.proto and b/materialize-boilerplate/testdata/validate/generated_specs/fewer-fields.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate/generated_specs/incompatible-changes.flow.proto b/materialize-boilerplate/testdata/validate/generated_specs/incompatible-changes.flow.proto index f989fb11fb..5d20a689a6 100644 Binary files a/materialize-boilerplate/testdata/validate/generated_specs/incompatible-changes.flow.proto and b/materialize-boilerplate/testdata/validate/generated_specs/incompatible-changes.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate/generated_specs/increment-backfill.flow.proto b/materialize-boilerplate/testdata/validate/generated_specs/increment-backfill.flow.proto index 17788b6dd1..ece78275e2 100644 Binary files a/materialize-boilerplate/testdata/validate/generated_specs/increment-backfill.flow.proto and b/materialize-boilerplate/testdata/validate/generated_specs/increment-backfill.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate/generated_specs/long-fields.flow.proto b/materialize-boilerplate/testdata/validate/generated_specs/long-fields.flow.proto index 93c90d01ff..9b37e3d806 100644 Binary files a/materialize-boilerplate/testdata/validate/generated_specs/long-fields.flow.proto and b/materialize-boilerplate/testdata/validate/generated_specs/long-fields.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate/generated_specs/nullable-key.flow.proto b/materialize-boilerplate/testdata/validate/generated_specs/nullable-key.flow.proto index 0c6e26781b..2e79b6e8a4 100644 Binary files a/materialize-boilerplate/testdata/validate/generated_specs/nullable-key.flow.proto and b/materialize-boilerplate/testdata/validate/generated_specs/nullable-key.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/add-and-remove-many.flow.proto b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/add-and-remove-many.flow.proto index c7e2f5a6c8..e4512ba95e 100644 Binary files a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/add-and-remove-many.flow.proto and b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/add-and-remove-many.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/add-single-optional.flow.proto b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/add-single-optional.flow.proto index 2e0b7c01fe..02ac8ea6f1 100644 Binary files a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/add-single-optional.flow.proto and b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/add-single-optional.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/base.flow.proto b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/base.flow.proto index ff12424bcd..53f52a264f 100644 Binary files a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/base.flow.proto and b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/base.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/big-schema-changed.flow.proto b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/big-schema-changed.flow.proto index 3a34417e38..a4fbba1f5c 100644 Binary files a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/big-schema-changed.flow.proto and b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/big-schema-changed.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/big-schema-nullable.flow.proto b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/big-schema-nullable.flow.proto index e25885b61a..4606ef0863 100644 Binary files a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/big-schema-nullable.flow.proto and b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/big-schema-nullable.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/big-schema.flow.proto b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/big-schema.flow.proto index 58b0bdc086..5daa6ca3fe 100644 Binary files a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/big-schema.flow.proto and b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/big-schema.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/challenging-fields.flow.proto b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/challenging-fields.flow.proto index 271d789308..51cbd48307 100644 Binary files a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/challenging-fields.flow.proto and b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/challenging-fields.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/remove-single-optional.flow.proto b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/remove-single-optional.flow.proto index 08ba3b990d..78f8bff8c0 100644 Binary files a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/remove-single-optional.flow.proto and b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/remove-single-optional.flow.proto differ diff --git a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/remove-single-required.flow.proto b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/remove-single-required.flow.proto index fd9053c700..9c9b278bba 100644 Binary files a/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/remove-single-required.flow.proto and b/materialize-boilerplate/testdata/validate_apply_test_cases/generated_specs/remove-single-required.flow.proto differ diff --git a/materialize-boilerplate/validate.go b/materialize-boilerplate/validate.go index 6a6b88e44e..7dfac7d57f 100644 --- a/materialize-boilerplate/validate.go +++ b/materialize-boilerplate/validate.go @@ -136,19 +136,24 @@ func (v Validator) validateNewBinding(boundCollection pf.CollectionSpec, deltaUp } sawRoot = true } else if ambiguousFields := v.ambiguousFields(p, boundCollection.Projections); len(ambiguousFields) > 0 && c.Type == pm.Response_Validated_Constraint_LOCATION_RECOMMENDED { - // Any fields that would be ambiguous to materialize should be marked as optional if - // they would otherwise be recommended. Only one of these fields should be selected to - // materialize. - c = &pm.Response_Validated_Constraint{ - Type: pm.Response_Validated_Constraint_FIELD_OPTIONAL, - Reason: fmt.Sprintf( - // See identical "reason" text in validateMatchesExistingBinding for optional - // ambiguous field constraints. These two messages should be kept in sync. - "Flow collection field '%s' would be materialized as '%s', which is ambiguous with fields [%s]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields", - p.Field, - v.is.translateField(p.Field), - strings.Join(ambiguousFields, ","), - ), + if p.Explicit { + // User-defined projections of ambiguous fields are allowed as-is. + } else { + // Any other fields that would be ambiguous to materialize are + // marked as optional if they would otherwise be recommended. + // Only one of these fields should be selected to materialize, + // and that will require manual field selection. + c = &pm.Response_Validated_Constraint{ + Type: pm.Response_Validated_Constraint_FIELD_OPTIONAL, + Reason: fmt.Sprintf( + // See identical "reason" text in validateMatchesExistingBinding for optional + // ambiguous field constraints. These two messages should be kept in sync. + "Flow collection field '%s' would be materialized as '%s', which is ambiguous with fields [%s]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields", + p.Field, + v.is.translateField(p.Field), + strings.Join(ambiguousFields, ","), + ), + } } } @@ -227,16 +232,20 @@ func (v Validator) validateMatchesExistingBinding( } else if c.Type == pm.Response_Validated_Constraint_LOCATION_RECOMMENDED || c.Type == pm.Response_Validated_Constraint_FIELD_OPTIONAL { // None of these ambiguous fields have been selected yet, so it's still possible to // pick one. - c = &pm.Response_Validated_Constraint{ - Type: pm.Response_Validated_Constraint_FIELD_OPTIONAL, - Reason: fmt.Sprintf( - // See identical "reason" text in validateNewBinding for optional ambiguous - // field constraints. These two messages should be kept in sync. - "Flow collection field '%s' would be materialized as '%s', which is ambiguous with fields [%s]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields", - p.Field, - v.is.translateField(p.Field), - strings.Join(ambiguousFields, ","), - ), + if p.Explicit { + // User-defined projections of ambiguous fields are allowed as-is. + } else { + c = &pm.Response_Validated_Constraint{ + Type: pm.Response_Validated_Constraint_FIELD_OPTIONAL, + Reason: fmt.Sprintf( + // See identical "reason" text in validateNewBinding for optional ambiguous + // field constraints. These two messages should be kept in sync. + "Flow collection field '%s' would be materialized as '%s', which is ambiguous with fields [%s]. Only a single field from this set should be selected. Consider using alternate projections if you want to materialize more than one of these fields", + p.Field, + v.is.translateField(p.Field), + strings.Join(ambiguousFields, ","), + ), + } } } } else if existingField, err := v.is.GetField(path, p.Field); err == nil {