From 2f6a3070b3da41954285836b75ba46beff6d10c0 Mon Sep 17 00:00:00 2001 From: klus Date: Mon, 24 Jul 2023 16:56:11 +0200 Subject: [PATCH] Fixed handling of comments in `databricks_sql_table` resource (#2472) * column comments and single quote escape * Delimiter collision avoidance table comment * compatible with user single quote escape * unit tests for parseComment * corrected fmt --------- Co-authored-by: Miles Yucht --- catalog/resource_sql_table.go | 12 ++++++++---- catalog/resource_sql_table_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/catalog/resource_sql_table.go b/catalog/resource_sql_table.go index ec9a7f3f0..f827d7e74 100644 --- a/catalog/resource_sql_table.go +++ b/catalog/resource_sql_table.go @@ -57,6 +57,10 @@ func (ti *SqlTableInfo) FullName() string { return fmt.Sprintf("%s.%s.%s", ti.CatalogName, ti.SchemaName, ti.Name) } +func parseComment(s string) string { + return strings.ReplaceAll(strings.ReplaceAll(s, `\'`, `'`), `'`, `\'`) +} + // These properties are added automatically // If we do not customize the diff using these then terraform will constantly try to remove them // `properties` is essentially a "partially" computed field @@ -146,9 +150,9 @@ func (ti *SqlTableInfo) serializeColumnInfo(col SqlColumnInfo) string { comment := "" if col.Comment != "" { - comment = fmt.Sprintf(" COMMENT %s", col.Comment) + comment = fmt.Sprintf(" COMMENT '%s'", parseComment(col.Comment)) } - return fmt.Sprintf("%s %s%s%s", col.Name, col.Type, notNull, comment) // id INT NOT NULL COMMENT something + return fmt.Sprintf("%s %s%s%s", col.Name, col.Type, notNull, comment) // id INT NOT NULL COMMENT 'something' } func (ti *SqlTableInfo) serializeColumnInfos() string { @@ -211,7 +215,7 @@ func (ti *SqlTableInfo) buildTableCreateStatement() string { } if ti.Comment != "" { - statements = append(statements, fmt.Sprintf("\nCOMMENT '%s'", ti.Comment)) // COMMENT 'this is a comment' + statements = append(statements, fmt.Sprintf("\nCOMMENT '%s'", parseComment(ti.Comment))) // COMMENT 'this is a comment' } if len(ti.Properties) > 0 { @@ -249,7 +253,7 @@ func (ti *SqlTableInfo) diff(oldti *SqlTableInfo) ([]string, error) { // Attributes common to both views and tables if ti.Comment != oldti.Comment { - statements = append(statements, fmt.Sprintf("COMMENT ON %s %s IS '%s'", typestring, ti.FullName(), ti.Comment)) + statements = append(statements, fmt.Sprintf("COMMENT ON %s %s IS '%s'", typestring, ti.FullName(), parseComment(ti.Comment))) } if !reflect.DeepEqual(ti.Properties, oldti.Properties) { diff --git a/catalog/resource_sql_table_test.go b/catalog/resource_sql_table_test.go index e1abb9814..dcd1eb0d5 100644 --- a/catalog/resource_sql_table_test.go +++ b/catalog/resource_sql_table_test.go @@ -485,3 +485,27 @@ var createClusterForSql = append([]qa.HTTPFixture{ func TestResourceSqlTableCornerCases(t *testing.T) { qa.ResourceCornerCases(t, ResourceSqlTable()) } + +func TestParseComment_empty(t *testing.T) { + cmt := "" + prsd := parseComment(cmt) + assert.Equal(t, "", prsd) +} + +func TestParseComment_noquote(t *testing.T) { + cmt := "Comment without single quote" + prsd := parseComment(cmt) + assert.Equal(t, "Comment without single quote", prsd) +} + +func TestParseComment_escapedquote(t *testing.T) { + cmt := `\'Comment with\'escaped quotes\'` + prsd := parseComment(cmt) + assert.Equal(t, `\'Comment with\'escaped quotes\'`, prsd) +} + +func TestParseComment_unescapedquote(t *testing.T) { + cmt := "Comment with' unescaped quotes '" + prsd := parseComment(cmt) + assert.Equal(t, `Comment with\' unescaped quotes \'`, prsd) +}