You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
6.1 KiB
Go
216 lines
6.1 KiB
Go
package db
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
_ "github.com/go-sql-driver/mysql"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
dbCredsEnvName = "DB_CREDS"
|
|
dbCredsHostName = "DB_HOST"
|
|
dsnTemplate = "dtookey:%s@tcp(%s)/%s?parseTime=true"
|
|
|
|
ClarityDatabaseName = "projects"
|
|
InsightDatabaseName = "insight"
|
|
MercuryDatabaseName = "mercury"
|
|
)
|
|
|
|
//<editor-fold name="ConnectorGeneric">
|
|
/*======================================================================================
|
|
ConnectorGeneric
|
|
======================================================================================*/
|
|
|
|
type Blocker interface {
|
|
ToQueryBlock() string
|
|
}
|
|
|
|
type ConnectorGeneric struct {
|
|
cachedConnection *sql.DB
|
|
}
|
|
|
|
type SqlScriptRunner struct {
|
|
ScriptName string
|
|
DatabaseName string
|
|
}
|
|
|
|
func (c *ConnectorGeneric) ExecuteSqlScript(runner *SqlScriptRunner) {
|
|
c.startConnection(runner.DatabaseName)
|
|
defer c.returnConnection()
|
|
queryWhole := *loadSqlFile(runner.ScriptName)
|
|
queryParts := strings.Split(queryWhole, ";")
|
|
|
|
log.Printf("\n=============================================\n%s\n==============================================\n", queryWhole)
|
|
|
|
for _, query := range queryParts {
|
|
if len(query) == 0 || query == "\n" {
|
|
continue
|
|
}
|
|
_, err := c.cachedConnection.Exec(query + ";")
|
|
if err != nil {
|
|
log.Printf("Query involved in error: %s\n", query)
|
|
log.Panic(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c *ConnectorGeneric) ExecuteString(dbName string, payload string) {
|
|
c.startConnection(dbName)
|
|
defer c.returnConnection()
|
|
|
|
//log.Println("==================================================================================================")
|
|
//log.Println(payload)
|
|
//log.Println("==================================================================================================")
|
|
|
|
_, err := c.cachedConnection.Exec(payload)
|
|
if err != nil {
|
|
log.Printf("Query involved in error: %s\n", payload)
|
|
log.Panic(err)
|
|
}
|
|
}
|
|
|
|
// startConnection this initializes, caches, and returns a connection for the desired database. If a connection already exists,
|
|
// it will be terminated and a new connection will be opened.
|
|
func (c *ConnectorGeneric) startConnection(dataBase string) {
|
|
if c.cachedConnection != nil {
|
|
c.returnConnection()
|
|
}
|
|
db := createDbConnection(dataBase)
|
|
c.cachedConnection = db
|
|
}
|
|
|
|
// returnConnection This just closes the cached db connection
|
|
func (c *ConnectorGeneric) returnConnection() {
|
|
err := c.cachedConnection.Close()
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
c.cachedConnection = nil
|
|
}
|
|
|
|
func (c *ConnectorGeneric) QueryFromScript(scriptName string) *sql.Rows {
|
|
query := loadSqlFile(scriptName)
|
|
rows, err := c.cachedConnection.Query(*query)
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
return rows
|
|
}
|
|
|
|
func (c *ConnectorGeneric) ProcessClarityScripts() { //@dream standardize these script names
|
|
tableCreationRunners := []*SqlScriptRunner{
|
|
NewRunner("0-run-first/1-sanitize_init.sql", ClarityDatabaseName),
|
|
NewRunner("0-run-first/all_projects.sql", ClarityDatabaseName),
|
|
NewRunner("0-run-first/billing.sql", ClarityDatabaseName),
|
|
NewRunner("0-run-first/contributions.sql", ClarityDatabaseName),
|
|
NewRunner("0-run-first/durations.sql", ClarityDatabaseName),
|
|
NewRunner("0-run-first/lifecycle.sql", ClarityDatabaseName),
|
|
}
|
|
|
|
for _, runner := range tableCreationRunners {
|
|
c.ExecuteSqlScript(runner)
|
|
}
|
|
}
|
|
|
|
func (c *ConnectorGeneric) CreateTables() {
|
|
tableCreationRunners := []*SqlScriptRunner{
|
|
NewRunner("create-any-database.sql", ""),
|
|
NewRunner("create-insight-user-table.sql", InsightDatabaseName),
|
|
NewRunner("create-insight-timeEntry-table.sql", InsightDatabaseName),
|
|
NewRunner("create-mercury-picturePatterns-table.sql", MercuryDatabaseName),
|
|
NewRunner("create-mercury-arReports-table.sql", MercuryDatabaseName),
|
|
NewRunner("create-mercury-telecomVoice-table.sql", MercuryDatabaseName),
|
|
NewRunner("create-mercury-failedReview-view.sql", MercuryDatabaseName),
|
|
}
|
|
|
|
for _, runner := range tableCreationRunners {
|
|
c.ExecuteSqlScript(runner)
|
|
}
|
|
}
|
|
|
|
//</editor-fold>
|
|
|
|
//<editor-fold name="Utility Functions">
|
|
/*======================================================================================
|
|
Utility Functions
|
|
======================================================================================*/
|
|
|
|
func createDbConnection(database string) *sql.DB {
|
|
cred := os.Getenv(dbCredsEnvName)
|
|
host := os.Getenv(dbCredsHostName)
|
|
dbString := dsnTemplate
|
|
connectString := fmt.Sprintf(dbString, cred, host, database)
|
|
fmt.Printf("Beginning connection to database\n")
|
|
|
|
db, err := sql.Open("mysql", connectString)
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
return db
|
|
}
|
|
|
|
func loadSqlFile(scriptName string) *string {
|
|
file, err := os.OpenFile("src/sql/"+scriptName, os.O_RDONLY, 0755)
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
defer file.Close()
|
|
raw, err := ioutil.ReadAll(file)
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
str := strings.Trim(string(raw), "\n")
|
|
return &str
|
|
}
|
|
|
|
func QueryForObjects[K any](db *ConnectorGeneric, dbName string, queryScript string, mapping func(rows *sql.Rows) *K) *[]*K {
|
|
rs := make([]*K, 0, 10000)
|
|
db.startConnection(dbName)
|
|
defer db.returnConnection()
|
|
|
|
res := db.QueryFromScript(queryScript)
|
|
for res.Next() {
|
|
o := mapping(res)
|
|
rs = append(rs, o)
|
|
}
|
|
|
|
return &rs
|
|
}
|
|
|
|
func BulkUpdate[K any](connector *ConnectorGeneric, dbName string, updateScript string, items *[]*K, mapping func(s *sql.Stmt, item *K)) {
|
|
connector.startConnection(dbName)
|
|
defer connector.returnConnection()
|
|
statement := loadSqlFile(updateScript)
|
|
s, err := connector.cachedConnection.Prepare(*statement)
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
for _, item := range *items {
|
|
mapping(s, item)
|
|
}
|
|
}
|
|
|
|
func BlockUpdate[K Blocker](connector *ConnectorGeneric, dbName string, updateScript string, items *[]*K) {
|
|
template := loadSqlFile(updateScript)
|
|
buff := strings.Builder{}
|
|
l := len(*items)
|
|
for i, item := range *items {
|
|
buff.WriteString((*item).ToQueryBlock())
|
|
if i < l-1 {
|
|
buff.WriteByte(',')
|
|
}
|
|
}
|
|
query := fmt.Sprintf(*template, buff.String())
|
|
connector.ExecuteString(dbName, query)
|
|
}
|
|
|
|
func NewRunner(scriptName string, databaseName string) *SqlScriptRunner {
|
|
return &SqlScriptRunner{scriptName, databaseName}
|
|
}
|
|
|
|
//</editor-fold>
|