func RemoveDatabase(db *sqlx.DB, database string) { query := fmt.Sprintf(`DROP DATABASE IF EXISTS %s`, database) tx, err := db.Begin() if err != nil { tx.Rollback() log.Error(err) } stmt, err := tx.Prepare(query) if err != nil { log.Error(err) } if _, err := stmt.Exec(); err != nil { log.Error(err) } tx.Commit() }
// Migrate executes all necessary migrations in the specified database. func (m Migrations) Migrate(db *sqlx.DB) error { var initialized bool for _, migration := range m { if !initialized { db.Exec("CREATE TABLE IF NOT EXISTS schema_migrations (id bigint PRIMARY KEY)") initialized = true } tx, err := db.Begin() if err != nil { return err } if _, err := tx.Exec("LOCK TABLE schema_migrations IN ACCESS EXCLUSIVE MODE"); err != nil { tx.Rollback() return err } var tmp bool if err := tx.QueryRow("SELECT true FROM schema_migrations WHERE id = $1", migration.ID).Scan(&tmp); err != sql.ErrNoRows { tx.Rollback() if err == nil { continue } return err } for _, s := range migration.Stmts { if _, err = tx.Exec(s); err != nil { tx.Rollback() return err } } if _, err := tx.Exec("INSERT INTO schema_migrations (id) VALUES ($1)", migration.ID); err != nil { tx.Rollback() return err } if err := tx.Commit(); err != nil { return err } } return nil }
// ExportBulk экспортирует данные из xml-файла в таблицу указанную в описании xml-структуры func ExportBulk(schema func(tableName string) string, xmlObject interface{}, w *sync.WaitGroup, c chan string, db *sqlx.DB, format *string, logger *log.Logger) { defer w.Done() const dateformat = "2006-01-02" objName := extractXMLObjectName(xmlObject) fields := extractFeilds(xmlObject) searchFileName := objName.tableName objName.tableName = strings.TrimSuffix(objName.tableName, "_") DropAndCreateTable(schema(objName.tableName), objName.tableName, db) var format2 string format2 = *format fileName, err2 := SearchFile(searchFileName, format2) if err2 != nil { logger.Fatalln("Error searching file:", err2) } pathToFile := format2 + "/" + fileName xmlFile, err := os.Open(pathToFile) if err != nil { logger.Fatalln("Error opening file:", err) } defer xmlFile.Close() decoder := xml.NewDecoder(xmlFile) var inElement string total := 0 i := 0 txn, err := db.Begin() if err != nil { logger.Fatalln(err) } query := pq.CopyIn(objName.tableName, fields...) stmt, err := txn.Prepare(query) if err != nil { logger.Fatalln(err) } for { if i == 50000 { i = 0 _, err = stmt.Exec() if err != nil { logger.Fatalln(err) } err = stmt.Close() if err != nil { logger.Fatalln(err) } err = txn.Commit() if err != nil { logger.Fatalln(err) } txn, err = db.Begin() if err != nil { logger.Fatalln(err) } stmt, err = txn.Prepare(query) if err != nil { logger.Fatalln(err) } } t, _ := decoder.Token() // Если достигли конца xml-файла if t == nil { if i > 0 { _, err = stmt.Exec() if err != nil { logger.Fatalln(err) } err = stmt.Close() if err != nil { logger.Fatalln(err) } err = txn.Commit() if err != nil { logger.Fatalln(err) } } //c <- helpers.PrintRowsAffected(elementName, total) break } // Inspect the type of the token just read. switch se := t.(type) { case xml.StartElement: // If we just read a StartElement token inElement = se.Name.Local if inElement == objName.elementName { total++ //var item xmlObject // decode a whole chunk of following XML into the // variable item which is a ActualStatus (se above) err = decoder.DecodeElement(&xmlObject, &se) if err != nil { logger.Fatalln("Error in decode element:", err) } values := extractValues(xmlObject) //logger.Println(values) _, err = stmt.Exec(values...) if err != nil { logger.Fatalln(err) } c <- PrintRowsAffected(objName.elementName, total) i++ } default: } } // Если закончили обработку всех записей, ставим вначале строки восклицательный знак. // Признак того, что все записи в данном файле обработаны c <- "!" + PrintRowsAffected(objName.elementName, total) }