@@ -152,13 +152,14 @@ func (p *PostgreSQLSourceConnector) ensureSourceTable(ctx context.Context) error
152152 return nil
153153 }
154154 p .logger .Info ("Creating source table" , "table" , p .config .Table )
155+ quotedTable := QuotePostgreSQLTableRef (p .config .Table )
155156 createQuery := fmt .Sprintf (`
156157 CREATE TABLE IF NOT EXISTS %s (
157158 id SERIAL PRIMARY KEY,
158159 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
159160 updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
160161 )
161- ` , p . config . Table )
162+ ` , quotedTable )
162163 _ , err = p .conn .Exec (ctx , createQuery )
163164 if err != nil {
164165 return fmt .Errorf ("failed to create source table: %w" , err )
@@ -348,12 +349,13 @@ func (p *PostgreSQLSourceConnector) buildReadQuery() string {
348349 p .checkpointMu .Lock ()
349350 lastRead := p .lastReadChangeTime
350351 p .checkpointMu .Unlock ()
352+ quotedTable := QuotePostgreSQLTableRef (p .config .Table )
351353 if lastRead != nil {
352354 // RFC3339Nano preserves sub-second precision to avoid re-reading or skipping rows at boundaries
353355 return fmt .Sprintf ("SELECT * FROM %s WHERE %s > '%s' ORDER BY %s, id" ,
354- p . config . Table , orderExpr , lastRead .UTC ().Format (time .RFC3339Nano ), orderExpr )
356+ quotedTable , orderExpr , lastRead .UTC ().Format (time .RFC3339Nano ), orderExpr )
355357 }
356- return fmt .Sprintf ("SELECT * FROM %s ORDER BY %s, id" , p . config . Table , orderExpr )
358+ return fmt .Sprintf ("SELECT * FROM %s ORDER BY %s, id" , quotedTable , orderExpr )
357359}
358360
359361// extractChangeTime returns the change tracking timestamp for the row (for checkpoint).
@@ -529,6 +531,7 @@ func (p *PostgreSQLSinkConnector) ensureTable(ctx context.Context) error {
529531 }
530532
531533 p .logger .Info ("Creating table (raw mode)" , "table" , p .config .Table )
534+ quotedTable := QuotePostgreSQLTableRef (p .config .Table )
532535 createQuery := fmt .Sprintf (`
533536 CREATE TABLE IF NOT EXISTS %s (
534537 id SERIAL PRIMARY KEY,
@@ -538,7 +541,7 @@ func (p *PostgreSQLSinkConnector) ensureTable(ctx context.Context) error {
538541 updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
539542 deleted_at TIMESTAMP
540543 )
541- ` , p . config . Table )
544+ ` , quotedTable )
542545
543546 _ , err = p .conn .Exec (ctx , createQuery )
544547 if err != nil {
@@ -549,7 +552,9 @@ func (p *PostgreSQLSinkConnector) ensureTable(ctx context.Context) error {
549552 p .hasJSONBCached = nil // raw mode table has value, not data column
550553 p .logger .Info ("Table created successfully" , "table" , p .config .Table )
551554
552- indexQuery := fmt .Sprintf (`CREATE INDEX IF NOT EXISTS idx_%s_value ON %s USING GIN (value)` , p .config .Table , p .config .Table )
555+ _ , tableName := ParseTableRef (p .config .Table )
556+ indexName := quotePostgreSQLIdentifier ("idx_" + tableName + "_value" )
557+ indexQuery := fmt .Sprintf (`CREATE INDEX IF NOT EXISTS %s ON %s USING GIN (value)` , indexName , quotedTable )
553558 _ , err = p .conn .Exec (ctx , indexQuery )
554559 if err != nil {
555560 p .logger .Info ("Failed to create index (non-critical)" , "table" , p .config .Table , "error" , err )
@@ -590,7 +595,7 @@ func (p *PostgreSQLSinkConnector) ensureTableFromMessage(ctx context.Context, da
590595 for _ , col := range columns {
591596 val := data [col ]
592597 pgType := inferPostgreSQLType (val )
593- def := fmt .Sprintf (`"%s" %s` , col , pgType )
598+ def := fmt .Sprintf (`%s %s` , quotePostgreSQLIdentifier ( col ) , pgType )
594599 if col == "id" {
595600 def += " PRIMARY KEY"
596601 }
@@ -607,7 +612,8 @@ func (p *PostgreSQLSinkConnector) ensureTableFromMessage(ctx context.Context, da
607612 }
608613
609614 p .logger .Info ("Creating table from message structure" , "table" , p .config .Table , "columns" , columns )
610- createQuery := fmt .Sprintf (`CREATE TABLE IF NOT EXISTS %s (%s)` , p .config .Table , joinStrings (colDefs , ", " ))
615+ quotedTable := QuotePostgreSQLTableRef (p .config .Table )
616+ createQuery := fmt .Sprintf (`CREATE TABLE IF NOT EXISTS %s (%s)` , quotedTable , joinStrings (colDefs , ", " ))
611617 _ , err = p .conn .Exec (ctx , createQuery )
612618 if err != nil {
613619 return fmt .Errorf ("failed to create table from message: %w" , err )
@@ -906,7 +912,8 @@ func (p *PostgreSQLSinkConnector) trySoftDelete(msg *types.Message, batch *pgx.B
906912 if p .config .ConflictKey != nil && * p .config .ConflictKey != "" {
907913 conflictKey = * p .config .ConflictKey
908914 }
909- query := fmt .Sprintf ("UPDATE %s SET %s = CURRENT_TIMESTAMP WHERE %s = $1" , p .config .Table , * p .config .SoftDeleteColumn , conflictKey )
915+ quotedTable := QuotePostgreSQLTableRef (p .config .Table )
916+ query := fmt .Sprintf ("UPDATE %s SET %s = CURRENT_TIMESTAMP WHERE %s = $1" , quotedTable , quotePostgreSQLIdentifier (* p .config .SoftDeleteColumn ), quotePostgreSQLIdentifier (conflictKey ))
910917 batch .Queue (query , idVal )
911918 * batchMessages = append (* batchMessages , msg )
912919 * count ++
@@ -959,21 +966,23 @@ func (p *PostgreSQLSinkConnector) buildInsertForMessage(ctx context.Context, dat
959966 }
960967 metaJSON , _ = json .Marshal (meta )
961968 }
969+ quotedTable := QuotePostgreSQLTableRef (p .config .Table )
962970 if upsertMode {
963- query = fmt .Sprintf ("INSERT INTO %s (value, _metadata) VALUES ($1::jsonb, $2::jsonb) ON CONFLICT (id) DO UPDATE SET value = EXCLUDED.value, _metadata = EXCLUDED._metadata" , p . config . Table )
971+ query = fmt .Sprintf ("INSERT INTO %s (value, _metadata) VALUES ($1::jsonb, $2::jsonb) ON CONFLICT (id) DO UPDATE SET value = EXCLUDED.value, _metadata = EXCLUDED._metadata" , quotedTable )
964972 } else {
965- query = fmt .Sprintf ("INSERT INTO %s (value, _metadata) VALUES ($1::jsonb, $2::jsonb)" , p . config . Table )
973+ query = fmt .Sprintf ("INSERT INTO %s (value, _metadata) VALUES ($1::jsonb, $2::jsonb)" , quotedTable )
966974 }
967975 values = []interface {}{string (valueJSON ), string (metaJSON )}
968976 return query , values , nil
969977 }
970978
971979 hasJSONB , e := p .hasJSONBColumn (ctx )
972980 if e == nil && hasJSONB {
981+ quotedTable := QuotePostgreSQLTableRef (p .config .Table )
973982 if upsertMode {
974- query = fmt .Sprintf ("INSERT INTO %s (data) VALUES ($1::jsonb) ON CONFLICT (id) DO UPDATE SET data = EXCLUDED.data" , p . config . Table )
983+ query = fmt .Sprintf ("INSERT INTO %s (data) VALUES ($1::jsonb) ON CONFLICT (id) DO UPDATE SET data = EXCLUDED.data" , quotedTable )
975984 } else {
976- query = fmt .Sprintf ("INSERT INTO %s (data) VALUES ($1::jsonb) ON CONFLICT DO NOTHING" , p . config . Table )
985+ query = fmt .Sprintf ("INSERT INTO %s (data) VALUES ($1::jsonb) ON CONFLICT DO NOTHING" , quotedTable )
977986 }
978987 jsonData , _ := json .Marshal (data )
979988 values = []interface {}{string (jsonData )}
@@ -996,14 +1005,15 @@ func (p *PostgreSQLSinkConnector) buildInsertForMessage(ctx context.Context, dat
9961005 if len (columns ) == 0 {
9971006 return "" , nil , fmt .Errorf ("empty message, no columns to insert" )
9981007 }
999- columnList := fmt . Sprintf ( `"%s"` , columns [0 ])
1008+ columnList := quotePostgreSQLIdentifier ( columns [0 ])
10001009 for i := 1 ; i < len (columns ); i ++ {
1001- columnList += fmt . Sprintf ( ` , "%s"` , columns [i ])
1010+ columnList += " , " + quotePostgreSQLIdentifier ( columns [i ])
10021011 }
10031012 placeholderList := "$1"
10041013 for i := 2 ; i <= len (placeholders ); i ++ {
10051014 placeholderList += fmt .Sprintf (", $%d" , i )
10061015 }
1016+ quotedTable := QuotePostgreSQLTableRef (p .config .Table )
10071017 if upsertMode {
10081018 conflictKey := "id"
10091019 if p .config .ConflictKey != nil && * p .config .ConflictKey != "" {
@@ -1012,20 +1022,20 @@ func (p *PostgreSQLSinkConnector) buildInsertForMessage(ctx context.Context, dat
10121022 updateClauses := make ([]string , 0 )
10131023 for _ , col := range columns {
10141024 if col != conflictKey {
1015- updateClauses = append (updateClauses , fmt .Sprintf (`"%s" = EXCLUDED."%s" ` , col , col ))
1025+ updateClauses = append (updateClauses , fmt .Sprintf (`%s = EXCLUDED.%s ` , quotePostgreSQLIdentifier ( col ), quotePostgreSQLIdentifier ( col ) ))
10161026 }
10171027 }
10181028 if len (updateClauses ) == 0 {
1019- query = fmt .Sprintf ("INSERT INTO %s (%s) VALUES (%s) ON CONFLICT (%s) DO NOTHING" , p . config . Table , columnList , placeholderList , conflictKey )
1029+ query = fmt .Sprintf ("INSERT INTO %s (%s) VALUES (%s) ON CONFLICT (%s) DO NOTHING" , quotedTable , columnList , placeholderList , quotePostgreSQLIdentifier ( conflictKey ) )
10201030 } else {
10211031 updateClause := updateClauses [0 ]
10221032 for i := 1 ; i < len (updateClauses ); i ++ {
10231033 updateClause += ", " + updateClauses [i ]
10241034 }
1025- query = fmt .Sprintf ("INSERT INTO %s (%s) VALUES (%s) ON CONFLICT (%s) DO UPDATE SET %s" , p . config . Table , columnList , placeholderList , conflictKey , updateClause )
1035+ query = fmt .Sprintf ("INSERT INTO %s (%s) VALUES (%s) ON CONFLICT (%s) DO UPDATE SET %s" , quotedTable , columnList , placeholderList , quotePostgreSQLIdentifier ( conflictKey ) , updateClause )
10261036 }
10271037 } else {
1028- query = fmt .Sprintf ("INSERT INTO %s (%s) VALUES (%s) ON CONFLICT DO NOTHING" , p . config . Table , columnList , placeholderList )
1038+ query = fmt .Sprintf ("INSERT INTO %s (%s) VALUES (%s) ON CONFLICT DO NOTHING" , quotedTable , columnList , placeholderList )
10291039 }
10301040 values = colValues
10311041 return query , values , nil
0 commit comments