diff --git a/internal/diff/column.go b/internal/diff/column.go index 8534bea2..fdacac45 100644 --- a/internal/diff/column.go +++ b/internal/diff/column.go @@ -27,7 +27,7 @@ func (cd *ColumnDiff) generateColumnSQL(tableSchema, tableName string, targetSch // If type is changing with USING clause and there's an existing default, drop the default first if needsUsing && hasOldDefault { sql := fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s DROP DEFAULT;", - qualifiedTableName, cd.New.Name) + qualifiedTableName, ir.QuoteIdentifier(cd.New.Name)) statements = append(statements, sql) } @@ -38,11 +38,11 @@ func (cd *ColumnDiff) generateColumnSQL(tableSchema, tableName string, targetSch // because PostgreSQL cannot implicitly cast these types if needsUsing { sql := fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s TYPE %s USING %s::%s;", - qualifiedTableName, cd.New.Name, newType, cd.New.Name, newType) + qualifiedTableName, ir.QuoteIdentifier(cd.New.Name), newType, ir.QuoteIdentifier(cd.New.Name), newType) statements = append(statements, sql) } else { sql := fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s TYPE %s;", - qualifiedTableName, cd.New.Name, newType) + qualifiedTableName, ir.QuoteIdentifier(cd.New.Name), newType) statements = append(statements, sql) } } @@ -52,12 +52,12 @@ func (cd *ColumnDiff) generateColumnSQL(tableSchema, tableName string, targetSch if cd.New.IsNullable { // DROP NOT NULL sql := fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s DROP NOT NULL;", - qualifiedTableName, cd.New.Name) + qualifiedTableName, ir.QuoteIdentifier(cd.New.Name)) statements = append(statements, sql) } else { // ADD NOT NULL - generate canonical SQL only sql := fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s SET NOT NULL;", - qualifiedTableName, cd.New.Name) + qualifiedTableName, ir.QuoteIdentifier(cd.New.Name)) statements = append(statements, sql) } } @@ -69,7 +69,7 @@ func (cd *ColumnDiff) generateColumnSQL(tableSchema, tableName string, targetSch // Default was dropped above; add new default if specified if newDefault != nil && *newDefault != "" { sql := fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s SET DEFAULT %s;", - qualifiedTableName, cd.New.Name, *newDefault) + qualifiedTableName, ir.QuoteIdentifier(cd.New.Name), *newDefault) statements = append(statements, sql) } } else { @@ -80,10 +80,10 @@ func (cd *ColumnDiff) generateColumnSQL(tableSchema, tableName string, targetSch var sql string if newDefault == nil { sql = fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s DROP DEFAULT;", - qualifiedTableName, cd.New.Name) + qualifiedTableName, ir.QuoteIdentifier(cd.New.Name)) } else { sql = fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s SET DEFAULT %s;", - qualifiedTableName, cd.New.Name, *newDefault) + qualifiedTableName, ir.QuoteIdentifier(cd.New.Name), *newDefault) } statements = append(statements, sql) diff --git a/internal/diff/table.go b/internal/diff/table.go index 927465ec..79205112 100644 --- a/internal/diff/table.go +++ b/internal/diff/table.go @@ -437,7 +437,7 @@ func generateCreateTablesSQL( for _, column := range table.Columns { if column.Comment != "" { tableName := qualifyEntityName(table.Schema, table.Name, targetSchema) - sql := fmt.Sprintf("COMMENT ON COLUMN %s.%s IS %s;", tableName, column.Name, quoteString(column.Comment)) + sql := fmt.Sprintf("COMMENT ON COLUMN %s.%s IS %s;", tableName, ir.QuoteIdentifier(column.Name), quoteString(column.Comment)) // Create context for this statement context := &diffContext{ @@ -1163,9 +1163,9 @@ func (td *tableDiff) generateAlterTableStatements(targetSchema string, collector tableName := getTableNameWithSchema(td.Table.Schema, td.Table.Name, targetSchema) var sql string if colDiff.New.Comment == "" { - sql = fmt.Sprintf("COMMENT ON COLUMN %s.%s IS NULL;", tableName, colDiff.New.Name) + sql = fmt.Sprintf("COMMENT ON COLUMN %s.%s IS NULL;", tableName, ir.QuoteIdentifier(colDiff.New.Name)) } else { - sql = fmt.Sprintf("COMMENT ON COLUMN %s.%s IS %s;", tableName, colDiff.New.Name, quoteString(colDiff.New.Comment)) + sql = fmt.Sprintf("COMMENT ON COLUMN %s.%s IS %s;", tableName, ir.QuoteIdentifier(colDiff.New.Name), quoteString(colDiff.New.Comment)) } context := &diffContext{ diff --git a/testdata/diff/comment/column_comment_quoted_identifier/diff.sql b/testdata/diff/comment/column_comment_quoted_identifier/diff.sql new file mode 100644 index 00000000..a55753ec --- /dev/null +++ b/testdata/diff/comment/column_comment_quoted_identifier/diff.sql @@ -0,0 +1 @@ +COMMENT ON COLUMN ex."ID" IS 'Primary identifier'; diff --git a/testdata/diff/comment/column_comment_quoted_identifier/new.sql b/testdata/diff/comment/column_comment_quoted_identifier/new.sql new file mode 100644 index 00000000..d9ab64cf --- /dev/null +++ b/testdata/diff/comment/column_comment_quoted_identifier/new.sql @@ -0,0 +1,5 @@ +CREATE TABLE public.ex ( + "ID" integer NOT NULL +); + +COMMENT ON COLUMN ex."ID" IS 'Primary identifier'; diff --git a/testdata/diff/comment/column_comment_quoted_identifier/old.sql b/testdata/diff/comment/column_comment_quoted_identifier/old.sql new file mode 100644 index 00000000..c59e48c6 --- /dev/null +++ b/testdata/diff/comment/column_comment_quoted_identifier/old.sql @@ -0,0 +1,3 @@ +CREATE TABLE public.ex ( + "ID" integer NOT NULL +); diff --git a/testdata/diff/comment/column_comment_quoted_identifier/plan.json b/testdata/diff/comment/column_comment_quoted_identifier/plan.json new file mode 100644 index 00000000..5e7d58a9 --- /dev/null +++ b/testdata/diff/comment/column_comment_quoted_identifier/plan.json @@ -0,0 +1,20 @@ +{ + "version": "1.0.0", + "pgschema_version": "1.6.1", + "created_at": "1970-01-01T00:00:00Z", + "source_fingerprint": { + "hash": "9d443bc536153eed8fce077bfacc3d7f42b1a94f02d33868bb78be3b9de05088" + }, + "groups": [ + { + "steps": [ + { + "sql": "COMMENT ON COLUMN ex.\"ID\" IS 'Primary identifier';", + "type": "table.column.comment", + "operation": "alter", + "path": "public.ex.ID" + } + ] + } + ] +} diff --git a/testdata/diff/comment/column_comment_quoted_identifier/plan.sql b/testdata/diff/comment/column_comment_quoted_identifier/plan.sql new file mode 100644 index 00000000..a55753ec --- /dev/null +++ b/testdata/diff/comment/column_comment_quoted_identifier/plan.sql @@ -0,0 +1 @@ +COMMENT ON COLUMN ex."ID" IS 'Primary identifier'; diff --git a/testdata/diff/comment/column_comment_quoted_identifier/plan.txt b/testdata/diff/comment/column_comment_quoted_identifier/plan.txt new file mode 100644 index 00000000..21265294 --- /dev/null +++ b/testdata/diff/comment/column_comment_quoted_identifier/plan.txt @@ -0,0 +1,13 @@ +Plan: 1 to modify. + +Summary by type: + tables: 1 to modify + +Tables: + ~ ex + ~ ID (column.comment) + +DDL to be executed: +-------------------------------------------------- + +COMMENT ON COLUMN ex."ID" IS 'Primary identifier'; diff --git a/testdata/diff/create_table/alter_column_quoted_identifier/diff.sql b/testdata/diff/create_table/alter_column_quoted_identifier/diff.sql new file mode 100644 index 00000000..3f8698d4 --- /dev/null +++ b/testdata/diff/create_table/alter_column_quoted_identifier/diff.sql @@ -0,0 +1 @@ +ALTER TABLE ex ALTER COLUMN "ID" TYPE bigint; diff --git a/testdata/diff/create_table/alter_column_quoted_identifier/new.sql b/testdata/diff/create_table/alter_column_quoted_identifier/new.sql new file mode 100644 index 00000000..764a70b7 --- /dev/null +++ b/testdata/diff/create_table/alter_column_quoted_identifier/new.sql @@ -0,0 +1,3 @@ +CREATE TABLE public.ex ( + "ID" bigint NOT NULL +); diff --git a/testdata/diff/create_table/alter_column_quoted_identifier/old.sql b/testdata/diff/create_table/alter_column_quoted_identifier/old.sql new file mode 100644 index 00000000..c59e48c6 --- /dev/null +++ b/testdata/diff/create_table/alter_column_quoted_identifier/old.sql @@ -0,0 +1,3 @@ +CREATE TABLE public.ex ( + "ID" integer NOT NULL +); diff --git a/testdata/diff/create_table/alter_column_quoted_identifier/plan.json b/testdata/diff/create_table/alter_column_quoted_identifier/plan.json new file mode 100644 index 00000000..8692bde5 --- /dev/null +++ b/testdata/diff/create_table/alter_column_quoted_identifier/plan.json @@ -0,0 +1,20 @@ +{ + "version": "1.0.0", + "pgschema_version": "1.6.1", + "created_at": "1970-01-01T00:00:00Z", + "source_fingerprint": { + "hash": "9d443bc536153eed8fce077bfacc3d7f42b1a94f02d33868bb78be3b9de05088" + }, + "groups": [ + { + "steps": [ + { + "sql": "ALTER TABLE ex ALTER COLUMN \"ID\" TYPE bigint;", + "type": "table.column", + "operation": "alter", + "path": "public.ex.ID" + } + ] + } + ] +} diff --git a/testdata/diff/create_table/alter_column_quoted_identifier/plan.sql b/testdata/diff/create_table/alter_column_quoted_identifier/plan.sql new file mode 100644 index 00000000..3f8698d4 --- /dev/null +++ b/testdata/diff/create_table/alter_column_quoted_identifier/plan.sql @@ -0,0 +1 @@ +ALTER TABLE ex ALTER COLUMN "ID" TYPE bigint; diff --git a/testdata/diff/create_table/alter_column_quoted_identifier/plan.txt b/testdata/diff/create_table/alter_column_quoted_identifier/plan.txt new file mode 100644 index 00000000..555ca8a6 --- /dev/null +++ b/testdata/diff/create_table/alter_column_quoted_identifier/plan.txt @@ -0,0 +1,13 @@ +Plan: 1 to modify. + +Summary by type: + tables: 1 to modify + +Tables: + ~ ex + ~ ID (column) + +DDL to be executed: +-------------------------------------------------- + +ALTER TABLE ex ALTER COLUMN "ID" TYPE bigint;