package migrate import ( "fmt" "strings" ) // Postgres returns a PostgreSQL dialect implementation func Postgres() Dialect { return postgres{} } type postgres struct{} // quoteIdentifier safely quotes a SQL identifier to prevent SQL injection // PostgreSQL uses double quotes for identifiers and doubles them for escaping func (p postgres) quoteIdentifier(identifier string) string { // Replace any existing quotes with double quotes (SQL escape mechanism) escaped := strings.ReplaceAll(identifier, `"`, `""`) return fmt.Sprintf(`"%s"`, escaped) } func (p postgres) CreateTable(table string) string { return fmt.Sprintf(`CREATE TABLE %s ( id SERIAL PRIMARY KEY, description VARCHAR, applied TIMESTAMP);`, p.quoteIdentifier(table)) } func (p postgres) TableExists(table string) string { // PostgreSQL-specific way to check if table exists return fmt.Sprintf("SELECT 1 FROM %s LIMIT 1;", p.quoteIdentifier(table)) } func (p postgres) CheckVersion(table string) string { return fmt.Sprintf("SELECT id FROM %s ORDER BY id DESC LIMIT 1;", p.quoteIdentifier(table)) } func (p postgres) InsertVersion(table string) string { // PostgreSQL uses $1, $2 for placeholders instead of ? return fmt.Sprintf("INSERT INTO %s(description, applied) VALUES ($1, $2);", p.quoteIdentifier(table)) }