github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/install/mysql.go (about) 1 /* 2 * 3 * Gosora MySQL Interface 4 * Copyright Azareal 2017 - 2020 5 * 6 */ 7 package install 8 9 import ( 10 "bytes" 11 "database/sql" 12 "fmt" 13 "io/ioutil" 14 "os" 15 "path/filepath" 16 "strconv" 17 "strings" 18 19 "github.com/Azareal/Gosora/query_gen" 20 _ "github.com/go-sql-driver/mysql" 21 ) 22 23 //var dbCollation string = "utf8mb4_general_ci" 24 25 func init() { 26 adapters["mysql"] = &MysqlInstaller{dbHost: ""} 27 } 28 29 type MysqlInstaller struct { 30 db *sql.DB 31 dbHost string 32 dbUsername string 33 dbPassword string 34 dbName string 35 dbPort string 36 } 37 38 func (ins *MysqlInstaller) SetConfig(dbHost string, dbUsername string, dbPassword string, dbName string, dbPort string) { 39 ins.dbHost = dbHost 40 ins.dbUsername = dbUsername 41 ins.dbPassword = dbPassword 42 ins.dbName = dbName 43 ins.dbPort = dbPort 44 } 45 46 func (ins *MysqlInstaller) Name() string { 47 return "mysql" 48 } 49 50 func (ins *MysqlInstaller) DefaultPort() string { 51 return "3306" 52 } 53 54 func (ins *MysqlInstaller) dbExists(dbName string) (bool, error) { 55 var waste string 56 err := ins.db.QueryRow("SHOW DATABASES LIKE '" + dbName + "'").Scan(&waste) 57 if err != nil && err != sql.ErrNoRows { 58 return false, err 59 } else if err == sql.ErrNoRows { 60 return false, nil 61 } 62 return true, nil 63 } 64 65 func (ins *MysqlInstaller) InitDatabase() (err error) { 66 _dbPassword := ins.dbPassword 67 if _dbPassword != "" { 68 _dbPassword = ":" + _dbPassword 69 } 70 db, err := sql.Open("mysql", ins.dbUsername+_dbPassword+"@tcp("+ins.dbHost+":"+ins.dbPort+")/") 71 if err != nil { 72 return err 73 } 74 75 // Make sure that the connection is alive.. 76 err = db.Ping() 77 if err != nil { 78 return err 79 } 80 fmt.Println("Successfully connected to the database") 81 82 ins.db = db 83 ok, err := ins.dbExists(ins.dbName) 84 if err != nil { 85 return err 86 } 87 88 if !ok { 89 fmt.Println("Unable to find the database. Attempting to create it") 90 _, err = db.Exec("CREATE DATABASE IF NOT EXISTS " + ins.dbName) 91 if err != nil { 92 return err 93 } 94 fmt.Println("The database was successfully created") 95 } 96 97 /*fmt.Println("Switching to database ", ins.dbName) 98 _, err = db.Exec("USE " + ins.dbName) 99 if err != nil { 100 return err 101 }*/ 102 db.Close() 103 104 db, err = sql.Open("mysql", ins.dbUsername+_dbPassword+"@tcp("+ins.dbHost+":"+ins.dbPort+")/"+ins.dbName) 105 if err != nil { 106 return err 107 } 108 109 // Make sure that the connection is alive.. 110 err = db.Ping() 111 if err != nil { 112 return err 113 } 114 fmt.Println("Successfully connected to the database") 115 116 // Ready the query builder 117 ins.db = db 118 qgen.Builder.SetConn(db) 119 return qgen.Builder.SetAdapter("mysql") 120 } 121 122 func (ins *MysqlInstaller) createTable(f os.FileInfo) error { 123 table := strings.TrimPrefix(f.Name(), "query_") 124 ext := filepath.Ext(table) 125 if ext != ".sql" { 126 return nil 127 } 128 table = strings.TrimSuffix(table, ext) 129 130 // ? - This is mainly here for tests, although it might allow the installer to overwrite a production database, so we might want to proceed with caution 131 q := "DROP TABLE IF EXISTS `" + table + "`;" 132 _, err := ins.db.Exec(q) 133 if err != nil { 134 fmt.Println("Failed query:", q) 135 fmt.Println("e:", err) 136 return err 137 } 138 139 data, err := ioutil.ReadFile("./schema/mysql/" + f.Name()) 140 if err != nil { 141 return err 142 } 143 data = bytes.TrimSpace(data) 144 145 q = string(data) 146 _, err = ins.db.Exec(q) 147 if err != nil { 148 fmt.Println("Failed query:", q) 149 fmt.Println("e:", err) 150 return err 151 } 152 fmt.Printf("Created table '%s'\n", table) 153 154 return nil 155 } 156 157 func (ins *MysqlInstaller) TableDefs() (err error) { 158 fmt.Println("Creating the tables") 159 files, err := ioutil.ReadDir("./schema/mysql/") 160 if err != nil { 161 return err 162 } 163 164 _, err = ins.db.Exec("SET FOREIGN_KEY_CHECKS = 0;") 165 if err != nil { 166 return err 167 } 168 169 for _, f := range files { 170 if !strings.HasPrefix(f.Name(), "query_") { 171 continue 172 } 173 err := ins.createTable(f) 174 if err != nil { 175 return err 176 } 177 } 178 179 _, err = ins.db.Exec("SET FOREIGN_KEY_CHECKS = 1;") 180 return err 181 } 182 183 // ? - Moved this here since it was breaking the installer, we need to add this at some point 184 /* TODO: Implement the html-attribute setting type before deploying this */ 185 /*INSERT INTO settings(`name`,`content`,`type`) VALUES ('meta_desc','','html-attribute');*/ 186 187 func (ins *MysqlInstaller) InitialData() error { 188 fmt.Println("Seeding the tables") 189 data, err := ioutil.ReadFile("./schema/mysql/inserts.sql") 190 if err != nil { 191 return err 192 } 193 data = bytes.TrimSpace(data) 194 195 statements := bytes.Split(data, []byte(";")) 196 for key, sBytes := range statements { 197 statement := string(sBytes) 198 if statement == "" { 199 continue 200 } 201 statement += ";" 202 203 fmt.Println("Executing query #" + strconv.Itoa(key) + " " + statement) 204 _, err = ins.db.Exec(statement) 205 if err != nil { 206 return err 207 } 208 } 209 return nil 210 } 211 212 func (ins *MysqlInstaller) CreateAdmin() error { 213 return createAdmin() 214 } 215 216 func (ins *MysqlInstaller) DBHost() string { 217 return ins.dbHost 218 } 219 220 func (ins *MysqlInstaller) DBUsername() string { 221 return ins.dbUsername 222 } 223 224 func (ins *MysqlInstaller) DBPassword() string { 225 return ins.dbPassword 226 } 227 228 func (ins *MysqlInstaller) DBName() string { 229 return ins.dbName 230 } 231 232 func (ins *MysqlInstaller) DBPort() string { 233 return ins.dbPort 234 }