// CreateDSN creates a DSN (data source name) string out of hostname, username, // password, and timeout. It validates the resulting DSN and returns an error // if the DSN is invalid. func CreateDSN(host, username, password string, timeout time.Duration) (string, error) { // Example: [username[:password]@][protocol[(address)]]/ dsn := host if username != "" || password != "" { dsn = "@" + dsn } if password != "" { dsn = ":" + password + dsn } if username != "" { dsn = username + dsn } config, err := mysql.ParseDSN(dsn) if err != nil { return "", errors.Wrapf(err, "config error for host '%s'", host) } if timeout > 0 { // Add connection timeouts to the DSN. config.Timeout = timeout config.ReadTimeout = timeout config.WriteTimeout = timeout } return config.FormatDSN(), nil }
func getDSNTag(dsn string) string { conf, err := mysql.ParseDSN(dsn) if err != nil { return "127.0.0.1:3306" } return conf.Addr }
func dsnAddTimeout(dsn string) (string, error) { conf, err := mysql.ParseDSN(dsn) if err != nil { return "", err } if conf.Timeout == 0 { conf.Timeout = time.Second * 5 } return conf.FormatDSN(), nil }
// NewDbMap creates the root gorp mapping object. Create one of these for each // database schema you wish to map. Each DbMap contains a list of mapped // tables. It automatically maps the tables for the primary parts of Boulder // around the Storage Authority. func NewDbMap(dbConnect string, maxOpenConns int) (*gorp.DbMap, error) { var err error var config *mysql.Config if strings.HasPrefix(dbConnect, "mysql+tcp://") { dbConnect, err = recombineCustomMySQLURL(dbConnect) if err != nil { return nil, err } } config, err = mysql.ParseDSN(dbConnect) if err != nil { return nil, err } return NewDbMapFromConfig(config, maxOpenConns) }
func init() { migrationsPath := "" mysql.Init(func(c *mysql.Config) { parse.Populate(c, config.Conf, "mysql") migrationsPath = c.MigrationsPath c2, err := mysqlReal.ParseDSN(c.ConnectString) if err == nil { Info.Printf("Attempting to connect to %s@%s\n", c2.User, c2.Addr) } else { Error.Println("Error parsing DSN:", c.ConnectString) } }) if migrationsPath != "" { mysql.Migrate(migrationsPath) } }
// ParseDSN creates a DSN (data source name) string by parsing the host. // It validates the resulting DSN and returns an error if the DSN is invalid. // // Format: [username[:password]@][protocol[(address)]]/ // Example: root:test@tcp(127.0.0.1:3306)/ func ParseDSN(mod mb.Module, host string) (mb.HostData, error) { c := struct { Username string `config:"username"` Password string `config:"password"` }{} if err := mod.UnpackConfig(&c); err != nil { return mb.HostData{}, err } config, err := mysql.ParseDSN(host) if err != nil { return mb.HostData{}, errors.Wrapf(err, "error parsing mysql host") } if config.User == "" { config.User = c.Username } if config.Passwd == "" { config.Passwd = c.Password } // Add connection timeouts to the DSN. if timeout := mod.Config().Timeout; timeout > 0 { config.Timeout = timeout config.ReadTimeout = timeout config.WriteTimeout = timeout } noCredentialsConfig := *config noCredentialsConfig.User = "" noCredentialsConfig.Passwd = "" return mb.HostData{ URI: config.FormatDSN(), SanitizedURI: noCredentialsConfig.FormatDSN(), Host: config.Addr, User: config.User, Password: config.Passwd, }, nil }
func openDB() *sql.DB { cfg, err := mysql.ParseDSN("") if err != nil { log.Printf("Error parsing null DSN: %s\n", err) } cfg.User = DBCreds.Username cfg.Passwd = DBCreds.Password cfg.Addr = DBCreds.Hostname + ":" + strconv.Itoa(DBCreds.Port) cfg.DBName = DBCreds.Name db, err := sql.Open("mysql", cfg.FormatDSN()) if err != nil { log.Printf("Error opening DB connection: %s\n", err) } if err = db.Ping(); err != nil { log.Printf("Error pinging DB: %s\n", err) } _, err = db.Exec("CREATE TABLE puzzles (ident VARCHAR(50) UNIQUE NOT NULL, author TEXT, solution TEXT, clues MEDIUMTEXT)") if err != nil && !strings.Contains(err.Error(), "Table 'puzzles' already exists") { log.Printf("Error creating table: %s\n", err) } return db }
// SetUpMySQLDatabase connects mysql container with given $connectURL and also creates a new database named $databaseName // A modified url used to connect the created database will be returned func SetUpMySQLDatabase(databaseName, connectURL string) (url string, err error) { if databaseName == defaultMySQLDBName { return connectURL, nil } db, err := sql.Open("mysql", connectURL) if err != nil { return "", err } defer db.Close() _, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", databaseName)) if err != nil { return "", err } // parse dsn config, err := mysql.ParseDSN(connectURL) if err != nil { return "", err } config.DBName = databaseName // overwrite database name return config.FormatDSN(), nil }
func dsnValidator(v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { dsn, err := mysql.ParseDSN(field.String()) return err == nil && dsn.ParseTime }
func main() { var origTargetDb, targetDb, tableNames, packageName string var tmplName string var driver, schemaName string var touchTimestamp, buildStruct, readPass, createTableMigration, requestVersion, rebuildAll bool var pCount int var structName string versionNum := "16.11.10" for _, arg := range os.Args { if arg == "--version" { fmt.Println("ModelQ Version", versionNum) return } } flag.StringVar(&origTargetDb, "db", "", "Target database source string: e.g. root@tcp(127.0.0.1:3306)/test?charset=utf-8") flag.StringVar(&tableNames, "tables", "", "You may specify which tables the models need to be created, e.g. \"user,article,blog\"") flag.StringVar(&packageName, "pkg", "models", "Go source code package for generated models") flag.StringVar(&driver, "driver", "mysql", "(default:mysql) Current supported drivers include mysql, postgres") flag.BoolVar(&rebuildAll, "rebuild-all", false, "rebuild everything with a _mq extension") flag.StringVar(&schemaName, "schema", "", "(default:detected from db string) Schema for postgresql, database name for mysql") flag.BoolVar(&touchTimestamp, "dont-touch-timestamp", false, "Should touch the datetime fields with default value or on update") flag.StringVar(&tmplName, "template", "", "Passing the template to generate code, or use the default one") flag.IntVar(&pCount, "p", 4, "Parallell running for code generator") flag.BoolVar(&gmq.Debug, "debug", false, "Debug on/off") flag.BoolVar(&buildStruct, "struct", false, "Generate the struct too") flag.BoolVar(&readPass, "pass", false, "Request db password from command line") flag.StringVar(&structName, "name", "", "Custom Struct name to use when generating structs. Only works on the first table") flag.BoolVar(&createTableMigration, "ct", false, "Create Table: Generate a migration file to create the table (requires mysqldump)") flag.BoolVar(&requestVersion, "-version", false, fmt.Sprintf("Version Number (matches release date) %s", versionNum)) flag.Parse() targetDb = string(origTargetDb) runtime.GOMAXPROCS(pCount) if targetDb == "" { fmt.Println("Please provide the target database source.") fmt.Println("Usage:") flag.PrintDefaults() return } if readPass { // break down the database as follows: // root:@tcp(localhost:3306)/dd // dbUser = root // dbHostPort = tcp(localhost:3306) // dbDatabase = dd reader := bufio.NewReader(os.Stdin) fmt.Print("Enter db password: "******"Error parsing DSN.") log.Fatal(err) } cfg.Passwd = pass targetDb = cfg.FormatDSN() // fmt.Println(targetDb) // This utilty doesn't work... dunno why. -Jeff // fmt.Printf("Enter database password: "******"AUTO_INCREMENT=\\d+") // this part executes a "mysqldmp --no-data command" and puts it into ./db/migrations cfg, err := mysql.ParseDSN(targetDb) if err != nil { log.Println("Error parsing DSN.") log.Fatal(err) } dbPort := 3306 dbHost := cfg.Addr if strings.Contains(cfg.Addr, ":") { dbHostPort := strings.Split(cfg.Addr, ":") dbHost = dbHostPort[0] var err error dbPort, err = strconv.Atoi(dbHostPort[1]) if err != nil { log.Println("Cannot parse port:", cfg.Addr) log.Fatal(err) return } } if dbHost == "localhost" { dbHost = "127.0.0.1" // apparently mysqldump doesn't like the word "localhost" -Jeff cfg.Addr = "127.0.0.1" } // targetDb2 := cfg.FormatDSN() // run mysqldump for each table for _, dbTable := range strings.Split(tableNames, ",") { //mySqlDumpCmd := fmt.Sprintf("mysqldump -u %s -p%s -h %s -P %d --no-data %s %s > db/migrations/%s.sql", cfg.User, cfg.Passwd, dbHost, dbPort, cfg.DBName, dbTable, dbTable) // this is the mysql string mySqlDumpCmd := fmt.Sprintf("mysqldump -u %s -p%s -h %s -P %d --no-data %s %s", cfg.User, cfg.Passwd, dbHost, dbPort, cfg.DBName, dbTable) // mySqlDumpCmd = fmt.Sprintf("mysql -u %s -p%s -h %s -P %d --batch --silent -e SHOW CREATE TABLE %s.%s;", cfg.User, cfg.Passwd, dbHost, dbPort, cfg.DBName, dbTable) // mySqlDumpCmd = fmt.Sprintf("mysql -u %s -p%s -h %s -P %d SHOW CREATE TABLE %s.%s;", cfg.User, cfg.Passwd, dbHost, dbPort, cfg.DBName, dbTable) mySqlDumpCmd = fmt.Sprintf("mysql -u %s -p%s -h %s -P %d --batch --silent -e", cfg.User, cfg.Passwd, dbHost, dbPort) mySqlDumpCmd2 := fmt.Sprintf("SHOW CREATE TABLE %s.%s;", cfg.DBName, dbTable) //mySqlDumpCmd2 := fmt.Sprintf("SHOW CREATE TABLE %s;", dbTable) // fmt.Println(mySqlDumpCmd) // we have to break it up into args for golang args := strings.Split(mySqlDumpCmd, " ") args = append(args, mySqlDumpCmd2) // execute and save the output data, err := exec.Command(args[0], args[1:]...).Output() // data, err := exec.Command("mysql" %s SHOW CREATE TABLE %s;", targetDb2, dbTable).Output() if err != nil { log.Println("Cannot run mysqldump:", mySqlDumpCmd) log.Fatal(err) return } // the newlines are shit, fix them s_data := strings.Replace(string(data), "\\n", "\n", -1) // fmt.Println(s_data) // for some dumbass reason, it places the table name in front of the create command, this removes it s_data = s_data[len(dbTable)+1:] // fmt.Println(s_data) dbTableWithHyphen := strings.Replace(dbTable, "_", "-", -1) dbTableWithoutUnderscores := strings.Replace(strings.Title(dbTable), "_", "", -1) // add the goose header and drop command header := `-- +goose Up -- name: drop-` + dbTableWithHyphen + `-table DROP TABLE IF EXISTS ` + "`" + dbTable + "`" + `; -- name: create-` + dbTableWithHyphen + `-table ` s_data = fmt.Sprintf("%s%s;", header, s_data) s_data = re_autoinc.ReplaceAllString(s_data, "AUTO_INCREMENT=1") // fmt.Println(s_data) filename := fmt.Sprintf("db/migrations/%s.sql", dbTableWithoutUnderscores) // files, err := ioutil.ReadDir("db/migrations") if err != nil { log.Fatal(err) } fnameMatches := strings.ToLower(fmt.Sprintf("Create%sTable.sql", dbTableWithoutUnderscores)) // fmt.Println(fnameMatches) for _, file := range files { // fmt.Println(strings.ToLower(file.Name())) if strings.Contains(strings.ToLower(file.Name()), fnameMatches) { filename = fmt.Sprintf("db/migrations/%s", file.Name()) fmt.Println("found matching file name", filename) break } } // write the file f, err := os.Create(filename) if err != nil { log.Println("Cannot open output file:", filename) log.Fatal(err) return } defer f.Close() f.Write([]byte(s_data)) } } if packageName == "" { printUsages("Please provide the go source code package name for generated models.") return } if driver != "mysql" && driver != "postgres" { printUsages("Current supported drivers include mysql, postgres.") return } if schemaName == "" { dbParts := strings.Split(targetDb, "/") suffexes := strings.Split(dbParts[len(dbParts)-1], "?") schemaName = suffexes[0] if schemaName == "" { printUsages("Please provide the schema namee.") return } } newOsArgs := append([]string{}, os.Args...) for idx, osArg := range newOsArgs { if len(osArg) > 3 && osArg[0:3] == "-db" { newOsArgs[idx] = `-db="` + origTargetDb + `"` break } } if rebuildAll { nameRegexp := regexp.MustCompile(`-name=(\S+)`) tablesRegexp := regexp.MustCompile(`-tables=(\S+)`) files, err := ioutil.ReadDir(packageName + "/") if err != nil { log.Fatal(err) } for _, fileInfo := range files { fnameLower := strings.ToLower(fileInfo.Name()) if strings.Contains(fnameLower, "_mq.go") { modelNameFromFile := fnameLower[:len(fnameLower)-6] // peel off "_mq.go" fmt.Println(fileInfo.Name(), modelNameFromFile) // when table and model match, there's no "-name=" ... only "-tables=" nameParam := "" tableParam := modelNameFromFile // let's pars the file to see if the modelq execution command has -name // open the file for reading; yes, FileInfo is retarded -- you can't open it directly file, err := os.Open(packageName + "/" + fileInfo.Name()) if err != nil { log.Fatal(err) } defer file.Close() // read the lines scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() // find the modelq execution one (should say "modelq" and "-tabels" ... can add more for certainty if strings.Contains(line, "modelq") && strings.Contains(line, "-tables") { fmt.Println(line) // see if it has the -name param if strings.Contains(line, "-name") { fmt.Println("nameee", nameParam) // get the part with the name nameParam = nameRegexp.FindStringSubmatch(line)[1] // see model matches the -name; otherwise it's a different table in the same run if nameParam == modelNameFromFile { // by rule, if using -name, then table param is required to be the first one tableParam = strings.Split(tablesRegexp.FindStringSubmatch(line)[1], ",")[0] // the first table name } else { // nope, disregard the name param, it's the wrong model nameParam = "" } } break } } var executionString string if len(nameParam) > 0 { executionString = fmt.Sprintf("modelq -db=%s -tables=%s -name=%s -struct=%t", origTargetDb, tableParam, nameParam, buildStruct) } else { executionString = fmt.Sprintf("modelq -db=%s -tables=%s -struct=%t", origTargetDb, tableParam, buildStruct) } fmt.Println(" " + executionString) // do the work dbSchema, err := drivers.LoadDatabaseSchema(driver, targetDb, schemaName, tableParam) if err != nil { log.Println("Cannot load table schemas from database.") log.Fatal(err) } codeConfig := &CodeConfig{ packageName: packageName, touchTimestamp: touchTimestamp, template: tmplName, buildStuct: buildStruct, ExecutionString: executionString, ExecutionDate: time.Now(), } codeConfig.MustCompileTemplate() generateModels(schemaName, dbSchema, *codeConfig, nameParam) formatCodes(packageName) } } } else { dbSchema, err := drivers.LoadDatabaseSchema(driver, targetDb, schemaName, tableNames) if err != nil { log.Println("Cannot load table schemas from database.") log.Fatal(err) } executionString := fmt.Sprintf("modelq %s", strings.Join(newOsArgs[1:], " ")) codeConfig := &CodeConfig{ packageName: packageName, touchTimestamp: touchTimestamp, template: tmplName, buildStuct: buildStruct, ExecutionString: executionString, ExecutionDate: time.Now(), } codeConfig.MustCompileTemplate() generateModels(schemaName, dbSchema, *codeConfig, structName) formatCodes(packageName) } }