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  }