diff --git a/postgresql/helpers.go b/postgresql/helpers.go index 1cc0cd1d..f74f0b78 100644 --- a/postgresql/helpers.go +++ b/postgresql/helpers.go @@ -606,3 +606,16 @@ func findStringSubmatchMap(expression string, text string) map[string]string { func defaultDiffSuppressFunc(k, old, new string, d *schema.ResourceData) bool { return old == new } + +// quoteTable can quote a table name with or without a schema prefix +// Example: +// +// my_table -> "my_table" +// public.my_table -> "public"."my_table" +func quoteTableName(tableName string) string { + parts := strings.Split(tableName, ".") + for i := range parts { + parts[i] = pq.QuoteIdentifier(parts[i]) + } + return strings.Join(parts, ".") +} diff --git a/postgresql/helpers_test.go b/postgresql/helpers_test.go index 95632d50..6b60d806 100644 --- a/postgresql/helpers_test.go +++ b/postgresql/helpers_test.go @@ -17,3 +17,31 @@ func TestFindStringSubmatchMap(t *testing.T) { }, ) } + +func TestQuoteTableName(t *testing.T) { + tests := []struct { + name string + input string + expected string + }{ + { + name: "simple table name", + input: "users", + expected: `"users"`, + }, + { + name: "table name with schema", + input: "test.users", + expected: `"test"."users"`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := quoteTableName(tt.input) + if actual != tt.expected { + t.Errorf("quoteTableName() = %v, want %v", actual, tt.expected) + } + }) + } +} diff --git a/postgresql/resource_postgresql_publication.go b/postgresql/resource_postgresql_publication.go index f8cea648..4e99ae55 100644 --- a/postgresql/resource_postgresql_publication.go +++ b/postgresql/resource_postgresql_publication.go @@ -183,12 +183,12 @@ func setPubTables(txn *sql.Tx, d *schema.ResourceData) error { added := arrayDifference(newList, oldList) for _, p := range added { - query := fmt.Sprintf("ALTER PUBLICATION %s ADD TABLE %s", pubName, p.(string)) + query := fmt.Sprintf("ALTER PUBLICATION %s ADD TABLE %s", pubName, quoteTableName(p.(string))) queries = append(queries, query) } for _, p := range dropped { - query := fmt.Sprintf("ALTER PUBLICATION %s DROP TABLE %s", pubName, p.(string)) + query := fmt.Sprintf("ALTER PUBLICATION %s DROP TABLE %s", pubName, quoteTableName(p.(string))) queries = append(queries, query) } @@ -461,7 +461,7 @@ func getTablesForPublication(d *schema.ResourceData) (string, error) { return tablesString, fmt.Errorf("'%s' is duplicated for attribute `%s`", elem.(string), pubTablesAttr) } for _, t := range tables { - tlist = append(tlist, t.(string)) + tlist = append(tlist, quoteTableName(t.(string))) } tablesString = fmt.Sprintf("FOR TABLE %s", strings.Join(tlist, ", ")) } diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index 87fa62cb..3cc75a8e 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -166,6 +166,7 @@ The following arguments are supported: * `clientcert` - (Optional) - Configure the SSL client certificate. * `cert` - (Required) - The SSL client certificate file path. The file must contain PEM encoded data. * `key` - (Required) - The SSL client certificate private key file path. The file must contain PEM encoded data. + * `sslinline` - (Optional) - If set to `true`, arguments accept inline ssl cert and key rather than a filename. Defaults to `false`. * `sslrootcert` - (Optional) - The SSL server root certificate file path. The file must contain PEM encoded data. * `connect_timeout` - (Optional) Maximum wait for connection, in seconds. The default is `180s`. Zero or not specified means wait indefinitely.