-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package migrations | ||
|
||
import ( | ||
"context" | ||
"database/sql" | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/lib/pq" | ||
|
||
"pg-roll/pkg/schema" | ||
) | ||
|
||
type OpSetUnique struct { | ||
Table string `json:"table"` | ||
Columns []string `json:"columns"` | ||
} | ||
|
||
var _ Operation = (*OpSetUnique)(nil) | ||
|
||
func (o *OpSetUnique) Start(ctx context.Context, conn *sql.DB, schemaName string, stateSchema string, s *schema.Schema) error { | ||
// create unique index concurrently | ||
_, err := conn.ExecContext(ctx, fmt.Sprintf("CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS %s ON %s (%s)", | ||
pq.QuoteIdentifier(IndexName(o.Table, o.Columns)), | ||
Check failure on line 24 in pkg/migrations/op_set_unique.go
|
||
pq.QuoteIdentifier(o.Table), | ||
strings.Join(quoteColumnNames(o.Columns), ", "))) | ||
return err | ||
} | ||
|
||
func (o *OpSetUnique) Complete(ctx context.Context, conn *sql.DB) error { | ||
// create a unique constraint using the unique index | ||
_, err := conn.ExecContext(ctx, fmt.Sprintf("ALTER TABLE IF EXISTS %s ADD CONSTRAINT %s UNIQUE USING INDEX %s", | ||
pq.QuoteIdentifier(o.Table), | ||
pq.QuoteIdentifier(UniqueConstraintName(o.Table, o.Columns)), | ||
pq.QuoteIdentifier(IndexName(o.Table, o.Columns)))) | ||
Check failure on line 35 in pkg/migrations/op_set_unique.go
|
||
|
||
return err | ||
} | ||
|
||
func (o *OpSetUnique) Rollback(ctx context.Context, conn *sql.DB) error { | ||
// drop the index concurrently | ||
_, err := conn.ExecContext(ctx, fmt.Sprintf("DROP INDEX CONCURRENTLY IF EXISTS %s", | ||
IndexName(o.Table, o.Columns))) | ||
Check failure on line 43 in pkg/migrations/op_set_unique.go
|
||
|
||
return err | ||
} | ||
|
||
func (o *OpSetUnique) Validate(ctx context.Context, s *schema.Schema) error { | ||
table := s.GetTable(o.Table) | ||
|
||
if table == nil { | ||
return TableDoesNotExistError{Name: o.Table} | ||
} | ||
|
||
for _, column := range o.Columns { | ||
if table.GetColumn(column) == nil { | ||
return ColumnDoesNotExistError{Table: o.Table, Name: column} | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func UniqueConstraintName(table string, columns []string) string { | ||
return "_pgroll_unique_" + table + "_" + strings.Join(columns, "_") | ||
} |