Utility Operations
Drop, rename, and inspect tables using Schema Builder utility methods.
Utility Operations
Beyond creating and altering tables, the Schema Builder provides utility methods for dropping, renaming, and inspecting tables and columns.
Drop Table
Remove a table from the database:
s.Drop("posts")This will fail with an error if the table doesn't exist.
Drop If Exists
Safely remove a table only if it exists:
s.DropIfExists("posts")This is the recommended approach in Down methods since it won't error if the table has already been removed:
func (m *CreatePostsTable) Down(s *schema.Builder) error {
return s.DropIfExists("posts")
}Rename Table
Rename an existing table:
s.Rename("posts", "articles")The first argument is the current table name, and the second is the new name.
package migrations
import (
"github.com/gopackx/go-migration/pkg/schema"
)
type RenamePostsToArticles struct{}
func (m *RenamePostsToArticles) Up(s *schema.Builder) error {
return s.Rename("posts", "articles")
}
func (m *RenamePostsToArticles) Down(s *schema.Builder) error {
return s.Rename("articles", "posts")
}Has Table
Check if a table exists in the database. It returns (bool, error):
exists, err := s.HasTable("users")
if err != nil {
return err
}
if exists {
// Table exists
}This is useful for conditional logic in migrations:
func (m *ConditionalMigration) Up(s *schema.Builder) error {
exists, err := s.HasTable("settings")
if err != nil {
return err
}
if !exists {
return s.Create("settings", func(bp *schema.Blueprint) {
bp.ID()
bp.String("key", 255).Unique()
bp.Text("value").Nullable()
})
}
return nil
}Has Column
Check if a column exists in a table. Like HasTable, it returns (bool, error):
exists, err := s.HasColumn("users", "phone")
if err != nil {
return err
}
if exists {
// Column exists
}Useful for safely adding columns that might already exist:
func (m *AddPhoneToUsers) Up(s *schema.Builder) error {
exists, err := s.HasColumn("users", "phone")
if err != nil {
return err
}
if !exists {
return s.Alter("users", func(bp *schema.Blueprint) {
bp.String("phone", 20).Nullable()
})
}
return nil
}HasTable and HasColumn query the database's information schema at runtime. They're useful for writing defensive migrations that can run safely even if the schema is in an unexpected state.
Raw SQL Execution (v1.0.0)
Execute arbitrary SQL statements directly, bypassing the fluent API. This is useful for materialized views, custom DDL, database-specific features, or anything the Schema Builder doesn't cover.
func (s *Builder) RawExec(statements ...string) error| Parameter | Type | Description |
|---|---|---|
statements | ...string | One or more raw SQL statements to execute |
Each statement is executed sequentially, and RawExec returns an error if any statement fails. Pass multiple statements as separate arguments:
func (m *CreateReportViews) Up(s *schema.Builder) error {
return s.RawExec(
`CREATE MATERIALIZED VIEW monthly_sales AS
SELECT date_trunc('month', created_at) AS month, SUM(amount) AS total
FROM orders GROUP BY month`,
`CREATE UNIQUE INDEX idx_monthly_sales_month ON monthly_sales (month)`,
)
}
func (m *CreateReportViews) Down(s *schema.Builder) error {
return s.RawExec(
"DROP MATERIALIZED VIEW IF EXISTS monthly_sales",
)
}Other common use cases:
// Enable a PostgreSQL extension
s.RawExec("CREATE EXTENSION IF NOT EXISTS pgcrypto")
// Create a partial index
s.RawExec("CREATE INDEX idx_active_users ON users (email) WHERE active = true")
// Set up a trigger
s.RawExec(
`CREATE OR REPLACE FUNCTION update_timestamp()
RETURNS TRIGGER AS $$
BEGIN NEW.updated_at = NOW(); RETURN NEW; END;
$$ LANGUAGE plpgsql`,
`CREATE TRIGGER set_updated_at BEFORE UPDATE ON users
FOR EACH ROW EXECUTE FUNCTION update_timestamp()`,
)RawExec sends SQL directly to the database without grammar validation. Make sure the SQL you write is compatible with the database driver you are using. For operations supported by the fluent API (create table, alter, drop, etc.), prefer the available Builder methods.
Quick Reference
| Method | Description |
|---|---|
s.Drop(table) | Drop a table (errors if not found); returns error |
s.DropIfExists(table) | Drop a table if it exists; returns error |
s.Rename(from, to) | Rename a table; returns error |
s.HasTable(table) | Check if a table exists (returns (bool, error)) |
s.HasColumn(table, column) | Check if a column exists (returns (bool, error)) |
s.RawExec(statements...) | Execute raw SQL statements directly; returns error |
What's Next?
- Database Grammars — how SQL is generated for different databases
- Migrations — using the Schema Builder within migrations