~netlandish/gobwebs

2ca831d2f3e406a8166b36f57851306ab79b98b9 — Peter Sanchez 5 days ago e6cc725 master v0.1.2
Adding GetPlaceholderFormat and SetPlaceholderFormat to the database
module to set global placeholder format for applications. This allows
easy database changes in the future without major changes needed in
applications.
3 files changed, 72 insertions(+), 39 deletions(-)

A database/middleware.go
M database/options.go
M database/sql.go
A database/middleware.go => database/middleware.go +48 -0
@@ 0,0 1,48 @@
package database

import (
	"context"
	"database/sql"
	"errors"
	"time"

	"github.com/labstack/echo/v4"
)

// This entire concept is inspired, ripped, and edited, from git.sr.ht/~sircmpwn/core-go

var dbCtxKey = &contextKey{"database"}

type contextKey struct {
	name string
}

// ContextWithTimeout returns a context with query timeout
func ContextWithTimeout(
	ctx context.Context, db *sql.DB, timeout int) (context.Context, context.CancelFunc) {
	return context.WithTimeout(Context(ctx, db), time.Duration(timeout)*time.Second)
}

// Context adds db connection to context for immediate use
func Context(ctx context.Context, db *sql.DB) context.Context {
	return context.WithValue(ctx, dbCtxKey, db)
}

// ForContext pulls *sql.DB obj for context
func ForContext(ctx context.Context) *sql.DB {
	db, ok := ctx.Value(dbCtxKey).(*sql.DB)
	if !ok {
		panic(errors.New("Invalid database context"))
	}
	return db
}

// Middleware will place the stripe client in the request context
func Middleware(db *sql.DB) echo.MiddlewareFunc {
	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			c.SetRequest(c.Request().WithContext(Context(c.Request().Context(), db)))
			return next(c)
		}
	}
}

M database/options.go => database/options.go +24 -0
@@ 38,3 38,27 @@ func (f *FilterOptions) GetBuilder(filter sq.Sqlizer) sq.SelectBuilder {
	}
	return query
}

var holderFormat sq.PlaceholderFormat

// SetPlaceholderFormat will set the application level placeholder format. This
// should be called early in your applications startup to avoid any issues with
// queries depending on this value.
func SetPlaceholderFormat(format sq.PlaceholderFormat) {
	holderFormat = format
}

// GetPlaceholderFormat will return the currently configured placeholder format.
// It can be used to set the format at the application level. This helps keep
// things easier to change database backends in the future. Will panic if no
// value is set, though the default value is "squirrel.Question" (question mark)
func GetPlaceholderFormat() sq.PlaceholderFormat {
	if holderFormat == nil {
		panic("Placeholder format not set. You MUST call SetPlaceholderFormat().")
	}
	return holderFormat
}

func init() {
	SetPlaceholderFormat(sq.Question) // default format
}

M database/sql.go => database/sql.go +0 -39
@@ 5,42 5,13 @@ import (
	"database/sql"
	sqldriver "database/sql/driver"
	"errors"
	"time"

	"github.com/labstack/echo/v4"
)

// This entire concept is inspired, ripped, and edited, from git.sr.ht/~sircmpwn/core-go

var dbCtxKey = &contextKey{"database"}

type contextKey struct {
	name string
}

// TxOptionsRO read only transaction rules
var TxOptionsRO = &sql.TxOptions{Isolation: 0, ReadOnly: true}

// ContextWithTimeout returns a context with query timeout
func ContextWithTimeout(
	ctx context.Context, db *sql.DB, timeout int) (context.Context, context.CancelFunc) {
	return context.WithTimeout(Context(ctx, db), time.Duration(timeout)*time.Second)
}

// Context adds db connection to context for immediate use
func Context(ctx context.Context, db *sql.DB) context.Context {
	return context.WithValue(ctx, dbCtxKey, db)
}

// ForContext pulls *sql.DB obj for context
func ForContext(ctx context.Context) *sql.DB {
	db, ok := ctx.Value(dbCtxKey).(*sql.DB)
	if !ok {
		panic(errors.New("Invalid database context"))
	}
	return db
}

// WithTx calls a function wrapped in a database transaction
func WithTx(ctx context.Context, opts *sql.TxOptions, fn func(tx *sql.Tx) error) error {
	db := ForContext(ctx)


@@ 71,13 42,3 @@ func WithTx(ctx context.Context, opts *sql.TxOptions, fn func(tx *sql.Tx) error)

	return err
}

// Middleware will place the stripe client in the request context
func Middleware(db *sql.DB) echo.MiddlewareFunc {
	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			c.SetRequest(c.Request().WithContext(Context(c.Request().Context(), db)))
			return next(c)
		}
	}
}

Do not follow this link