-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
267 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module example | ||
|
||
go 1.19 | ||
|
||
require ( | ||
github.com/alfarih31/nb-go-env v1.0.4 // indirect | ||
github.com/alfarih31/nb-go-parser v1.0.11 // indirect | ||
github.com/joho/godotenv v1.5.1 // indirect | ||
github.com/lib/pq v1.10.9 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
github.com/alfarih31/nb-go-env v1.0.4 h1:jIrQUsunn9uUMecqHQaK1lMJ3XgEqa420HQSJkUkTlg= | ||
github.com/alfarih31/nb-go-env v1.0.4/go.mod h1:oPDLWPYpw2X/NVLoJfhr5KzZ3Wy+UPxKktOBIk7TL5s= | ||
github.com/alfarih31/nb-go-parser v1.0.11 h1:jW+pU/UH1pBwP/HSavsGhsVmIzEDS6cvmLiAAheKaao= | ||
github.com/alfarih31/nb-go-parser v1.0.11/go.mod h1:0+2qf5oT5sEy4qyNxY/ewsREpHtUYfis3/bERolDFGI= | ||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= | ||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= | ||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= | ||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package main | ||
|
||
import ( | ||
"database/sql" | ||
"fmt" | ||
env2 "github.com/alfarih31/nb-go-env" | ||
sql_config_server "github.com/alfarih31/nb-go-env/sql-config-server" | ||
_ "github.com/lib/pq" | ||
) | ||
|
||
const ( | ||
host = "localhost" | ||
port = 5432 | ||
user = "postgres" | ||
password = "postgres" | ||
dbname = "postgres" | ||
namespace = "example" | ||
) | ||
|
||
func CheckError(err error) { | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
func main() { | ||
psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname) | ||
|
||
// open database | ||
db, err := sql.Open("postgres", psqlconn) | ||
CheckError(err) | ||
|
||
// create config server | ||
configService, err := sql_config_server.NewSqlConfigServer(db, "configs", | ||
sql_config_server.WithNamespace(namespace), | ||
sql_config_server.WithTableCreation(sql_config_server.DialectPostgres)) | ||
|
||
CheckError(err) | ||
|
||
// seed the database | ||
insertStmt := fmt.Sprintf(`insert into "configs"("key", "value", "namespace") values('foo', 'ba2', '%s')`, namespace) | ||
_, e := db.Exec(insertStmt) | ||
CheckError(e) | ||
|
||
env, err := env2.LoadWithConfigServer(configService) | ||
CheckError(err) | ||
|
||
fmt.Printf("Config with key 'foo' -> '%s'\n", env.MustGetString("foo")) | ||
|
||
db.Close() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
go 1.19 | ||
|
||
use ( | ||
examples/using-sql-config-server | ||
. | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package internal | ||
|
||
import "reflect" | ||
|
||
// HasZeroValue Check a variable has Zero Value | ||
func HasZeroValue(v interface{}) bool { | ||
if v == nil { | ||
return true | ||
} | ||
|
||
t := reflect.TypeOf(v) | ||
if t == nil { | ||
return true | ||
} | ||
|
||
switch t.Kind() { | ||
case reflect.Map, reflect.Slice, reflect.Array: | ||
return false | ||
} | ||
|
||
return v == reflect.Zero(t).Interface() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package sql_config_server | ||
|
||
type Dialect uint | ||
|
||
const ( | ||
DialectPostgres Dialect = iota | ||
DialectMysql | ||
DialectSqlite | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package sql_config_server | ||
|
||
type Option func(*sqlConfigServer) | ||
|
||
func WithTableCreation(dialect Dialect) Option { | ||
return func(server *sqlConfigServer) { | ||
server.dialect = &dialect | ||
} | ||
} | ||
|
||
func WithNamespace(ns string) Option { | ||
return func(server *sqlConfigServer) { | ||
server.namespace = &ns | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package sql_config_server | ||
|
||
import ( | ||
"database/sql" | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
env "github.com/alfarih31/nb-go-env" | ||
"github.com/alfarih31/nb-go-env/internal" | ||
"log" | ||
) | ||
|
||
type sqlConfigServer struct { | ||
tableName string | ||
namespace *string | ||
db *sql.DB | ||
dialect *Dialect | ||
} | ||
|
||
type SqlConfigServer interface { | ||
env.ConfigServer | ||
} | ||
|
||
func (s *sqlConfigServer) Get(key string) (string, bool) { | ||
var r *sql.Row | ||
if s.namespace != nil { | ||
r = s.db.QueryRow(fmt.Sprintf(`SELECT value FROM "%s" WHERE key = '%s' AND namespace = '%s' ORDER BY id DESC LIMIT 1`, s.tableName, key, *s.namespace)) | ||
} else { | ||
r = s.db.QueryRow(fmt.Sprintf(`SELECT value FROM "%s" WHERE key = '%s' ORDER BY id DESC LIMIT 1`, s.tableName, key)) | ||
} | ||
|
||
var v string | ||
if err := r.Scan(&v); err != nil { | ||
log.Println(err) | ||
return "", false | ||
} | ||
|
||
return v, !internal.HasZeroValue(v) | ||
} | ||
|
||
func (s *sqlConfigServer) Dump() (string, error) { | ||
var ( | ||
rs *sql.Rows | ||
err error | ||
) | ||
if s.namespace != nil { | ||
rs, err = s.db.Query(fmt.Sprintf(`SELECT key, value FROM "%s" WHERE namespace = '%s' ORDER BY id DESC`, s.tableName, *s.namespace)) | ||
} else { | ||
rs, err = s.db.Query(fmt.Sprintf(`SELECT key, value FROM "%s" ORDER BY id DESC`, s.tableName)) | ||
} | ||
|
||
if err != nil { | ||
return "", err | ||
} | ||
|
||
configs := map[string]string{} | ||
for rs.Next() { | ||
var k, v string | ||
if err = rs.Scan(&k, &v); err != nil { | ||
return "", err | ||
} | ||
configs[k] = v | ||
} | ||
|
||
if err = rs.Close(); err != nil { | ||
return "", err | ||
} | ||
|
||
j, e := json.Marshal(configs) | ||
|
||
return string(j), e | ||
} | ||
|
||
func (s *sqlConfigServer) executeTableCreation() error { | ||
if s.dialect != nil { | ||
var createStmt string | ||
switch *s.dialect { | ||
case DialectPostgres: | ||
createStmt = fmt.Sprintf(` | ||
CREATE TABLE IF NOT EXISTS "%s" ( | ||
id SERIAL PRIMARY KEY, | ||
namespace CHARACTER VARYING(511), | ||
key VARCHAR(511) NOT NULL, | ||
value TEXT NOT NULL | ||
);`, s.tableName) | ||
case DialectMysql: | ||
createStmt = fmt.Sprintf(` | ||
CREATE TABLE IF NOT EXISTS "%s" ( | ||
id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||
namespace VARCHAR(511), | ||
key VARCHAR(511) NOT NULL, | ||
value TEXT NOT NULL | ||
);`, s.tableName) | ||
case DialectSqlite: | ||
createStmt = fmt.Sprintf(` | ||
CREATE TABLE IF NOT EXISTS "%s" ( | ||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
namespace VARCHAR(511), | ||
key VARCHAR(511) NOT NULL, | ||
value TEXT NOT NULL | ||
);`, s.tableName) | ||
default: | ||
return errors.New("unknown dialect") | ||
} | ||
|
||
_, err := s.db.Exec(createStmt) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (s *sqlConfigServer) init() error { | ||
if err := s.executeTableCreation(); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func NewSqlConfigServer(db *sql.DB, tableName string, opts ...Option) (SqlConfigServer, error) { | ||
cs := &sqlConfigServer{ | ||
db: db, | ||
tableName: tableName, | ||
} | ||
|
||
for _, opt := range opts { | ||
opt(cs) | ||
} | ||
|
||
if err := cs.init(); err != nil { | ||
return nil, err | ||
} | ||
|
||
return cs, nil | ||
} |