/*
* db_sync.go
*
* Synchronize data between SQL capable databases, client code.
*
* Author:
* Mark Taylor (mtaylor@taylor-hq.com)
*
* Version:
* July 2014
*
* See presentation:
* http://www.taylor-hq.com/~mtaylor/presentations/dbsync/DBSync.html
*
* Color-code this script:
* pygmentize -f html -o ~/public_html/presentations/dbsync/db_sync-main.go.html -O full db_sync.go
*
* NOTES:
* Using goroutines (gophers) to parallelize loading data into Postgres:
* http://www.acloudtree.com/how-to-shove-data-into-postgres-using-goroutinesgophers-and-golang/
*
* TODO:
* - Add command-line parameter for sync table definitions (from a file, and from source-db table)
* - Generate DAG, and parallel process in topological order.
*
*/
package main
import (
"log"
"flag"
"fmt"
"strings"
"time"
"database/sql"
_ "github.com/lib/pq" // http://godoc.org/github.com/lib/pq
//_ "github.com/go-sql-driver/mysql" // http://godoc.org/github.com/go-sql-driver/mysql
"database/sql/sync"
)
func main() {
var err error
var db_src, db_dest *sql.DB
var results sync.TableSyncResults
var start time.Time
var verbosity int
var source_db = "postgres://postgres:@localhost/tva?sslmode=disable"
var dest_db = "postgres://postgres:@localhost/tva2?sslmode=disable"
//var dest_db = "mysql://root:xxxx@localhost/test"
var tables = []sync.TableSyncParams{
{ Table_Name:"gauges", Insert_Only:false, Unique_ID:"id" },
{ Table_Name:"gauges_daily", Insert_Only:true, Timestamp_Column:"date" },
}
flag.IntVar( &verbosity, "v", verbosity, "Set verbosity level" )
flag.StringVar(&source_db, "src", source_db, "Set source database" )
flag.StringVar( &dest_db, "dest", dest_db, "Set destination database")
flag.Parse()
db_src, err = sql.Open(strings.Split(source_db, ":")[0], source_db)
if err != nil {
log.Fatal(fmt.Sprintf("ERROR: Open() SQL source(%v): %s", source_db, err))
}
defer db_src.Close()
db_dest, err = sql.Open(strings.Split(dest_db, ":")[0], dest_db)
if err != nil {
log.Fatal(fmt.Sprintf("ERROR: Open() SQL dest(%v): %s", dest_db, err))
}
defer db_dest.Close()
for _, tparams := range tables {
start = time.Now()
results, err = tparams.Sync(db_src, db_dest, verbosity)
if ! results.Failed {
fmt.Printf("%s: SUCCESS: INSERTS: %d; UPDATES: %d\n",
tparams.Table_Name, results.Inserts, results.Updates)
} else {
fmt.Printf("%s: FAILURE\n", tparams.Table_Name)
}
fmt.Printf("Duration: %.2fs\n", time.Since(start).Seconds())
}
}