Fixing database interaction + adding stored routine calls
This commit is contained in:
parent
b03e2d2af1
commit
c40d035f30
@ -51,6 +51,7 @@ func Init(router *mux.Router) {
|
|||||||
|
|
||||||
func apiRoot(w http.ResponseWriter, r *http.Request) {
|
func apiRoot(w http.ResponseWriter, r *http.Request) {
|
||||||
tStart := time.Now()
|
tStart := time.Now()
|
||||||
|
database.ExecuteStoredRoutine("test")
|
||||||
fmt.Fprintf(w, "API ROOT")
|
fmt.Fprintf(w, "API ROOT")
|
||||||
profiler.Add(profiler_API_PROCESS_REQUEST, time.Duration(time.Since(tStart).Microseconds()))
|
profiler.Add(profiler_API_PROCESS_REQUEST, time.Duration(time.Since(tStart).Microseconds()))
|
||||||
}
|
}
|
||||||
@ -66,7 +67,6 @@ func apiAuth(w http.ResponseWriter, r *http.Request) {
|
|||||||
func apiAuthLogin(w http.ResponseWriter, r *http.Request) {
|
func apiAuthLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
tStart := time.Now()
|
tStart := time.Now()
|
||||||
fmt.Fprintf(w, "API Auth Login")
|
fmt.Fprintf(w, "API Auth Login")
|
||||||
database.Ping()
|
|
||||||
profiler.Add(profiler_API_PROCESS_REQUEST, time.Duration(time.Since(tStart).Microseconds()))
|
profiler.Add(profiler_API_PROCESS_REQUEST, time.Duration(time.Since(tStart).Microseconds()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
@ -14,12 +15,18 @@ import (
|
|||||||
const (
|
const (
|
||||||
profiler_DATABASE_CONNECT string = "Database Connect"
|
profiler_DATABASE_CONNECT string = "Database Connect"
|
||||||
profiler_DATABASE_QUERY string = "Database Query"
|
profiler_DATABASE_QUERY string = "Database Query"
|
||||||
profiler_DATABASE_PING string = "Database Ping"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var db *sql.DB
|
const (
|
||||||
|
database_ROUTINE_TYPE_PROCEDURE uint8 = 1
|
||||||
|
database_ROUTINE_TYPE_FUNCTION uint8 = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
var dbPath string
|
||||||
var dbConfig config.Database
|
var dbConfig config.Database
|
||||||
var isInit bool
|
var isInit bool
|
||||||
|
var storedRoutines map[string]uint8
|
||||||
|
var db *sql.DB
|
||||||
|
|
||||||
func Init() {
|
func Init() {
|
||||||
if isInit {
|
if isInit {
|
||||||
@ -27,47 +34,21 @@ func Init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbConfig = config.GetConfig().Database
|
dbConfig = config.GetConfig().Database
|
||||||
|
dbPath = fmt.Sprintf("%s:%s@(%s:%d)/%s", dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Database)
|
||||||
|
|
||||||
profiler.Register(profiler_DATABASE_CONNECT, 20, "µs")
|
profiler.Register(profiler_DATABASE_CONNECT, 200, "µs")
|
||||||
profiler.Register(profiler_DATABASE_QUERY, 4000, "µs")
|
profiler.Register(profiler_DATABASE_QUERY, 4000, "µs")
|
||||||
profiler.Register(profiler_DATABASE_PING, 20, "µs")
|
|
||||||
|
|
||||||
isInit = true
|
isInit = true
|
||||||
|
fetchStoredRoutines()
|
||||||
Connect()
|
|
||||||
|
|
||||||
var query string = `SHOW GRANTS;`
|
|
||||||
var rows *sql.Rows = executeQuery(query)
|
|
||||||
if rows != nil {
|
|
||||||
defer rows.Close()
|
|
||||||
for rows.Next() {
|
|
||||||
var res string
|
|
||||||
rows.Scan(&res)
|
|
||||||
fmt.Println(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Terminate() {
|
func connect() {
|
||||||
isInit = false
|
|
||||||
if db != nil {
|
|
||||||
db.Close()
|
|
||||||
db = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Connect() {
|
|
||||||
if !isInit {
|
if !isInit {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if db != nil {
|
|
||||||
db.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var dbPath string = fmt.Sprintf("%s:%s@(%s:%d)/%s?parseTime=true", dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Database)
|
|
||||||
log.Printf("Connecting to database %s at %s:%d as %s\n", dbConfig.Database, dbConfig.Host, dbConfig.Port, dbConfig.User)
|
log.Printf("Connecting to database %s at %s:%d as %s\n", dbConfig.Database, dbConfig.Host, dbConfig.Port, dbConfig.User)
|
||||||
|
|
||||||
tStart := time.Now()
|
tStart := time.Now()
|
||||||
@ -77,82 +58,145 @@ func Connect() {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
log.Printf("Error while connecting the database [%d/%d] : %s\n", i+1, dbConfig.RetriesOnError, err)
|
log.Printf("Error while connecting the database [%d/%d] : %s\n", i+1, dbConfig.RetriesOnError, err)
|
||||||
|
if i+1 == dbConfig.RetriesOnError {
|
||||||
|
break
|
||||||
|
}
|
||||||
time.Sleep((time.Duration)(dbConfig.TimeBetweenRetriesMs) * time.Millisecond)
|
time.Sleep((time.Duration)(dbConfig.TimeBetweenRetriesMs) * time.Millisecond)
|
||||||
}
|
}
|
||||||
profiler.Add(profiler_DATABASE_CONNECT, time.Duration(time.Since(tStart).Microseconds()))
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Cannot connect to database !")
|
log.Fatalln("Cannot connect to database !")
|
||||||
}
|
}
|
||||||
|
|
||||||
Ping()
|
db.SetConnMaxLifetime(time.Minute * 1)
|
||||||
|
db.SetMaxOpenConns(100)
|
||||||
|
db.SetMaxIdleConns(100)
|
||||||
|
|
||||||
|
ping()
|
||||||
|
|
||||||
|
profiler.Add(profiler_DATABASE_CONNECT, time.Duration(time.Since(tStart).Microseconds()))
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Disconnect() {
|
func ExecuteStoredRoutine(name string, args ...any) {
|
||||||
if !isInit {
|
if !isInit {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if storedRoutines == nil {
|
||||||
|
fetchStoredRoutines()
|
||||||
|
}
|
||||||
|
|
||||||
if db == nil {
|
var exist bool
|
||||||
|
var routineType uint8
|
||||||
|
routineType, exist = storedRoutines[name]
|
||||||
|
if !exist {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
db.Close()
|
switch routineType {
|
||||||
|
case database_ROUTINE_TYPE_PROCEDURE:
|
||||||
|
callStoredProcedure(name, args...)
|
||||||
|
case database_ROUTINE_TYPE_FUNCTION:
|
||||||
|
callStoredFunction(name, args...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Ping() {
|
func ping() {
|
||||||
if !isInit {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if db == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
tStart := time.Now()
|
|
||||||
for i := range dbConfig.RetriesOnError {
|
for i := range dbConfig.RetriesOnError {
|
||||||
err = db.Ping()
|
err = db.Ping()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
log.Printf("Error while pinging the database [%d/%d] : %s\n", i+1, dbConfig.RetriesOnError, err)
|
log.Printf("Error while pinging the database [%d/%d] : %s\n", i+1, dbConfig.RetriesOnError, err)
|
||||||
|
if i+1 == dbConfig.RetriesOnError {
|
||||||
|
break
|
||||||
|
}
|
||||||
time.Sleep((time.Duration)(dbConfig.TimeBetweenRetriesMs) * time.Millisecond)
|
time.Sleep((time.Duration)(dbConfig.TimeBetweenRetriesMs) * time.Millisecond)
|
||||||
}
|
}
|
||||||
profiler.Add(profiler_DATABASE_PING, time.Duration(time.Since(tStart).Microseconds()))
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Cannot ping the database !")
|
log.Fatalln("Cannot ping the database !")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeQuery(query string) *sql.Rows {
|
func executeQuery(query string, args ...any) *sql.Rows {
|
||||||
if !isInit {
|
if !isInit {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if db == nil {
|
if db == nil {
|
||||||
return nil
|
connect()
|
||||||
}
|
}
|
||||||
|
|
||||||
Ping()
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var rows *sql.Rows
|
var rows *sql.Rows
|
||||||
tStart := time.Now()
|
tStart := time.Now()
|
||||||
for i := range dbConfig.RetriesOnError {
|
for i := range dbConfig.RetriesOnError {
|
||||||
rows, err = db.Query(query)
|
rows, err = db.Query(query, args...)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
log.Printf("Error while querying the database [%d/%d] : %s\n", i+1, dbConfig.RetriesOnError, err)
|
log.Printf("Error while querying the database [%d/%d] : %s\n", i+1, dbConfig.RetriesOnError, err)
|
||||||
|
if i+1 == dbConfig.RetriesOnError {
|
||||||
|
break
|
||||||
|
}
|
||||||
time.Sleep((time.Duration)(dbConfig.TimeBetweenRetriesMs) * time.Millisecond)
|
time.Sleep((time.Duration)(dbConfig.TimeBetweenRetriesMs) * time.Millisecond)
|
||||||
|
ping()
|
||||||
}
|
}
|
||||||
profiler.Add(profiler_DATABASE_QUERY, time.Duration(time.Since(tStart).Microseconds()))
|
profiler.Add(profiler_DATABASE_QUERY, time.Duration(time.Since(tStart).Microseconds()))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Cannot query the database !")
|
log.Printf("Cannot query the database ! (Query : %s) with args ", query)
|
||||||
|
log.Fatalln(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return rows
|
return rows
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fetchStoredRoutines() {
|
||||||
|
storedRoutines = nil
|
||||||
|
var query string = fmt.Sprintf("SELECT ROUTINE_NAME, ROUTINE_TYPE FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA=\"%s\";", dbConfig.Database)
|
||||||
|
var rows *sql.Rows = executeQuery(query)
|
||||||
|
if rows != nil {
|
||||||
|
storedRoutines = make(map[string]uint8, 0)
|
||||||
|
defer rows.Close()
|
||||||
|
for rows.Next() {
|
||||||
|
var resName, resType string
|
||||||
|
rows.Scan(&resName, &resType)
|
||||||
|
switch resType {
|
||||||
|
case "PROCEDURE":
|
||||||
|
storedRoutines[resName] = database_ROUTINE_TYPE_PROCEDURE
|
||||||
|
case "FUNCTION":
|
||||||
|
storedRoutines[resName] = database_ROUTINE_TYPE_FUNCTION
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println(storedRoutines)
|
||||||
|
}
|
||||||
|
|
||||||
|
func callStoredProcedure(name string, args ...any) {
|
||||||
|
var query string
|
||||||
|
if len(args) == 0 {
|
||||||
|
query = fmt.Sprintf("CALL %s()", name)
|
||||||
|
} else if len(args) == 1 {
|
||||||
|
query = fmt.Sprintf("CALL %s(?)", name)
|
||||||
|
} else {
|
||||||
|
query = strings.Repeat(", ?", len(args)-1)
|
||||||
|
query = fmt.Sprintf("CALL %s(?%s)", name, query)
|
||||||
|
}
|
||||||
|
|
||||||
|
var rows *sql.Rows = executeQuery(query, args...)
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var res string
|
||||||
|
rows.Scan(&res)
|
||||||
|
log.Println(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func callStoredFunction(name string, args ...any) {
|
||||||
|
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user