From ef2d50a5d69b296eaa32aa39a089a956379e3a6c Mon Sep 17 00:00:00 2001 From: Jakub Michalak Date: Tue, 6 Aug 2024 13:27:20 +0200 Subject: [PATCH] feat: Upgrade view sdk (#2969) - add acceptance clients for aggregation and projection policies (with jiras to use proper SDK clients) - adjust SDK to match snowflake - change handling of `PolicyReference` to be more generic - add new sturct `ExtendedIn` to handle SHOWs that can specify applications and applications packages (will be useful in other resources) - add more validations - add quotes for fields with column names - update resource and datasource to be compatible with sdk - update statuses of remaining objects - NOTE: view behavior is not consistent with docs, that is: - adding columns is not working - columns with options in CREATE are without () in docs - this is not correct, they need to be wrapped in (), this will be reported on doc-discuss ## Test Plan * [x] integration tests * [x] unit tests ## References https://docs.snowflake.com/en/sql-reference/sql/create-view#examples --- pkg/acceptance/bettertestspoc/README.md | 4 +- .../assert/objectassert/gen/sdk_object_def.go | 5 + .../assert/objectassert/view_snowflake_ext.go | 30 ++ .../assert/objectassert/view_snowflake_gen.go | 174 ++++++++ .../view_show_output_gen.go | 106 +++++ .../helpers/aggregation_policy_client.go | 47 +++ pkg/acceptance/helpers/common.go | 18 + .../helpers/data_metric_function_client.go | 50 +++ .../data_metric_function_references_client.go | 47 +++ .../helpers/policy_references_client.go | 47 +++ .../helpers/projection_policy_client.go | 47 +++ .../helpers/row_access_policy_client.go | 32 -- pkg/acceptance/helpers/test_client.go | 162 ++++---- pkg/acceptance/helpers/view_client.go | 11 +- pkg/datasources/views.go | 2 +- pkg/resources/view.go | 26 +- pkg/sdk/common_types.go | 6 + pkg/sdk/poc/generator/keyword_builders.go | 4 + pkg/sdk/poc/main.go | 1 + pkg/sdk/policy_references.go | 31 ++ .../testint/event_tables_integration_test.go | 10 +- ...materialized_views_gen_integration_test.go | 2 +- pkg/sdk/testint/views_gen_integration_test.go | 378 ++++++++++++++---- pkg/sdk/views_def.go | 127 +++++- pkg/sdk/views_dto_builders_gen.go | 319 +++++++++++---- pkg/sdk/views_dto_gen.go | 140 +++++-- pkg/sdk/views_gen.go | 250 +++++++----- pkg/sdk/views_gen_test.go | 257 ++++++++++-- pkg/sdk/views_impl_gen.go | 139 +++++-- pkg/sdk/views_validations_gen.go | 51 ++- v1-preparations/ESSENTIAL_GA_OBJECTS.MD | 10 +- 31 files changed, 2024 insertions(+), 509 deletions(-) create mode 100644 pkg/acceptance/bettertestspoc/assert/objectassert/view_snowflake_ext.go create mode 100644 pkg/acceptance/bettertestspoc/assert/objectassert/view_snowflake_gen.go create mode 100644 pkg/acceptance/bettertestspoc/assert/resourceshowoutputassert/view_show_output_gen.go create mode 100644 pkg/acceptance/helpers/aggregation_policy_client.go create mode 100644 pkg/acceptance/helpers/data_metric_function_client.go create mode 100644 pkg/acceptance/helpers/data_metric_function_references_client.go create mode 100644 pkg/acceptance/helpers/policy_references_client.go create mode 100644 pkg/acceptance/helpers/projection_policy_client.go diff --git a/pkg/acceptance/bettertestspoc/README.md b/pkg/acceptance/bettertestspoc/README.md index da1038cd3f..e17e502334 100644 --- a/pkg/acceptance/bettertestspoc/README.md +++ b/pkg/acceptance/bettertestspoc/README.md @@ -49,7 +49,7 @@ func (w *WarehouseResourceParametersAssert) HasDefaultMaxConcurrencyLevel() *War ### Adding new Snowflake object assertions Snowflake object assertions can be generated automatically. For object `abc` do the following: -- add object you want to generate to `allStructs` slice in the `assert/objectassert/gen/main/main.go` +- add object you want to generate to `allStructs` slice in the `assert/objectassert/gen/sdk_object_def.go` - to add custom (not generated assertions) create file `abc_snowflake_ext.go` in the `objectassert` package. Example would be: ```go func (w *WarehouseAssert) HasStateOneOf(expected ...sdk.WarehouseState) *WarehouseAssert { @@ -77,7 +77,7 @@ func (w *WarehouseParametersAssert) HasDefaultMaxConcurrencyLevel() *WarehousePa } ``` -### Adding new models +### Adding new resource config model builders Resource config model builders can be generated automatically. For object `abc` do the following: - add object you want to generate to `allResourceSchemaDefs` slice in the `assert/resourceassert/gen/resource_schema_def.go` - to add custom (not generated) config builder methods create file `warehouse_model_ext` in the `config/model` package. Example would be: diff --git a/pkg/acceptance/bettertestspoc/assert/objectassert/gen/sdk_object_def.go b/pkg/acceptance/bettertestspoc/assert/objectassert/gen/sdk_object_def.go index c634be1256..47e1a3b2e4 100644 --- a/pkg/acceptance/bettertestspoc/assert/objectassert/gen/sdk_object_def.go +++ b/pkg/acceptance/bettertestspoc/assert/objectassert/gen/sdk_object_def.go @@ -22,6 +22,11 @@ var allStructs = []SdkObjectDef{ ObjectType: sdk.ObjectTypeWarehouse, ObjectStruct: sdk.Warehouse{}, }, + { + IdType: "sdk.SchemaObjectIdentifier", + ObjectType: sdk.ObjectTypeView, + ObjectStruct: sdk.View{}, + }, } func GetSdkObjectDetails() []genhelpers.SdkObjectDetails { diff --git a/pkg/acceptance/bettertestspoc/assert/objectassert/view_snowflake_ext.go b/pkg/acceptance/bettertestspoc/assert/objectassert/view_snowflake_ext.go new file mode 100644 index 0000000000..05598f49ad --- /dev/null +++ b/pkg/acceptance/bettertestspoc/assert/objectassert/view_snowflake_ext.go @@ -0,0 +1,30 @@ +package objectassert + +import ( + "fmt" + "testing" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" +) + +func (w *ViewAssert) HasCreatedOnNotEmpty() *ViewAssert { + w.AddAssertion(func(t *testing.T, o *sdk.View) error { + t.Helper() + if o.CreatedOn == "" { + return fmt.Errorf("expected created on not empty; got: %v", o.CreatedOn) + } + return nil + }) + return w +} + +func (v *ViewAssert) HasNonEmptyText() *ViewAssert { + v.AddAssertion(func(t *testing.T, o *sdk.View) error { + t.Helper() + if o.Text == "" { + return fmt.Errorf("expected non empty text") + } + return nil + }) + return v +} diff --git a/pkg/acceptance/bettertestspoc/assert/objectassert/view_snowflake_gen.go b/pkg/acceptance/bettertestspoc/assert/objectassert/view_snowflake_gen.go new file mode 100644 index 0000000000..655ffa9567 --- /dev/null +++ b/pkg/acceptance/bettertestspoc/assert/objectassert/view_snowflake_gen.go @@ -0,0 +1,174 @@ +// Code generated by assertions generator; DO NOT EDIT. + +package objectassert + +import ( + "fmt" + "testing" + + acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" +) + +type ViewAssert struct { + *assert.SnowflakeObjectAssert[sdk.View, sdk.SchemaObjectIdentifier] +} + +func View(t *testing.T, id sdk.SchemaObjectIdentifier) *ViewAssert { + t.Helper() + return &ViewAssert{ + assert.NewSnowflakeObjectAssertWithProvider(sdk.ObjectTypeView, id, acc.TestClient().View.Show), + } +} + +func ViewFromObject(t *testing.T, view *sdk.View) *ViewAssert { + t.Helper() + return &ViewAssert{ + assert.NewSnowflakeObjectAssertWithObject(sdk.ObjectTypeView, view.ID(), view), + } +} + +func (v *ViewAssert) HasCreatedOn(expected string) *ViewAssert { + v.AddAssertion(func(t *testing.T, o *sdk.View) error { + t.Helper() + if o.CreatedOn != expected { + return fmt.Errorf("expected created on: %v; got: %v", expected, o.CreatedOn) + } + return nil + }) + return v +} + +func (v *ViewAssert) HasName(expected string) *ViewAssert { + v.AddAssertion(func(t *testing.T, o *sdk.View) error { + t.Helper() + if o.Name != expected { + return fmt.Errorf("expected name: %v; got: %v", expected, o.Name) + } + return nil + }) + return v +} + +func (v *ViewAssert) HasKind(expected string) *ViewAssert { + v.AddAssertion(func(t *testing.T, o *sdk.View) error { + t.Helper() + if o.Kind != expected { + return fmt.Errorf("expected kind: %v; got: %v", expected, o.Kind) + } + return nil + }) + return v +} + +func (v *ViewAssert) HasReserved(expected string) *ViewAssert { + v.AddAssertion(func(t *testing.T, o *sdk.View) error { + t.Helper() + if o.Reserved != expected { + return fmt.Errorf("expected reserved: %v; got: %v", expected, o.Reserved) + } + return nil + }) + return v +} + +func (v *ViewAssert) HasDatabaseName(expected string) *ViewAssert { + v.AddAssertion(func(t *testing.T, o *sdk.View) error { + t.Helper() + if o.DatabaseName != expected { + return fmt.Errorf("expected database name: %v; got: %v", expected, o.DatabaseName) + } + return nil + }) + return v +} + +func (v *ViewAssert) HasSchemaName(expected string) *ViewAssert { + v.AddAssertion(func(t *testing.T, o *sdk.View) error { + t.Helper() + if o.SchemaName != expected { + return fmt.Errorf("expected schema name: %v; got: %v", expected, o.SchemaName) + } + return nil + }) + return v +} + +func (v *ViewAssert) HasOwner(expected string) *ViewAssert { + v.AddAssertion(func(t *testing.T, o *sdk.View) error { + t.Helper() + if o.Owner != expected { + return fmt.Errorf("expected owner: %v; got: %v", expected, o.Owner) + } + return nil + }) + return v +} + +func (v *ViewAssert) HasComment(expected string) *ViewAssert { + v.AddAssertion(func(t *testing.T, o *sdk.View) error { + t.Helper() + if o.Comment != expected { + return fmt.Errorf("expected comment: %v; got: %v", expected, o.Comment) + } + return nil + }) + return v +} + +func (v *ViewAssert) HasText(expected string) *ViewAssert { + v.AddAssertion(func(t *testing.T, o *sdk.View) error { + t.Helper() + if o.Text != expected { + return fmt.Errorf("expected text: %v; got: %v", expected, o.Text) + } + return nil + }) + return v +} + +func (v *ViewAssert) HasIsSecure(expected bool) *ViewAssert { + v.AddAssertion(func(t *testing.T, o *sdk.View) error { + t.Helper() + if o.IsSecure != expected { + return fmt.Errorf("expected is secure: %v; got: %v", expected, o.IsSecure) + } + return nil + }) + return v +} + +func (v *ViewAssert) HasIsMaterialized(expected bool) *ViewAssert { + v.AddAssertion(func(t *testing.T, o *sdk.View) error { + t.Helper() + if o.IsMaterialized != expected { + return fmt.Errorf("expected is materialized: %v; got: %v", expected, o.IsMaterialized) + } + return nil + }) + return v +} + +func (v *ViewAssert) HasOwnerRoleType(expected string) *ViewAssert { + v.AddAssertion(func(t *testing.T, o *sdk.View) error { + t.Helper() + if o.OwnerRoleType != expected { + return fmt.Errorf("expected owner role type: %v; got: %v", expected, o.OwnerRoleType) + } + return nil + }) + return v +} + +func (v *ViewAssert) HasChangeTracking(expected string) *ViewAssert { + v.AddAssertion(func(t *testing.T, o *sdk.View) error { + t.Helper() + if o.ChangeTracking != expected { + return fmt.Errorf("expected change tracking: %v; got: %v", expected, o.ChangeTracking) + } + return nil + }) + return v +} diff --git a/pkg/acceptance/bettertestspoc/assert/resourceshowoutputassert/view_show_output_gen.go b/pkg/acceptance/bettertestspoc/assert/resourceshowoutputassert/view_show_output_gen.go new file mode 100644 index 0000000000..7b34df4371 --- /dev/null +++ b/pkg/acceptance/bettertestspoc/assert/resourceshowoutputassert/view_show_output_gen.go @@ -0,0 +1,106 @@ +// Code generated by assertions generator; DO NOT EDIT. + +package resourceshowoutputassert + +import ( + "testing" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" +) + +// to ensure sdk package is used +var _ = sdk.Object{} + +type ViewShowOutputAssert struct { + *assert.ResourceAssert +} + +func ViewShowOutput(t *testing.T, name string) *ViewShowOutputAssert { + t.Helper() + + v := ViewShowOutputAssert{ + ResourceAssert: assert.NewResourceAssert(name, "show_output"), + } + v.AddAssertion(assert.ValueSet("show_output.#", "1")) + return &v +} + +func ImportedViewShowOutput(t *testing.T, id string) *ViewShowOutputAssert { + t.Helper() + + v := ViewShowOutputAssert{ + ResourceAssert: assert.NewImportedResourceAssert(id, "show_output"), + } + v.AddAssertion(assert.ValueSet("show_output.#", "1")) + return &v +} + +//////////////////////////// +// Attribute value checks // +//////////////////////////// + +func (v *ViewShowOutputAssert) HasCreatedOn(expected string) *ViewShowOutputAssert { + v.AddAssertion(assert.ResourceShowOutputValueSet("created_on", expected)) + return v +} + +func (v *ViewShowOutputAssert) HasName(expected string) *ViewShowOutputAssert { + v.AddAssertion(assert.ResourceShowOutputValueSet("name", expected)) + return v +} + +func (v *ViewShowOutputAssert) HasKind(expected string) *ViewShowOutputAssert { + v.AddAssertion(assert.ResourceShowOutputValueSet("kind", expected)) + return v +} + +func (v *ViewShowOutputAssert) HasReserved(expected string) *ViewShowOutputAssert { + v.AddAssertion(assert.ResourceShowOutputValueSet("reserved", expected)) + return v +} + +func (v *ViewShowOutputAssert) HasDatabaseName(expected string) *ViewShowOutputAssert { + v.AddAssertion(assert.ResourceShowOutputValueSet("database_name", expected)) + return v +} + +func (v *ViewShowOutputAssert) HasSchemaName(expected string) *ViewShowOutputAssert { + v.AddAssertion(assert.ResourceShowOutputValueSet("schema_name", expected)) + return v +} + +func (v *ViewShowOutputAssert) HasOwner(expected string) *ViewShowOutputAssert { + v.AddAssertion(assert.ResourceShowOutputValueSet("owner", expected)) + return v +} + +func (v *ViewShowOutputAssert) HasComment(expected string) *ViewShowOutputAssert { + v.AddAssertion(assert.ResourceShowOutputValueSet("comment", expected)) + return v +} + +func (v *ViewShowOutputAssert) HasText(expected string) *ViewShowOutputAssert { + v.AddAssertion(assert.ResourceShowOutputValueSet("text", expected)) + return v +} + +func (v *ViewShowOutputAssert) HasIsSecure(expected bool) *ViewShowOutputAssert { + v.AddAssertion(assert.ResourceShowOutputBoolValueSet("is_secure", expected)) + return v +} + +func (v *ViewShowOutputAssert) HasIsMaterialized(expected bool) *ViewShowOutputAssert { + v.AddAssertion(assert.ResourceShowOutputBoolValueSet("is_materialized", expected)) + return v +} + +func (v *ViewShowOutputAssert) HasOwnerRoleType(expected string) *ViewShowOutputAssert { + v.AddAssertion(assert.ResourceShowOutputValueSet("owner_role_type", expected)) + return v +} + +func (v *ViewShowOutputAssert) HasChangeTracking(expected string) *ViewShowOutputAssert { + v.AddAssertion(assert.ResourceShowOutputValueSet("change_tracking", expected)) + return v +} diff --git a/pkg/acceptance/helpers/aggregation_policy_client.go b/pkg/acceptance/helpers/aggregation_policy_client.go new file mode 100644 index 0000000000..d04114a55d --- /dev/null +++ b/pkg/acceptance/helpers/aggregation_policy_client.go @@ -0,0 +1,47 @@ +package helpers + +import ( + "context" + "fmt" + "testing" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/stretchr/testify/require" +) + +// TODO(SNOW-1564954): change raw sqls to proper client +type AggregationPolicyClient struct { + context *TestClientContext + ids *IdsGenerator +} + +func NewAggregationPolicyClient(context *TestClientContext, idsGenerator *IdsGenerator) *AggregationPolicyClient { + return &AggregationPolicyClient{ + context: context, + ids: idsGenerator, + } +} + +func (c *AggregationPolicyClient) client() *sdk.Client { + return c.context.client +} + +func (c *AggregationPolicyClient) CreateAggregationPolicy(t *testing.T) (sdk.SchemaObjectIdentifier, func()) { + t.Helper() + ctx := context.Background() + + id := c.ids.RandomSchemaObjectIdentifier() + _, err := c.client().ExecForTests(ctx, fmt.Sprintf(`CREATE AGGREGATION POLICY %s AS () RETURNS AGGREGATION_CONSTRAINT -> AGGREGATION_CONSTRAINT(MIN_GROUP_SIZE => 5)`, id.Name())) + require.NoError(t, err) + return id, c.DropAggregationPolicyFunc(t, id) +} + +func (c *AggregationPolicyClient) DropAggregationPolicyFunc(t *testing.T, id sdk.SchemaObjectIdentifier) func() { + t.Helper() + ctx := context.Background() + + return func() { + _, err := c.client().ExecForTests(ctx, fmt.Sprintf(`DROP AGGREGATION POLICY IF EXISTS %s`, id.Name())) + require.NoError(t, err) + } +} diff --git a/pkg/acceptance/helpers/common.go b/pkg/acceptance/helpers/common.go index 153b007e39..574f33a1fb 100644 --- a/pkg/acceptance/helpers/common.go +++ b/pkg/acceptance/helpers/common.go @@ -2,6 +2,7 @@ package helpers import ( "context" + "database/sql" "fmt" "log" "testing" @@ -70,3 +71,20 @@ func AssertErrorContainsPartsFunc(t *testing.T, parts []string) resource.ErrorCh return nil } } + +type PolicyReference struct { + PolicyDb string `db:"POLICY_DB"` + PolicySchema string `db:"POLICY_SCHEMA"` + PolicyName string `db:"POLICY_NAME"` + PolicyKind string `db:"POLICY_KIND"` + RefDatabaseName string `db:"REF_DATABASE_NAME"` + RefSchemaName string `db:"REF_SCHEMA_NAME"` + RefEntityName string `db:"REF_ENTITY_NAME"` + RefEntityDomain string `db:"REF_ENTITY_DOMAIN"` + RefColumnName sql.NullString `db:"REF_COLUMN_NAME"` + RefArgColumnNames sql.NullString `db:"REF_ARG_COLUMN_NAMES"` + TagDatabase sql.NullString `db:"TAG_DATABASE"` + TagSchema sql.NullString `db:"TAG_SCHEMA"` + TagName sql.NullString `db:"TAG_NAME"` + PolicyStatus string `db:"POLICY_STATUS"` +} diff --git a/pkg/acceptance/helpers/data_metric_function_client.go b/pkg/acceptance/helpers/data_metric_function_client.go new file mode 100644 index 0000000000..dec2584914 --- /dev/null +++ b/pkg/acceptance/helpers/data_metric_function_client.go @@ -0,0 +1,50 @@ +package helpers + +import ( + "context" + "fmt" + "testing" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/stretchr/testify/require" +) + +// TODO(SNOW-1564959): change raw sqls to proper client +type DataMetricFunctionClient struct { + context *TestClientContext + ids *IdsGenerator +} + +func NewDataMetricFunctionClient(context *TestClientContext, idsGenerator *IdsGenerator) *DataMetricFunctionClient { + return &DataMetricFunctionClient{ + context: context, + ids: idsGenerator, + } +} + +func (c *DataMetricFunctionClient) client() *sdk.Client { + return c.context.client +} + +func (c *DataMetricFunctionClient) CreateDataMetricFunction(t *testing.T, viewID sdk.SchemaObjectIdentifier) (sdk.SchemaObjectIdentifier, func()) { + t.Helper() + ctx := context.Background() + + id := c.ids.RandomSchemaObjectIdentifier() + _, err := c.client().ExecForTests(ctx, fmt.Sprintf(`CREATE DATA METRIC FUNCTION %s(arg_t TABLE (arg_c INT)) +RETURNS NUMBER AS +'SELECT COUNT(*) FROM arg_t + WHERE arg_c IN (SELECT id FROM %s)'`, id.Name(), viewID.Name())) + require.NoError(t, err) + return id, c.DropDataMetricFunctionFunc(t, id) +} + +func (c *DataMetricFunctionClient) DropDataMetricFunctionFunc(t *testing.T, id sdk.SchemaObjectIdentifier) func() { + t.Helper() + ctx := context.Background() + + return func() { + _, err := c.client().ExecForTests(ctx, fmt.Sprintf(`DROP FUNCTION IF EXISTS %s (TABLE (INT))`, id.Name())) + require.NoError(t, err) + } +} diff --git a/pkg/acceptance/helpers/data_metric_function_references_client.go b/pkg/acceptance/helpers/data_metric_function_references_client.go new file mode 100644 index 0000000000..dcdbaacd6b --- /dev/null +++ b/pkg/acceptance/helpers/data_metric_function_references_client.go @@ -0,0 +1,47 @@ +package helpers + +import ( + "context" + "fmt" + "testing" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" +) + +type DataMetricFunctionReferencesClient struct { + context *TestClientContext +} + +func NewDataMetricFunctionReferencesClient(context *TestClientContext) *DataMetricFunctionReferencesClient { + return &DataMetricFunctionReferencesClient{ + context: context, + } +} + +// GetDataMetricFunctionReferences is based on https://docs.snowflake.com/en/sql-reference/functions/data_metric_function_references. +func (c *DataMetricFunctionReferencesClient) GetDataMetricFunctionReferences(t *testing.T, id sdk.SchemaObjectIdentifier, objectType sdk.ObjectType) ([]DataMetricFunctionReference, error) { + t.Helper() + ctx := context.Background() + + s := []DataMetricFunctionReference{} + dmfReferencesId := sdk.NewSchemaObjectIdentifier(id.DatabaseName(), "INFORMATION_SCHEMA", "DATA_METRIC_FUNCTION_REFERENCES") + err := c.context.client.QueryForTests(ctx, &s, fmt.Sprintf(`SELECT * FROM TABLE(%s(REF_ENTITY_NAME => '%s', REF_ENTITY_DOMAIN => '%v'))`, dmfReferencesId.FullyQualifiedName(), id.FullyQualifiedName(), objectType)) + + return s, err +} + +type DataMetricFunctionReference struct { + MetricDatabaseName string `db:"METRIC_DATABASE_NAME"` + MetricSchemaName string `db:"METRIC_SCHEMA_NAME"` + MetricName string `db:"METRIC_NAME"` + MetricSignature string `db:"METRIC_SIGNATURE"` + MetricDataType string `db:"METRIC_DATA_TYPE"` + RefEntityDatabaseName string `db:"REF_ENTITY_DATABASE_NAME"` + RefEntitySchemaName string `db:"REF_ENTITY_SCHEMA_NAME"` + RefEntityName string `db:"REF_ENTITY_NAME"` + RefEntityDomain string `db:"REF_ENTITY_DOMAIN"` + RefArguments string `db:"REF_ARGUMENTS"` + RefId string `db:"REF_ID"` + Schedule string `db:"SCHEDULE"` + ScheduleStatus string `db:"SCHEDULE_STATUS"` +} diff --git a/pkg/acceptance/helpers/policy_references_client.go b/pkg/acceptance/helpers/policy_references_client.go new file mode 100644 index 0000000000..15b6d6b736 --- /dev/null +++ b/pkg/acceptance/helpers/policy_references_client.go @@ -0,0 +1,47 @@ +package helpers + +import ( + "context" + "fmt" + "testing" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" +) + +type PolicyReferencesClient struct { + context *TestClientContext +} + +func NewPolicyReferencesClient(context *TestClientContext) *PolicyReferencesClient { + return &PolicyReferencesClient{ + context: context, + } +} + +func (c *PolicyReferencesClient) client() sdk.RowAccessPolicies { + return c.context.client.RowAccessPolicies +} + +// GetPolicyReferences is based on https://docs.snowflake.com/en/sql-reference/functions/policy_references. +func (c *PolicyReferencesClient) GetPolicyReferences(t *testing.T, id sdk.SchemaObjectIdentifier, objectType sdk.ObjectType) ([]PolicyReference, error) { + t.Helper() + ctx := context.Background() + + s := []PolicyReference{} + policyReferencesId := sdk.NewSchemaObjectIdentifier(id.DatabaseName(), "INFORMATION_SCHEMA", "POLICY_REFERENCES") + err := c.context.client.QueryForTests(ctx, &s, fmt.Sprintf(`SELECT * FROM TABLE(%s(REF_ENTITY_NAME => '%s', REF_ENTITY_DOMAIN => '%v'))`, policyReferencesId.FullyQualifiedName(), id.FullyQualifiedName(), objectType)) + + return s, err +} + +// GetPolicyReference is based on https://docs.snowflake.com/en/sql-reference/functions/policy_references. +func (c *PolicyReferencesClient) GetPolicyReference(t *testing.T, id sdk.SchemaObjectIdentifier, objectType sdk.ObjectType) (*PolicyReference, error) { + t.Helper() + ctx := context.Background() + + s := &PolicyReference{} + policyReferencesId := sdk.NewSchemaObjectIdentifier(id.DatabaseName(), "INFORMATION_SCHEMA", "POLICY_REFERENCES") + err := c.context.client.QueryOneForTests(ctx, s, fmt.Sprintf(`SELECT * FROM TABLE(%s(REF_ENTITY_NAME => '%s', REF_ENTITY_DOMAIN => '%v'))`, policyReferencesId.FullyQualifiedName(), id.FullyQualifiedName(), objectType)) + + return s, err +} diff --git a/pkg/acceptance/helpers/projection_policy_client.go b/pkg/acceptance/helpers/projection_policy_client.go new file mode 100644 index 0000000000..4adf3c07d4 --- /dev/null +++ b/pkg/acceptance/helpers/projection_policy_client.go @@ -0,0 +1,47 @@ +package helpers + +import ( + "context" + "fmt" + "testing" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/stretchr/testify/require" +) + +// TODO(SNOW-1564959): change raw sqls to proper client +type ProjectionPolicyClient struct { + context *TestClientContext + ids *IdsGenerator +} + +func NewProjectionPolicyClient(context *TestClientContext, idsGenerator *IdsGenerator) *ProjectionPolicyClient { + return &ProjectionPolicyClient{ + context: context, + ids: idsGenerator, + } +} + +func (c *ProjectionPolicyClient) client() *sdk.Client { + return c.context.client +} + +func (c *ProjectionPolicyClient) CreateProjectionPolicy(t *testing.T) (sdk.SchemaObjectIdentifier, func()) { + t.Helper() + ctx := context.Background() + + id := c.ids.RandomSchemaObjectIdentifier() + _, err := c.client().ExecForTests(ctx, fmt.Sprintf(`CREATE PROJECTION POLICY %s AS () RETURNS PROJECTION_CONSTRAINT -> PROJECTION_CONSTRAINT(ALLOW => false)`, id.Name())) + require.NoError(t, err) + return id, c.DropProjectionPolicyFunc(t, id) +} + +func (c *ProjectionPolicyClient) DropProjectionPolicyFunc(t *testing.T, id sdk.SchemaObjectIdentifier) func() { + t.Helper() + ctx := context.Background() + + return func() { + _, err := c.client().ExecForTests(ctx, fmt.Sprintf(`DROP PROJECTION POLICY IF EXISTS %s`, id.Name())) + require.NoError(t, err) + } +} diff --git a/pkg/acceptance/helpers/row_access_policy_client.go b/pkg/acceptance/helpers/row_access_policy_client.go index 280afe3071..29d8700f08 100644 --- a/pkg/acceptance/helpers/row_access_policy_client.go +++ b/pkg/acceptance/helpers/row_access_policy_client.go @@ -2,8 +2,6 @@ package helpers import ( "context" - "database/sql" - "fmt" "testing" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -53,33 +51,3 @@ func (c *RowAccessPolicyClient) DropRowAccessPolicyFunc(t *testing.T, id sdk.Sch require.NoError(t, err) } } - -// GetRowAccessPolicyFor is based on https://docs.snowflake.com/en/user-guide/security-row-intro#obtain-database-objects-with-a-row-access-policy. -// TODO: extract getting row access policies as resource (like getting tag in system functions) -func (c *RowAccessPolicyClient) GetRowAccessPolicyFor(t *testing.T, id sdk.SchemaObjectIdentifier, objectType sdk.ObjectType) (*PolicyReference, error) { - t.Helper() - ctx := context.Background() - - s := &PolicyReference{} - policyReferencesId := sdk.NewSchemaObjectIdentifier(id.DatabaseName(), "INFORMATION_SCHEMA", "POLICY_REFERENCES") - err := c.context.client.QueryOneForTests(ctx, s, fmt.Sprintf(`SELECT * FROM TABLE(%s(REF_ENTITY_NAME => '%s', REF_ENTITY_DOMAIN => '%v'))`, policyReferencesId.FullyQualifiedName(), id.FullyQualifiedName(), objectType)) - - return s, err -} - -type PolicyReference struct { - PolicyDb string `db:"POLICY_DB"` - PolicySchema string `db:"POLICY_SCHEMA"` - PolicyName string `db:"POLICY_NAME"` - PolicyKind string `db:"POLICY_KIND"` - RefDatabaseName string `db:"REF_DATABASE_NAME"` - RefSchemaName string `db:"REF_SCHEMA_NAME"` - RefEntityName string `db:"REF_ENTITY_NAME"` - RefEntityDomain string `db:"REF_ENTITY_DOMAIN"` - RefColumnName sql.NullString `db:"REF_COLUMN_NAME"` - RefArgColumnNames string `db:"REF_ARG_COLUMN_NAMES"` - TagDatabase sql.NullString `db:"TAG_DATABASE"` - TagSchema sql.NullString `db:"TAG_SCHEMA"` - TagName sql.NullString `db:"TAG_NAME"` - PolicyStatus string `db:"POLICY_STATUS"` -} diff --git a/pkg/acceptance/helpers/test_client.go b/pkg/acceptance/helpers/test_client.go index c629c37a0e..e443b4fac1 100644 --- a/pkg/acceptance/helpers/test_client.go +++ b/pkg/acceptance/helpers/test_client.go @@ -9,44 +9,49 @@ type TestClient struct { Ids *IdsGenerator - Account *AccountClient - Alert *AlertClient - ApiIntegration *ApiIntegrationClient - Application *ApplicationClient - ApplicationPackage *ApplicationPackageClient - Context *ContextClient - CortexSearchService *CortexSearchServiceClient - CatalogIntegration *CatalogIntegrationClient - Database *DatabaseClient - DatabaseRole *DatabaseRoleClient - DynamicTable *DynamicTableClient - ExternalAccessIntegration *ExternalAccessIntegrationClient - ExternalVolume *ExternalVolumeClient - FailoverGroup *FailoverGroupClient - FileFormat *FileFormatClient - Grant *GrantClient - MaskingPolicy *MaskingPolicyClient - MaterializedView *MaterializedViewClient - NetworkPolicy *NetworkPolicyClient - NetworkRule *NetworkRuleClient - Parameter *ParameterClient - PasswordPolicy *PasswordPolicyClient - Pipe *PipeClient - ResourceMonitor *ResourceMonitorClient - Role *RoleClient - RowAccessPolicy *RowAccessPolicyClient - Schema *SchemaClient - SecurityIntegration *SecurityIntegrationClient - SessionPolicy *SessionPolicyClient - Share *ShareClient - Stage *StageClient - Streamlit *StreamlitClient - Table *TableClient - Tag *TagClient - Task *TaskClient - User *UserClient - View *ViewClient - Warehouse *WarehouseClient + Account *AccountClient + AggregationPolicy *AggregationPolicyClient + Alert *AlertClient + ApiIntegration *ApiIntegrationClient + Application *ApplicationClient + ApplicationPackage *ApplicationPackageClient + Context *ContextClient + CortexSearchService *CortexSearchServiceClient + CatalogIntegration *CatalogIntegrationClient + Database *DatabaseClient + DatabaseRole *DatabaseRoleClient + DataMetricFunctionClient *DataMetricFunctionClient + DataMetricFunctionReferences *DataMetricFunctionReferencesClient + DynamicTable *DynamicTableClient + ExternalAccessIntegration *ExternalAccessIntegrationClient + ExternalVolume *ExternalVolumeClient + FailoverGroup *FailoverGroupClient + FileFormat *FileFormatClient + Grant *GrantClient + MaskingPolicy *MaskingPolicyClient + MaterializedView *MaterializedViewClient + NetworkPolicy *NetworkPolicyClient + NetworkRule *NetworkRuleClient + Parameter *ParameterClient + PasswordPolicy *PasswordPolicyClient + Pipe *PipeClient + ProjectionPolicy *ProjectionPolicyClient + PolicyReferences *PolicyReferencesClient + ResourceMonitor *ResourceMonitorClient + Role *RoleClient + RowAccessPolicy *RowAccessPolicyClient + Schema *SchemaClient + SecurityIntegration *SecurityIntegrationClient + SessionPolicy *SessionPolicyClient + Share *ShareClient + Stage *StageClient + Streamlit *StreamlitClient + Table *TableClient + Tag *TagClient + Task *TaskClient + User *UserClient + View *ViewClient + Warehouse *WarehouseClient } func NewTestClient(c *sdk.Client, database string, schema string, warehouse string, testObjectSuffix string) *TestClient { @@ -63,44 +68,49 @@ func NewTestClient(c *sdk.Client, database string, schema string, warehouse stri Ids: idsGenerator, - Account: NewAccountClient(context), - Alert: NewAlertClient(context, idsGenerator), - ApiIntegration: NewApiIntegrationClient(context, idsGenerator), - Application: NewApplicationClient(context, idsGenerator), - ApplicationPackage: NewApplicationPackageClient(context, idsGenerator), - Context: NewContextClient(context), - CortexSearchService: NewCortexSearchServiceClient(context, idsGenerator), - CatalogIntegration: NewCatalogIntegrationClient(context, idsGenerator), - Database: NewDatabaseClient(context, idsGenerator), - DatabaseRole: NewDatabaseRoleClient(context, idsGenerator), - DynamicTable: NewDynamicTableClient(context, idsGenerator), - ExternalAccessIntegration: NewExternalAccessIntegrationClient(context, idsGenerator), - ExternalVolume: NewExternalVolumeClient(context, idsGenerator), - FailoverGroup: NewFailoverGroupClient(context, idsGenerator), - FileFormat: NewFileFormatClient(context, idsGenerator), - Grant: NewGrantClient(context, idsGenerator), - MaskingPolicy: NewMaskingPolicyClient(context, idsGenerator), - MaterializedView: NewMaterializedViewClient(context, idsGenerator), - NetworkPolicy: NewNetworkPolicyClient(context, idsGenerator), - NetworkRule: NewNetworkRuleClient(context, idsGenerator), - Parameter: NewParameterClient(context), - PasswordPolicy: NewPasswordPolicyClient(context, idsGenerator), - Pipe: NewPipeClient(context, idsGenerator), - ResourceMonitor: NewResourceMonitorClient(context, idsGenerator), - Role: NewRoleClient(context, idsGenerator), - RowAccessPolicy: NewRowAccessPolicyClient(context, idsGenerator), - Schema: NewSchemaClient(context, idsGenerator), - SecurityIntegration: NewSecurityIntegrationClient(context, idsGenerator), - SessionPolicy: NewSessionPolicyClient(context, idsGenerator), - Share: NewShareClient(context, idsGenerator), - Streamlit: NewStreamlitClient(context, idsGenerator), - Stage: NewStageClient(context, idsGenerator), - Table: NewTableClient(context, idsGenerator), - Tag: NewTagClient(context, idsGenerator), - Task: NewTaskClient(context, idsGenerator), - User: NewUserClient(context, idsGenerator), - View: NewViewClient(context, idsGenerator), - Warehouse: NewWarehouseClient(context, idsGenerator), + Account: NewAccountClient(context), + AggregationPolicy: NewAggregationPolicyClient(context, idsGenerator), + Alert: NewAlertClient(context, idsGenerator), + ApiIntegration: NewApiIntegrationClient(context, idsGenerator), + Application: NewApplicationClient(context, idsGenerator), + ApplicationPackage: NewApplicationPackageClient(context, idsGenerator), + Context: NewContextClient(context), + CortexSearchService: NewCortexSearchServiceClient(context, idsGenerator), + CatalogIntegration: NewCatalogIntegrationClient(context, idsGenerator), + Database: NewDatabaseClient(context, idsGenerator), + DatabaseRole: NewDatabaseRoleClient(context, idsGenerator), + DataMetricFunctionClient: NewDataMetricFunctionClient(context, idsGenerator), + DataMetricFunctionReferences: NewDataMetricFunctionReferencesClient(context), + DynamicTable: NewDynamicTableClient(context, idsGenerator), + ExternalAccessIntegration: NewExternalAccessIntegrationClient(context, idsGenerator), + ExternalVolume: NewExternalVolumeClient(context, idsGenerator), + FailoverGroup: NewFailoverGroupClient(context, idsGenerator), + FileFormat: NewFileFormatClient(context, idsGenerator), + Grant: NewGrantClient(context, idsGenerator), + MaskingPolicy: NewMaskingPolicyClient(context, idsGenerator), + MaterializedView: NewMaterializedViewClient(context, idsGenerator), + NetworkPolicy: NewNetworkPolicyClient(context, idsGenerator), + NetworkRule: NewNetworkRuleClient(context, idsGenerator), + Parameter: NewParameterClient(context), + PasswordPolicy: NewPasswordPolicyClient(context, idsGenerator), + Pipe: NewPipeClient(context, idsGenerator), + ProjectionPolicy: NewProjectionPolicyClient(context, idsGenerator), + PolicyReferences: NewPolicyReferencesClient(context), + ResourceMonitor: NewResourceMonitorClient(context, idsGenerator), + Role: NewRoleClient(context, idsGenerator), + RowAccessPolicy: NewRowAccessPolicyClient(context, idsGenerator), + Schema: NewSchemaClient(context, idsGenerator), + SecurityIntegration: NewSecurityIntegrationClient(context, idsGenerator), + SessionPolicy: NewSessionPolicyClient(context, idsGenerator), + Share: NewShareClient(context, idsGenerator), + Streamlit: NewStreamlitClient(context, idsGenerator), + Stage: NewStageClient(context, idsGenerator), + Table: NewTableClient(context, idsGenerator), + Tag: NewTagClient(context, idsGenerator), + Task: NewTaskClient(context, idsGenerator), + User: NewUserClient(context, idsGenerator), + View: NewViewClient(context, idsGenerator), + Warehouse: NewWarehouseClient(context, idsGenerator), } } diff --git a/pkg/acceptance/helpers/view_client.go b/pkg/acceptance/helpers/view_client.go index 9c39c08888..0a1ae71632 100644 --- a/pkg/acceptance/helpers/view_client.go +++ b/pkg/acceptance/helpers/view_client.go @@ -43,7 +43,7 @@ func (c *ViewClient) RecreateView(t *testing.T, id sdk.SchemaObjectIdentifier, q t.Helper() ctx := context.Background() - err := c.client().Create(ctx, sdk.NewCreateViewRequest(id, query).WithOrReplace(sdk.Bool(true))) + err := c.client().Create(ctx, sdk.NewCreateViewRequest(id, query).WithOrReplace(true)) require.NoError(t, err) view, err := c.client().ShowByID(ctx, id) @@ -57,7 +57,14 @@ func (c *ViewClient) DropViewFunc(t *testing.T, id sdk.SchemaObjectIdentifier) f ctx := context.Background() return func() { - err := c.client().Drop(ctx, sdk.NewDropViewRequest(id).WithIfExists(sdk.Bool(true))) + err := c.client().Drop(ctx, sdk.NewDropViewRequest(id).WithIfExists(true)) require.NoError(t, err) } } + +func (c *ViewClient) Show(t *testing.T, id sdk.SchemaObjectIdentifier) (*sdk.View, error) { + t.Helper() + ctx := context.Background() + + return c.client().ShowByID(ctx, id) +} diff --git a/pkg/datasources/views.go b/pkg/datasources/views.go index e019971f41..2d17aa7d59 100644 --- a/pkg/datasources/views.go +++ b/pkg/datasources/views.go @@ -65,7 +65,7 @@ func ReadViews(d *schema.ResourceData, meta interface{}) error { schemaId := sdk.NewDatabaseObjectIdentifier(databaseName, schemaName) extractedViews, err := client.Views.Show(ctx, sdk.NewShowViewRequest().WithIn( - &sdk.In{Schema: schemaId}, + sdk.ExtendedIn{In: sdk.In{Schema: schemaId}}, )) if err != nil { log.Printf("[DEBUG] failed when searching views in schema (%s), err = %s", schemaId.FullyQualifiedName(), err.Error()) diff --git a/pkg/resources/view.go b/pkg/resources/view.go index 7d1e6c7233..8fea269008 100644 --- a/pkg/resources/view.go +++ b/pkg/resources/view.go @@ -105,19 +105,19 @@ func CreateView(d *schema.ResourceData, meta interface{}) error { createRequest := sdk.NewCreateViewRequest(id, s) if v, ok := d.GetOk("or_replace"); ok && v.(bool) { - createRequest.WithOrReplace(sdk.Bool(true)) + createRequest.WithOrReplace(true) } if v, ok := d.GetOk("is_secure"); ok && v.(bool) { - createRequest.WithSecure(sdk.Bool(true)) + createRequest.WithSecure(true) } if v, ok := d.GetOk("copy_grants"); ok && v.(bool) { - createRequest.WithCopyGrants(sdk.Bool(true)) + createRequest.WithCopyGrants(true) } if v, ok := d.GetOk("comment"); ok { - createRequest.WithComment(sdk.String(v.(string))) + createRequest.WithComment(v.(string)) } err := client.Views.Create(ctx, createRequest) @@ -206,13 +206,13 @@ func UpdateView(d *schema.ResourceData, meta interface{}) error { oldTags, _ := d.GetChange("tag") createRequest := sdk.NewCreateViewRequest(id, d.Get("statement").(string)). - WithOrReplace(sdk.Bool(true)). - WithCopyGrants(sdk.Bool(true)). - WithComment(sdk.String(oldComment.(string))). + WithOrReplace(true). + WithCopyGrants(true). + WithComment(oldComment.(string)). WithTag(getTagsFromList(oldTags.([]any))) if oldIsSecure.(bool) { - createRequest.WithSecure(sdk.Bool(true)) + createRequest.WithSecure(true) } err := client.Views.Create(ctx, createRequest) @@ -224,7 +224,7 @@ func UpdateView(d *schema.ResourceData, meta interface{}) error { if d.HasChange("name") { newId := sdk.NewSchemaObjectIdentifierInSchema(id.SchemaId(), d.Get("name").(string)) - err := client.Views.Alter(ctx, sdk.NewAlterViewRequest(id).WithRenameTo(&newId)) + err := client.Views.Alter(ctx, sdk.NewAlterViewRequest(id).WithRenameTo(newId)) if err != nil { return fmt.Errorf("error renaming view %v err = %w", d.Id(), err) } @@ -235,12 +235,12 @@ func UpdateView(d *schema.ResourceData, meta interface{}) error { if d.HasChange("comment") { if comment := d.Get("comment").(string); comment == "" { - err := client.Views.Alter(ctx, sdk.NewAlterViewRequest(id).WithUnsetComment(sdk.Bool(true))) + err := client.Views.Alter(ctx, sdk.NewAlterViewRequest(id).WithUnsetComment(true)) if err != nil { return fmt.Errorf("error unsetting comment for view %v", d.Id()) } } else { - err := client.Views.Alter(ctx, sdk.NewAlterViewRequest(id).WithSetComment(sdk.String(comment))) + err := client.Views.Alter(ctx, sdk.NewAlterViewRequest(id).WithSetComment(comment)) if err != nil { return fmt.Errorf("error updating comment for view %v", d.Id()) } @@ -249,12 +249,12 @@ func UpdateView(d *schema.ResourceData, meta interface{}) error { if d.HasChange("is_secure") { if d.Get("is_secure").(bool) { - err := client.Views.Alter(ctx, sdk.NewAlterViewRequest(id).WithSetSecure(sdk.Bool(true))) + err := client.Views.Alter(ctx, sdk.NewAlterViewRequest(id).WithSetSecure(true)) if err != nil { return fmt.Errorf("error setting secure for view %v", d.Id()) } } else { - err := client.Views.Alter(ctx, sdk.NewAlterViewRequest(id).WithUnsetSecure(sdk.Bool(true))) + err := client.Views.Alter(ctx, sdk.NewAlterViewRequest(id).WithUnsetSecure(true)) if err != nil { return fmt.Errorf("error unsetting secure for view %v", d.Id()) } diff --git a/pkg/sdk/common_types.go b/pkg/sdk/common_types.go index 6b1294b7e1..8455f8526b 100644 --- a/pkg/sdk/common_types.go +++ b/pkg/sdk/common_types.go @@ -57,6 +57,12 @@ type In struct { Schema DatabaseObjectIdentifier `ddl:"identifier" sql:"SCHEMA"` } +type ExtendedIn struct { + In + Application AccountObjectIdentifier `ddl:"identifier" sql:"APPLICATION"` + ApplicationPackage AccountObjectIdentifier `ddl:"identifier" sql:"APPLICATION PACKAGE"` +} + type Like struct { Pattern *string `ddl:"keyword,single_quotes"` } diff --git a/pkg/sdk/poc/generator/keyword_builders.go b/pkg/sdk/poc/generator/keyword_builders.go index dc72e34b7d..556c5fbbcc 100644 --- a/pkg/sdk/poc/generator/keyword_builders.go +++ b/pkg/sdk/poc/generator/keyword_builders.go @@ -106,6 +106,10 @@ func (v *QueryStruct) OptionalIn() *QueryStruct { return v.PredefinedQueryStructField("In", "*In", KeywordOptions().SQL("IN")) } +func (v *QueryStruct) OptionalExtendedIn() *QueryStruct { + return v.PredefinedQueryStructField("In", "*ExtendedIn", KeywordOptions().SQL("IN")) +} + func (v *QueryStruct) OptionalStartsWith() *QueryStruct { return v.PredefinedQueryStructField("StartsWith", "*string", ParameterOptions().NoEquals().SingleQuotes().SQL("STARTS WITH")) } diff --git a/pkg/sdk/poc/main.go b/pkg/sdk/poc/main.go index ed5b340deb..f8f1014bdb 100644 --- a/pkg/sdk/poc/main.go +++ b/pkg/sdk/poc/main.go @@ -10,6 +10,7 @@ import ( "os" "strings" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/genhelpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/poc/example" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/poc/generator" diff --git a/pkg/sdk/policy_references.go b/pkg/sdk/policy_references.go index 6e782009bf..b5aeb6c361 100644 --- a/pkg/sdk/policy_references.go +++ b/pkg/sdk/policy_references.go @@ -3,6 +3,8 @@ package sdk import ( "context" "database/sql" + "fmt" + "strings" ) var _ convertibleRow[PolicyReference] = new(policyReferenceDBRow) @@ -32,6 +34,35 @@ const ( PolicyEntityDomainView PolicyEntityDomain = "VIEW" ) +var AllPolicyEntityDomains = []PolicyEntityDomain{ + PolicyEntityDomainAccount, + PolicyEntityDomainIntegration, + PolicyEntityDomainTable, + PolicyEntityDomainTag, + PolicyEntityDomainUser, + PolicyEntityDomainView, +} + +func ToPolicyEntityDomain(s string) (PolicyEntityDomain, error) { + s = strings.ToUpper(s) + switch s { + case string(PolicyEntityDomainAccount): + return PolicyEntityDomainAccount, nil + case string(PolicyEntityDomainIntegration): + return PolicyEntityDomainIntegration, nil + case string(PolicyEntityDomainTable): + return PolicyEntityDomainTable, nil + case string(PolicyEntityDomainTag): + return PolicyEntityDomainTag, nil + case string(PolicyEntityDomainUser): + return PolicyEntityDomainUser, nil + case string(PolicyEntityDomainView): + return PolicyEntityDomainView, nil + default: + return "", fmt.Errorf("invalid PolicyEntityDomain: %s", s) + } +} + type policyReferenceFunctionArguments struct { refEntityName []ObjectIdentifier `ddl:"parameter,single_quotes,arrow_equals" sql:"REF_ENTITY_NAME"` refEntityDomain *PolicyEntityDomain `ddl:"parameter,single_quotes,arrow_equals" sql:"REF_ENTITY_DOMAIN"` diff --git a/pkg/sdk/testint/event_tables_integration_test.go b/pkg/sdk/testint/event_tables_integration_test.go index ec43a812a9..6ecfb53a44 100644 --- a/pkg/sdk/testint/event_tables_integration_test.go +++ b/pkg/sdk/testint/event_tables_integration_test.go @@ -224,7 +224,7 @@ func TestInt_EventTables(t *testing.T) { err := client.EventTables.Alter(ctx, alterRequest) require.NoError(t, err) - e, err := testClientHelper().RowAccessPolicy.GetRowAccessPolicyFor(t, table.ID(), sdk.ObjectTypeTable) + e, err := testClientHelper().PolicyReferences.GetPolicyReference(t, table.ID(), sdk.ObjectTypeTable) require.NoError(t, err) assert.Equal(t, rowAccessPolicy.ID().Name(), e.PolicyName) assert.Equal(t, "ROW_ACCESS_POLICY", e.PolicyKind) @@ -237,7 +237,7 @@ func TestInt_EventTables(t *testing.T) { err = client.EventTables.Alter(ctx, alterRequest) require.NoError(t, err) - _, err = testClientHelper().RowAccessPolicy.GetRowAccessPolicyFor(t, table.ID(), sdk.ObjectTypeTable) + _, err = testClientHelper().PolicyReferences.GetPolicyReference(t, table.ID(), sdk.ObjectTypeTable) require.Error(t, err, "no rows in result set") // add policy again @@ -245,7 +245,7 @@ func TestInt_EventTables(t *testing.T) { err = client.EventTables.Alter(ctx, alterRequest) require.NoError(t, err) - e, err = testClientHelper().RowAccessPolicy.GetRowAccessPolicyFor(t, table.ID(), sdk.ObjectTypeTable) + e, err = testClientHelper().PolicyReferences.GetPolicyReference(t, table.ID(), sdk.ObjectTypeTable) require.NoError(t, err) assert.Equal(t, rowAccessPolicy.ID().Name(), e.PolicyName) @@ -257,7 +257,7 @@ func TestInt_EventTables(t *testing.T) { err = client.EventTables.Alter(ctx, alterRequest) require.NoError(t, err) - e, err = testClientHelper().RowAccessPolicy.GetRowAccessPolicyFor(t, table.ID(), sdk.ObjectTypeTable) + e, err = testClientHelper().PolicyReferences.GetPolicyReference(t, table.ID(), sdk.ObjectTypeTable) require.NoError(t, err) assert.Equal(t, rowAccessPolicy2.ID().Name(), e.PolicyName) @@ -266,7 +266,7 @@ func TestInt_EventTables(t *testing.T) { err = client.EventTables.Alter(ctx, alterRequest) require.NoError(t, err) - _, err = testClientHelper().RowAccessPolicy.GetRowAccessPolicyFor(t, table.ID(), sdk.ObjectTypeView) + _, err = testClientHelper().PolicyReferences.GetPolicyReference(t, table.ID(), sdk.ObjectTypeView) require.Error(t, err, "no rows in result set") }) } diff --git a/pkg/sdk/testint/materialized_views_gen_integration_test.go b/pkg/sdk/testint/materialized_views_gen_integration_test.go index 61b06c18e1..5fdf47085b 100644 --- a/pkg/sdk/testint/materialized_views_gen_integration_test.go +++ b/pkg/sdk/testint/materialized_views_gen_integration_test.go @@ -136,7 +136,7 @@ func TestInt_MaterializedViews(t *testing.T) { view := createMaterializedViewWithRequest(t, request) assertMaterializedViewWithOptions(t, view, id, true, "comment", fmt.Sprintf(`LINEAR("%s")`, "COLUMN_WITH_COMMENT")) - rowAccessPolicyReference, err := testClientHelper().RowAccessPolicy.GetRowAccessPolicyFor(t, view.ID(), sdk.ObjectTypeView) + rowAccessPolicyReference, err := testClientHelper().PolicyReferences.GetPolicyReference(t, view.ID(), sdk.ObjectTypeView) require.NoError(t, err) assert.Equal(t, rowAccessPolicy.Name, rowAccessPolicyReference.PolicyName) assert.Equal(t, "ROW_ACCESS_POLICY", rowAccessPolicyReference.PolicyKind) diff --git a/pkg/sdk/testint/views_gen_integration_test.go b/pkg/sdk/testint/views_gen_integration_test.go index 707b7292df..8d4510cdae 100644 --- a/pkg/sdk/testint/views_gen_integration_test.go +++ b/pkg/sdk/testint/views_gen_integration_test.go @@ -1,18 +1,23 @@ package testint import ( + "cmp" "errors" "fmt" + "slices" "testing" + assertions "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert/objectassert" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/snowflakeroles" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/internal/collections" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -// TODO [SNOW-1016430]: add tests for setting masking policy on creation -// TODO [SNOW-1016430]: add tests for setting recursive on creation func TestInt_Views(t *testing.T) { client := testClient(t) ctx := testContext(t) @@ -24,20 +29,20 @@ func TestInt_Views(t *testing.T) { assertViewWithOptions := func(t *testing.T, view *sdk.View, id sdk.SchemaObjectIdentifier, isSecure bool, comment string) { t.Helper() - assert.NotEmpty(t, view.CreatedOn) - assert.Equal(t, id.Name(), view.Name) - // Kind is filled out only in TERSE response. - assert.Empty(t, view.Kind) - assert.Empty(t, view.Reserved) - assert.Equal(t, testDb(t).Name, view.DatabaseName) - assert.Equal(t, testSchema(t).Name, view.SchemaName) - assert.Equal(t, "ACCOUNTADMIN", view.Owner) - assert.Equal(t, comment, view.Comment) - assert.NotEmpty(t, view.Text) - assert.Equal(t, isSecure, view.IsSecure) - assert.Equal(t, false, view.IsMaterialized) - assert.Equal(t, "ROLE", view.OwnerRoleType) - assert.Equal(t, "OFF", view.ChangeTracking) + assertions.AssertThatObject(t, objectassert.ViewFromObject(t, view). + HasCreatedOnNotEmpty(). + HasName(id.Name()). + HasKind(""). + HasReserved(""). + HasDatabaseName(testDb(t).Name). + HasSchemaName(testSchema(t).Name). + HasOwner(snowflakeroles.Accountadmin.Name()). + HasComment(comment). + HasNonEmptyText(). + HasIsSecure(isSecure). + HasIsMaterialized(false). + HasOwnerRoleType("ROLE"). + HasChangeTracking("OFF")) } assertView := func(t *testing.T, view *sdk.View, id sdk.SchemaObjectIdentifier) { @@ -47,21 +52,21 @@ func TestInt_Views(t *testing.T) { assertViewTerse := func(t *testing.T, view *sdk.View, id sdk.SchemaObjectIdentifier) { t.Helper() - assert.NotEmpty(t, view.CreatedOn) - assert.Equal(t, id.Name(), view.Name) - assert.Equal(t, "VIEW", view.Kind) - assert.Equal(t, testDb(t).Name, view.DatabaseName) - assert.Equal(t, testSchema(t).Name, view.SchemaName) - - // all below are not contained in the terse response, that's why all of them we expect to be empty - assert.Empty(t, view.Reserved) - assert.Empty(t, view.Owner) - assert.Empty(t, view.Comment) - assert.Empty(t, view.Text) - assert.Empty(t, view.IsSecure) - assert.Empty(t, view.IsMaterialized) - assert.Empty(t, view.OwnerRoleType) - assert.Empty(t, view.ChangeTracking) + assertions.AssertThatObject(t, objectassert.ViewFromObject(t, view). + HasCreatedOnNotEmpty(). + HasName(id.Name()). + HasKind("VIEW"). + HasDatabaseName(testDb(t).Name). + HasSchemaName(testSchema(t).Name). + // all below are not contained in the terse response, that's why all of them we expect to be empty + HasReserved(""). + HasOwner(""). + HasComment(""). + HasText(""). + HasIsSecure(false). + HasIsMaterialized(false). + HasOwnerRoleType(""). + HasChangeTracking("")) } assertViewDetailsRow := func(t *testing.T, viewDetails *sdk.ViewDetails) { @@ -81,6 +86,36 @@ func TestInt_Views(t *testing.T) { }, *viewDetails) } + assertPolicyReference := func(t *testing.T, policyRef helpers.PolicyReference, + policyId sdk.SchemaObjectIdentifier, + policyType string, + viewId sdk.SchemaObjectIdentifier, + refColumnName *string, + ) { + t.Helper() + assert.Equal(t, policyId.Name(), policyRef.PolicyName) + assert.Equal(t, policyType, policyRef.PolicyKind) + assert.Equal(t, viewId.Name(), policyRef.RefEntityName) + assert.Equal(t, "VIEW", policyRef.RefEntityDomain) + assert.Equal(t, "ACTIVE", policyRef.PolicyStatus) + if refColumnName != nil { + assert.True(t, policyRef.RefColumnName.Valid) + assert.Equal(t, *refColumnName, policyRef.RefColumnName.String) + } else { + assert.False(t, policyRef.RefColumnName.Valid) + } + } + + assertDataMetricFunctionReference := func(t *testing.T, dataMetricFunctionReference helpers.DataMetricFunctionReference, + viewId sdk.SchemaObjectIdentifier, + schedule string, + ) { + t.Helper() + assert.Equal(t, viewId.Name(), dataMetricFunctionReference.RefEntityName) + assert.Equal(t, "View", dataMetricFunctionReference.RefEntityDomain) + assert.Equal(t, schedule, dataMetricFunctionReference.Schedule) + } + cleanupViewProvider := func(id sdk.SchemaObjectIdentifier) func() { return func() { err := client.Views.Drop(ctx, sdk.NewDropViewRequest(id)) @@ -132,23 +167,27 @@ func TestInt_Views(t *testing.T) { assertView(t, view, request.GetName()) }) - t.Run("create view: almost complete case", func(t *testing.T) { + t.Run("create view: almost complete case - without masking and projection policies", func(t *testing.T) { rowAccessPolicy, rowAccessPolicyCleanup := testClientHelper().RowAccessPolicy.CreateRowAccessPolicy(t) t.Cleanup(rowAccessPolicyCleanup) + aggregationPolicy, aggregationPolicyCleanup := testClientHelper().AggregationPolicy.CreateAggregationPolicy(t) + t.Cleanup(aggregationPolicyCleanup) + tag, tagCleanup := testClientHelper().Tag.CreateTag(t) t.Cleanup(tagCleanup) request := createViewBasicRequest(t). - WithOrReplace(sdk.Bool(true)). - WithSecure(sdk.Bool(true)). - WithTemporary(sdk.Bool(true)). + WithOrReplace(true). + WithSecure(true). + WithTemporary(true). WithColumns([]sdk.ViewColumnRequest{ - *sdk.NewViewColumnRequest("COLUMN_WITH_COMMENT").WithComment(sdk.String("column comment")), + *sdk.NewViewColumnRequest("column_with_comment").WithComment("column comment"), }). - WithCopyGrants(sdk.Bool(true)). - WithComment(sdk.String("comment")). - WithRowAccessPolicy(sdk.NewViewRowAccessPolicyRequest(rowAccessPolicy.ID(), []string{"column_with_comment"})). + WithCopyGrants(true). + WithComment("comment"). + WithRowAccessPolicy(*sdk.NewViewRowAccessPolicyRequest(rowAccessPolicy.ID(), []sdk.DoubleQuotedString{{Value: "column_with_comment"}})). + WithAggregationPolicy(*sdk.NewViewAggregationPolicyRequest(aggregationPolicy).WithEntityKey([]sdk.DoubleQuotedString{{Value: "column_with_comment"}})). WithTag([]sdk.TagAssociation{{ Name: tag.ID(), Value: "v2", @@ -159,13 +198,55 @@ func TestInt_Views(t *testing.T) { view := createViewWithRequest(t, request) assertViewWithOptions(t, view, id, true, "comment") - rowAccessPolicyReference, err := testClientHelper().RowAccessPolicy.GetRowAccessPolicyFor(t, view.ID(), sdk.ObjectTypeView) + rowAccessPolicyReferences, err := testClientHelper().PolicyReferences.GetPolicyReferences(t, view.ID(), sdk.ObjectTypeView) + require.NoError(t, err) + assert.Len(t, rowAccessPolicyReferences, 2) + slices.SortFunc(rowAccessPolicyReferences, func(x, y helpers.PolicyReference) int { + return cmp.Compare(x.PolicyKind, y.PolicyKind) + }) + + assertPolicyReference(t, rowAccessPolicyReferences[0], aggregationPolicy, "AGGREGATION_POLICY", view.ID(), nil) + + assertPolicyReference(t, rowAccessPolicyReferences[1], rowAccessPolicy.ID(), "ROW_ACCESS_POLICY", view.ID(), nil) + assert.True(t, rowAccessPolicyReferences[1].RefArgColumnNames.Valid) + refArgColumnNames := sdk.ParseCommaSeparatedStringArray(rowAccessPolicyReferences[1].RefArgColumnNames.String, true) + assert.Len(t, refArgColumnNames, 1) + assert.Equal(t, "column_with_comment", refArgColumnNames[0]) + }) + + t.Run("create view: masking and projection policies", func(t *testing.T) { + maskingPolicy, maskingPolicyCleanup := testClientHelper().MaskingPolicy.CreateMaskingPolicyIdentity(t, sdk.DataTypeNumber) + t.Cleanup(maskingPolicyCleanup) + + projectionPolicy, projectionPolicyCleanup := testClientHelper().ProjectionPolicy.CreateProjectionPolicy(t) + t.Cleanup(projectionPolicyCleanup) + + request := createViewBasicRequest(t). + WithOrReplace(true). + WithRecursive(true). + WithColumns([]sdk.ViewColumnRequest{ + *sdk.NewViewColumnRequest("col1").WithMaskingPolicy( + *sdk.NewViewColumnMaskingPolicyRequest(maskingPolicy.ID()).WithUsing([]sdk.DoubleQuotedString{{Value: "col1"}}), + ).WithProjectionPolicy( + *sdk.NewViewColumnProjectionPolicyRequest(projectionPolicy), + ), + }) + + id := request.GetName() + + view := createViewWithRequest(t, request) + + assertViewWithOptions(t, view, id, false, "") + assert.Contains(t, view.Text, "RECURSIVE VIEW") + rowAccessPolicyReferences, err := testClientHelper().PolicyReferences.GetPolicyReferences(t, view.ID(), sdk.ObjectTypeView) require.NoError(t, err) - assert.Equal(t, rowAccessPolicy.Name, rowAccessPolicyReference.PolicyName) - assert.Equal(t, "ROW_ACCESS_POLICY", rowAccessPolicyReference.PolicyKind) - assert.Equal(t, view.ID().Name(), rowAccessPolicyReference.RefEntityName) - assert.Equal(t, "VIEW", rowAccessPolicyReference.RefEntityDomain) - assert.Equal(t, "ACTIVE", rowAccessPolicyReference.PolicyStatus) + assert.Len(t, rowAccessPolicyReferences, 2) + slices.SortFunc(rowAccessPolicyReferences, func(x, y helpers.PolicyReference) int { + return cmp.Compare(x.PolicyKind, y.PolicyKind) + }) + + assertPolicyReference(t, rowAccessPolicyReferences[0], maskingPolicy.ID(), "MASKING_POLICY", view.ID(), sdk.Pointer("col1")) + assertPolicyReference(t, rowAccessPolicyReferences[1], projectionPolicy, "PROJECTION_POLICY", view.ID(), sdk.Pointer("col1")) }) t.Run("drop view: existing", func(t *testing.T) { @@ -195,7 +276,7 @@ func TestInt_Views(t *testing.T) { require.NoError(t, err) newId := testClientHelper().Ids.RandomSchemaObjectIdentifier() - alterRequest := sdk.NewAlterViewRequest(id).WithRenameTo(&newId) + alterRequest := sdk.NewAlterViewRequest(id).WithRenameTo(newId) err = client.Views.Alter(ctx, alterRequest) if err != nil { @@ -218,7 +299,7 @@ func TestInt_Views(t *testing.T) { view := createView(t) id := view.ID() - alterRequest := sdk.NewAlterViewRequest(id).WithSetComment(sdk.String("new comment")) + alterRequest := sdk.NewAlterViewRequest(id).WithSetComment("new comment") err := client.Views.Alter(ctx, alterRequest) require.NoError(t, err) @@ -227,7 +308,7 @@ func TestInt_Views(t *testing.T) { assert.Equal(t, "new comment", alteredView.Comment) - alterRequest = sdk.NewAlterViewRequest(id).WithSetSecure(sdk.Bool(true)) + alterRequest = sdk.NewAlterViewRequest(id).WithSetSecure(true) err = client.Views.Alter(ctx, alterRequest) require.NoError(t, err) @@ -236,7 +317,7 @@ func TestInt_Views(t *testing.T) { assert.Equal(t, true, alteredView.IsSecure) - alterRequest = sdk.NewAlterViewRequest(id).WithSetChangeTracking(sdk.Bool(true)) + alterRequest = sdk.NewAlterViewRequest(id).WithSetChangeTracking(true) err = client.Views.Alter(ctx, alterRequest) require.NoError(t, err) @@ -245,7 +326,7 @@ func TestInt_Views(t *testing.T) { assert.Equal(t, "ON", alteredView.ChangeTracking) - alterRequest = sdk.NewAlterViewRequest(id).WithUnsetComment(sdk.Bool(true)) + alterRequest = sdk.NewAlterViewRequest(id).WithUnsetComment(true) err = client.Views.Alter(ctx, alterRequest) require.NoError(t, err) @@ -254,7 +335,7 @@ func TestInt_Views(t *testing.T) { assert.Equal(t, "", alteredView.Comment) - alterRequest = sdk.NewAlterViewRequest(id).WithUnsetSecure(sdk.Bool(true)) + alterRequest = sdk.NewAlterViewRequest(id).WithUnsetSecure(true) err = client.Views.Alter(ctx, alterRequest) require.NoError(t, err) @@ -263,7 +344,7 @@ func TestInt_Views(t *testing.T) { assert.Equal(t, false, alteredView.IsSecure) - alterRequest = sdk.NewAlterViewRequest(id).WithSetChangeTracking(sdk.Bool(false)) + alterRequest = sdk.NewAlterViewRequest(id).WithSetChangeTracking(false) err = client.Views.Alter(ctx, alterRequest) require.NoError(t, err) @@ -311,7 +392,7 @@ func TestInt_Views(t *testing.T) { require.Error(t, err) }) - t.Run("alter view: set and unset masking policy", func(t *testing.T) { + t.Run("alter view: set and unset masking policy on column", func(t *testing.T) { maskingPolicy, maskingPolicyCleanup := testClientHelper().MaskingPolicy.CreateMaskingPolicyIdentity(t, sdk.DataTypeNumber) t.Cleanup(maskingPolicyCleanup) @@ -319,7 +400,7 @@ func TestInt_Views(t *testing.T) { id := view.ID() alterRequest := sdk.NewAlterViewRequest(id).WithSetMaskingPolicyOnColumn( - sdk.NewViewSetColumnMaskingPolicyRequest("id", maskingPolicy.ID()), + *sdk.NewViewSetColumnMaskingPolicyRequest("ID", maskingPolicy.ID()), ) err := client.Views.Alter(ctx, alterRequest) require.NoError(t, err) @@ -332,7 +413,7 @@ func TestInt_Views(t *testing.T) { assert.Equal(t, maskingPolicy.ID().FullyQualifiedName(), sdk.NewSchemaObjectIdentifierFromFullyQualifiedName(*alteredViewDetails[0].PolicyName).FullyQualifiedName()) alterRequest = sdk.NewAlterViewRequest(id).WithUnsetMaskingPolicyOnColumn( - sdk.NewViewUnsetColumnMaskingPolicyRequest("id"), + *sdk.NewViewUnsetColumnMaskingPolicyRequest("ID"), ) err = client.Views.Alter(ctx, alterRequest) require.NoError(t, err) @@ -344,6 +425,35 @@ func TestInt_Views(t *testing.T) { assert.Empty(t, alteredViewDetails[0].PolicyName) }) + t.Run("alter view: set and unset projection policy on column", func(t *testing.T) { + projectionPolicy, projectionPolicyCleanup := testClientHelper().ProjectionPolicy.CreateProjectionPolicy(t) + t.Cleanup(projectionPolicyCleanup) + + view := createView(t) + id := view.ID() + + alterRequest := sdk.NewAlterViewRequest(id).WithSetProjectionPolicyOnColumn( + *sdk.NewViewSetProjectionPolicyRequest("ID", projectionPolicy), + ) + err := client.Views.Alter(ctx, alterRequest) + require.NoError(t, err) + + rowAccessPolicyReferences, err := testClientHelper().PolicyReferences.GetPolicyReferences(t, view.ID(), sdk.ObjectTypeView) + require.NoError(t, err) + require.Len(t, rowAccessPolicyReferences, 1) + + assertPolicyReference(t, rowAccessPolicyReferences[0], projectionPolicy, "PROJECTION_POLICY", view.ID(), sdk.Pointer("ID")) + + alterRequest = sdk.NewAlterViewRequest(id).WithUnsetProjectionPolicyOnColumn( + *sdk.NewViewUnsetProjectionPolicyRequest("ID"), + ) + err = client.Views.Alter(ctx, alterRequest) + require.NoError(t, err) + + _, err = testClientHelper().PolicyReferences.GetPolicyReference(t, view.ID(), sdk.ObjectTypeView) + require.Error(t, err, "no rows in result set") + }) + t.Run("alter view: set and unset tags on column", func(t *testing.T) { tag, tagCleanup := testClientHelper().Tag.CreateTag(t) t.Cleanup(tagCleanup) @@ -360,7 +470,7 @@ func TestInt_Views(t *testing.T) { } alterRequest := sdk.NewAlterViewRequest(id).WithSetTagsOnColumn( - sdk.NewViewSetColumnTagsRequest("id", tags), + *sdk.NewViewSetColumnTagsRequest("ID", tags), ) err := client.Views.Alter(ctx, alterRequest) require.NoError(t, err) @@ -375,7 +485,7 @@ func TestInt_Views(t *testing.T) { } alterRequest = sdk.NewAlterViewRequest(id).WithUnsetTagsOnColumn( - sdk.NewViewUnsetColumnTagsRequest("id", unsetTags), + *sdk.NewViewUnsetColumnTagsRequest("ID", unsetTags), ) err = client.Views.Alter(ctx, alterRequest) require.NoError(t, err) @@ -394,53 +504,167 @@ func TestInt_Views(t *testing.T) { id := view.ID() // add policy - alterRequest := sdk.NewAlterViewRequest(id).WithAddRowAccessPolicy(sdk.NewViewAddRowAccessPolicyRequest(rowAccessPolicy.ID(), []string{"ID"})) + alterRequest := sdk.NewAlterViewRequest(id).WithAddRowAccessPolicy(*sdk.NewViewAddRowAccessPolicyRequest(rowAccessPolicy.ID(), []sdk.DoubleQuotedString{{Value: "ID"}})) err := client.Views.Alter(ctx, alterRequest) require.NoError(t, err) - rowAccessPolicyReference, err := testClientHelper().RowAccessPolicy.GetRowAccessPolicyFor(t, view.ID(), sdk.ObjectTypeView) + rowAccessPolicyReference, err := testClientHelper().PolicyReferences.GetPolicyReference(t, view.ID(), sdk.ObjectTypeView) require.NoError(t, err) - assert.Equal(t, rowAccessPolicy.ID().Name(), rowAccessPolicyReference.PolicyName) - assert.Equal(t, "ROW_ACCESS_POLICY", rowAccessPolicyReference.PolicyKind) - assert.Equal(t, view.ID().Name(), rowAccessPolicyReference.RefEntityName) - assert.Equal(t, "VIEW", rowAccessPolicyReference.RefEntityDomain) - assert.Equal(t, "ACTIVE", rowAccessPolicyReference.PolicyStatus) + + assertPolicyReference(t, *rowAccessPolicyReference, rowAccessPolicy.ID(), "ROW_ACCESS_POLICY", view.ID(), nil) // remove policy - alterRequest = sdk.NewAlterViewRequest(id).WithDropRowAccessPolicy(sdk.NewViewDropRowAccessPolicyRequest(rowAccessPolicy.ID())) + alterRequest = sdk.NewAlterViewRequest(id).WithDropRowAccessPolicy(*sdk.NewViewDropRowAccessPolicyRequest(rowAccessPolicy.ID())) err = client.Views.Alter(ctx, alterRequest) require.NoError(t, err) - _, err = testClientHelper().RowAccessPolicy.GetRowAccessPolicyFor(t, view.ID(), sdk.ObjectTypeView) + _, err = testClientHelper().PolicyReferences.GetPolicyReference(t, view.ID(), sdk.ObjectTypeView) require.Error(t, err, "no rows in result set") // add policy again - alterRequest = sdk.NewAlterViewRequest(id).WithAddRowAccessPolicy(sdk.NewViewAddRowAccessPolicyRequest(rowAccessPolicy.ID(), []string{"ID"})) + alterRequest = sdk.NewAlterViewRequest(id).WithAddRowAccessPolicy(*sdk.NewViewAddRowAccessPolicyRequest(rowAccessPolicy.ID(), []sdk.DoubleQuotedString{{Value: "ID"}})) err = client.Views.Alter(ctx, alterRequest) require.NoError(t, err) - rowAccessPolicyReference, err = testClientHelper().RowAccessPolicy.GetRowAccessPolicyFor(t, view.ID(), sdk.ObjectTypeView) + rowAccessPolicyReference, err = testClientHelper().PolicyReferences.GetPolicyReference(t, view.ID(), sdk.ObjectTypeView) require.NoError(t, err) assert.Equal(t, rowAccessPolicy.ID().Name(), rowAccessPolicyReference.PolicyName) // drop and add other policy simultaneously - alterRequest = sdk.NewAlterViewRequest(id).WithDropAndAddRowAccessPolicy(sdk.NewViewDropAndAddRowAccessPolicyRequest( + alterRequest = sdk.NewAlterViewRequest(id).WithDropAndAddRowAccessPolicy(*sdk.NewViewDropAndAddRowAccessPolicyRequest( *sdk.NewViewDropRowAccessPolicyRequest(rowAccessPolicy.ID()), - *sdk.NewViewAddRowAccessPolicyRequest(rowAccessPolicy2.ID(), []string{"ID"}), + *sdk.NewViewAddRowAccessPolicyRequest(rowAccessPolicy2.ID(), []sdk.DoubleQuotedString{{Value: "ID"}}), )) err = client.Views.Alter(ctx, alterRequest) require.NoError(t, err) - rowAccessPolicyReference, err = testClientHelper().RowAccessPolicy.GetRowAccessPolicyFor(t, view.ID(), sdk.ObjectTypeView) + rowAccessPolicyReference, err = testClientHelper().PolicyReferences.GetPolicyReference(t, view.ID(), sdk.ObjectTypeView) require.NoError(t, err) assert.Equal(t, rowAccessPolicy2.ID().Name(), rowAccessPolicyReference.PolicyName) // drop all policies - alterRequest = sdk.NewAlterViewRequest(id).WithDropAllRowAccessPolicies(sdk.Bool(true)) + alterRequest = sdk.NewAlterViewRequest(id).WithDropAllRowAccessPolicies(true) + err = client.Views.Alter(ctx, alterRequest) + require.NoError(t, err) + + _, err = testClientHelper().PolicyReferences.GetPolicyReference(t, view.ID(), sdk.ObjectTypeView) + require.Error(t, err, "no rows in result set") + }) + + t.Run("alter view: add and drop data metrics", func(t *testing.T) { + view := createView(t) + id := view.ID() + + dataMetricFunction, dataMetricFunctionCleanup := testClientHelper().DataMetricFunctionClient.CreateDataMetricFunction(t, id) + t.Cleanup(dataMetricFunctionCleanup) + dataMetricFunction2, dataMetricFunction2Cleanup := testClientHelper().DataMetricFunctionClient.CreateDataMetricFunction(t, id) + t.Cleanup(dataMetricFunction2Cleanup) + + // set cron schedule + cron := "5 * * * * UTC" + alterRequest := sdk.NewAlterViewRequest(id).WithSetDataMetricSchedule(*sdk.NewViewSetDataMetricScheduleRequest().WithUsingCron(sdk.ViewUsingCronRequest{Cron: cron})) + err := client.Views.Alter(ctx, alterRequest) + require.NoError(t, err) + + // add data metric function + alterRequest = sdk.NewAlterViewRequest(id).WithAddDataMetricFunction(*sdk.NewViewAddDataMetricFunctionRequest([]sdk.ViewDataMetricFunction{ + { + DataMetricFunction: dataMetricFunction, + On: []sdk.DoubleQuotedString{{Value: "ID"}}, + }, + })) + err = client.Views.Alter(ctx, alterRequest) + require.NoError(t, err) + + dataMetricFunctionReferences, err := testClientHelper().DataMetricFunctionReferences.GetDataMetricFunctionReferences(t, view.ID(), sdk.ObjectTypeView) + require.NoError(t, err) + require.Len(t, dataMetricFunctionReferences, 1) + + assertDataMetricFunctionReference(t, dataMetricFunctionReferences[0], view.ID(), cron) + + // remove function + alterRequest = sdk.NewAlterViewRequest(id).WithDropDataMetricFunction(*sdk.NewViewDropDataMetricFunctionRequest([]sdk.ViewDataMetricFunction{ + { + DataMetricFunction: dataMetricFunction, + On: []sdk.DoubleQuotedString{{Value: "ID"}}, + }, + })) + err = client.Views.Alter(ctx, alterRequest) + require.NoError(t, err) + + dataMetricFunctionReferences, err = testClientHelper().DataMetricFunctionReferences.GetDataMetricFunctionReferences(t, view.ID(), sdk.ObjectTypeView) + require.NoError(t, err) + require.Len(t, dataMetricFunctionReferences, 0) + + // add two functions + alterRequest = sdk.NewAlterViewRequest(id).WithAddDataMetricFunction(*sdk.NewViewAddDataMetricFunctionRequest([]sdk.ViewDataMetricFunction{ + { + DataMetricFunction: dataMetricFunction, + On: []sdk.DoubleQuotedString{{Value: "ID"}}, + }, + { + DataMetricFunction: dataMetricFunction2, + On: []sdk.DoubleQuotedString{{Value: "ID"}}, + }, + })) + err = client.Views.Alter(ctx, alterRequest) + require.NoError(t, err) + + dataMetricFunctionReferences, err = testClientHelper().DataMetricFunctionReferences.GetDataMetricFunctionReferences(t, view.ID(), sdk.ObjectTypeView) + require.NoError(t, err) + require.Len(t, dataMetricFunctionReferences, 2) + + assertDataMetricFunctionReference(t, dataMetricFunctionReferences[0], view.ID(), cron) + assertDataMetricFunctionReference(t, dataMetricFunctionReferences[1], view.ID(), cron) + + // drop all functions + alterRequest = sdk.NewAlterViewRequest(id).WithDropAllRowAccessPolicies(true) + err = client.Views.Alter(ctx, alterRequest) + require.NoError(t, err) + + _, err = testClientHelper().PolicyReferences.GetPolicyReference(t, view.ID(), sdk.ObjectTypeView) + require.Error(t, err, "no rows in result set") + }) + + t.Run("alter view: set and unset aggregation policies", func(t *testing.T) { + aggregationPolicy, aggregationPolicyCleanup := testClientHelper().AggregationPolicy.CreateAggregationPolicy(t) + t.Cleanup(aggregationPolicyCleanup) + aggregationPolicy2, aggregationPolicy2Cleanup := testClientHelper().AggregationPolicy.CreateAggregationPolicy(t) + t.Cleanup(aggregationPolicy2Cleanup) + + view := createView(t) + id := view.ID() + + // set policy + alterRequest := sdk.NewAlterViewRequest(id).WithSetAggregationPolicy(*sdk.NewViewSetAggregationPolicyRequest(aggregationPolicy).WithEntityKey([]sdk.DoubleQuotedString{{Value: "ID"}})) + err := client.Views.Alter(ctx, alterRequest) + require.NoError(t, err) + + rowAccessPolicyReferences, err := testClientHelper().PolicyReferences.GetPolicyReferences(t, view.ID(), sdk.ObjectTypeView) + require.NoError(t, err) + require.Len(t, rowAccessPolicyReferences, 1) + + assertPolicyReference(t, rowAccessPolicyReferences[0], aggregationPolicy, "AGGREGATION_POLICY", view.ID(), nil) + + // set policy with force + alterRequest = sdk.NewAlterViewRequest(id).WithSetAggregationPolicy(*sdk.NewViewSetAggregationPolicyRequest(aggregationPolicy2). + WithEntityKey([]sdk.DoubleQuotedString{{Value: "ID"}}). + WithForce(true)) + err = client.Views.Alter(ctx, alterRequest) + require.NoError(t, err) + + rowAccessPolicyReferences, err = testClientHelper().PolicyReferences.GetPolicyReferences(t, view.ID(), sdk.ObjectTypeView) + require.NoError(t, err) + require.Len(t, rowAccessPolicyReferences, 1) + + assertPolicyReference(t, rowAccessPolicyReferences[0], aggregationPolicy2, "AGGREGATION_POLICY", view.ID(), nil) + + // remove policy + alterRequest = sdk.NewAlterViewRequest(id).WithUnsetAggregationPolicy(*sdk.NewViewUnsetAggregationPolicyRequest()) err = client.Views.Alter(ctx, alterRequest) require.NoError(t, err) - _, err = testClientHelper().RowAccessPolicy.GetRowAccessPolicyFor(t, view.ID(), sdk.ObjectTypeView) + _, err = testClientHelper().PolicyReferences.GetPolicyReference(t, view.ID(), sdk.ObjectTypeView) require.Error(t, err, "no rows in result set") }) @@ -460,7 +684,7 @@ func TestInt_Views(t *testing.T) { t.Run("show view: terse", func(t *testing.T) { view := createView(t) - showRequest := sdk.NewShowViewRequest().WithTerse(sdk.Bool(true)) + showRequest := sdk.NewShowViewRequest().WithTerse(true) returnedViews, err := client.Views.Show(ctx, showRequest) require.NoError(t, err) @@ -473,9 +697,9 @@ func TestInt_Views(t *testing.T) { view2 := createView(t) showRequest := sdk.NewShowViewRequest(). - WithLike(&sdk.Like{Pattern: &view1.Name}). - WithIn(&sdk.In{Schema: testClientHelper().Ids.SchemaId()}). - WithLimit(&sdk.LimitFrom{Rows: sdk.Int(5)}) + WithLike(sdk.Like{Pattern: &view1.Name}). + WithIn(sdk.ExtendedIn{In: sdk.In{Schema: testClientHelper().Ids.SchemaId()}}). + WithLimit(sdk.LimitFrom{Rows: sdk.Int(5)}) returnedViews, err := client.Views.Show(ctx, showRequest) require.NoError(t, err) diff --git a/pkg/sdk/views_def.go b/pkg/sdk/views_def.go index 85db9d7b34..fef265a355 100644 --- a/pkg/sdk/views_def.go +++ b/pkg/sdk/views_def.go @@ -34,6 +34,7 @@ var view = g.PlainStruct("View"). Text("OwnerRoleType"). Text("ChangeTracking") +// TODO [SNOW-965322]: extract common type for describe var viewDetailsDbRow = g.DbStruct("viewDetailsRow"). Text("name"). Field("type", "DataType"). @@ -45,7 +46,8 @@ var viewDetailsDbRow = g.DbStruct("viewDetailsRow"). OptionalText("check"). OptionalText("expression"). OptionalText("comment"). - OptionalText("policy name") + OptionalText("policy name"). + OptionalText("privacy domain") var viewDetails = g.PlainStruct("ViewDetails"). Text("Name"). @@ -58,27 +60,71 @@ var viewDetails = g.PlainStruct("ViewDetails"). OptionalBool("Check"). OptionalText("Expression"). OptionalText("Comment"). - OptionalText("PolicyName") + OptionalText("PolicyName"). + OptionalText("PrivacyDomain") + +var doubleQuotedStringDef = g.NewQueryStruct("DoubleQuotedString"). + Text("Value", g.KeywordOptions().Required().DoubleQuotes()) + +var viewMinute = g.NewQueryStruct("ViewMinute"). + Number("Minutes", g.KeywordOptions().Required()). + SQL("MINUTE") + +var viewUsingCron = g.NewQueryStruct("ViewUsingCron"). + SQL("USING CRON"). + Text("Cron", g.KeywordOptions().Required()) + +var dataMetricFunctionDef = g.NewQueryStruct("ViewDataMetricFunction"). + Identifier("DataMetricFunction", g.KindOfT[SchemaObjectIdentifier](), g.IdentifierOptions().Required()). + ListAssignment("ON", "DoubleQuotedString", g.ParameterOptions().Required().NoEquals().Parentheses()). + WithValidation(g.ValidIdentifier, "DataMetricFunction") var viewColumn = g.NewQueryStruct("ViewColumn"). - Text("Name", g.KeywordOptions().DoubleQuotes().Required()). - OptionalTextAssignment("COMMENT", g.ParameterOptions().SingleQuotes().NoEquals()) + Text("Name", g.KeywordOptions().Required().DoubleQuotes()). + OptionalQueryStructField("ProjectionPolicy", viewColumnProjectionPolicy, g.KeywordOptions()). + OptionalQueryStructField("MaskingPolicy", viewColumnMaskingPolicy, g.KeywordOptions()). + OptionalTextAssignment("COMMENT", g.ParameterOptions().SingleQuotes().NoEquals()). + OptionalTags() var viewColumnMaskingPolicy = g.NewQueryStruct("ViewColumnMaskingPolicy"). - Text("Name", g.KeywordOptions().Required()). Identifier("MaskingPolicy", g.KindOfT[SchemaObjectIdentifier](), g.IdentifierOptions().SQL("MASKING POLICY").Required()). - NamedListWithParens("USING", g.KindOfT[string](), nil). // TODO: double quotes here? - OptionalTags() + ListAssignment("USING", "DoubleQuotedString", g.ParameterOptions().NoEquals().Parentheses()) + +var viewColumnProjectionPolicy = g.NewQueryStruct("ViewColumnProjectionPolicy"). + Identifier("ProjectionPolicy", g.KindOfT[SchemaObjectIdentifier](), g.IdentifierOptions().SQL("PROJECTION POLICY").Required()) var viewRowAccessPolicy = g.NewQueryStruct("ViewRowAccessPolicy"). Identifier("RowAccessPolicy", g.KindOfT[SchemaObjectIdentifier](), g.IdentifierOptions().SQL("ROW ACCESS POLICY").Required()). - NamedListWithParens("ON", g.KindOfT[string](), g.KeywordOptions().Required()). // TODO: double quotes here? + ListAssignment("ON", "DoubleQuotedString", g.ParameterOptions().Required().NoEquals().Parentheses()). WithValidation(g.ValidIdentifier, "RowAccessPolicy") +var viewAggregationPolicy = g.NewQueryStruct("ViewAggregationPolicy"). + Identifier("AggregationPolicy", g.KindOfT[SchemaObjectIdentifier](), g.IdentifierOptions().SQL("AGGREGATION POLICY").Required()). + ListAssignment("ENTITY KEY", "DoubleQuotedString", g.ParameterOptions().NoEquals().Parentheses()). + WithValidation(g.ValidIdentifier, "AggregationPolicy") + +var viewAddDataMetricFunction = g.NewQueryStruct("ViewAddDataMetricFunction"). + SQL("ADD"). + ListAssignment("DATA METRIC FUNCTION", "ViewDataMetricFunction", g.ParameterOptions().NoEquals().Required()) + +var viewDropDataMetricFunction = g.NewQueryStruct("ViewDropDataMetricFunction"). + SQL("DROP"). + ListAssignment("DATA METRIC FUNCTION", "ViewDataMetricFunction", g.ParameterOptions().NoEquals().Required()) + +var viewSetDataMetricSchedule = g.NewQueryStruct("ViewSetDataMetricSchedule"). + SQL("SET DATA_METRIC_SCHEDULE ="). + OptionalQueryStructField("Minutes", viewMinute, g.KeywordOptions()). + OptionalQueryStructField("UsingCron", viewUsingCron, g.KeywordOptions()). + OptionalSQL("TRIGGER_ON_CHANGES"). + WithValidation(g.ExactlyOneValueSet, "Minutes", "UsingCron", "TriggerOnChanges") + +var viewUnsetDataMetricSchedule = g.NewQueryStruct("ViewUnsetDataMetricSchedule"). + SQL("UNSET DATA_METRIC_SCHEDULE") + var viewAddRowAccessPolicy = g.NewQueryStruct("ViewAddRowAccessPolicy"). SQL("ADD"). Identifier("RowAccessPolicy", g.KindOfT[SchemaObjectIdentifier](), g.IdentifierOptions().SQL("ROW ACCESS POLICY").Required()). - NamedListWithParens("ON", g.KindOfT[string](), g.KeywordOptions().Required()). // TODO: double quotes here? + ListAssignment("ON", "DoubleQuotedString", g.ParameterOptions().Required().NoEquals().Parentheses()). WithValidation(g.ValidIdentifier, "RowAccessPolicy") var viewDropRowAccessPolicy = g.NewQueryStruct("ViewDropRowAccessPolicy"). @@ -90,36 +136,63 @@ var viewDropAndAddRowAccessPolicy = g.NewQueryStruct("ViewDropAndAddRowAccessPol QueryStructField("Drop", viewDropRowAccessPolicy, g.KeywordOptions().Required()). QueryStructField("Add", viewAddRowAccessPolicy, g.KeywordOptions().Required()) +var viewSetAggregationPolicy = g.NewQueryStruct("ViewSetAggregationPolicy"). + SQL("SET"). + Identifier("AggregationPolicy", g.KindOfT[SchemaObjectIdentifier](), g.IdentifierOptions().SQL("AGGREGATION POLICY").Required()). + ListAssignment("ENTITY KEY", "DoubleQuotedString", g.ParameterOptions().NoEquals().Parentheses()). + OptionalSQL("FORCE"). + WithValidation(g.ValidIdentifier, "AggregationPolicy") + +var viewUnsetAggregationPolicy = g.NewQueryStruct("ViewUnsetAggregationPolicy"). + SQL("UNSET AGGREGATION POLICY") + var viewSetColumnMaskingPolicy = g.NewQueryStruct("ViewSetColumnMaskingPolicy"). // In the docs there is a MODIFY alternative, but for simplicity only one is supported here. SQL("ALTER"). SQL("COLUMN"). - Text("Name", g.KeywordOptions().Required()). + Text("Name", g.KeywordOptions().Required().DoubleQuotes()). SQL("SET"). Identifier("MaskingPolicy", g.KindOfT[SchemaObjectIdentifier](), g.IdentifierOptions().SQL("MASKING POLICY").Required()). - NamedListWithParens("USING", g.KindOfT[string](), nil). // TODO: double quotes here? + ListAssignment("USING", "DoubleQuotedString", g.ParameterOptions().NoEquals().Parentheses()). OptionalSQL("FORCE") var viewUnsetColumnMaskingPolicy = g.NewQueryStruct("ViewUnsetColumnMaskingPolicy"). // In the docs there is a MODIFY alternative, but for simplicity only one is supported here. SQL("ALTER"). SQL("COLUMN"). - Text("Name", g.KeywordOptions().Required()). + Text("Name", g.KeywordOptions().Required().DoubleQuotes()). SQL("UNSET"). SQL("MASKING POLICY") +var viewSetProjectionPolicy = g.NewQueryStruct("ViewSetProjectionPolicy"). + // In the docs there is a MODIFY alternative, but for simplicity only one is supported here. + SQL("ALTER"). + SQL("COLUMN"). + Text("Name", g.KeywordOptions().Required().DoubleQuotes()). + SQL("SET"). + Identifier("ProjectionPolicy", g.KindOfT[SchemaObjectIdentifier](), g.IdentifierOptions().SQL("PROJECTION POLICY").Required()). + OptionalSQL("FORCE") + +var viewUnsetProjectionPolicy = g.NewQueryStruct("ViewUnsetProjectionPolicy"). + // In the docs there is a MODIFY alternative, but for simplicity only one is supported here. + SQL("ALTER"). + SQL("COLUMN"). + Text("Name", g.KeywordOptions().Required().DoubleQuotes()). + SQL("UNSET"). + SQL("PROJECTION POLICY") + var viewSetColumnTags = g.NewQueryStruct("ViewSetColumnTags"). // In the docs there is a MODIFY alternative, but for simplicity only one is supported here. SQL("ALTER"). SQL("COLUMN"). - Text("Name", g.KeywordOptions().Required()). + Text("Name", g.KeywordOptions().Required().DoubleQuotes()). SetTags() var viewUnsetColumnTags = g.NewQueryStruct("ViewUnsetColumnTags"). // In the docs there is a MODIFY alternative, but for simplicity only one is supported here. SQL("ALTER"). SQL("COLUMN"). - Text("Name", g.KeywordOptions().Required()). + Text("Name", g.KeywordOptions().Required().DoubleQuotes()). UnsetTags() var ViewsDef = g.NewInterface( @@ -141,19 +214,20 @@ var ViewsDef = g.NewInterface( IfNotExists(). Name(). ListQueryStructField("Columns", viewColumn, g.ListOptions().Parentheses()). - ListQueryStructField("ColumnsMaskingPolicies", viewColumnMaskingPolicy, g.ListOptions().NoParentheses().NoEquals()). OptionalSQL("COPY GRANTS"). OptionalTextAssignment("COMMENT", g.ParameterOptions().SingleQuotes()). // In the current docs ROW ACCESS POLICY and TAG are specified twice. // It is a mistake probably so here they are present only once. OptionalQueryStructField("RowAccessPolicy", viewRowAccessPolicy, g.KeywordOptions()). + OptionalQueryStructField("AggregationPolicy", viewAggregationPolicy, g.KeywordOptions()). OptionalTags(). SQL("AS"). Text("sql", g.KeywordOptions().NoQuotes().Required()). WithValidation(g.ValidIdentifier, "name"). WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), ). - AlterOperation( + CustomOperation( + "Alter", "https://docs.snowflake.com/en/sql-reference/sql/alter-view", g.NewQueryStruct("AlterView"). Alter(). @@ -168,16 +242,33 @@ var ViewsDef = g.NewInterface( OptionalSQL("UNSET SECURE"). OptionalSetTags(). OptionalUnsetTags(). + OptionalQueryStructField("AddDataMetricFunction", viewAddDataMetricFunction, g.KeywordOptions()). + OptionalQueryStructField("DropDataMetricFunction", viewDropDataMetricFunction, g.KeywordOptions()). + OptionalQueryStructField("SetDataMetricSchedule", viewSetDataMetricSchedule, g.KeywordOptions()). + OptionalQueryStructField("UnsetDataMetricSchedule", viewUnsetDataMetricSchedule, g.KeywordOptions()). OptionalQueryStructField("AddRowAccessPolicy", viewAddRowAccessPolicy, g.KeywordOptions()). OptionalQueryStructField("DropRowAccessPolicy", viewDropRowAccessPolicy, g.KeywordOptions()). OptionalQueryStructField("DropAndAddRowAccessPolicy", viewDropAndAddRowAccessPolicy, g.ListOptions().NoParentheses()). OptionalSQL("DROP ALL ROW ACCESS POLICIES"). + OptionalQueryStructField("SetAggregationPolicy", viewSetAggregationPolicy, g.KeywordOptions()). + OptionalQueryStructField("UnsetAggregationPolicy", viewUnsetAggregationPolicy, g.KeywordOptions()). OptionalQueryStructField("SetMaskingPolicyOnColumn", viewSetColumnMaskingPolicy, g.KeywordOptions()). OptionalQueryStructField("UnsetMaskingPolicyOnColumn", viewUnsetColumnMaskingPolicy, g.KeywordOptions()). + OptionalQueryStructField("SetProjectionPolicyOnColumn", viewSetProjectionPolicy, g.KeywordOptions()). + OptionalQueryStructField("UnsetProjectionPolicyOnColumn", viewUnsetProjectionPolicy, g.KeywordOptions()). OptionalQueryStructField("SetTagsOnColumn", viewSetColumnTags, g.KeywordOptions()). OptionalQueryStructField("UnsetTagsOnColumn", viewUnsetColumnTags, g.KeywordOptions()). WithValidation(g.ValidIdentifier, "name"). - WithValidation(g.ExactlyOneValueSet, "RenameTo", "SetComment", "UnsetComment", "SetSecure", "SetChangeTracking", "UnsetSecure", "SetTags", "UnsetTags", "AddRowAccessPolicy", "DropRowAccessPolicy", "DropAndAddRowAccessPolicy", "DropAllRowAccessPolicies", "SetMaskingPolicyOnColumn", "UnsetMaskingPolicyOnColumn", "SetTagsOnColumn", "UnsetTagsOnColumn"), + WithValidation(g.ExactlyOneValueSet, "RenameTo", "SetComment", "UnsetComment", "SetSecure", "SetChangeTracking", + "UnsetSecure", "SetTags", "UnsetTags", "AddDataMetricFunction", "DropDataMetricFunction", "SetDataMetricSchedule", "UnsetDataMetricSchedule", + "AddRowAccessPolicy", "DropRowAccessPolicy", "DropAndAddRowAccessPolicy", + "DropAllRowAccessPolicies", "SetAggregationPolicy", "UnsetAggregationPolicy", "SetMaskingPolicyOnColumn", + "UnsetMaskingPolicyOnColumn", "SetProjectionPolicyOnColumn", "UnsetProjectionPolicyOnColumn", "SetTagsOnColumn", + "UnsetTagsOnColumn"). + WithValidation(g.ConflictingFields, "IfExists", "SetSecure"). + WithValidation(g.ConflictingFields, "IfExists", "UnsetSecure"), + doubleQuotedStringDef, + dataMetricFunctionDef, ). DropOperation( "https://docs.snowflake.com/en/sql-reference/sql/drop-view", @@ -197,7 +288,7 @@ var ViewsDef = g.NewInterface( Terse(). SQL("VIEWS"). OptionalLike(). - OptionalIn(). + OptionalExtendedIn(). OptionalStartsWith(). OptionalLimit(), ). diff --git a/pkg/sdk/views_dto_builders_gen.go b/pkg/sdk/views_dto_builders_gen.go index d357ee3a27..47d65f0e29 100644 --- a/pkg/sdk/views_dto_builders_gen.go +++ b/pkg/sdk/views_dto_builders_gen.go @@ -14,28 +14,28 @@ func NewCreateViewRequest( return &s } -func (s *CreateViewRequest) WithOrReplace(OrReplace *bool) *CreateViewRequest { - s.OrReplace = OrReplace +func (s *CreateViewRequest) WithOrReplace(OrReplace bool) *CreateViewRequest { + s.OrReplace = &OrReplace return s } -func (s *CreateViewRequest) WithSecure(Secure *bool) *CreateViewRequest { - s.Secure = Secure +func (s *CreateViewRequest) WithSecure(Secure bool) *CreateViewRequest { + s.Secure = &Secure return s } -func (s *CreateViewRequest) WithTemporary(Temporary *bool) *CreateViewRequest { - s.Temporary = Temporary +func (s *CreateViewRequest) WithTemporary(Temporary bool) *CreateViewRequest { + s.Temporary = &Temporary return s } -func (s *CreateViewRequest) WithRecursive(Recursive *bool) *CreateViewRequest { - s.Recursive = Recursive +func (s *CreateViewRequest) WithRecursive(Recursive bool) *CreateViewRequest { + s.Recursive = &Recursive return s } -func (s *CreateViewRequest) WithIfNotExists(IfNotExists *bool) *CreateViewRequest { - s.IfNotExists = IfNotExists +func (s *CreateViewRequest) WithIfNotExists(IfNotExists bool) *CreateViewRequest { + s.IfNotExists = &IfNotExists return s } @@ -44,23 +44,23 @@ func (s *CreateViewRequest) WithColumns(Columns []ViewColumnRequest) *CreateView return s } -func (s *CreateViewRequest) WithColumnsMaskingPolicies(ColumnsMaskingPolicies []ViewColumnMaskingPolicyRequest) *CreateViewRequest { - s.ColumnsMaskingPolicies = ColumnsMaskingPolicies +func (s *CreateViewRequest) WithCopyGrants(CopyGrants bool) *CreateViewRequest { + s.CopyGrants = &CopyGrants return s } -func (s *CreateViewRequest) WithCopyGrants(CopyGrants *bool) *CreateViewRequest { - s.CopyGrants = CopyGrants +func (s *CreateViewRequest) WithComment(Comment string) *CreateViewRequest { + s.Comment = &Comment return s } -func (s *CreateViewRequest) WithComment(Comment *string) *CreateViewRequest { - s.Comment = Comment +func (s *CreateViewRequest) WithRowAccessPolicy(RowAccessPolicy ViewRowAccessPolicyRequest) *CreateViewRequest { + s.RowAccessPolicy = &RowAccessPolicy return s } -func (s *CreateViewRequest) WithRowAccessPolicy(RowAccessPolicy *ViewRowAccessPolicyRequest) *CreateViewRequest { - s.RowAccessPolicy = RowAccessPolicy +func (s *CreateViewRequest) WithAggregationPolicy(AggregationPolicy ViewAggregationPolicyRequest) *CreateViewRequest { + s.AggregationPolicy = &AggregationPolicy return s } @@ -77,34 +77,50 @@ func NewViewColumnRequest( return &s } -func (s *ViewColumnRequest) WithComment(Comment *string) *ViewColumnRequest { - s.Comment = Comment +func (s *ViewColumnRequest) WithProjectionPolicy(ProjectionPolicy ViewColumnProjectionPolicyRequest) *ViewColumnRequest { + s.ProjectionPolicy = &ProjectionPolicy + return s +} + +func (s *ViewColumnRequest) WithMaskingPolicy(MaskingPolicy ViewColumnMaskingPolicyRequest) *ViewColumnRequest { + s.MaskingPolicy = &MaskingPolicy + return s +} + +func (s *ViewColumnRequest) WithComment(Comment string) *ViewColumnRequest { + s.Comment = &Comment return s } +func (s *ViewColumnRequest) WithTag(Tag []TagAssociation) *ViewColumnRequest { + s.Tag = Tag + return s +} + +func NewViewColumnProjectionPolicyRequest( + ProjectionPolicy SchemaObjectIdentifier, +) *ViewColumnProjectionPolicyRequest { + s := ViewColumnProjectionPolicyRequest{} + s.ProjectionPolicy = ProjectionPolicy + return &s +} + func NewViewColumnMaskingPolicyRequest( - Name string, MaskingPolicy SchemaObjectIdentifier, ) *ViewColumnMaskingPolicyRequest { s := ViewColumnMaskingPolicyRequest{} - s.Name = Name s.MaskingPolicy = MaskingPolicy return &s } -func (s *ViewColumnMaskingPolicyRequest) WithUsing(Using []string) *ViewColumnMaskingPolicyRequest { +func (s *ViewColumnMaskingPolicyRequest) WithUsing(Using []DoubleQuotedString) *ViewColumnMaskingPolicyRequest { s.Using = Using return s } -func (s *ViewColumnMaskingPolicyRequest) WithTag(Tag []TagAssociation) *ViewColumnMaskingPolicyRequest { - s.Tag = Tag - return s -} - func NewViewRowAccessPolicyRequest( RowAccessPolicy SchemaObjectIdentifier, - On []string, + On []DoubleQuotedString, ) *ViewRowAccessPolicyRequest { s := ViewRowAccessPolicyRequest{} s.RowAccessPolicy = RowAccessPolicy @@ -112,6 +128,19 @@ func NewViewRowAccessPolicyRequest( return &s } +func NewViewAggregationPolicyRequest( + AggregationPolicy SchemaObjectIdentifier, +) *ViewAggregationPolicyRequest { + s := ViewAggregationPolicyRequest{} + s.AggregationPolicy = AggregationPolicy + return &s +} + +func (s *ViewAggregationPolicyRequest) WithEntityKey(EntityKey []DoubleQuotedString) *ViewAggregationPolicyRequest { + s.EntityKey = EntityKey + return s +} + func NewAlterViewRequest( name SchemaObjectIdentifier, ) *AlterViewRequest { @@ -120,38 +149,38 @@ func NewAlterViewRequest( return &s } -func (s *AlterViewRequest) WithIfExists(IfExists *bool) *AlterViewRequest { - s.IfExists = IfExists +func (s *AlterViewRequest) WithIfExists(IfExists bool) *AlterViewRequest { + s.IfExists = &IfExists return s } -func (s *AlterViewRequest) WithRenameTo(RenameTo *SchemaObjectIdentifier) *AlterViewRequest { - s.RenameTo = RenameTo +func (s *AlterViewRequest) WithRenameTo(RenameTo SchemaObjectIdentifier) *AlterViewRequest { + s.RenameTo = &RenameTo return s } -func (s *AlterViewRequest) WithSetComment(SetComment *string) *AlterViewRequest { - s.SetComment = SetComment +func (s *AlterViewRequest) WithSetComment(SetComment string) *AlterViewRequest { + s.SetComment = &SetComment return s } -func (s *AlterViewRequest) WithUnsetComment(UnsetComment *bool) *AlterViewRequest { - s.UnsetComment = UnsetComment +func (s *AlterViewRequest) WithUnsetComment(UnsetComment bool) *AlterViewRequest { + s.UnsetComment = &UnsetComment return s } -func (s *AlterViewRequest) WithSetSecure(SetSecure *bool) *AlterViewRequest { - s.SetSecure = SetSecure +func (s *AlterViewRequest) WithSetSecure(SetSecure bool) *AlterViewRequest { + s.SetSecure = &SetSecure return s } -func (s *AlterViewRequest) WithSetChangeTracking(SetChangeTracking *bool) *AlterViewRequest { - s.SetChangeTracking = SetChangeTracking +func (s *AlterViewRequest) WithSetChangeTracking(SetChangeTracking bool) *AlterViewRequest { + s.SetChangeTracking = &SetChangeTracking return s } -func (s *AlterViewRequest) WithUnsetSecure(UnsetSecure *bool) *AlterViewRequest { - s.UnsetSecure = UnsetSecure +func (s *AlterViewRequest) WithUnsetSecure(UnsetSecure bool) *AlterViewRequest { + s.UnsetSecure = &UnsetSecure return s } @@ -165,49 +194,144 @@ func (s *AlterViewRequest) WithUnsetTags(UnsetTags []ObjectIdentifier) *AlterVie return s } -func (s *AlterViewRequest) WithAddRowAccessPolicy(AddRowAccessPolicy *ViewAddRowAccessPolicyRequest) *AlterViewRequest { - s.AddRowAccessPolicy = AddRowAccessPolicy +func (s *AlterViewRequest) WithAddDataMetricFunction(AddDataMetricFunction ViewAddDataMetricFunctionRequest) *AlterViewRequest { + s.AddDataMetricFunction = &AddDataMetricFunction + return s +} + +func (s *AlterViewRequest) WithDropDataMetricFunction(DropDataMetricFunction ViewDropDataMetricFunctionRequest) *AlterViewRequest { + s.DropDataMetricFunction = &DropDataMetricFunction + return s +} + +func (s *AlterViewRequest) WithSetDataMetricSchedule(SetDataMetricSchedule ViewSetDataMetricScheduleRequest) *AlterViewRequest { + s.SetDataMetricSchedule = &SetDataMetricSchedule + return s +} + +func (s *AlterViewRequest) WithUnsetDataMetricSchedule(UnsetDataMetricSchedule ViewUnsetDataMetricScheduleRequest) *AlterViewRequest { + s.UnsetDataMetricSchedule = &UnsetDataMetricSchedule + return s +} + +func (s *AlterViewRequest) WithAddRowAccessPolicy(AddRowAccessPolicy ViewAddRowAccessPolicyRequest) *AlterViewRequest { + s.AddRowAccessPolicy = &AddRowAccessPolicy + return s +} + +func (s *AlterViewRequest) WithDropRowAccessPolicy(DropRowAccessPolicy ViewDropRowAccessPolicyRequest) *AlterViewRequest { + s.DropRowAccessPolicy = &DropRowAccessPolicy + return s +} + +func (s *AlterViewRequest) WithDropAndAddRowAccessPolicy(DropAndAddRowAccessPolicy ViewDropAndAddRowAccessPolicyRequest) *AlterViewRequest { + s.DropAndAddRowAccessPolicy = &DropAndAddRowAccessPolicy + return s +} + +func (s *AlterViewRequest) WithDropAllRowAccessPolicies(DropAllRowAccessPolicies bool) *AlterViewRequest { + s.DropAllRowAccessPolicies = &DropAllRowAccessPolicies + return s +} + +func (s *AlterViewRequest) WithSetAggregationPolicy(SetAggregationPolicy ViewSetAggregationPolicyRequest) *AlterViewRequest { + s.SetAggregationPolicy = &SetAggregationPolicy return s } -func (s *AlterViewRequest) WithDropRowAccessPolicy(DropRowAccessPolicy *ViewDropRowAccessPolicyRequest) *AlterViewRequest { - s.DropRowAccessPolicy = DropRowAccessPolicy +func (s *AlterViewRequest) WithUnsetAggregationPolicy(UnsetAggregationPolicy ViewUnsetAggregationPolicyRequest) *AlterViewRequest { + s.UnsetAggregationPolicy = &UnsetAggregationPolicy return s } -func (s *AlterViewRequest) WithDropAndAddRowAccessPolicy(DropAndAddRowAccessPolicy *ViewDropAndAddRowAccessPolicyRequest) *AlterViewRequest { - s.DropAndAddRowAccessPolicy = DropAndAddRowAccessPolicy +func (s *AlterViewRequest) WithSetMaskingPolicyOnColumn(SetMaskingPolicyOnColumn ViewSetColumnMaskingPolicyRequest) *AlterViewRequest { + s.SetMaskingPolicyOnColumn = &SetMaskingPolicyOnColumn return s } -func (s *AlterViewRequest) WithDropAllRowAccessPolicies(DropAllRowAccessPolicies *bool) *AlterViewRequest { - s.DropAllRowAccessPolicies = DropAllRowAccessPolicies +func (s *AlterViewRequest) WithUnsetMaskingPolicyOnColumn(UnsetMaskingPolicyOnColumn ViewUnsetColumnMaskingPolicyRequest) *AlterViewRequest { + s.UnsetMaskingPolicyOnColumn = &UnsetMaskingPolicyOnColumn return s } -func (s *AlterViewRequest) WithSetMaskingPolicyOnColumn(SetMaskingPolicyOnColumn *ViewSetColumnMaskingPolicyRequest) *AlterViewRequest { - s.SetMaskingPolicyOnColumn = SetMaskingPolicyOnColumn +func (s *AlterViewRequest) WithSetProjectionPolicyOnColumn(SetProjectionPolicyOnColumn ViewSetProjectionPolicyRequest) *AlterViewRequest { + s.SetProjectionPolicyOnColumn = &SetProjectionPolicyOnColumn return s } -func (s *AlterViewRequest) WithUnsetMaskingPolicyOnColumn(UnsetMaskingPolicyOnColumn *ViewUnsetColumnMaskingPolicyRequest) *AlterViewRequest { - s.UnsetMaskingPolicyOnColumn = UnsetMaskingPolicyOnColumn +func (s *AlterViewRequest) WithUnsetProjectionPolicyOnColumn(UnsetProjectionPolicyOnColumn ViewUnsetProjectionPolicyRequest) *AlterViewRequest { + s.UnsetProjectionPolicyOnColumn = &UnsetProjectionPolicyOnColumn return s } -func (s *AlterViewRequest) WithSetTagsOnColumn(SetTagsOnColumn *ViewSetColumnTagsRequest) *AlterViewRequest { - s.SetTagsOnColumn = SetTagsOnColumn +func (s *AlterViewRequest) WithSetTagsOnColumn(SetTagsOnColumn ViewSetColumnTagsRequest) *AlterViewRequest { + s.SetTagsOnColumn = &SetTagsOnColumn return s } -func (s *AlterViewRequest) WithUnsetTagsOnColumn(UnsetTagsOnColumn *ViewUnsetColumnTagsRequest) *AlterViewRequest { - s.UnsetTagsOnColumn = UnsetTagsOnColumn +func (s *AlterViewRequest) WithUnsetTagsOnColumn(UnsetTagsOnColumn ViewUnsetColumnTagsRequest) *AlterViewRequest { + s.UnsetTagsOnColumn = &UnsetTagsOnColumn return s } +func NewViewAddDataMetricFunctionRequest( + DataMetricFunction []ViewDataMetricFunction, +) *ViewAddDataMetricFunctionRequest { + s := ViewAddDataMetricFunctionRequest{} + s.DataMetricFunction = DataMetricFunction + return &s +} + +func NewViewDropDataMetricFunctionRequest( + DataMetricFunction []ViewDataMetricFunction, +) *ViewDropDataMetricFunctionRequest { + s := ViewDropDataMetricFunctionRequest{} + s.DataMetricFunction = DataMetricFunction + return &s +} + +func NewViewSetDataMetricScheduleRequest() *ViewSetDataMetricScheduleRequest { + return &ViewSetDataMetricScheduleRequest{} +} + +func (s *ViewSetDataMetricScheduleRequest) WithMinutes(Minutes ViewMinuteRequest) *ViewSetDataMetricScheduleRequest { + s.Minutes = &Minutes + return s +} + +func (s *ViewSetDataMetricScheduleRequest) WithUsingCron(UsingCron ViewUsingCronRequest) *ViewSetDataMetricScheduleRequest { + s.UsingCron = &UsingCron + return s +} + +func (s *ViewSetDataMetricScheduleRequest) WithTriggerOnChanges(TriggerOnChanges bool) *ViewSetDataMetricScheduleRequest { + s.TriggerOnChanges = &TriggerOnChanges + return s +} + +func NewViewMinuteRequest( + Minutes int, +) *ViewMinuteRequest { + s := ViewMinuteRequest{} + s.Minutes = Minutes + return &s +} + +func NewViewUsingCronRequest( + Cron string, +) *ViewUsingCronRequest { + s := ViewUsingCronRequest{} + s.Cron = Cron + return &s +} + +func NewViewUnsetDataMetricScheduleRequest() *ViewUnsetDataMetricScheduleRequest { + return &ViewUnsetDataMetricScheduleRequest{} +} + func NewViewAddRowAccessPolicyRequest( RowAccessPolicy SchemaObjectIdentifier, - On []string, + On []DoubleQuotedString, ) *ViewAddRowAccessPolicyRequest { s := ViewAddRowAccessPolicyRequest{} s.RowAccessPolicy = RowAccessPolicy @@ -233,6 +357,28 @@ func NewViewDropAndAddRowAccessPolicyRequest( return &s } +func NewViewSetAggregationPolicyRequest( + AggregationPolicy SchemaObjectIdentifier, +) *ViewSetAggregationPolicyRequest { + s := ViewSetAggregationPolicyRequest{} + s.AggregationPolicy = AggregationPolicy + return &s +} + +func (s *ViewSetAggregationPolicyRequest) WithEntityKey(EntityKey []DoubleQuotedString) *ViewSetAggregationPolicyRequest { + s.EntityKey = EntityKey + return s +} + +func (s *ViewSetAggregationPolicyRequest) WithForce(Force bool) *ViewSetAggregationPolicyRequest { + s.Force = &Force + return s +} + +func NewViewUnsetAggregationPolicyRequest() *ViewUnsetAggregationPolicyRequest { + return &ViewUnsetAggregationPolicyRequest{} +} + func NewViewSetColumnMaskingPolicyRequest( Name string, MaskingPolicy SchemaObjectIdentifier, @@ -243,13 +389,13 @@ func NewViewSetColumnMaskingPolicyRequest( return &s } -func (s *ViewSetColumnMaskingPolicyRequest) WithUsing(Using []string) *ViewSetColumnMaskingPolicyRequest { +func (s *ViewSetColumnMaskingPolicyRequest) WithUsing(Using []DoubleQuotedString) *ViewSetColumnMaskingPolicyRequest { s.Using = Using return s } -func (s *ViewSetColumnMaskingPolicyRequest) WithForce(Force *bool) *ViewSetColumnMaskingPolicyRequest { - s.Force = Force +func (s *ViewSetColumnMaskingPolicyRequest) WithForce(Force bool) *ViewSetColumnMaskingPolicyRequest { + s.Force = &Force return s } @@ -261,6 +407,29 @@ func NewViewUnsetColumnMaskingPolicyRequest( return &s } +func NewViewSetProjectionPolicyRequest( + Name string, + ProjectionPolicy SchemaObjectIdentifier, +) *ViewSetProjectionPolicyRequest { + s := ViewSetProjectionPolicyRequest{} + s.Name = Name + s.ProjectionPolicy = ProjectionPolicy + return &s +} + +func (s *ViewSetProjectionPolicyRequest) WithForce(Force bool) *ViewSetProjectionPolicyRequest { + s.Force = &Force + return s +} + +func NewViewUnsetProjectionPolicyRequest( + Name string, +) *ViewUnsetProjectionPolicyRequest { + s := ViewUnsetProjectionPolicyRequest{} + s.Name = Name + return &s +} + func NewViewSetColumnTagsRequest( Name string, SetTags []TagAssociation, @@ -289,8 +458,8 @@ func NewDropViewRequest( return &s } -func (s *DropViewRequest) WithIfExists(IfExists *bool) *DropViewRequest { - s.IfExists = IfExists +func (s *DropViewRequest) WithIfExists(IfExists bool) *DropViewRequest { + s.IfExists = &IfExists return s } @@ -298,28 +467,28 @@ func NewShowViewRequest() *ShowViewRequest { return &ShowViewRequest{} } -func (s *ShowViewRequest) WithTerse(Terse *bool) *ShowViewRequest { - s.Terse = Terse +func (s *ShowViewRequest) WithTerse(Terse bool) *ShowViewRequest { + s.Terse = &Terse return s } -func (s *ShowViewRequest) WithLike(Like *Like) *ShowViewRequest { - s.Like = Like +func (s *ShowViewRequest) WithLike(Like Like) *ShowViewRequest { + s.Like = &Like return s } -func (s *ShowViewRequest) WithIn(In *In) *ShowViewRequest { - s.In = In +func (s *ShowViewRequest) WithIn(In ExtendedIn) *ShowViewRequest { + s.In = &In return s } -func (s *ShowViewRequest) WithStartsWith(StartsWith *string) *ShowViewRequest { - s.StartsWith = StartsWith +func (s *ShowViewRequest) WithStartsWith(StartsWith string) *ShowViewRequest { + s.StartsWith = &StartsWith return s } -func (s *ShowViewRequest) WithLimit(Limit *LimitFrom) *ShowViewRequest { - s.Limit = Limit +func (s *ShowViewRequest) WithLimit(Limit LimitFrom) *ShowViewRequest { + s.Limit = &Limit return s } diff --git a/pkg/sdk/views_dto_gen.go b/pkg/sdk/views_dto_gen.go index a3b2ac4cee..b14b8f5083 100644 --- a/pkg/sdk/views_dto_gen.go +++ b/pkg/sdk/views_dto_gen.go @@ -11,19 +11,19 @@ var ( ) type CreateViewRequest struct { - OrReplace *bool - Secure *bool - Temporary *bool - Recursive *bool - IfNotExists *bool - name SchemaObjectIdentifier // required - Columns []ViewColumnRequest - ColumnsMaskingPolicies []ViewColumnMaskingPolicyRequest - CopyGrants *bool - Comment *string - RowAccessPolicy *ViewRowAccessPolicyRequest - Tag []TagAssociation - sql string // required + OrReplace *bool + Secure *bool + Temporary *bool + Recursive *bool + IfNotExists *bool + name SchemaObjectIdentifier // required + Columns []ViewColumnRequest + CopyGrants *bool + Comment *string + RowAccessPolicy *ViewRowAccessPolicyRequest + AggregationPolicy *ViewAggregationPolicyRequest + Tag []TagAssociation + sql string // required } func (r *CreateViewRequest) GetName() SchemaObjectIdentifier { @@ -31,46 +31,88 @@ func (r *CreateViewRequest) GetName() SchemaObjectIdentifier { } type ViewColumnRequest struct { - Name string // required - Comment *string + Name string // required + ProjectionPolicy *ViewColumnProjectionPolicyRequest + MaskingPolicy *ViewColumnMaskingPolicyRequest + Comment *string + Tag []TagAssociation +} + +type ViewColumnProjectionPolicyRequest struct { + ProjectionPolicy SchemaObjectIdentifier // required } type ViewColumnMaskingPolicyRequest struct { - Name string // required MaskingPolicy SchemaObjectIdentifier // required - Using []string - Tag []TagAssociation + Using []DoubleQuotedString } type ViewRowAccessPolicyRequest struct { RowAccessPolicy SchemaObjectIdentifier // required - On []string // required + On []DoubleQuotedString // required +} + +type ViewAggregationPolicyRequest struct { + AggregationPolicy SchemaObjectIdentifier // required + EntityKey []DoubleQuotedString } type AlterViewRequest struct { - IfExists *bool - name SchemaObjectIdentifier // required - RenameTo *SchemaObjectIdentifier - SetComment *string - UnsetComment *bool - SetSecure *bool - SetChangeTracking *bool - UnsetSecure *bool - SetTags []TagAssociation - UnsetTags []ObjectIdentifier - AddRowAccessPolicy *ViewAddRowAccessPolicyRequest - DropRowAccessPolicy *ViewDropRowAccessPolicyRequest - DropAndAddRowAccessPolicy *ViewDropAndAddRowAccessPolicyRequest - DropAllRowAccessPolicies *bool - SetMaskingPolicyOnColumn *ViewSetColumnMaskingPolicyRequest - UnsetMaskingPolicyOnColumn *ViewUnsetColumnMaskingPolicyRequest - SetTagsOnColumn *ViewSetColumnTagsRequest - UnsetTagsOnColumn *ViewUnsetColumnTagsRequest + IfExists *bool + name SchemaObjectIdentifier // required + RenameTo *SchemaObjectIdentifier + SetComment *string + UnsetComment *bool + SetSecure *bool + SetChangeTracking *bool + UnsetSecure *bool + SetTags []TagAssociation + UnsetTags []ObjectIdentifier + AddDataMetricFunction *ViewAddDataMetricFunctionRequest + DropDataMetricFunction *ViewDropDataMetricFunctionRequest + SetDataMetricSchedule *ViewSetDataMetricScheduleRequest + UnsetDataMetricSchedule *ViewUnsetDataMetricScheduleRequest + AddRowAccessPolicy *ViewAddRowAccessPolicyRequest + DropRowAccessPolicy *ViewDropRowAccessPolicyRequest + DropAndAddRowAccessPolicy *ViewDropAndAddRowAccessPolicyRequest + DropAllRowAccessPolicies *bool + SetAggregationPolicy *ViewSetAggregationPolicyRequest + UnsetAggregationPolicy *ViewUnsetAggregationPolicyRequest + SetMaskingPolicyOnColumn *ViewSetColumnMaskingPolicyRequest + UnsetMaskingPolicyOnColumn *ViewUnsetColumnMaskingPolicyRequest + SetProjectionPolicyOnColumn *ViewSetProjectionPolicyRequest + UnsetProjectionPolicyOnColumn *ViewUnsetProjectionPolicyRequest + SetTagsOnColumn *ViewSetColumnTagsRequest + UnsetTagsOnColumn *ViewUnsetColumnTagsRequest +} + +type ViewAddDataMetricFunctionRequest struct { + DataMetricFunction []ViewDataMetricFunction // required +} + +type ViewDropDataMetricFunctionRequest struct { + DataMetricFunction []ViewDataMetricFunction // required +} + +type ViewSetDataMetricScheduleRequest struct { + Minutes *ViewMinuteRequest + UsingCron *ViewUsingCronRequest + TriggerOnChanges *bool +} + +type ViewMinuteRequest struct { + Minutes int // required +} + +type ViewUsingCronRequest struct { + Cron string // required } +type ViewUnsetDataMetricScheduleRequest struct{} + type ViewAddRowAccessPolicyRequest struct { RowAccessPolicy SchemaObjectIdentifier // required - On []string // required + On []DoubleQuotedString // required } type ViewDropRowAccessPolicyRequest struct { @@ -82,10 +124,18 @@ type ViewDropAndAddRowAccessPolicyRequest struct { Add ViewAddRowAccessPolicyRequest // required } +type ViewSetAggregationPolicyRequest struct { + AggregationPolicy SchemaObjectIdentifier // required + EntityKey []DoubleQuotedString + Force *bool +} + +type ViewUnsetAggregationPolicyRequest struct{} + type ViewSetColumnMaskingPolicyRequest struct { Name string // required MaskingPolicy SchemaObjectIdentifier // required - Using []string + Using []DoubleQuotedString Force *bool } @@ -93,6 +143,16 @@ type ViewUnsetColumnMaskingPolicyRequest struct { Name string // required } +type ViewSetProjectionPolicyRequest struct { + Name string // required + ProjectionPolicy SchemaObjectIdentifier // required + Force *bool +} + +type ViewUnsetProjectionPolicyRequest struct { + Name string // required +} + type ViewSetColumnTagsRequest struct { Name string // required SetTags []TagAssociation // required @@ -111,7 +171,7 @@ type DropViewRequest struct { type ShowViewRequest struct { Terse *bool Like *Like - In *In + In *ExtendedIn StartsWith *string Limit *LimitFrom } diff --git a/pkg/sdk/views_gen.go b/pkg/sdk/views_gen.go index ae69da702d..8b6ab59535 100644 --- a/pkg/sdk/views_gen.go +++ b/pkg/sdk/views_gen.go @@ -17,110 +17,177 @@ type Views interface { // CreateViewOptions is based on https://docs.snowflake.com/en/sql-reference/sql/create-view. type CreateViewOptions struct { - create bool `ddl:"static" sql:"CREATE"` - OrReplace *bool `ddl:"keyword" sql:"OR REPLACE"` - Secure *bool `ddl:"keyword" sql:"SECURE"` - Temporary *bool `ddl:"keyword" sql:"TEMPORARY"` - Recursive *bool `ddl:"keyword" sql:"RECURSIVE"` - view bool `ddl:"static" sql:"VIEW"` - IfNotExists *bool `ddl:"keyword" sql:"IF NOT EXISTS"` - name SchemaObjectIdentifier `ddl:"identifier"` - Columns []ViewColumn `ddl:"list,parentheses"` - ColumnsMaskingPolicies []ViewColumnMaskingPolicy `ddl:"list,no_parentheses,no_equals"` - CopyGrants *bool `ddl:"keyword" sql:"COPY GRANTS"` - Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` - RowAccessPolicy *ViewRowAccessPolicy `ddl:"keyword"` - Tag []TagAssociation `ddl:"keyword,parentheses" sql:"TAG"` - as bool `ddl:"static" sql:"AS"` - sql string `ddl:"keyword,no_quotes"` + create bool `ddl:"static" sql:"CREATE"` + OrReplace *bool `ddl:"keyword" sql:"OR REPLACE"` + Secure *bool `ddl:"keyword" sql:"SECURE"` + Temporary *bool `ddl:"keyword" sql:"TEMPORARY"` + Recursive *bool `ddl:"keyword" sql:"RECURSIVE"` + view bool `ddl:"static" sql:"VIEW"` + IfNotExists *bool `ddl:"keyword" sql:"IF NOT EXISTS"` + name SchemaObjectIdentifier `ddl:"identifier"` + Columns []ViewColumn `ddl:"list,parentheses"` + CopyGrants *bool `ddl:"keyword" sql:"COPY GRANTS"` + Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` + RowAccessPolicy *ViewRowAccessPolicy `ddl:"keyword"` + AggregationPolicy *ViewAggregationPolicy `ddl:"keyword"` + Tag []TagAssociation `ddl:"keyword,parentheses" sql:"TAG"` + as bool `ddl:"static" sql:"AS"` + sql string `ddl:"keyword,no_quotes"` } - type ViewColumn struct { - Name string `ddl:"keyword,double_quotes"` - Comment *string `ddl:"parameter,single_quotes,no_equals" sql:"COMMENT"` + Name string `ddl:"keyword,double_quotes"` + ProjectionPolicy *ViewColumnProjectionPolicy `ddl:"keyword"` + MaskingPolicy *ViewColumnMaskingPolicy `ddl:"keyword"` + Comment *string `ddl:"parameter,single_quotes,no_equals" sql:"COMMENT"` + Tag []TagAssociation `ddl:"keyword,parentheses" sql:"TAG"` +} +type ViewColumnProjectionPolicy struct { + ProjectionPolicy SchemaObjectIdentifier `ddl:"identifier" sql:"PROJECTION POLICY"` } - type ViewColumnMaskingPolicy struct { - Name string `ddl:"keyword"` MaskingPolicy SchemaObjectIdentifier `ddl:"identifier" sql:"MASKING POLICY"` - Using []string `ddl:"keyword,parentheses" sql:"USING"` - Tag []TagAssociation `ddl:"keyword,parentheses" sql:"TAG"` + Using []DoubleQuotedString `ddl:"parameter,parentheses,no_equals" sql:"USING"` } - type ViewRowAccessPolicy struct { RowAccessPolicy SchemaObjectIdentifier `ddl:"identifier" sql:"ROW ACCESS POLICY"` - On []string `ddl:"keyword,parentheses" sql:"ON"` + On []DoubleQuotedString `ddl:"parameter,parentheses,no_equals" sql:"ON"` +} +type ViewAggregationPolicy struct { + AggregationPolicy SchemaObjectIdentifier `ddl:"identifier" sql:"AGGREGATION POLICY"` + EntityKey []DoubleQuotedString `ddl:"parameter,parentheses,no_equals" sql:"ENTITY KEY"` } // AlterViewOptions is based on https://docs.snowflake.com/en/sql-reference/sql/alter-view. type AlterViewOptions struct { - alter bool `ddl:"static" sql:"ALTER"` - view bool `ddl:"static" sql:"VIEW"` - IfExists *bool `ddl:"keyword" sql:"IF EXISTS"` - name SchemaObjectIdentifier `ddl:"identifier"` - RenameTo *SchemaObjectIdentifier `ddl:"identifier" sql:"RENAME TO"` - SetComment *string `ddl:"parameter,single_quotes" sql:"SET COMMENT"` - UnsetComment *bool `ddl:"keyword" sql:"UNSET COMMENT"` - SetSecure *bool `ddl:"keyword" sql:"SET SECURE"` - SetChangeTracking *bool `ddl:"parameter" sql:"SET CHANGE_TRACKING"` - UnsetSecure *bool `ddl:"keyword" sql:"UNSET SECURE"` - SetTags []TagAssociation `ddl:"keyword" sql:"SET TAG"` - UnsetTags []ObjectIdentifier `ddl:"keyword" sql:"UNSET TAG"` - AddRowAccessPolicy *ViewAddRowAccessPolicy `ddl:"keyword"` - DropRowAccessPolicy *ViewDropRowAccessPolicy `ddl:"keyword"` - DropAndAddRowAccessPolicy *ViewDropAndAddRowAccessPolicy `ddl:"list,no_parentheses"` - DropAllRowAccessPolicies *bool `ddl:"keyword" sql:"DROP ALL ROW ACCESS POLICIES"` - SetMaskingPolicyOnColumn *ViewSetColumnMaskingPolicy `ddl:"keyword"` - UnsetMaskingPolicyOnColumn *ViewUnsetColumnMaskingPolicy `ddl:"keyword"` - SetTagsOnColumn *ViewSetColumnTags `ddl:"keyword"` - UnsetTagsOnColumn *ViewUnsetColumnTags `ddl:"keyword"` + alter bool `ddl:"static" sql:"ALTER"` + view bool `ddl:"static" sql:"VIEW"` + IfExists *bool `ddl:"keyword" sql:"IF EXISTS"` + name SchemaObjectIdentifier `ddl:"identifier"` + RenameTo *SchemaObjectIdentifier `ddl:"identifier" sql:"RENAME TO"` + SetComment *string `ddl:"parameter,single_quotes" sql:"SET COMMENT"` + UnsetComment *bool `ddl:"keyword" sql:"UNSET COMMENT"` + SetSecure *bool `ddl:"keyword" sql:"SET SECURE"` + SetChangeTracking *bool `ddl:"parameter" sql:"SET CHANGE_TRACKING"` + UnsetSecure *bool `ddl:"keyword" sql:"UNSET SECURE"` + SetTags []TagAssociation `ddl:"keyword" sql:"SET TAG"` + UnsetTags []ObjectIdentifier `ddl:"keyword" sql:"UNSET TAG"` + AddDataMetricFunction *ViewAddDataMetricFunction `ddl:"keyword"` + DropDataMetricFunction *ViewDropDataMetricFunction `ddl:"keyword"` + SetDataMetricSchedule *ViewSetDataMetricSchedule `ddl:"keyword"` + UnsetDataMetricSchedule *ViewUnsetDataMetricSchedule `ddl:"keyword"` + AddRowAccessPolicy *ViewAddRowAccessPolicy `ddl:"keyword"` + DropRowAccessPolicy *ViewDropRowAccessPolicy `ddl:"keyword"` + DropAndAddRowAccessPolicy *ViewDropAndAddRowAccessPolicy `ddl:"list,no_parentheses"` + DropAllRowAccessPolicies *bool `ddl:"keyword" sql:"DROP ALL ROW ACCESS POLICIES"` + SetAggregationPolicy *ViewSetAggregationPolicy `ddl:"keyword"` + UnsetAggregationPolicy *ViewUnsetAggregationPolicy `ddl:"keyword"` + SetMaskingPolicyOnColumn *ViewSetColumnMaskingPolicy `ddl:"keyword"` + UnsetMaskingPolicyOnColumn *ViewUnsetColumnMaskingPolicy `ddl:"keyword"` + SetProjectionPolicyOnColumn *ViewSetProjectionPolicy `ddl:"keyword"` + UnsetProjectionPolicyOnColumn *ViewUnsetProjectionPolicy `ddl:"keyword"` + SetTagsOnColumn *ViewSetColumnTags `ddl:"keyword"` + UnsetTagsOnColumn *ViewUnsetColumnTags `ddl:"keyword"` +} +type DoubleQuotedString struct { + Value string `ddl:"keyword,double_quotes"` +} +type ViewDataMetricFunction struct { + DataMetricFunction SchemaObjectIdentifier `ddl:"identifier"` + On []DoubleQuotedString `ddl:"parameter,parentheses,no_equals" sql:"ON"` +} +type ViewAddDataMetricFunction struct { + add bool `ddl:"static" sql:"ADD"` + DataMetricFunction []ViewDataMetricFunction `ddl:"parameter,no_equals" sql:"DATA METRIC FUNCTION"` +} +type ViewDropDataMetricFunction struct { + drop bool `ddl:"static" sql:"DROP"` + DataMetricFunction []ViewDataMetricFunction `ddl:"parameter,no_equals" sql:"DATA METRIC FUNCTION"` +} +type ViewSetDataMetricSchedule struct { + setDataMetricSchedule bool `ddl:"static" sql:"SET DATA_METRIC_SCHEDULE ="` + Minutes *ViewMinute `ddl:"keyword"` + UsingCron *ViewUsingCron `ddl:"keyword"` + TriggerOnChanges *bool `ddl:"keyword,single_quotes" sql:"TRIGGER_ON_CHANGES"` +} +type ViewMinute struct { + prefix bool `ddl:"static" sql:"'"` + Minutes int `ddl:"keyword"` + suffix bool `ddl:"static" sql:"MINUTE'"` +} +type ViewUsingCron struct { + prefix bool `ddl:"static" sql:"'USING CRON"` + Cron string `ddl:"keyword"` + suffix bool `ddl:"static" sql:"'"` +} +type ViewTriggerOnChanges struct { + triggerOnChanges bool `ddl:"static" sql:"TRIGGER_ON_CHANGES"` +} +type ViewUnsetDataMetricSchedule struct { + unsetDataMetricSchedule bool `ddl:"static" sql:"UNSET DATA_METRIC_SCHEDULE"` } - type ViewAddRowAccessPolicy struct { add bool `ddl:"static" sql:"ADD"` RowAccessPolicy SchemaObjectIdentifier `ddl:"identifier" sql:"ROW ACCESS POLICY"` - On []string `ddl:"keyword,parentheses" sql:"ON"` + On []DoubleQuotedString `ddl:"parameter,parentheses,no_equals" sql:"ON"` } - type ViewDropRowAccessPolicy struct { drop bool `ddl:"static" sql:"DROP"` RowAccessPolicy SchemaObjectIdentifier `ddl:"identifier" sql:"ROW ACCESS POLICY"` } - type ViewDropAndAddRowAccessPolicy struct { Drop ViewDropRowAccessPolicy `ddl:"keyword"` Add ViewAddRowAccessPolicy `ddl:"keyword"` } - +type ViewSetAggregationPolicy struct { + set bool `ddl:"static" sql:"SET"` + AggregationPolicy SchemaObjectIdentifier `ddl:"identifier" sql:"AGGREGATION POLICY"` + EntityKey []DoubleQuotedString `ddl:"parameter,parentheses,no_equals" sql:"ENTITY KEY"` + Force *bool `ddl:"keyword" sql:"FORCE"` +} +type ViewUnsetAggregationPolicy struct { + unsetAggregationPolicy bool `ddl:"static" sql:"UNSET AGGREGATION POLICY"` +} type ViewSetColumnMaskingPolicy struct { alter bool `ddl:"static" sql:"ALTER"` column bool `ddl:"static" sql:"COLUMN"` - Name string `ddl:"keyword"` + Name string `ddl:"keyword,double_quotes"` set bool `ddl:"static" sql:"SET"` MaskingPolicy SchemaObjectIdentifier `ddl:"identifier" sql:"MASKING POLICY"` - Using []string `ddl:"keyword,parentheses" sql:"USING"` + Using []DoubleQuotedString `ddl:"parameter,parentheses,no_equals" sql:"USING"` Force *bool `ddl:"keyword" sql:"FORCE"` } - type ViewUnsetColumnMaskingPolicy struct { alter bool `ddl:"static" sql:"ALTER"` column bool `ddl:"static" sql:"COLUMN"` - Name string `ddl:"keyword"` + Name string `ddl:"keyword,double_quotes"` unset bool `ddl:"static" sql:"UNSET"` maskingPolicy bool `ddl:"static" sql:"MASKING POLICY"` } - +type ViewSetProjectionPolicy struct { + alter bool `ddl:"static" sql:"ALTER"` + column bool `ddl:"static" sql:"COLUMN"` + Name string `ddl:"keyword,double_quotes"` + set bool `ddl:"static" sql:"SET"` + ProjectionPolicy SchemaObjectIdentifier `ddl:"identifier" sql:"PROJECTION POLICY"` + Force *bool `ddl:"keyword" sql:"FORCE"` +} +type ViewUnsetProjectionPolicy struct { + alter bool `ddl:"static" sql:"ALTER"` + column bool `ddl:"static" sql:"COLUMN"` + Name string `ddl:"keyword,double_quotes"` + unset bool `ddl:"static" sql:"UNSET"` + projectionPolicy bool `ddl:"static" sql:"PROJECTION POLICY"` +} type ViewSetColumnTags struct { alter bool `ddl:"static" sql:"ALTER"` column bool `ddl:"static" sql:"COLUMN"` - Name string `ddl:"keyword"` + Name string `ddl:"keyword,double_quotes"` SetTags []TagAssociation `ddl:"keyword" sql:"SET TAG"` } - type ViewUnsetColumnTags struct { alter bool `ddl:"static" sql:"ALTER"` column bool `ddl:"static" sql:"COLUMN"` - Name string `ddl:"keyword"` + Name string `ddl:"keyword,double_quotes"` UnsetTags []ObjectIdentifier `ddl:"keyword" sql:"UNSET TAG"` } @@ -134,15 +201,14 @@ type DropViewOptions struct { // ShowViewOptions is based on https://docs.snowflake.com/en/sql-reference/sql/show-views. type ShowViewOptions struct { - show bool `ddl:"static" sql:"SHOW"` - Terse *bool `ddl:"keyword" sql:"TERSE"` - views bool `ddl:"static" sql:"VIEWS"` - Like *Like `ddl:"keyword" sql:"LIKE"` - In *In `ddl:"keyword" sql:"IN"` - StartsWith *string `ddl:"parameter,no_equals,single_quotes" sql:"STARTS WITH"` - Limit *LimitFrom `ddl:"keyword" sql:"LIMIT"` + show bool `ddl:"static" sql:"SHOW"` + Terse *bool `ddl:"keyword" sql:"TERSE"` + views bool `ddl:"static" sql:"VIEWS"` + Like *Like `ddl:"keyword" sql:"LIKE"` + In *ExtendedIn `ddl:"keyword" sql:"IN"` + StartsWith *string `ddl:"parameter,single_quotes,no_equals" sql:"STARTS WITH"` + Limit *LimitFrom `ddl:"keyword" sql:"LIMIT"` } - type viewDBRow struct { CreatedOn string `db:"created_on"` Name string `db:"name"` @@ -158,7 +224,6 @@ type viewDBRow struct { OwnerRoleType sql.NullString `db:"owner_role_type"` ChangeTracking sql.NullString `db:"change_tracking"` } - type View struct { CreatedOn string Name string @@ -189,34 +254,31 @@ type DescribeViewOptions struct { view bool `ddl:"static" sql:"VIEW"` name SchemaObjectIdentifier `ddl:"identifier"` } - -// TODO [SNOW-965322]: extract common type for describe -// viewDetailsRow is a copy of externalTableColumnDetailsRow. type viewDetailsRow struct { - Name string `db:"name"` - Type DataType `db:"type"` - Kind string `db:"kind"` - IsNullable string `db:"null?"` - Default sql.NullString `db:"default"` - IsPrimary string `db:"primary key"` - IsUnique string `db:"unique key"` - Check sql.NullString `db:"check"` - Expression sql.NullString `db:"expression"` - Comment sql.NullString `db:"comment"` - PolicyName sql.NullString `db:"policy name"` + Name string `db:"name"` + Type DataType `db:"type"` + Kind string `db:"kind"` + Null string `db:"null?"` + Default sql.NullString `db:"default"` + PrimaryKey string `db:"primary key"` + UniqueKey string `db:"unique key"` + Check sql.NullString `db:"check"` + Expression sql.NullString `db:"expression"` + Comment sql.NullString `db:"comment"` + PolicyName sql.NullString `db:"policy name"` + PrivacyDomain sql.NullString `db:"privacy domain"` } - -// ViewDetails is a copy of ExternalTableColumnDetails. type ViewDetails struct { - Name string - Type DataType - Kind string - IsNullable bool - Default *string - IsPrimary bool - IsUnique bool - Check *bool - Expression *string - Comment *string - PolicyName *string + Name string + Type DataType + Kind string + IsNullable bool + Default *string + IsPrimary bool + IsUnique bool + Check *bool + Expression *string + Comment *string + PolicyName *string + PrivacyDomain *string } diff --git a/pkg/sdk/views_gen_test.go b/pkg/sdk/views_gen_test.go index 80ec68535c..d32e775e3a 100644 --- a/pkg/sdk/views_gen_test.go +++ b/pkg/sdk/views_gen_test.go @@ -1,6 +1,7 @@ package sdk import ( + "fmt" "testing" ) @@ -46,11 +47,37 @@ func TestViews_Create(t *testing.T) { opts := defaultOpts() opts.RowAccessPolicy = &ViewRowAccessPolicy{ RowAccessPolicy: randomSchemaObjectIdentifier(), - On: []string{}, + On: []DoubleQuotedString{}, } assertOptsInvalidJoinedErrors(t, opts, errNotSet("CreateViewOptions.RowAccessPolicy", "On")) }) + t.Run("validation: valid identifier for [opts.MaskingPolicy.MaskingPolicy]", func(t *testing.T) { + opts := defaultOpts() + opts.Columns = []ViewColumn{ + { + Name: "foo", + MaskingPolicy: &ViewColumnMaskingPolicy{ + MaskingPolicy: emptySchemaObjectIdentifier, + }, + }, + } + assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) + }) + + t.Run("validation: valid identifier for [opts.ProjectionPolicy.ProjectionPolicy]", func(t *testing.T) { + opts := defaultOpts() + opts.Columns = []ViewColumn{ + { + Name: "foo", + ProjectionPolicy: &ViewColumnProjectionPolicy{ + ProjectionPolicy: emptySchemaObjectIdentifier, + }, + }, + } + assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) + }) + t.Run("basic", func(t *testing.T) { opts := defaultOpts() assertOptsValidAndSQLEquals(t, opts, "CREATE VIEW %s AS %s", id.FullyQualifiedName(), sql) @@ -58,38 +85,39 @@ func TestViews_Create(t *testing.T) { t.Run("all options", func(t *testing.T) { rowAccessPolicyId := randomSchemaObjectIdentifier() + aggregationPolicyId := randomSchemaObjectIdentifier() tag1Id := randomSchemaObjectIdentifier() tag2Id := randomSchemaObjectIdentifier() maskingPolicy1Id := randomSchemaObjectIdentifier() maskingPolicy2Id := randomSchemaObjectIdentifier() req := NewCreateViewRequest(id, sql). - WithOrReplace(Bool(true)). - WithSecure(Bool(true)). - WithTemporary(Bool(true)). - WithRecursive(Bool(true)). + WithOrReplace(true). + WithSecure(true). + WithTemporary(true). + WithRecursive(true). WithColumns([]ViewColumnRequest{ *NewViewColumnRequest("column_without_comment"), - *NewViewColumnRequest("column_with_comment").WithComment(String("column 2 comment")), - }). - WithColumnsMaskingPolicies([]ViewColumnMaskingPolicyRequest{ - *NewViewColumnMaskingPolicyRequest("column", maskingPolicy1Id). - WithUsing([]string{"a", "b"}). - WithTag([]TagAssociation{{ - Name: tag1Id, - Value: "v1", - }}), - *NewViewColumnMaskingPolicyRequest("column 2", maskingPolicy2Id), + *NewViewColumnRequest("column_with_comment").WithComment("column 2 comment"), + *NewViewColumnRequest("column").WithMaskingPolicy( + *NewViewColumnMaskingPolicyRequest(maskingPolicy1Id). + WithUsing([]DoubleQuotedString{{"a"}, {"b"}}), + ).WithTag([]TagAssociation{{Name: tag1Id, Value: "v1"}}), + *NewViewColumnRequest("column 2").WithProjectionPolicy( + *NewViewColumnProjectionPolicyRequest(maskingPolicy2Id), + ), }). - WithCopyGrants(Bool(true)). - WithComment(String("comment")). - WithRowAccessPolicy(NewViewRowAccessPolicyRequest(rowAccessPolicyId, []string{"c", "d"})). + WithCopyGrants(true). + WithComment("comment"). + WithRowAccessPolicy(*NewViewRowAccessPolicyRequest(rowAccessPolicyId, []DoubleQuotedString{{"c"}, {"d"}})). + WithAggregationPolicy(*NewViewAggregationPolicyRequest(aggregationPolicyId).WithEntityKey([]DoubleQuotedString{{"column_with_comment"}})). WithTag([]TagAssociation{{ Name: tag2Id, Value: "v2", }}) - assertOptsValidAndSQLEquals(t, req.toOpts(), `CREATE OR REPLACE SECURE TEMPORARY RECURSIVE VIEW %s ("column_without_comment", "column_with_comment" COMMENT 'column 2 comment') column MASKING POLICY %s USING (a, b) TAG (%s = 'v1'), column 2 MASKING POLICY %s COPY GRANTS COMMENT = 'comment' ROW ACCESS POLICY %s ON (c, d) TAG (%s = 'v2') AS %s`, id.FullyQualifiedName(), maskingPolicy1Id.FullyQualifiedName(), tag1Id.FullyQualifiedName(), maskingPolicy2Id.FullyQualifiedName(), rowAccessPolicyId.FullyQualifiedName(), tag2Id.FullyQualifiedName(), sql) + assertOptsValidAndSQLEquals(t, req.toOpts(), `CREATE OR REPLACE SECURE TEMPORARY RECURSIVE VIEW %s `+ + `("column_without_comment", "column_with_comment" COMMENT 'column 2 comment', "column" MASKING POLICY %s USING ("a", "b") TAG (%s = 'v1'), "column 2" PROJECTION POLICY %s) COPY GRANTS COMMENT = 'comment' ROW ACCESS POLICY %s ON ("c", "d") AGGREGATION POLICY %s ENTITY KEY ("column_with_comment") TAG (%s = 'v2') AS %s`, id.FullyQualifiedName(), maskingPolicy1Id.FullyQualifiedName(), tag1Id.FullyQualifiedName(), maskingPolicy2Id.FullyQualifiedName(), rowAccessPolicyId.FullyQualifiedName(), aggregationPolicyId.FullyQualifiedName(), tag2Id.FullyQualifiedName(), sql) }) } @@ -114,16 +142,43 @@ func TestViews_Alter(t *testing.T) { assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) - t.Run("validation: exactly one field from [opts.RenameTo opts.SetComment opts.UnsetComment opts.SetSecure opts.SetChangeTracking opts.UnsetSecure opts.SetTags opts.UnsetTags opts.AddRowAccessPolicy opts.DropRowAccessPolicy opts.DropAndAddRowAccessPolicy opts.DropAllRowAccessPolicies opts.SetMaskingPolicyOnColumn opts.UnsetMaskingPolicyOnColumn opts.SetTagsOnColumn opts.UnsetTagsOnColumn] should be present", func(t *testing.T) { + t.Run("validation: exactly one field from [opts.RenameTo opts.SetComment opts.UnsetComment opts.SetSecure opts.SetChangeTracking opts.UnsetSecure opts.SetTags opts.UnsetTags opts.AddDataMetricFunction opts.DropDataMetricFunction opts.AddRowAccessPolicy opts.DropRowAccessPolicy opts.DropAndAddRowAccessPolicy opts.DropAllRowAccessPolicies opts.SetMaskingPolicyOnColumn opts.UnsetMaskingPolicyOnColumn opts.SetTagsOnColumn opts.UnsetTagsOnColumn] should be present", func(t *testing.T) { opts := defaultOpts() - assertOptsInvalidJoinedErrors(t, opts, errExactlyOneOf("AlterViewOptions", "RenameTo", "SetComment", "UnsetComment", "SetSecure", "SetChangeTracking", "UnsetSecure", "SetTags", "UnsetTags", "AddRowAccessPolicy", "DropRowAccessPolicy", "DropAndAddRowAccessPolicy", "DropAllRowAccessPolicies", "SetMaskingPolicyOnColumn", "UnsetMaskingPolicyOnColumn", "SetTagsOnColumn", "UnsetTagsOnColumn")) + assertOptsInvalidJoinedErrors(t, opts, errExactlyOneOf("AlterViewOptions", "RenameTo", "SetComment", "UnsetComment", "SetSecure", "SetChangeTracking", "UnsetSecure", "SetTags", "UnsetTags", "AddDataMetricFunction", "DropDataMetricFunction", "SetDataMetricSchedule", "UnsetDataMetricSchedule", "AddRowAccessPolicy", "DropRowAccessPolicy", "DropAndAddRowAccessPolicy", "DropAllRowAccessPolicies", "SetAggregationPolicy", "UnsetAggregationPolicy", "SetMaskingPolicyOnColumn", "UnsetMaskingPolicyOnColumn", "SetProjectionPolicyOnColumn", "UnsetProjectionPolicyOnColumn", "SetTagsOnColumn", "UnsetTagsOnColumn")) }) - t.Run("validation: exactly one field from [opts.RenameTo opts.SetComment opts.UnsetComment opts.SetSecure opts.SetChangeTracking opts.UnsetSecure opts.SetTags opts.UnsetTags opts.AddRowAccessPolicy opts.DropRowAccessPolicy opts.DropAndAddRowAccessPolicy opts.DropAllRowAccessPolicies opts.SetMaskingPolicyOnColumn opts.UnsetMaskingPolicyOnColumn opts.SetTagsOnColumn opts.UnsetTagsOnColumn] should be present - more present", func(t *testing.T) { + t.Run("validation: exactly one field from [opts.RenameTo opts.SetComment opts.UnsetComment opts.SetSecure opts.SetChangeTracking opts.UnsetSecure opts.SetTags opts.UnsetTags opts.AddDataMetricFunction opts.DropDataMetricFunction opts.AddRowAccessPolicy opts.DropRowAccessPolicy opts.DropAndAddRowAccessPolicy opts.DropAllRowAccessPolicies opts.SetMaskingPolicyOnColumn opts.UnsetMaskingPolicyOnColumn opts.SetTagsOnColumn opts.UnsetTagsOnColumn] should be present - more present", func(t *testing.T) { opts := defaultOpts() opts.SetChangeTracking = Bool(true) opts.DropAllRowAccessPolicies = Bool(true) - assertOptsInvalidJoinedErrors(t, opts, errExactlyOneOf("AlterViewOptions", "RenameTo", "SetComment", "UnsetComment", "SetSecure", "SetChangeTracking", "UnsetSecure", "SetTags", "UnsetTags", "AddRowAccessPolicy", "DropRowAccessPolicy", "DropAndAddRowAccessPolicy", "DropAllRowAccessPolicies", "SetMaskingPolicyOnColumn", "UnsetMaskingPolicyOnColumn", "SetTagsOnColumn", "UnsetTagsOnColumn")) + assertOptsInvalidJoinedErrors(t, opts, errExactlyOneOf("AlterViewOptions", "RenameTo", "SetComment", "UnsetComment", "SetSecure", "SetChangeTracking", "UnsetSecure", "SetTags", "UnsetTags", "AddDataMetricFunction", "DropDataMetricFunction", "SetDataMetricSchedule", "UnsetDataMetricSchedule", "AddRowAccessPolicy", "DropRowAccessPolicy", "DropAndAddRowAccessPolicy", "DropAllRowAccessPolicies", "SetAggregationPolicy", "UnsetAggregationPolicy", "SetMaskingPolicyOnColumn", "UnsetMaskingPolicyOnColumn", "SetProjectionPolicyOnColumn", "UnsetProjectionPolicyOnColumn", "SetTagsOnColumn", "UnsetTagsOnColumn")) + }) + + t.Run("validation: exactly one field from [opts.SetDataMetricSchedule.UsingCron opts.SetDataMetricSchedule.TriggerOnChanges opts.SetDataMetricSchedule.Minutes] should be present - more present", func(t *testing.T) { + opts := defaultOpts() + opts.SetDataMetricSchedule = &ViewSetDataMetricSchedule{ + UsingCron: &ViewUsingCron{ + Cron: "5 * * * * UTC", + }, + TriggerOnChanges: Pointer(true), + } + + opts.DropAllRowAccessPolicies = Bool(true) + assertOptsInvalidJoinedErrors(t, opts, errExactlyOneOf("AlterViewOptions.SetDataMetricSchedule", "Minutes", "UsingCron", "TriggerOnChanges")) + }) + + t.Run("validation: conflicting fields for [opts.IfExists opts.SetSecure]", func(t *testing.T) { + opts := defaultOpts() + opts.IfExists = Bool(true) + opts.SetSecure = Bool(true) + assertOptsInvalidJoinedErrors(t, opts, errOneOf("AlterViewOptions", "IfExists", "SetSecure")) + }) + + t.Run("validation: conflicting fields for [opts.IfExists opts.UnsetSecure]", func(t *testing.T) { + opts := defaultOpts() + opts.IfExists = Bool(true) + opts.UnsetSecure = Bool(true) + assertOptsInvalidJoinedErrors(t, opts, errOneOf("AlterViewOptions", "IfExists", "UnsetSecure")) }) t.Run("validation: valid identifier for [opts.DropRowAccessPolicy.RowAccessPolicy]", func(t *testing.T) { @@ -146,7 +201,7 @@ func TestViews_Alter(t *testing.T) { opts := defaultOpts() opts.AddRowAccessPolicy = &ViewAddRowAccessPolicy{ RowAccessPolicy: randomSchemaObjectIdentifier(), - On: []string{}, + On: []DoubleQuotedString{}, } assertOptsInvalidJoinedErrors(t, opts, errNotSet("AlterViewOptions.AddRowAccessPolicy", "On")) }) @@ -185,7 +240,7 @@ func TestViews_Alter(t *testing.T) { }, Add: ViewAddRowAccessPolicy{ RowAccessPolicy: randomSchemaObjectIdentifier(), - On: []string{}, + On: []DoubleQuotedString{}, }, } assertOptsInvalidJoinedErrors(t, opts, errNotSet("AlterViewOptions.DropAndAddRowAccessPolicy.Add", "On")) @@ -235,6 +290,56 @@ func TestViews_Alter(t *testing.T) { assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s UNSET SECURE", id.FullyQualifiedName()) }) + t.Run("add data metric function", func(t *testing.T) { + dmfId := randomSchemaObjectIdentifier() + + opts := defaultOpts() + opts.AddDataMetricFunction = &ViewAddDataMetricFunction{ + DataMetricFunction: []ViewDataMetricFunction{{DataMetricFunction: dmfId, On: []DoubleQuotedString{{"foo"}}}}, + } + assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s ADD DATA METRIC FUNCTION %s ON (\"foo\")", id.FullyQualifiedName(), dmfId.FullyQualifiedName()) + }) + + t.Run("drop data metric function", func(t *testing.T) { + dmfId := randomSchemaObjectIdentifier() + + opts := defaultOpts() + opts.DropDataMetricFunction = &ViewDropDataMetricFunction{ + DataMetricFunction: []ViewDataMetricFunction{{DataMetricFunction: dmfId, On: []DoubleQuotedString{{"foo"}}}}, + } + assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s DROP DATA METRIC FUNCTION %s ON (\"foo\")", id.FullyQualifiedName(), dmfId.FullyQualifiedName()) + }) + + t.Run("set data metric schedule", func(t *testing.T) { + opts := defaultOpts() + opts.SetDataMetricSchedule = &ViewSetDataMetricSchedule{ + Minutes: &ViewMinute{ + Minutes: 5, + }, + } + assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s SET DATA_METRIC_SCHEDULE = ' 5 MINUTE'", id.FullyQualifiedName()) + + opts = defaultOpts() + opts.SetDataMetricSchedule = &ViewSetDataMetricSchedule{ + UsingCron: &ViewUsingCron{ + Cron: "5 * * * * UTC", + }, + } + assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s SET DATA_METRIC_SCHEDULE = 'USING CRON 5 * * * * UTC '", id.FullyQualifiedName()) + + opts = defaultOpts() + opts.SetDataMetricSchedule = &ViewSetDataMetricSchedule{ + TriggerOnChanges: Pointer(true), + } + assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s SET DATA_METRIC_SCHEDULE = 'TRIGGER_ON_CHANGES'", id.FullyQualifiedName()) + }) + + t.Run("unset data metric schedule", func(t *testing.T) { + opts := defaultOpts() + opts.UnsetDataMetricSchedule = &ViewUnsetDataMetricSchedule{} + assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s UNSET DATA_METRIC_SCHEDULE", id.FullyQualifiedName()) + }) + t.Run("set tags", func(t *testing.T) { opts := defaultOpts() opts.SetTags = []TagAssociation{ @@ -265,9 +370,9 @@ func TestViews_Alter(t *testing.T) { opts := defaultOpts() opts.AddRowAccessPolicy = &ViewAddRowAccessPolicy{ RowAccessPolicy: rowAccessPolicyId, - On: []string{"a", "b"}, + On: []DoubleQuotedString{{"a"}, {"b"}}, } - assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s ADD ROW ACCESS POLICY %s ON (a, b)", id.FullyQualifiedName(), rowAccessPolicyId.FullyQualifiedName()) + assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s ADD ROW ACCESS POLICY %s ON (\"a\", \"b\")", id.FullyQualifiedName(), rowAccessPolicyId.FullyQualifiedName()) }) t.Run("drop row access policy", func(t *testing.T) { @@ -291,10 +396,10 @@ func TestViews_Alter(t *testing.T) { }, Add: ViewAddRowAccessPolicy{ RowAccessPolicy: rowAccessPolicy2Id, - On: []string{"a", "b"}, + On: []DoubleQuotedString{{"a"}, {"b"}}, }, } - assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s DROP ROW ACCESS POLICY %s, ADD ROW ACCESS POLICY %s ON (a, b)", id.FullyQualifiedName(), rowAccessPolicy1Id.FullyQualifiedName(), rowAccessPolicy2Id.FullyQualifiedName()) + assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s DROP ROW ACCESS POLICY %s, ADD ROW ACCESS POLICY %s ON (\"a\", \"b\")", id.FullyQualifiedName(), rowAccessPolicy1Id.FullyQualifiedName(), rowAccessPolicy2Id.FullyQualifiedName()) }) t.Run("drop all row access policies", func(t *testing.T) { @@ -303,6 +408,24 @@ func TestViews_Alter(t *testing.T) { assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s DROP ALL ROW ACCESS POLICIES", id.FullyQualifiedName()) }) + t.Run("set aggregation policy", func(t *testing.T) { + aggregationPolicyId := randomSchemaObjectIdentifier() + + opts := defaultOpts() + opts.SetAggregationPolicy = &ViewSetAggregationPolicy{ + AggregationPolicy: aggregationPolicyId, + EntityKey: []DoubleQuotedString{{"a"}, {"b"}}, + Force: Bool(true), + } + assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s SET AGGREGATION POLICY %s ENTITY KEY (\"a\", \"b\") FORCE", id.FullyQualifiedName(), aggregationPolicyId.FullyQualifiedName()) + }) + + t.Run("unset aggregation policy", func(t *testing.T) { + opts := defaultOpts() + opts.UnsetAggregationPolicy = &ViewUnsetAggregationPolicy{} + assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s UNSET AGGREGATION POLICY", id.FullyQualifiedName()) + }) + t.Run("set masking policy on column", func(t *testing.T) { maskingPolicyId := randomSchemaObjectIdentifier() @@ -310,10 +433,10 @@ func TestViews_Alter(t *testing.T) { opts.SetMaskingPolicyOnColumn = &ViewSetColumnMaskingPolicy{ Name: "column", MaskingPolicy: maskingPolicyId, - Using: []string{"a", "b"}, + Using: []DoubleQuotedString{{"a"}, {"b"}}, Force: Bool(true), } - assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s ALTER COLUMN column SET MASKING POLICY %s USING (a, b) FORCE", id.FullyQualifiedName(), maskingPolicyId.FullyQualifiedName()) + assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s ALTER COLUMN \"column\" SET MASKING POLICY %s USING (\"a\", \"b\") FORCE", id.FullyQualifiedName(), maskingPolicyId.FullyQualifiedName()) }) t.Run("unset masking policy on column", func(t *testing.T) { @@ -321,7 +444,27 @@ func TestViews_Alter(t *testing.T) { opts.UnsetMaskingPolicyOnColumn = &ViewUnsetColumnMaskingPolicy{ Name: "column", } - assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s ALTER COLUMN column UNSET MASKING POLICY", id.FullyQualifiedName()) + assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s ALTER COLUMN \"column\" UNSET MASKING POLICY", id.FullyQualifiedName()) + }) + + t.Run("set projection policy on column", func(t *testing.T) { + projectionPolicyId := randomSchemaObjectIdentifier() + + opts := defaultOpts() + opts.SetProjectionPolicyOnColumn = &ViewSetProjectionPolicy{ + Name: "column", + ProjectionPolicy: projectionPolicyId, + Force: Bool(true), + } + assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s ALTER COLUMN \"column\" SET PROJECTION POLICY %s FORCE", id.FullyQualifiedName(), projectionPolicyId.FullyQualifiedName()) + }) + + t.Run("unset projection policy on column", func(t *testing.T) { + opts := defaultOpts() + opts.UnsetProjectionPolicyOnColumn = &ViewUnsetProjectionPolicy{ + Name: "column", + } + assertOptsValidAndSQLEquals(t, opts, "ALTER VIEW %s ALTER COLUMN \"column\" UNSET PROJECTION POLICY", id.FullyQualifiedName()) }) t.Run("set tags on column", func(t *testing.T) { @@ -339,7 +482,7 @@ func TestViews_Alter(t *testing.T) { }, }, } - assertOptsValidAndSQLEquals(t, opts, `ALTER VIEW %s ALTER COLUMN column SET TAG "tag1" = 'value1', "tag2" = 'value2'`, id.FullyQualifiedName()) + assertOptsValidAndSQLEquals(t, opts, `ALTER VIEW %s ALTER COLUMN "column" SET TAG "tag1" = 'value1', "tag2" = 'value2'`, id.FullyQualifiedName()) }) t.Run("unset tags on column", func(t *testing.T) { @@ -351,7 +494,7 @@ func TestViews_Alter(t *testing.T) { NewAccountObjectIdentifier("tag2"), }, } - assertOptsValidAndSQLEquals(t, opts, `ALTER VIEW %s ALTER COLUMN column UNSET TAG "tag1", "tag2"`, id.FullyQualifiedName()) + assertOptsValidAndSQLEquals(t, opts, `ALTER VIEW %s ALTER COLUMN "column" UNSET TAG "tag1", "tag2"`, id.FullyQualifiedName()) }) } @@ -398,14 +541,56 @@ func TestViews_Show(t *testing.T) { assertOptsValidAndSQLEquals(t, opts, "SHOW VIEWS") }) + t.Run("in database", func(t *testing.T) { + id := randomAccountObjectIdentifier() + opts := defaultOpts() + opts.In = &ExtendedIn{ + In: In{ + Database: id, + }, + } + assertOptsValidAndSQLEquals(t, opts, fmt.Sprintf("SHOW VIEWS IN DATABASE %s", id.FullyQualifiedName())) + }) + + t.Run("in schema", func(t *testing.T) { + id := randomDatabaseObjectIdentifier() + opts := defaultOpts() + opts.In = &ExtendedIn{ + In: In{ + Schema: id, + }, + } + assertOptsValidAndSQLEquals(t, opts, fmt.Sprintf("SHOW VIEWS IN SCHEMA %s", id.FullyQualifiedName())) + }) + + t.Run("in application", func(t *testing.T) { + id := randomAccountObjectIdentifier() + opts := defaultOpts() + opts.In = &ExtendedIn{ + Application: id, + } + assertOptsValidAndSQLEquals(t, opts, fmt.Sprintf("SHOW VIEWS IN APPLICATION %s", id.FullyQualifiedName())) + }) + + t.Run("in application package", func(t *testing.T) { + id := randomAccountObjectIdentifier() + opts := defaultOpts() + opts.In = &ExtendedIn{ + ApplicationPackage: id, + } + assertOptsValidAndSQLEquals(t, opts, fmt.Sprintf("SHOW VIEWS IN APPLICATION PACKAGE %s", id.FullyQualifiedName())) + }) + t.Run("all options", func(t *testing.T) { opts := defaultOpts() opts.Terse = Bool(true) opts.Like = &Like{ Pattern: String("myaccount"), } - opts.In = &In{ - Account: Bool(true), + opts.In = &ExtendedIn{ + In: In{ + Account: Bool(true), + }, } opts.StartsWith = String("abc") opts.Limit = &LimitFrom{Rows: Int(10)} diff --git a/pkg/sdk/views_impl_gen.go b/pkg/sdk/views_impl_gen.go index e41fb0bd63..0bf564d6b8 100644 --- a/pkg/sdk/views_impl_gen.go +++ b/pkg/sdk/views_impl_gen.go @@ -38,7 +38,7 @@ func (v *views) Show(ctx context.Context, request *ShowViewRequest) ([]View, err } func (v *views) ShowByID(ctx context.Context, id SchemaObjectIdentifier) (*View, error) { - request := NewShowViewRequest().WithIn(&In{Schema: id.SchemaId()}).WithLike(&Like{String(id.Name())}) + request := NewShowViewRequest().WithIn(ExtendedIn{In: In{Schema: id.SchemaId()}}).WithLike(Like{String(id.Name())}) views, err := v.Show(ctx, request) if err != nil { return nil, err @@ -72,64 +72,135 @@ func (r *CreateViewRequest) toOpts() *CreateViewOptions { Tag: r.Tag, sql: r.sql, } + if r.Columns != nil { s := make([]ViewColumn, len(r.Columns)) for i, v := range r.Columns { - s[i] = ViewColumn(v) + s[i] = ViewColumn{ + Name: v.Name, + Tag: v.Tag, + Comment: v.Comment, + } + if v.ProjectionPolicy != nil { + s[i].ProjectionPolicy = &ViewColumnProjectionPolicy{ + ProjectionPolicy: v.ProjectionPolicy.ProjectionPolicy, + } + } + if v.MaskingPolicy != nil { + s[i].MaskingPolicy = &ViewColumnMaskingPolicy{ + MaskingPolicy: v.MaskingPolicy.MaskingPolicy, + Using: v.MaskingPolicy.Using, + } + } } opts.Columns = s } - if r.ColumnsMaskingPolicies != nil { - s := make([]ViewColumnMaskingPolicy, len(r.ColumnsMaskingPolicies)) - for i, v := range r.ColumnsMaskingPolicies { - s[i] = ViewColumnMaskingPolicy(v) - } - opts.ColumnsMaskingPolicies = s - } + if r.RowAccessPolicy != nil { opts.RowAccessPolicy = &ViewRowAccessPolicy{ RowAccessPolicy: r.RowAccessPolicy.RowAccessPolicy, On: r.RowAccessPolicy.On, } } + + if r.AggregationPolicy != nil { + opts.AggregationPolicy = &ViewAggregationPolicy{ + AggregationPolicy: r.AggregationPolicy.AggregationPolicy, + EntityKey: r.AggregationPolicy.EntityKey, + } + } + return opts } func (r *AlterViewRequest) toOpts() *AlterViewOptions { opts := &AlterViewOptions{ - IfExists: r.IfExists, - name: r.name, - RenameTo: r.RenameTo, - SetComment: r.SetComment, - UnsetComment: r.UnsetComment, - SetSecure: r.SetSecure, - SetChangeTracking: r.SetChangeTracking, - UnsetSecure: r.UnsetSecure, - SetTags: r.SetTags, - UnsetTags: r.UnsetTags, + IfExists: r.IfExists, + name: r.name, + RenameTo: r.RenameTo, + SetComment: r.SetComment, + UnsetComment: r.UnsetComment, + SetSecure: r.SetSecure, + SetChangeTracking: r.SetChangeTracking, + UnsetSecure: r.UnsetSecure, + SetTags: r.SetTags, + UnsetTags: r.UnsetTags, + DropAllRowAccessPolicies: r.DropAllRowAccessPolicies, } + + if r.AddDataMetricFunction != nil { + opts.AddDataMetricFunction = &ViewAddDataMetricFunction{ + DataMetricFunction: r.AddDataMetricFunction.DataMetricFunction, + } + } + + if r.DropDataMetricFunction != nil { + opts.DropDataMetricFunction = &ViewDropDataMetricFunction{ + DataMetricFunction: r.DropDataMetricFunction.DataMetricFunction, + } + } + + if r.SetDataMetricSchedule != nil { + opts.SetDataMetricSchedule = &ViewSetDataMetricSchedule{ + TriggerOnChanges: r.SetDataMetricSchedule.TriggerOnChanges, + } + + if r.SetDataMetricSchedule.Minutes != nil { + opts.SetDataMetricSchedule.Minutes = &ViewMinute{ + Minutes: r.SetDataMetricSchedule.Minutes.Minutes, + } + } + + if r.SetDataMetricSchedule.UsingCron != nil { + opts.SetDataMetricSchedule.UsingCron = &ViewUsingCron{ + Cron: r.SetDataMetricSchedule.UsingCron.Cron, + } + } + } + + if r.UnsetDataMetricSchedule != nil { + opts.UnsetDataMetricSchedule = &ViewUnsetDataMetricSchedule{} + } + if r.AddRowAccessPolicy != nil { opts.AddRowAccessPolicy = &ViewAddRowAccessPolicy{ RowAccessPolicy: r.AddRowAccessPolicy.RowAccessPolicy, On: r.AddRowAccessPolicy.On, } } + if r.DropRowAccessPolicy != nil { opts.DropRowAccessPolicy = &ViewDropRowAccessPolicy{ RowAccessPolicy: r.DropRowAccessPolicy.RowAccessPolicy, } } + if r.DropAndAddRowAccessPolicy != nil { opts.DropAndAddRowAccessPolicy = &ViewDropAndAddRowAccessPolicy{} + opts.DropAndAddRowAccessPolicy.Drop = ViewDropRowAccessPolicy{ RowAccessPolicy: r.DropAndAddRowAccessPolicy.Drop.RowAccessPolicy, } + opts.DropAndAddRowAccessPolicy.Add = ViewAddRowAccessPolicy{ RowAccessPolicy: r.DropAndAddRowAccessPolicy.Add.RowAccessPolicy, On: r.DropAndAddRowAccessPolicy.Add.On, } } + + if r.SetAggregationPolicy != nil { + opts.SetAggregationPolicy = &ViewSetAggregationPolicy{ + AggregationPolicy: r.SetAggregationPolicy.AggregationPolicy, + EntityKey: r.SetAggregationPolicy.EntityKey, + Force: r.SetAggregationPolicy.Force, + } + } + + if r.UnsetAggregationPolicy != nil { + opts.UnsetAggregationPolicy = &ViewUnsetAggregationPolicy{} + } + if r.SetMaskingPolicyOnColumn != nil { opts.SetMaskingPolicyOnColumn = &ViewSetColumnMaskingPolicy{ Name: r.SetMaskingPolicyOnColumn.Name, @@ -138,23 +209,41 @@ func (r *AlterViewRequest) toOpts() *AlterViewOptions { Force: r.SetMaskingPolicyOnColumn.Force, } } + if r.UnsetMaskingPolicyOnColumn != nil { opts.UnsetMaskingPolicyOnColumn = &ViewUnsetColumnMaskingPolicy{ Name: r.UnsetMaskingPolicyOnColumn.Name, } } + + if r.SetProjectionPolicyOnColumn != nil { + opts.SetProjectionPolicyOnColumn = &ViewSetProjectionPolicy{ + Name: r.SetProjectionPolicyOnColumn.Name, + ProjectionPolicy: r.SetProjectionPolicyOnColumn.ProjectionPolicy, + Force: r.SetProjectionPolicyOnColumn.Force, + } + } + + if r.UnsetProjectionPolicyOnColumn != nil { + opts.UnsetProjectionPolicyOnColumn = &ViewUnsetProjectionPolicy{ + Name: r.UnsetProjectionPolicyOnColumn.Name, + } + } + if r.SetTagsOnColumn != nil { opts.SetTagsOnColumn = &ViewSetColumnTags{ Name: r.SetTagsOnColumn.Name, SetTags: r.SetTagsOnColumn.SetTags, } } + if r.UnsetTagsOnColumn != nil { opts.UnsetTagsOnColumn = &ViewUnsetColumnTags{ Name: r.UnsetTagsOnColumn.Name, UnsetTags: r.UnsetTagsOnColumn.UnsetTags, } } + return opts } @@ -184,9 +273,6 @@ func (r viewDBRow) convert() *View { DatabaseName: r.DatabaseName, SchemaName: r.SchemaName, } - if r.Kind.Valid { - view.Kind = r.Kind.String - } if r.Reserved.Valid { view.Reserved = r.Reserved.String } @@ -199,6 +285,9 @@ func (r viewDBRow) convert() *View { if r.Text.Valid { view.Text = r.Text.String } + if r.Kind.Valid { + view.Kind = r.Kind.String + } if r.IsSecure.Valid { view.IsSecure = r.IsSecure.Bool } @@ -226,9 +315,9 @@ func (r viewDetailsRow) convert() *ViewDetails { Name: r.Name, Type: r.Type, Kind: r.Kind, - IsNullable: r.IsNullable == "Y", - IsPrimary: r.IsPrimary == "Y", - IsUnique: r.IsUnique == "Y", + IsNullable: r.Null == "Y", + IsPrimary: r.PrimaryKey == "Y", + IsUnique: r.UniqueKey == "Y", } if r.Default.Valid { details.Default = String(r.Default.String) diff --git a/pkg/sdk/views_validations_gen.go b/pkg/sdk/views_validations_gen.go index cbc47adb61..7f8fd1fd55 100644 --- a/pkg/sdk/views_validations_gen.go +++ b/pkg/sdk/views_validations_gen.go @@ -1,5 +1,7 @@ package sdk +import "fmt" + var ( _ validatable = new(CreateViewOptions) _ validatable = new(AlterViewOptions) @@ -21,12 +23,31 @@ func (opts *CreateViewOptions) validate() error { } if valueSet(opts.RowAccessPolicy) { if !ValidObjectIdentifier(opts.RowAccessPolicy.RowAccessPolicy) { - errs = append(errs, ErrInvalidObjectIdentifier) + errs = append(errs, errInvalidIdentifier("CreateViewOptions", "RowAccessPolicy")) } if !valueSet(opts.RowAccessPolicy.On) { errs = append(errs, errNotSet("CreateViewOptions.RowAccessPolicy", "On")) } } + if valueSet(opts.AggregationPolicy) { + if !ValidObjectIdentifier(opts.AggregationPolicy.AggregationPolicy) { + errs = append(errs, errInvalidIdentifier("CreateViewOptions", "AggregationPolicy")) + } + } + if valueSet(opts.Columns) { + for i, columnOption := range opts.Columns { + if valueSet(columnOption.MaskingPolicy) { + if !ValidObjectIdentifier(columnOption.MaskingPolicy.MaskingPolicy) { + errs = append(errs, errInvalidIdentifier(fmt.Sprintf("CreateViewOptions.Columns[%d]", i), "MaskingPolicy")) + } + } + if valueSet(columnOption.ProjectionPolicy) { + if !ValidObjectIdentifier(columnOption.ProjectionPolicy.ProjectionPolicy) { + errs = append(errs, errInvalidIdentifier(fmt.Sprintf("CreateViewOptions.Columns[%d]", i), "ProjectionPolicy")) + } + } + } + } return JoinErrors(errs...) } @@ -38,12 +59,23 @@ func (opts *AlterViewOptions) validate() error { if !ValidObjectIdentifier(opts.name) { errs = append(errs, ErrInvalidObjectIdentifier) } - if !exactlyOneValueSet(opts.RenameTo, opts.SetComment, opts.UnsetComment, opts.SetSecure, opts.SetChangeTracking, opts.UnsetSecure, opts.SetTags, opts.UnsetTags, opts.AddRowAccessPolicy, opts.DropRowAccessPolicy, opts.DropAndAddRowAccessPolicy, opts.DropAllRowAccessPolicies, opts.SetMaskingPolicyOnColumn, opts.UnsetMaskingPolicyOnColumn, opts.SetTagsOnColumn, opts.UnsetTagsOnColumn) { - errs = append(errs, errExactlyOneOf("AlterViewOptions", "RenameTo", "SetComment", "UnsetComment", "SetSecure", "SetChangeTracking", "UnsetSecure", "SetTags", "UnsetTags", "AddRowAccessPolicy", "DropRowAccessPolicy", "DropAndAddRowAccessPolicy", "DropAllRowAccessPolicies", "SetMaskingPolicyOnColumn", "UnsetMaskingPolicyOnColumn", "SetTagsOnColumn", "UnsetTagsOnColumn")) + if !exactlyOneValueSet(opts.RenameTo, opts.SetComment, opts.UnsetComment, opts.SetSecure, opts.SetChangeTracking, opts.UnsetSecure, opts.SetTags, opts.UnsetTags, opts.AddDataMetricFunction, opts.DropDataMetricFunction, opts.SetDataMetricSchedule, opts.UnsetDataMetricSchedule, opts.AddRowAccessPolicy, opts.DropRowAccessPolicy, opts.DropAndAddRowAccessPolicy, opts.DropAllRowAccessPolicies, opts.SetAggregationPolicy, opts.UnsetAggregationPolicy, opts.SetMaskingPolicyOnColumn, opts.UnsetMaskingPolicyOnColumn, opts.SetProjectionPolicyOnColumn, opts.UnsetProjectionPolicyOnColumn, opts.SetTagsOnColumn, opts.UnsetTagsOnColumn) { + errs = append(errs, errExactlyOneOf("AlterViewOptions", "RenameTo", "SetComment", "UnsetComment", "SetSecure", "SetChangeTracking", "UnsetSecure", "SetTags", "UnsetTags", "AddDataMetricFunction", "DropDataMetricFunction", "SetDataMetricSchedule", "UnsetDataMetricSchedule", "AddRowAccessPolicy", "DropRowAccessPolicy", "DropAndAddRowAccessPolicy", "DropAllRowAccessPolicies", "SetAggregationPolicy", "UnsetAggregationPolicy", "SetMaskingPolicyOnColumn", "UnsetMaskingPolicyOnColumn", "SetProjectionPolicyOnColumn", "UnsetProjectionPolicyOnColumn", "SetTagsOnColumn", "UnsetTagsOnColumn")) + } + if everyValueSet(opts.IfExists, opts.SetSecure) { + errs = append(errs, errOneOf("AlterViewOptions", "IfExists", "SetSecure")) + } + if everyValueSet(opts.IfExists, opts.UnsetSecure) { + errs = append(errs, errOneOf("AlterViewOptions", "IfExists", "UnsetSecure")) + } + if valueSet(opts.SetDataMetricSchedule) { + if !exactlyOneValueSet(opts.SetDataMetricSchedule.Minutes, opts.SetDataMetricSchedule.UsingCron, opts.SetDataMetricSchedule.TriggerOnChanges) { + errs = append(errs, errExactlyOneOf("AlterViewOptions.SetDataMetricSchedule", "Minutes", "UsingCron", "TriggerOnChanges")) + } } if valueSet(opts.AddRowAccessPolicy) { if !ValidObjectIdentifier(opts.AddRowAccessPolicy.RowAccessPolicy) { - errs = append(errs, ErrInvalidObjectIdentifier) + errs = append(errs, errInvalidIdentifier("AlterViewOptions.AddRowAccessPolicy", "RowAccessPolicy")) } if !valueSet(opts.AddRowAccessPolicy.On) { errs = append(errs, errNotSet("AlterViewOptions.AddRowAccessPolicy", "On")) @@ -51,24 +83,29 @@ func (opts *AlterViewOptions) validate() error { } if valueSet(opts.DropRowAccessPolicy) { if !ValidObjectIdentifier(opts.DropRowAccessPolicy.RowAccessPolicy) { - errs = append(errs, ErrInvalidObjectIdentifier) + errs = append(errs, errInvalidIdentifier("AlterViewOptions.DropRowAccessPolicy", "RowAccessPolicy")) } } if valueSet(opts.DropAndAddRowAccessPolicy) { if valueSet(opts.DropAndAddRowAccessPolicy.Drop) { if !ValidObjectIdentifier(opts.DropAndAddRowAccessPolicy.Drop.RowAccessPolicy) { - errs = append(errs, ErrInvalidObjectIdentifier) + errs = append(errs, errInvalidIdentifier("AlterViewOptions.DropAndAddRowAccessPolicy.Drop", "RowAccessPolicy")) } } if valueSet(opts.DropAndAddRowAccessPolicy.Add) { if !ValidObjectIdentifier(opts.DropAndAddRowAccessPolicy.Add.RowAccessPolicy) { - errs = append(errs, ErrInvalidObjectIdentifier) + errs = append(errs, errInvalidIdentifier("AlterViewOptions.DropAndAddRowAccessPolicy.Add", "RowAccessPolicy")) } if !valueSet(opts.DropAndAddRowAccessPolicy.Add.On) { errs = append(errs, errNotSet("AlterViewOptions.DropAndAddRowAccessPolicy.Add", "On")) } } } + if valueSet(opts.SetAggregationPolicy) { + if !ValidObjectIdentifier(opts.SetAggregationPolicy.AggregationPolicy) { + errs = append(errs, errInvalidIdentifier("AlterViewOptions.SetAggregationPolicy", "AggregationPolicy")) + } + } return JoinErrors(errs...) } diff --git a/v1-preparations/ESSENTIAL_GA_OBJECTS.MD b/v1-preparations/ESSENTIAL_GA_OBJECTS.MD index 9e9d3ea9f1..b2536e25f9 100644 --- a/v1-preparations/ESSENTIAL_GA_OBJECTS.MD +++ b/v1-preparations/ESSENTIAL_GA_OBJECTS.MD @@ -17,9 +17,9 @@ newer provider versions. We will address these while working on the given object | ACCOUNT | ❌ | [#2030](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2030), [#2015](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2015), [#1891](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1891), [#1679](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1679), [#1671](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1671), [#1501](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1501), [#1062](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1062) | | DATABASE | 🚀 | [#2590](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2590), [#2321](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2321), [#2277](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2277), [#1833](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1833), [#1770](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1770), [#1453](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1453), [#1371](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1371), [#1367](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1367), [#1045](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1045), [#506](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/506) | | DATABASE ROLE | ❌ | - | -| NETWORK POLICY | 👨‍💻 | - | +| NETWORK POLICY | 🚀 | - | | RESOURCE MONITOR | ❌ | [#1990](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1990), [#1832](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1832), [#1821](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1821), [#1754](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1754), [#1716](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1716), [#1714](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1714), [#1624](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1624), [#1500](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1500), [#1175](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1175) | -| ROLE | 👨‍💻 | - | +| ROLE | 🚀 | - | | SECURITY INTEGRATION | 🚀 | [#2855](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2855), [#2719](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2719), [#2568](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2568), [#2177](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2177), [#1851](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1851), [#1773](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1773), [#1741](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1741), [#1637](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1637), [#1503](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1503), [#1498](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1498), [#1421](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1421), [#1224](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1224) | | USER | 👨‍💻 | [#2970](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2970), [#2951](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2951), [#2942](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2942), [#2938](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2938), [#2902](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2902), [#2817](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2817), [#2662](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2662), [#1572](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1572), [#1535](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1535), [#1155](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1155) | | WAREHOUSE | 🚀 | issues in the older versions: [resources](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues?q=label%3Aresource%3Awarehouse+) and [datasources](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues?q=label%3Adata_source%3Awarehouses+) | @@ -27,13 +27,13 @@ newer provider versions. We will address these while working on the given object | MASKING POLICY | ❌ | [#2236](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2236), [#2035](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2035), [#1799](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1799), [#1764](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1764), [#1656](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1656), [#1444](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1444), [#1422](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1422), [#1097](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1097) | | PROCEDURE | ❌ | [#2735](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2735), [#2623](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2623), [#2257](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2257), [#2146](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2146), [#1855](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1855), [#1695](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1695), [#1640](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1640), [#1195](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1195), [#1189](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1189), [#1178](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1178), [#1050](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1050) | | ROW ACCESS POLICY | ❌ | [#2053](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2053), [#1600](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1600), [#1151](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1151) | -| SCHEMA | 👨‍💻 | [#2826](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2826), [#2211](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2211), [#1243](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1243), [#506](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/506) | +| SCHEMA | 🚀 | [#2826](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2826), [#2211](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2211), [#1243](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1243), [#506](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/506) | | STAGE | ❌ | [#2818](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2818), [#2505](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2505), [#1911](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1911), [#1903](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1903), [#1795](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1795), [#1705](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1705), [#1544](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1544), [#1491](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1491), [#1087](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1087), [#265](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/265) | | STREAM | ❌ | [#2975](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2975), [#2413](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2413), [#2201](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2201), [#1150](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1150) | -| STREAMLIT | 👨‍💻 | [#1933](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1933) | +| STREAMLIT | 🚀 | [#1933](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1933) | | TABLE | ❌ | [#2844](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2844), [#2839](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2839), [#2735](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2735), [#2733](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2733), [#2683](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2683), [#2676](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2676), [#2674](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2674), [#2629](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2629), [#2418](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2418), [#2415](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2415), [#2406](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2406), [#2236](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2236), [#2035](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2035), [#1823](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1823), [#1799](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1799), [#1764](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1764), [#1600](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1600), [#1387](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1387), [#1272](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1272), [#1271](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1271), [#1248](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1248), [#1241](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1241), [#1146](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1146), [#1032](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1032), [#420](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/420) | | TAG | ❌ | [#2943](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2902), [#2598](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2598), [#1910](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1910), [#1909](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1909), [#1862](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1862), [#1806](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1806), [#1657](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1657), [#1496](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1496), [#1443](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1443), [#1394](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1394), [#1372](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1372), [#1074](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1074) | | TASK | ❌ | [#1419](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1419), [#1250](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1250), [#1194](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1194), [#1088](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1088) | -| VIEW | ❌ | [#2430](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2430), [#2085](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2085), [#2055](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2055), [#2031](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2031), [#1526](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1526), [#1253](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1253), [#1049](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1049) | +| VIEW | 👨‍💻 | [#2430](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2430), [#2085](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2085), [#2055](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2055), [#2031](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2031), [#1526](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1526), [#1253](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1253), [#1049](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1049) | | snowflake_unsafe_execute | ❌ | [#2934](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2934) |