Move sq + ParseDurShortString() to goext and change conf values by env

This commit is contained in:
Mike Schwörer 2022-12-07 23:32:58 +01:00
parent 8db0fa37db
commit 0cae24a612
Signed by: Mikescher
GPG Key ID: D3C7172E0A70F8CF
22 changed files with 170 additions and 226 deletions

View File

@ -4,34 +4,37 @@ import (
"fmt"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"gogs.mikescher.com/BlackForestBytes/goext/timeext"
"os"
"reflect"
"strconv"
"time"
)
type Config struct {
Namespace string
BaseURL string
GinDebug bool
LogLevel zerolog.Level
ServerIP string
ServerPort string
DBFile string
DBJournal string
DBTimeout time.Duration
DBMaxOpenConns int
DBMaxIdleConns int
DBConnMaxLifetime time.Duration
DBConnMaxIdleTime time.Duration
DBCheckForeignKeys bool
RequestTimeout time.Duration
ReturnRawErrors bool
DummyFirebase bool
BaseURL string `env:"SCN_URL"`
GinDebug bool `env:"SCN_GINDEBUG"`
LogLevel zerolog.Level `env:"SCN_LOGLEVEL"`
ServerIP string `env:"SCN_IP"`
ServerPort string `env:"SCN_PORT"`
DBFile string `env:"SCN_DB_FILE"`
DBJournal string `env:"SCN_DB_JOURNAL"`
DBTimeout time.Duration `env:"SCN_DB_TIMEOUT"`
DBMaxOpenConns int `env:"SCN_DB_MAXOPENCONNECTIONS"`
DBMaxIdleConns int `env:"SCN_DB_MAXIDLECONNECTIONS"`
DBConnMaxLifetime time.Duration `env:"SCN_DB_CONNEXTIONMAXLIFETIME"`
DBConnMaxIdleTime time.Duration `env:"SCN_DB_CONNEXTIONMAXIDLETIME"`
DBCheckForeignKeys bool `env:"SCN_DB_CHECKFOREIGNKEYS"`
RequestTimeout time.Duration `env:"SCN_REQUEST_TIMEOUT"`
ReturnRawErrors bool `env:"SCN_ERROR_RETURN"`
DummyFirebase bool `env:"SCN_DUMMY_FB"`
DummyGoogleAPI bool `env:"SCN_DUMMY_GOOG"`
FirebaseTokenURI string
FirebaseProjectID string
FirebasePrivKeyID string
FirebaseClientMail string
FirebasePrivateKey string
DummyGoogleAPI bool
GoogleAPITokenURI string
GoogleAPIPrivKeyID string
GoogleAPIClientMail string
@ -181,7 +184,7 @@ var configStag = func() Config {
var configProd = func() Config {
return Config{
Namespace: "production",
BaseURL: confEnv("BASE_URL"),
BaseURL: confEnv("SCN_URL"),
GinDebug: false,
LogLevel: zerolog.InfoLevel,
ServerIP: "0.0.0.0",
@ -198,17 +201,17 @@ var configProd = func() Config {
ReturnRawErrors: false,
DummyFirebase: false,
FirebaseTokenURI: "https://oauth2.googleapis.com/token",
FirebaseProjectID: confEnv("FB_PROJECTID"),
FirebasePrivKeyID: confEnv("FB_PRIVATEKEYID"),
FirebaseClientMail: confEnv("FB_CLIENTEMAIL"),
FirebasePrivateKey: confEnv("FB_PRIVATEKEY"),
FirebaseProjectID: confEnv("SCN_FB_PROJECTID"),
FirebasePrivKeyID: confEnv("SCN_FB_PRIVATEKEYID"),
FirebaseClientMail: confEnv("SCN_FB_CLIENTEMAIL"),
FirebasePrivateKey: confEnv("SCN_FB_PRIVATEKEY"),
DummyGoogleAPI: false,
GoogleAPITokenURI: "https://oauth2.googleapis.com/token",
GoogleAPIPrivKeyID: confEnv("GOOG_PRIVATEKEYID"),
GoogleAPIClientMail: confEnv("GOOG_CLIENTEMAIL"),
GoogleAPIPrivateKey: confEnv("GOOG_PRIVATEKEY"),
GooglePackageName: confEnv("GOOG_PACKAGENAME"),
GoogleProProductID: confEnv("GOOG_PROPRODUCTID"),
GoogleAPIPrivKeyID: confEnv("SCN_GOOG_PRIVATEKEYID"),
GoogleAPIClientMail: confEnv("SCN_GOOG_CLIENTEMAIL"),
GoogleAPIPrivateKey: confEnv("SCN_GOOG_PRIVATEKEY"),
GooglePackageName: confEnv("SCN_GOOG_PACKAGENAME"),
GoogleProProductID: confEnv("SCN_GOOG_PROPRODUCTID"),
}
}
@ -222,10 +225,12 @@ var allConfig = map[string]func() Config{
func getConfig(ns string) (Config, bool) {
if ns == "" {
return configLocHost(), true
ns = "local-host"
}
if c, ok := allConfig[ns]; ok {
return c(), true
if cfn, ok := allConfig[ns]; ok {
c := cfn()
parseConfOverride(&c)
return c, true
}
return Config{}, false
}
@ -249,3 +254,62 @@ func init() {
Conf = cfg
}
func parseConfOverride(c *Config) {
rval := reflect.ValueOf(c).Elem()
rtyp := rval.Type()
for i := 0; i < rtyp.NumField(); i++ {
rsfield := rtyp.Field(i)
rvfield := rval.Field(i)
envkey := rsfield.Tag.Get("env")
if envkey == "" {
continue
}
envval, efound := os.LookupEnv(envkey)
if !efound {
continue
}
if rvfield.Kind() == reflect.String {
rvfield.Set(reflect.ValueOf(envval))
fmt.Printf("[CONF] Overwrite config '%s' with '%s'\n", envkey, envval)
} else if rvfield.Type() == reflect.TypeOf(zerolog.Level(0)) {
envint, err := strconv.ParseInt(envval, 10, 8)
if err != nil {
panic(fmt.Sprintf("Failed to parse env-config variable '%s' to int (value := '%s')", envkey, envval))
}
if envint < -1 || envint > 7 {
panic(fmt.Sprintf("Failed to parse zerolog-level (invalid number: %d)", envint))
}
lvl := zerolog.Level(envint)
rvfield.Set(reflect.ValueOf(lvl))
fmt.Printf("[CONF] Overwrite config '%s' with '%s'\n", envkey, lvl.String())
} else if rvfield.Type() == reflect.TypeOf(time.Duration(0)) {
dur, err := timeext.ParseDurationShortString(envval)
if err != nil {
panic(fmt.Sprintf("Failed to parse env-config variable '%s' to duration (value := '%s')", envkey, envval))
}
rvfield.Set(reflect.ValueOf(dur))
fmt.Printf("[CONF] Overwrite config '%s' with '%s'\n", envkey, dur.String())
} else {
panic(fmt.Sprintf("Unknown kind/type in config: [ %s | %s ]", rvfield.Kind().String(), rvfield.Type().String()))
}
}
}

View File

@ -2,8 +2,8 @@ package db
import (
"blackforestbytes.com/simplecloudnotifier/models"
"blackforestbytes.com/simplecloudnotifier/sq"
"database/sql"
"gogs.mikescher.com/BlackForestBytes/goext/sq"
"time"
)

View File

@ -2,8 +2,8 @@ package db
import (
"blackforestbytes.com/simplecloudnotifier/models"
"blackforestbytes.com/simplecloudnotifier/sq"
"gogs.mikescher.com/BlackForestBytes/goext/langext"
"gogs.mikescher.com/BlackForestBytes/goext/sq"
"time"
)

View File

@ -1,7 +1,7 @@
package db
import (
"blackforestbytes.com/simplecloudnotifier/sq"
"gogs.mikescher.com/BlackForestBytes/goext/sq"
"time"
)

View File

@ -3,14 +3,15 @@ package db
import (
server "blackforestbytes.com/simplecloudnotifier"
"blackforestbytes.com/simplecloudnotifier/db/schema"
"blackforestbytes.com/simplecloudnotifier/sq"
"context"
"database/sql"
"errors"
"fmt"
"github.com/jmoiron/sqlx"
_ "github.com/mattn/go-sqlite3"
"github.com/rs/zerolog/log"
"gogs.mikescher.com/BlackForestBytes/goext/langext"
"gogs.mikescher.com/BlackForestBytes/goext/sq"
"time"
)
@ -33,7 +34,11 @@ func NewDatabase(conf server.Config) (*Database, error) {
qqdb := sq.NewDB(xdb)
return &Database{qqdb}, nil
scndb := &Database{qqdb}
qqdb.SetListener(scndb)
return scndb, nil
}
func (db *Database) Migrate(ctx context.Context) error {
@ -74,3 +79,35 @@ func (db *Database) Ping(ctx context.Context) error {
func (db *Database) BeginTx(ctx context.Context) (sq.Tx, error) {
return db.db.BeginTransaction(ctx, sql.LevelDefault)
}
func (db *Database) OnQuery(txID *uint16, sql string, _ *sq.PP) {
if txID == nil {
log.Debug().Msg(fmt.Sprintf("[SQL-QUERY] %s", fmtSQLPrint(sql)))
} else {
log.Debug().Msg(fmt.Sprintf("[SQL-TX<%d>-QUERY] %s", *txID, fmtSQLPrint(sql)))
}
}
func (db *Database) OnExec(txID *uint16, sql string, _ *sq.PP) {
if txID == nil {
log.Debug().Msg(fmt.Sprintf("[SQL-EXEC] %s", fmtSQLPrint(sql)))
} else {
log.Debug().Msg(fmt.Sprintf("[SQL-TX<%d>-EXEC] %s", *txID, fmtSQLPrint(sql)))
}
}
func (db *Database) OnPing() {
log.Debug().Msg("[SQL-PING]")
}
func (db *Database) OnTxBegin(txid uint16) {
log.Debug().Msg(fmt.Sprintf("[SQL-TX<%d>-START]", txid))
}
func (db *Database) OnTxCommit(txid uint16) {
log.Debug().Msg(fmt.Sprintf("[SQL-TX<%d>-COMMIT]", txid))
}
func (db *Database) OnTxRollback(txid uint16) {
log.Debug().Msg(fmt.Sprintf("[SQL-TX<%d>-ROLLBACK]", txid))
}

View File

@ -3,8 +3,8 @@ package db
import (
scn "blackforestbytes.com/simplecloudnotifier"
"blackforestbytes.com/simplecloudnotifier/models"
"blackforestbytes.com/simplecloudnotifier/sq"
"gogs.mikescher.com/BlackForestBytes/goext/langext"
"gogs.mikescher.com/BlackForestBytes/goext/sq"
"time"
)

View File

@ -3,9 +3,9 @@ package db
import (
"blackforestbytes.com/simplecloudnotifier/db/cursortoken"
"blackforestbytes.com/simplecloudnotifier/models"
"blackforestbytes.com/simplecloudnotifier/sq"
"database/sql"
"fmt"
"gogs.mikescher.com/BlackForestBytes/goext/sq"
"time"
)

View File

@ -1,10 +1,10 @@
package db
import (
"blackforestbytes.com/simplecloudnotifier/sq"
"context"
"errors"
"gogs.mikescher.com/BlackForestBytes/goext/langext"
"gogs.mikescher.com/BlackForestBytes/goext/sq"
)
func (db *Database) ReadSchema(ctx context.Context) (retval int, reterr error) {

View File

@ -2,8 +2,8 @@ package db
import (
"blackforestbytes.com/simplecloudnotifier/models"
"blackforestbytes.com/simplecloudnotifier/sq"
"database/sql"
"gogs.mikescher.com/BlackForestBytes/goext/sq"
"time"
)

View File

@ -3,8 +3,8 @@ package db
import (
scn "blackforestbytes.com/simplecloudnotifier"
"blackforestbytes.com/simplecloudnotifier/models"
"blackforestbytes.com/simplecloudnotifier/sq"
"database/sql"
"gogs.mikescher.com/BlackForestBytes/goext/sq"
"time"
)

View File

@ -2,6 +2,7 @@ package db
import (
"gogs.mikescher.com/BlackForestBytes/goext/langext"
"strings"
"time"
)
@ -23,3 +24,14 @@ func time2DBOpt(t *time.Time) *int64 {
}
return langext.Ptr(t.UnixMilli())
}
func fmtSQLPrint(sql string) string {
if strings.Contains(sql, ";") {
return "(...multi...)"
}
sql = strings.ReplaceAll(sql, "\r", "")
sql = strings.ReplaceAll(sql, "\n", " ")
return sql
}

View File

@ -7,7 +7,7 @@ require (
github.com/mattn/go-sqlite3 v1.14.16
github.com/rs/zerolog v1.28.0
github.com/swaggo/swag v1.8.7
gogs.mikescher.com/BlackForestBytes/goext v0.0.27
gogs.mikescher.com/BlackForestBytes/goext v0.0.31
github.com/jmoiron/sqlx v1.3.5
)

View File

@ -4,8 +4,6 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/blockloop/scan v1.3.0 h1:p8xnajpGA3d/V6o23IBFdQ764+JnNJ+PQj+OwT+rkdg=
github.com/blockloop/scan v1.3.0/go.mod h1:qd+3w68+o7m5Xhj9X5SlJH2rbFyK8w0WT47Rkuer010=
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -33,6 +31,7 @@ github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/j
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0=
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM=
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
@ -58,6 +57,7 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@ -67,7 +67,6 @@ github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZb
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
@ -99,8 +98,8 @@ github.com/swaggo/swag v1.8.7/go.mod h1:ezQVUUhly8dludpVk+/PuwJWvLLanB13ygV5Pr9e
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
gogs.mikescher.com/BlackForestBytes/goext v0.0.27 h1:Psjv/EGFI2smJoRv+1yUccmms8szmLIN0r1th9JQcik=
gogs.mikescher.com/BlackForestBytes/goext v0.0.27/go.mod h1:TMBOjo3FRFh/GiTT0z3nwLmgcFJB87oSF2VMs4XUCTQ=
gogs.mikescher.com/BlackForestBytes/goext v0.0.31 h1:DC2RZe7/tSDDbPRbjDcYa+BLRlY0SgLTAkI2DPw5WJQ=
gogs.mikescher.com/BlackForestBytes/goext v0.0.31/go.mod h1:/u9JtMwCP68ix4R9BJ/MT0Lm+QScmqIoyYZFKBGzv9g=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=

View File

@ -4,11 +4,11 @@ import (
"blackforestbytes.com/simplecloudnotifier/api/apierr"
"blackforestbytes.com/simplecloudnotifier/common/ginresp"
"blackforestbytes.com/simplecloudnotifier/db"
"blackforestbytes.com/simplecloudnotifier/sq"
"context"
"errors"
"github.com/gin-gonic/gin"
"github.com/rs/zerolog/log"
"gogs.mikescher.com/BlackForestBytes/goext/sq"
"time"
)

View File

@ -2,10 +2,10 @@ package logic
import (
"blackforestbytes.com/simplecloudnotifier/db"
"blackforestbytes.com/simplecloudnotifier/sq"
"context"
"errors"
"github.com/rs/zerolog/log"
"gogs.mikescher.com/BlackForestBytes/goext/sq"
"time"
)

View File

@ -1,77 +0,0 @@
package sq
import (
"context"
"database/sql"
"fmt"
"github.com/jmoiron/sqlx"
"github.com/rs/zerolog/log"
"sync"
)
type DB interface {
Exec(ctx context.Context, sql string, prep PP) (sql.Result, error)
Query(ctx context.Context, sql string, prep PP) (*sqlx.Rows, error)
Ping(ctx context.Context) error
BeginTransaction(ctx context.Context, iso sql.IsolationLevel) (Tx, error)
}
type database struct {
db *sqlx.DB
txctr uint16
lock sync.Mutex
}
func NewDB(db *sqlx.DB) DB {
return &database{
db: db,
txctr: 0,
lock: sync.Mutex{},
}
}
func (db *database) Exec(ctx context.Context, sql string, prep PP) (sql.Result, error) {
log.Debug().Msg(fmt.Sprintf("[SQL-EXEC] %s", fmtSQLPrint(sql)))
res, err := db.db.NamedExecContext(ctx, sql, prep)
if err != nil {
return nil, err
}
return res, nil
}
func (db *database) Query(ctx context.Context, sql string, prep PP) (*sqlx.Rows, error) {
log.Debug().Msg(fmt.Sprintf("[SQL-QUERY] %s", fmtSQLPrint(sql)))
rows, err := db.db.NamedQueryContext(ctx, sql, prep)
if err != nil {
return nil, err
}
return rows, nil
}
func (db *database) Ping(ctx context.Context) error {
log.Debug().Msg("[SQL-PING]")
err := db.db.PingContext(ctx)
if err != nil {
return err
}
return nil
}
func (db *database) BeginTransaction(ctx context.Context, iso sql.IsolationLevel) (Tx, error) {
db.lock.Lock()
txid := db.txctr
db.txctr += 1 // with overflow !
db.lock.Unlock()
log.Debug().Msg(fmt.Sprintf("[SQL-TX<%d>-START]", txid))
xtx, err := db.db.BeginTxx(ctx, &sql.TxOptions{Isolation: iso})
if err != nil {
return nil, err
}
return NewTransaction(xtx, txid), nil
}

View File

@ -1,3 +0,0 @@
package sq
type PP map[string]any

View File

@ -1,12 +0,0 @@
package sq
import (
"context"
"database/sql"
"github.com/jmoiron/sqlx"
)
type Queryable interface {
Exec(ctx context.Context, sql string, prep PP) (sql.Result, error)
Query(ctx context.Context, sql string, prep PP) (*sqlx.Rows, error)
}

View File

@ -1,60 +0,0 @@
package sq
import (
"context"
"database/sql"
"fmt"
"github.com/jmoiron/sqlx"
"github.com/rs/zerolog/log"
)
type Tx interface {
Rollback() error
Commit() error
Exec(ctx context.Context, sql string, prep PP) (sql.Result, error)
Query(ctx context.Context, sql string, prep PP) (*sqlx.Rows, error)
}
type transaction struct {
tx *sqlx.Tx
id uint16
}
func NewTransaction(xtx *sqlx.Tx, txid uint16) Tx {
return &transaction{
tx: xtx,
id: txid,
}
}
func (tx *transaction) Rollback() error {
log.Debug().Msg(fmt.Sprintf("[SQL-TX<%d>-ROLLBACK]", tx.id))
return tx.tx.Rollback()
}
func (tx *transaction) Commit() error {
log.Debug().Msg(fmt.Sprintf("[SQL-TX<%d>-COMMIT]", tx.id))
return tx.tx.Commit()
}
func (tx *transaction) Exec(ctx context.Context, sql string, prep PP) (sql.Result, error) {
log.Debug().Msg(fmt.Sprintf("[SQL-TX<%d>-EXEC] %s", tx.id, fmtSQLPrint(sql)))
res, err := tx.tx.NamedExecContext(ctx, sql, prep)
if err != nil {
return nil, err
}
return res, nil
}
func (tx *transaction) Query(ctx context.Context, sql string, prep PP) (*sqlx.Rows, error) {
log.Debug().Msg(fmt.Sprintf("[SQL-TX<%d>-QUERY] %s", tx.id, fmtSQLPrint(sql)))
rows, err := sqlx.NamedQueryContext(ctx, tx.tx, sql, prep)
if err != nil {
return nil, err
}
return rows, nil
}

View File

@ -1,16 +0,0 @@
package sq
import (
"strings"
)
func fmtSQLPrint(sql string) string {
if strings.Contains(sql, ";") {
return "(...multi...)"
}
sql = strings.ReplaceAll(sql, "\r", "")
sql = strings.ReplaceAll(sql, "\n", " ")
return sql
}

View File

@ -2800,7 +2800,7 @@
"timestamp_created": {
"type": "string"
},
"timestamp_last_sent": {
"timestamp_lastsent": {
"type": "string"
}
}
@ -2957,10 +2957,10 @@
"timestamp_created": {
"type": "string"
},
"timestamp_last_read": {
"timestamp_lastread": {
"type": "string"
},
"timestamp_last_sent": {
"timestamp_lastsent": {
"type": "string"
},
"user_id": {
@ -3007,10 +3007,10 @@
"timestamp_created": {
"type": "string"
},
"timestamp_last_read": {
"timestamp_lastread": {
"type": "string"
},
"timestamp_last_sent": {
"timestamp_lastsent": {
"type": "string"
},
"user_id": {

View File

@ -347,7 +347,7 @@ definitions:
type: string
timestamp_created:
type: string
timestamp_last_sent:
timestamp_lastsent:
type: string
type: object
models.ClientJSON:
@ -450,9 +450,9 @@ definitions:
type: string
timestamp_created:
type: string
timestamp_last_read:
timestamp_lastread:
type: string
timestamp_last_sent:
timestamp_lastsent:
type: string
user_id:
type: integer
@ -483,9 +483,9 @@ definitions:
type: string
timestamp_created:
type: string
timestamp_last_read:
timestamp_lastread:
type: string
timestamp_last_sent:
timestamp_lastsent:
type: string
user_id:
type: integer