Skip to content

Snowflake: mixed-case column names break MERGE during schema delta replay #4186

@kang8

Description

@kang8

Bug Description

When a PostgreSQL source table has mixed-case column names (e.g., "pulseArmor", "highGold"), the Snowflake CDC normalization fails with:

SQL compilation error: error line 14 at position 281 invalid identifier '"pulseArmor"'

Root Cause

There is an inconsistency in column name handling between ALTER TABLE ADD COLUMN (schema delta replay) and MERGE statement generation:

  • snowflake.go:377-378 (ALTER TABLE ADD COLUMN) uses strings.ToUpper(addedColumn.Name):

    fmt.Sprintf("ALTER TABLE %s ADD COLUMN IF NOT EXISTS \"%s\" %s",
        schemaDelta.DstTableName, strings.ToUpper(addedColumn.Name), sfColtype)

    This creates the column as "PULSEARMOR" in Snowflake.

  • merge_stmt_generator.go uses SnowflakeIdentifierNormalize(column.Name):

    targetColumnName := SnowflakeIdentifierNormalize(column.Name)

    For mixed-case identifiers, SnowflakeIdentifierNormalize preserves the original case (per client.go:19-27), producing "pulseArmor" in the MERGE statement.

Since Snowflake treats quoted identifiers as case-sensitive, "PULSEARMOR""pulseArmor", causing the MERGE to fail.

Suggested Fix

In flow/connectors/snowflake/snowflake.go:377-378, replace:

fmt.Sprintf("ALTER TABLE %s ADD COLUMN IF NOT EXISTS \"%s\" %s",
    schemaDelta.DstTableName, strings.ToUpper(addedColumn.Name), sfColtype)

with:

fmt.Sprintf("ALTER TABLE %s ADD COLUMN IF NOT EXISTS %s %s",
    schemaDelta.DstTableName, SnowflakeIdentifierNormalize(addedColumn.Name), sfColtype)

This ensures both ALTER TABLE and MERGE use the same normalization logic.

Steps to Reproduce

  1. Create a PG → Snowflake CDC mirror
  2. Add a mixed-case column to the source table:
    ALTER TABLE users ADD COLUMN "pulseArmor" INTEGER;
  3. Insert a row with data in the new column
  4. Wait for the next sync cycle — normalization fails

Environment

  • PeerDB version: latest main branch
  • Source: PostgreSQL (RDS)
  • Destination: Snowflake

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions