/reform-db/main.go

https://github.com/go-reform/reform · Go · 152 lines · 124 code · 24 blank · 4 comment · 31 complexity · 64af0d227506730cdd039404ec152155 MD5 · raw file

  1. // Package reform-db implements reform-db command.
  2. package main
  3. import (
  4. "database/sql"
  5. "flag"
  6. "fmt"
  7. "os"
  8. "path/filepath"
  9. "strings"
  10. "time"
  11. _ "github.com/denisenkom/go-mssqldb"
  12. _ "github.com/go-sql-driver/mysql"
  13. _ "github.com/jackc/pgx/stdlib"
  14. _ "github.com/lib/pq"
  15. _ "github.com/mattn/go-sqlite3"
  16. "gopkg.in/reform.v1"
  17. "gopkg.in/reform.v1/dialects"
  18. "gopkg.in/reform.v1/internal"
  19. )
  20. var (
  21. logger *internal.Logger
  22. debugF = flag.Bool("debug", false, "Enable debug logging")
  23. driverF = flag.String("db-driver", "", "Database driver (required)")
  24. sourceF = flag.String("db-source", "", "Database connection string (required)")
  25. waitF = flag.Duration("db-wait", 0, "Wait for database connection to be established, retrying every second")
  26. versionF = flag.Bool("version", false, "Print version and exit")
  27. )
  28. func init() {
  29. flag.Usage = func() {
  30. fmt.Fprintf(os.Stderr, "reform-db - a better ORM tool. %s.\n\n", reform.Version)
  31. fmt.Fprintf(os.Stderr, "Usage:\n")
  32. fmt.Fprintf(os.Stderr, " %s [global flags] [command] [command flags] [arguments]\n\n", os.Args[0])
  33. fmt.Fprintf(os.Stderr, "Global flags:\n")
  34. flag.PrintDefaults()
  35. fmt.Fprintf(os.Stderr, "\nCommands (run reform-db [command] -h for more information):\n")
  36. fmt.Fprintf(os.Stderr, " exec - executes SQL queries from given files or stdin\n")
  37. fmt.Fprintf(os.Stderr, " query - executes SQL queries from given files or stdin, and returns results\n")
  38. fmt.Fprintf(os.Stderr, " init - generates Go model files for existing database schema\n\n")
  39. fmt.Fprintf(os.Stderr, "Registered database drivers: %s.\n", strings.Join(sql.Drivers(), ", "))
  40. }
  41. }
  42. func getDB() *reform.DB {
  43. if *driverF == "" || *sourceF == "" {
  44. logger.Fatalf("Please set both -db-driver and -db-source flags.")
  45. }
  46. sqlDB, err := sql.Open(*driverF, *sourceF)
  47. if err != nil {
  48. logger.Fatalf("Failed to connect to %s %q: %s", *driverF, *sourceF, err)
  49. }
  50. // Use single connection so various session-related variables work.
  51. // For example: "PRAGMA foreign_keys" for SQLite3, "SET IDENTITY_INSERT" for MS SQL, etc.
  52. sqlDB.SetMaxIdleConns(1)
  53. sqlDB.SetMaxOpenConns(1)
  54. sqlDB.SetConnMaxLifetime(0)
  55. start := time.Now()
  56. for {
  57. err = sqlDB.Ping()
  58. if err == nil {
  59. break
  60. }
  61. if time.Since(start) > *waitF {
  62. logger.Fatalf("Failed to ping database: %s.", err)
  63. }
  64. logger.Debugf("Failed to ping database: %s.", err)
  65. time.Sleep(time.Second)
  66. }
  67. logger.Debugf("Connected to database.")
  68. dialect := dialects.ForDriver(*driverF)
  69. return reform.NewDB(sqlDB, dialect, reform.NewPrintfLogger(logger.Debugf))
  70. }
  71. func main() {
  72. flag.Parse()
  73. if *versionF {
  74. fmt.Println(reform.Version)
  75. os.Exit(0)
  76. }
  77. if flag.NArg() == 0 {
  78. flag.Usage()
  79. os.Exit(1)
  80. }
  81. *driverF = strings.TrimSpace(*driverF)
  82. *sourceF = strings.TrimSpace(*sourceF)
  83. logger = internal.NewLogger("reform-db: ", *debugF)
  84. // flagsets used below are created with ExitOnError, so Parse() is not expected to return errors
  85. switch flag.Arg(0) {
  86. case "exec":
  87. if err := execFlags.Parse(flag.Args()[1:]); err != nil {
  88. panic(err)
  89. }
  90. cmdExec(getDB(), execFlags.Args())
  91. case "query":
  92. if err := queryFlags.Parse(flag.Args()[1:]); err != nil {
  93. panic(err)
  94. }
  95. cmdQuery(getDB(), queryFlags.Args())
  96. case "init":
  97. if err := initFlags.Parse(flag.Args()[1:]); err != nil {
  98. panic(err)
  99. }
  100. if initFlags.NArg() > 1 {
  101. logger.Fatalf("Expected zero or one argument for %q, got %d", "init", initFlags.NArg())
  102. }
  103. dir := initFlags.Arg(0)
  104. var err error
  105. if dir == "" {
  106. if dir, err = os.Getwd(); err != nil {
  107. logger.Fatalf("%s", err)
  108. }
  109. }
  110. if dir, err = filepath.Abs(dir); err != nil {
  111. logger.Fatalf("%s", err)
  112. }
  113. fi, err := os.Stat(dir)
  114. if os.IsNotExist(err) {
  115. logger.Fatalf("%q should be existing directory", dir)
  116. }
  117. if err != nil {
  118. logger.Fatalf("%s", err)
  119. }
  120. if !fi.IsDir() {
  121. logger.Fatalf("%q should be existing directory", dir)
  122. }
  123. cmdInit(getDB(), dir)
  124. default:
  125. flag.Usage()
  126. logger.Fatalf("Unexpected command %q", flag.Arg(0))
  127. }
  128. }