func (r *Runner) invokeMigration(isTest bool, m Migration, c *spiffy.DbConnection, optionalTx ...*sql.Tx) (err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("%v", err) } }() if m.IsTransactionIsolated() { err = m.Apply(c, spiffy.OptionalTx(optionalTx...)) return } var tx *sql.Tx tx, err = c.Begin() if err != nil { return err } defer func() { if err == nil { err = exception.Wrap(tx.Commit()) } else { err = exception.WrapMany(err, exception.New(tx.Rollback())) } }() err = m.Apply(c, tx) return }
// Invoke executes the statement block func (s Statement) Invoke(c *spiffy.DbConnection, tx *sql.Tx) (err error) { for _, step := range s { err = c.ExecInTx(step, tx) if err != nil { return } } return }
// Test runs the data file reader and then rolls-back the txn. func (dfr *DataFileReader) Test(c *spiffy.DbConnection, optionalTx ...*sql.Tx) (err error) { tx, err := c.Begin() if err != nil { return } defer func() { if r := recover(); r != nil { err = fmt.Errorf("%v", err) } if err == nil { dfr.logger.Applyf(dfr, "done!") } else { dfr.logger.Errorf(dfr, err) } tx.Rollback() }() err = dfr.invoke(c, tx) return }
// Invoke consumes the data file and writes it to the db. func (dfr *DataFileReader) invoke(c *spiffy.DbConnection, tx *sql.Tx) (err error) { var f *os.File if f, err = os.Open(dfr.path); err != nil { return } defer f.Close() var stmt *sql.Stmt var state int var cursor int64 var readBuffer = make([]byte, 32) var readErr error var lineBuffer = bytes.NewBuffer([]byte{}) var line string var pieces []interface{} for readErr == nil { lineBuffer.Reset() switch state { case 0: cursor, readErr = dfr.readLine(f, cursor, readBuffer, lineBuffer) if readErr != nil { continue } line = lineBuffer.String() if spiffy.HasPrefixCaseInsensitive(line, "--") { continue } if spiffy.HasPrefixCaseInsensitive(line, "set") { continue } if spiffy.HasPrefixCaseInsensitive(line, "copy") { if !spiffy.HasSuffixCaseInsensitive(line, "from stdin;") { err = fmt.Errorf("Only `stdin` from clauses supported at this time, cannot continue.") return } stmt, err = dfr.executeCopyLine(line, c, tx) if err != nil { return } state = 1 continue } err = c.ExecInTx(line, tx) if err != nil { return } case 1: pieces, cursor, readErr = dfr.readTabLine(f, cursor, readBuffer, lineBuffer) if readErr != nil { continue } if len(pieces) == 0 { err = fmt.Errorf("Empty data line, we error on this for now.") return } if len(pieces) == 1 && spiffy.HasPrefixCaseInsensitive(pieces[0].(string), `\.`) { err = stmt.Close() if err != nil { return } state = 0 continue } _, err = stmt.Exec(pieces...) if err != nil { return } } } return nil }
func spiffyAccess(db *spiffy.DbConnection, queryLimit int) ([]testObject, error) { var results []testObject err := db.GetAll(&results) return results, err }
// roleExists returns if a role exists or not. func roleExists(c *spiffy.DbConnection, tx *sql.Tx, roleName string) (bool, error) { return c.QueryInTx(`SELECT 1 FROM pg_roles WHERE rolname ilike $1`, tx, roleName).Any() }
// IndexExists returns if a index exists on a table on the given connection. func indexExists(c *spiffy.DbConnection, tx *sql.Tx, tableName, indexName string) (bool, error) { return c.QueryInTx(`SELECT 1 FROM pg_catalog.pg_index ix join pg_catalog.pg_class t on t.oid = ix.indrelid join pg_catalog.pg_class i on i.oid = ix.indexrelid WHERE t.relname = $1 and i.relname = $2 and t.relkind = 'r'`, tx, strings.ToLower(tableName), strings.ToLower(indexName)).Any() }
// ConstraintExists returns if a constraint exists on a table on the given connection. func constraintExists(c *spiffy.DbConnection, tx *sql.Tx, constraintName string) (bool, error) { return c.QueryInTx(`SELECT 1 FROM pg_constraint WHERE conname = $1`, tx, strings.ToLower(constraintName)).Any() }
// ColumnExists returns if a column exists on a table on the given connection. func columnExists(c *spiffy.DbConnection, tx *sql.Tx, tableName, columnName string) (bool, error) { return c.QueryInTx(`SELECT 1 FROM information_schema.columns i WHERE i.table_name = $1 and i.column_name = $2`, tx, strings.ToLower(tableName), strings.ToLower(columnName)).Any() }
// TableExists returns if a table exists on the given connection. func tableExists(c *spiffy.DbConnection, tx *sql.Tx, tableName string) (bool, error) { return c.QueryInTx(`SELECT 1 FROM pg_catalog.pg_tables WHERE tablename = $1`, tx, strings.ToLower(tableName)).Any() }