Skip to content

Commit

Permalink
feat: Add support for table column comments and to control a tables d…
Browse files Browse the repository at this point in the history
…ata retention and change tracking settings (#614)
  • Loading branch information
robbruce authored Jul 28, 2021
1 parent b9ad9ed commit daa46a0
Show file tree
Hide file tree
Showing 9 changed files with 656 additions and 62 deletions.
32 changes: 24 additions & 8 deletions docs/resources/table.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,21 @@ description: |-
## Example Usage

```terraform
resource snowflake_table table {
database = "database"
schema = "schmea"
name = "table"
comment = "A table."
cluster_by = ["to_date(DATE)"]
resource "snowflake_schema" "schema" {
database = "database"
name = "schema"
data_retention_days = 1
}
resource "snowflake_table" "table" {
database = snowflake_schema.schema.database
schema = snowflake_schema.schema.name
name = "table"
comment = "A table."
cluster_by = ["to_date(DATE)"]
data_retention_days = snowflake_schema.schema.data_retention_days
change_tracking = false
column {
name = "id"
type = "int"
Expand All @@ -37,10 +45,15 @@ resource snowflake_table table {
type = "TIMESTAMP_NTZ(9)"
}
column {
name = "extra"
type = "VARIANT"
comment = "extra data"
}
primary_key {
name = "my_key"
keys = ["data"]
}
}
```
Expand All @@ -57,8 +70,10 @@ resource snowflake_table table {

### Optional

- **change_tracking** (Boolean) Specifies whether to enable change tracking on the table. Default false.
- **cluster_by** (List of String) A list of one or more table columns/expressions to be used as clustering key(s) for the table
- **comment** (String) Specifies a comment for the table.
- **data_retention_days** (Number) Specifies the retention period for the table so that Time Travel actions (SELECT, CLONE, UNDROP) can be performed on historical data in the table. Default value is 1, if you wish to inherit the parent schema setting then pass in the schema attribute to this argument.
- **id** (String) The ID of this resource.
- **primary_key** (Block List, Max: 1) Definitions of primary key constraint to create on table (see [below for nested schema](#nestedblock--primary_key))

Expand All @@ -76,6 +91,7 @@ Required:

Optional:

- **comment** (String) Column comment
- **nullable** (Boolean) Whether this column can contain null values. **Note**: Depending on your Snowflake version, the default value will not suffice if this column is used in a primary key constraint.


Expand Down
29 changes: 21 additions & 8 deletions examples/resources/snowflake_table/resource.tf
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
resource snowflake_table table {
database = "database"
schema = "schmea"
name = "table"
comment = "A table."
cluster_by = ["to_date(DATE)"]

resource "snowflake_schema" "schema" {
database = "database"
name = "schema"
data_retention_days = 1
}

resource "snowflake_table" "table" {
database = snowflake_schema.schema.database
schema = snowflake_schema.schema.name
name = "table"
comment = "A table."
cluster_by = ["to_date(DATE)"]
data_retention_days = snowflake_schema.schema.data_retention_days
change_tracking = false

column {
name = "id"
type = "int"
Expand All @@ -22,9 +30,14 @@ resource snowflake_table table {
type = "TIMESTAMP_NTZ(9)"
}

column {
name = "extra"
type = "VARIANT"
comment = "extra data"
}

primary_key {
name = "my_key"
keys = ["data"]

}
}
10 changes: 6 additions & 4 deletions pkg/resources/stream_acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@ resource "snowflake_schema" "test_schema" {
}
resource "snowflake_table" "test_stream_on_table" {
database = snowflake_database.test_database.name
schema = snowflake_schema.test_schema.name
name = "STREAM_ON_TABLE"
comment = "Terraform acceptance test"
database = snowflake_database.test_database.name
schema = snowflake_schema.test_schema.name
name = "STREAM_ON_TABLE"
comment = "Terraform acceptance test"
change_tracking = true
column {
name = "column1"
type = "VARIANT"
Expand Down
10 changes: 6 additions & 4 deletions pkg/resources/stream_grant_acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,12 @@ resource "snowflake_role" "test" {
name = "{{.role_name}}"
}
resource "snowflake_table" "test" {
database = snowflake_database.test.name
schema = snowflake_schema.test.name
name = "{{ .table_name }}"
comment = "Terraform acceptance test"
database = snowflake_database.test.name
schema = snowflake_schema.test.name
name = "{{ .table_name }}"
change_tracking = true
comment = "Terraform acceptance test"
column {
name = "column1"
type = "VARIANT"
Expand Down
84 changes: 73 additions & 11 deletions pkg/resources/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/chanzuckerberg/terraform-provider-snowflake/pkg/snowflake"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -65,6 +66,12 @@ var tableSchema = map[string]*schema.Schema{
Default: true,
Description: "Whether this column can contain null values. **Note**: Depending on your Snowflake version, the default value will not suffice if this column is used in a primary key constraint.",
},
"comment": {
Type: schema.TypeString,
Optional: true,
Default: "",
Description: "Column comment",
},
},
},
},
Expand Down Expand Up @@ -101,6 +108,19 @@ var tableSchema = map[string]*schema.Schema{
},
},
},
"data_retention_days": {
Type: schema.TypeInt,
Optional: true,
Default: 1,
Description: "Specifies the retention period for the table so that Time Travel actions (SELECT, CLONE, UNDROP) can be performed on historical data in the table. Default value is 1, if you wish to inherit the parent schema setting then pass in the schema attribute to this argument.",
ValidateFunc: validation.IntBetween(0, 90),
},
"change_tracking": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Specifies whether to enable change tracking on the table. Default false.",
},
}

func Table() *schema.Resource {
Expand Down Expand Up @@ -167,11 +187,12 @@ type column struct {
name string
dataType string
nullable bool
comment string
}

func (c column) toSnowflakeColumn() snowflake.Column {
sC := snowflake.Column{}
return *sC.WithName(c.name).WithType(c.dataType).WithNullable(c.nullable)
return *sC.WithName(c.name).WithType(c.dataType).WithNullable(c.nullable).WithComment(c.comment)
}

type columns []column
Expand Down Expand Up @@ -207,19 +228,23 @@ type changedColumn struct {
newColumn column //our new column
changedDataType bool
changedNullConstraint bool
changedComment bool
}

func (old columns) getChangedColumnProperties(new columns) (changed changedColumns) {
changed = changedColumns{}
for _, cO := range old {
for _, cN := range new {
changeColumn := changedColumn{cN, false, false}
changeColumn := changedColumn{cN, false, false, false}
if cO.name == cN.name && cO.dataType != cN.dataType {
changeColumn.changedDataType = true
}
if cO.name == cN.name && cO.nullable != cN.nullable {
changeColumn.changedNullConstraint = true
}
if cO.name == cN.name && cO.comment != cN.comment {
changeColumn.changedComment = true
}

changed = append(changed, changeColumn)
}
Expand All @@ -237,6 +262,7 @@ func getColumn(from interface{}) (to column) {
name: c["name"].(string),
dataType: c["type"].(string),
nullable: c["nullable"].(bool),
comment: c["comment"].(string),
}
}

Expand Down Expand Up @@ -297,6 +323,14 @@ func CreateTable(d *schema.ResourceData, meta interface{}) error {
builder.WithPrimaryKey(pk.toSnowflakePrimaryKey())
}

if v, ok := d.GetOk("data_retention_days"); ok {
builder.WithDataRetentionTimeInDays(v.(int))
}

if v, ok := d.GetOk("change_tracking"); ok {
builder.WithChangeTracking(v.(bool))
}

stmt := builder.Create()
err := snowflake.Exec(db, stmt)
if err != nil {
Expand Down Expand Up @@ -361,14 +395,16 @@ func ReadTable(d *schema.ResourceData, meta interface{}) error {

// Set the relevant data in the state
toSet := map[string]interface{}{
"name": table.TableName.String,
"owner": table.Owner.String,
"database": tableID.DatabaseName,
"schema": tableID.SchemaName,
"comment": table.Comment.String,
"column": snowflake.NewColumns(tableDescription).Flatten(),
"cluster_by": snowflake.ClusterStatementToList(table.ClusterBy.String),
"primary_key": snowflake.FlattenTablePrimaryKey(pkDescription),
"name": table.TableName.String,
"owner": table.Owner.String,
"database": tableID.DatabaseName,
"schema": tableID.SchemaName,
"comment": table.Comment.String,
"column": snowflake.NewColumns(tableDescription).Flatten(),
"cluster_by": snowflake.ClusterStatementToList(table.ClusterBy.String),
"primary_key": snowflake.FlattenTablePrimaryKey(pkDescription),
"data_retention_days": table.RetentionTime.Int32,
"change_tracking": (table.ChangeTracking.String == "ON"),
}

for key, val := range toSet {
Expand Down Expand Up @@ -430,7 +466,7 @@ func UpdateTable(d *schema.ResourceData, meta interface{}) error {
}
}
for _, cA := range added {
q := builder.AddColumn(cA.name, cA.dataType, cA.nullable)
q := builder.AddColumn(cA.name, cA.dataType, cA.nullable, cA.comment)
err := snowflake.Exec(db, q)
if err != nil {
return errors.Wrapf(err, "error adding column on %v", d.Id())
Expand All @@ -456,6 +492,14 @@ func UpdateTable(d *schema.ResourceData, meta interface{}) error {

}
}
if cA.changedComment {
q := builder.ChangeColumnComment(cA.newColumn.name, cA.newColumn.comment)
err := snowflake.Exec(db, q)
if err != nil {
return errors.Wrapf(err, "error changing property on %v", d.Id())

}
}

}
}
Expand Down Expand Up @@ -483,6 +527,24 @@ func UpdateTable(d *schema.ResourceData, meta interface{}) error {
}
}
}
if d.HasChange("data_retention_days") {
_, ndr := d.GetChange("data_retention_days")

q := builder.ChangeDataRetention(ndr.(int))
err := snowflake.Exec(db, q)
if err != nil {
return errors.Wrapf(err, "error changing property on %v", d.Id())
}
}
if d.HasChange("change_tracking") {
_, nct := d.GetChange("change_tracking")

q := builder.ChangeChangeTracking(nct.(bool))
err := snowflake.Exec(db, q)
if err != nil {
return errors.Wrapf(err, "error changing property on %v", d.Id())
}
}

return ReadTable(d, meta)
}
Expand Down
Loading

0 comments on commit daa46a0

Please sign in to comment.