You've already forked golang-saas-starter-kit
mirror of
https://github.com/raseels-repos/golang-saas-starter-kit.git
synced 2025-07-17 01:42:36 +02:00
schema check for type before create
This commit is contained in:
@ -59,13 +59,9 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest
|
|||||||
{
|
{
|
||||||
ID: "20190522-01c",
|
ID: "20190522-01c",
|
||||||
Migrate: func(tx *sql.Tx) error {
|
Migrate: func(tx *sql.Tx) error {
|
||||||
if err := dropTypeIfExists(tx, "account_status_t"); err != nil {
|
if err := createTypeIfNotExists(tx, "account_status_t", "enum('active','pending','disabled')"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
q1 := `CREATE TYPE account_status_t as enum('active','pending','disabled')`
|
|
||||||
if _, err := tx.Exec(q1); err != nil && !errorIsAlreadyExists(err) {
|
|
||||||
return errors.WithMessagef(err, "Query failed %s", q1)
|
|
||||||
}
|
|
||||||
|
|
||||||
q2 := `CREATE TABLE IF NOT EXISTS accounts (
|
q2 := `CREATE TABLE IF NOT EXISTS accounts (
|
||||||
id char(36) NOT NULL,
|
id char(36) NOT NULL,
|
||||||
@ -108,23 +104,15 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest
|
|||||||
{
|
{
|
||||||
ID: "20190522-01e",
|
ID: "20190522-01e",
|
||||||
Migrate: func(tx *sql.Tx) error {
|
Migrate: func(tx *sql.Tx) error {
|
||||||
if err := dropTypeIfExists(tx, "user_account_role_t"); err != nil {
|
if err := createTypeIfNotExists(tx, "user_account_role_t", "enum('admin', 'user')"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
q1 := `CREATE TYPE user_account_role_t as enum('admin', 'user')`
|
|
||||||
if _, err := tx.Exec(q1); err != nil && !errorIsAlreadyExists(err) {
|
|
||||||
return errors.WithMessagef(err, "Query failed %s", q1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := dropTypeIfExists(tx, "user_account_status_t"); err != nil {
|
if err := createTypeIfNotExists(tx, "user_account_status_t", "enum('active', 'invited','disabled'"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
q2 := `CREATE TYPE user_account_status_t as enum('active', 'invited','disabled')`
|
|
||||||
if _, err := tx.Exec(q2); err != nil && !errorIsAlreadyExists(err) {
|
|
||||||
return errors.WithMessagef(err, "Query failed %s", q2)
|
|
||||||
}
|
|
||||||
|
|
||||||
q3 := `CREATE TABLE IF NOT EXISTS users_accounts (
|
q1 := `CREATE TABLE IF NOT EXISTS users_accounts (
|
||||||
id char(36) NOT NULL,
|
id char(36) NOT NULL,
|
||||||
account_id char(36) NOT NULL REFERENCES accounts(id) ON DELETE NO ACTION,
|
account_id char(36) NOT NULL REFERENCES accounts(id) ON DELETE NO ACTION,
|
||||||
user_id char(36) NOT NULL REFERENCES users(id) ON DELETE NO ACTION,
|
user_id char(36) NOT NULL REFERENCES users(id) ON DELETE NO ACTION,
|
||||||
@ -136,19 +124,19 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest
|
|||||||
PRIMARY KEY (id),
|
PRIMARY KEY (id),
|
||||||
CONSTRAINT user_account UNIQUE (user_id,account_id)
|
CONSTRAINT user_account UNIQUE (user_id,account_id)
|
||||||
)`
|
)`
|
||||||
if _, err := tx.Exec(q3); err != nil {
|
if _, err := tx.Exec(q1); err != nil {
|
||||||
return errors.WithMessagef(err, "Query failed %s", q3)
|
return errors.WithMessagef(err, "Query failed %s", q1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
Rollback: func(tx *sql.Tx) error {
|
Rollback: func(tx *sql.Tx) error {
|
||||||
q1 := `DROP TYPE user_account_role_t`
|
q1 := `DROP TYPE IF EXISTS user_account_role_t`
|
||||||
if _, err := tx.Exec(q1); err != nil {
|
if _, err := tx.Exec(q1); err != nil {
|
||||||
return errors.WithMessagef(err, "Query failed %s", q1)
|
return errors.WithMessagef(err, "Query failed %s", q1)
|
||||||
}
|
}
|
||||||
|
|
||||||
q2 := `DROP TYPE user_account_status_t`
|
q2 := `DROP TYPE IF EXISTS user_account_status_t`
|
||||||
if _, err := tx.Exec(q2); err != nil {
|
if _, err := tx.Exec(q2); err != nil {
|
||||||
return errors.WithMessagef(err, "Query failed %s", q2)
|
return errors.WithMessagef(err, "Query failed %s", q2)
|
||||||
}
|
}
|
||||||
@ -165,16 +153,11 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest
|
|||||||
{
|
{
|
||||||
ID: "20190622-01",
|
ID: "20190622-01",
|
||||||
Migrate: func(tx *sql.Tx) error {
|
Migrate: func(tx *sql.Tx) error {
|
||||||
if err := dropTypeIfExists(tx, "project_status_t"); err != nil {
|
if err := createTypeIfNotExists(tx, "project_status_t", "enum('active','disabled')"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
q1 := `CREATE TYPE project_status_t as enum('active','disabled')`
|
q1 := `CREATE TABLE IF NOT EXISTS projects (
|
||||||
if _, err := tx.Exec(q1); err != nil && !errorIsAlreadyExists(err) {
|
|
||||||
return errors.WithMessagef(err, "Query failed %s", q1)
|
|
||||||
}
|
|
||||||
|
|
||||||
q2 := `CREATE TABLE IF NOT EXISTS projects (
|
|
||||||
id char(36) NOT NULL,
|
id char(36) NOT NULL,
|
||||||
account_id char(36) NOT NULL REFERENCES accounts(id) ON DELETE SET NULL,
|
account_id char(36) NOT NULL REFERENCES accounts(id) ON DELETE SET NULL,
|
||||||
name varchar(255) NOT NULL,
|
name varchar(255) NOT NULL,
|
||||||
@ -184,13 +167,13 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest
|
|||||||
archived_at TIMESTAMP WITH TIME ZONE DEFAULT NULL,
|
archived_at TIMESTAMP WITH TIME ZONE DEFAULT NULL,
|
||||||
PRIMARY KEY (id)
|
PRIMARY KEY (id)
|
||||||
)`
|
)`
|
||||||
if _, err := tx.Exec(q2); err != nil {
|
if _, err := tx.Exec(q1); err != nil {
|
||||||
return errors.WithMessagef(err, "Query failed %s", q2)
|
return errors.WithMessagef(err, "Query failed %s", q1)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
Rollback: func(tx *sql.Tx) error {
|
Rollback: func(tx *sql.Tx) error {
|
||||||
q1 := `DROP TYPE project_status_t`
|
q1 := `DROP TYPE IF EXISTS project_status_t`
|
||||||
if _, err := tx.Exec(q1); err != nil && !errorIsAlreadyExists(err) {
|
if _, err := tx.Exec(q1); err != nil && !errorIsAlreadyExists(err) {
|
||||||
return errors.WithMessagef(err, "Query failed %s", q1)
|
return errors.WithMessagef(err, "Query failed %s", q1)
|
||||||
}
|
}
|
||||||
@ -691,6 +674,41 @@ func dropTypeIfExists(tx *sql.Tx, name string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createTypeIfNotExists checks to ensure a type doesn't exist before creating.
|
||||||
|
func createTypeIfNotExists(tx *sql.Tx, name, val string) error {
|
||||||
|
|
||||||
|
q1 := "select exists (select 1 from pg_type where typname = '"+name+"')"
|
||||||
|
rows, err := tx.Query(q1)
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithMessagef(err, "Query failed %s", q1)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var exists bool
|
||||||
|
for rows.Next() {
|
||||||
|
err := rows.Scan(&exists)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
q2 := `CREATE TYPE "+name+" AS `+val
|
||||||
|
if _, err := tx.Exec(q2); err != nil && !errorIsAlreadyExists(err) {
|
||||||
|
return errors.WithMessagef(err, "Query failed %s", q2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// errorIsAlreadyExists checks an error message for the error "already exists"
|
// errorIsAlreadyExists checks an error message for the error "already exists"
|
||||||
func errorIsAlreadyExists(err error) bool {
|
func errorIsAlreadyExists(err error) bool {
|
||||||
if strings.Contains(err.Error(), "already exists") {
|
if strings.Contains(err.Error(), "already exists") {
|
||||||
|
Reference in New Issue
Block a user