@@ -24,11 +24,13 @@ type PartitionResult struct {
2424}
2525
2626func (p Postgres ) IsPartitionAttached (schema , table string ) (exists bool , err error ) {
27- query := `SELECT EXISTS(
28- SELECT 1 FROM pg_inherits WHERE inhrelid = $1::regclass
29- )`
27+ query := `SELECT EXISTS (SELECT 1 FROM pg_catalog.pg_inherits WHERE inhrelid = (SELECT c.oid
28+ FROM pg_catalog.pg_class c
29+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
30+ WHERE n.nspname = $1 AND c.relname = $2 AND c.relkind='r'))
31+ `
3032
31- err = p .conn .QueryRow (p .ctx , query , fmt . Sprintf ( "%s.%s" , schema , table ) ).Scan (& exists )
33+ err = p .conn .QueryRow (p .ctx , query , schema , table ).Scan (& exists )
3234 if err != nil {
3335 return false , fmt .Errorf ("failed to check partition attachment: %w" , err )
3436 }
@@ -37,7 +39,10 @@ func (p Postgres) IsPartitionAttached(schema, table string) (exists bool, err er
3739}
3840
3941func (p Postgres ) AttachPartition (schema , table , parent , lowerBound , upperBound string ) error {
40- query := fmt .Sprintf ("ALTER TABLE %s.%s ATTACH PARTITION %s.%s FOR VALUES FROM ('%s') TO ('%s')" , schema , parent , schema , table , lowerBound , upperBound )
42+ query := fmt .Sprintf ("ALTER TABLE %s ATTACH PARTITION %s FOR VALUES FROM ('%s') TO ('%s')" ,
43+ pgx.Identifier {schema , parent }.Sanitize (),
44+ pgx.Identifier {schema , table }.Sanitize (),
45+ lowerBound , upperBound )
4146 p .logger .Debug ("Attach partition" , "query" , query , "schema" , schema , "table" , table )
4247
4348 _ , err := p .conn .Exec (p .ctx , query )
@@ -52,7 +57,10 @@ func (p Postgres) AttachPartition(schema, table, parent, lowerBound, upperBound
5257// The partition still exists as standalone table after detaching
5358// More info: https://www.postgresql.org/docs/current/sql-altertable.html#SQL-ALTERTABLE-DETACH-PARTITION
5459func (p Postgres ) DetachPartitionConcurrently (schema , table , parent string ) error {
55- query := fmt .Sprintf (`ALTER TABLE %s.%s DETACH PARTITION %s.%s CONCURRENTLY` , schema , parent , schema , table )
60+ query := fmt .Sprintf ("ALTER TABLE %s DETACH PARTITION %s CONCURRENTLY" ,
61+ pgx.Identifier {schema , parent }.Sanitize (),
62+ pgx.Identifier {schema , table }.Sanitize ())
63+
5664 p .logger .Debug ("Detach partition" , "schema" , schema , "table" , table , "query" , query , "parent_table" , parent )
5765
5866 _ , err := p .conn .Exec (p .ctx , query )
@@ -67,7 +75,9 @@ func (p Postgres) DetachPartitionConcurrently(schema, table, parent string) erro
6775// It's required when a partition is in "detach pending" status.
6876// More info: https://www.postgresql.org/docs/current/sql-altertable.html#SQL-ALTERTABLE-DETACH-PARTITION
6977func (p Postgres ) FinalizePartitionDetach (schema , table , parent string ) error {
70- query := fmt .Sprintf (`ALTER TABLE %s.%s DETACH PARTITION %s.%s FINALIZE` , schema , parent , schema , table )
78+ query := fmt .Sprintf (`ALTER TABLE %s DETACH PARTITION %s FINALIZE` ,
79+ pgx.Identifier {schema , parent }.Sanitize (),
80+ pgx.Identifier {schema , table }.Sanitize ())
7181 p .logger .Debug ("finialize detach partition" , "schema" , schema , "table" , table , "query" , query , "parent_table" , parent )
7282
7383 _ , err := p .conn .Exec (p .ctx , query )
@@ -79,28 +89,33 @@ func (p Postgres) FinalizePartitionDetach(schema, table, parent string) error {
7989}
8090
8191func (p Postgres ) ListPartitions (schema , table string ) (partitions []PartitionResult , err error ) {
82- query := fmt . Sprintf ( `
92+ query := `
8393 WITH parts as (
8494 SELECT
85- relnamespace::regnamespace as schema,
86- c.oid::pg_catalog.regclass AS part_name,
95+ n.nspname as schema,
96+ c.relname AS part_name,
8797 regexp_match(pg_get_expr(c.relpartbound, c.oid),
8898 'FOR VALUES FROM \(''(.*)''\) TO \(''(.*)''\)') AS bounds
8999 FROM
90100 pg_catalog.pg_class c JOIN pg_catalog.pg_inherits i ON (c.oid = i.inhrelid)
91- WHERE i.inhparent = '%s.%s'::regclass
101+ JOIN pg_catalog.pg_namespace n ON (c.relnamespace = n.oid)
102+ WHERE i.inhparent = (SELECT c.oid
103+ FROM pg_catalog.pg_class c
104+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
105+ WHERE n.nspname = $1 AND c.relname = $2 AND c.relkind='p' -- parent
106+ )
92107 AND c.relkind='r'
93108 )
94109 SELECT
95110 schema,
96111 part_name as name,
97- '%s' as parentTable,
112+ $2 as parentTable,
98113 bounds[1]::text AS lowerBound,
99114 bounds[2]::text AS upperBound
100115 FROM parts
101- ORDER BY part_name;` , schema , table , table )
116+ ORDER BY part_name`
102117
103- rows , err := p .conn .Query (p .ctx , query )
118+ rows , err := p .conn .Query (p .ctx , query , schema , table )
104119 if err != nil {
105120 return nil , fmt .Errorf ("failed to list partitions: %w" , err )
106121 }
@@ -119,12 +134,15 @@ func (p Postgres) GetPartitionSettings(schema, table string) (strategy, key stri
119134 // pg_get_partkeydef() is a system function returning the definition of a partitioning key
120135 // It return a text string: <partitioningStrategy> (<partitioning key definition>)
121136 // Example for RANGE (created_at)
122- query := fmt . Sprintf ( `
137+ query := `
123138 SELECT regexp_match(partkeydef, '^(.*) \((.*)\)$')
124- FROM pg_catalog.pg_get_partkeydef('%s.%s'::regclass) as partkeydef
125- ` , schema , table )
139+ FROM pg_catalog.pg_get_partkeydef((SELECT c.oid
140+ FROM pg_catalog.pg_class c
141+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
142+ WHERE n.nspname = $1 AND c.relname = $2 AND c.relkind='p')) as partkeydef
143+ `
126144
127- err = p .conn .QueryRow (p .ctx , query ).Scan (& partkeydef )
145+ err = p .conn .QueryRow (p .ctx , query , schema , table ).Scan (& partkeydef )
128146 if err != nil {
129147 p .logger .Warn ("failed to get partitioning key" , "error" , err , "schema" , schema , "table" , table )
130148
@@ -153,7 +171,8 @@ func (p Postgres) SetPartitionReplicaIdentity(schema, table, parent string) erro
153171 }
154172
155173 if replIdent == "f" { // replica identity = full
156- queryFull := fmt .Sprintf ("ALTER TABLE %s.%s REPLICA IDENTITY FULL" , schema , table )
174+ queryFull := fmt .Sprintf ("ALTER TABLE %s REPLICA IDENTITY FULL" ,
175+ pgx.Identifier {schema , table }.Sanitize ())
157176 p .logger .Debug ("Set identity full" , "query" , queryFull )
158177
159178 _ , err = p .conn .Exec (p .ctx , queryFull )
@@ -184,7 +203,9 @@ SELECT c_idx_child.relname
184203 return fmt .Errorf ("failed to find the child index for the new partition: %w" , err )
185204 }
186205
187- queryAlter := fmt .Sprintf ("ALTER TABLE %s.%s REPLICA IDENTITY USING INDEX %s" , schema , table , indexName )
206+ queryAlter := fmt .Sprintf ("ALTER TABLE %s REPLICA IDENTITY USING INDEX %s" ,
207+ pgx.Identifier {schema , table }.Sanitize (),
208+ pgx.Identifier {indexName }.Sanitize ())
188209 p .logger .Debug ("Set replica identity" , "schema" , schema , "table" , table , "index" , indexName , "query" , queryAlter )
189210
190211 _ , err := p .conn .Exec (p .ctx , queryAlter )
0 commit comments