qsql

package module
v0.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2025 License: MIT Imports: 16 Imported by: 4

README

qsql is a supplement to the go sql package

Refere to:

database/sql
https://github.com/jmoiron/sqlx

Example:

More example see the example directory.

Directing use

package main

import (
	"github.com/gwaylib/conf"
	"github.com/gwaylib/errors"
	"github.com/gwaylib/qsql"
	_ "github.com/go-sql-driver/mysql"
)

func main() {
    mdb, err := qsql.Open(qsql.DRV_NAME_MYSQL, dsn)
    if err != nil{
        panic(err)
    }
    arr := make([]string, 3)
    if err := mdb.QueryElems(&arr, "SELECT id, created_at, updated_at WHERE id=?", 1); err != nil{
        panic(err)
    }
}

Using ini cache

the configuration file path like : './etc/db.cfg'

The etc file content

[main]
driver: mysql
dsn: username:passwd@tcp(127.0.0.1:3306)/main?timeout=30s&strict=true&loc=Local&parseTime=true&allowOldPasswords=1
max_life_time:7200 # seconds
max_idle_time:0 # seconds
max_idle_conns:0 # num
max_open_conns:0 # num

[log]
driver: mysql
dsn: username:passwd@tcp(127.0.0.1:3306)/log?timeout=30s&strict=true&loc=Local&parseTime=true&allowOldPasswords=1
max_life_time:7200

Make a package for cache.go with ini

package db

import (
	"github.com/gwaylib/conf"
	"github.com/gwaylib/qsql"
	_ "github.com/go-sql-driver/mysql"
)

func init() {
    qsql.RegCacheWithIni(conf.RootDir() + "/etc/db.cfg")

    // Register cache without ini
    // db, err := qsql.Open(qsql.DRV_NAME_MYSQL, dsn)
    // if err != nil{
    //     panic(err)
    // }
    // qsql.RegCache("main", db)
}

func GetCache(section string) *qsql.DB {
	return qsql.GetCache(section)
}

func HasCache(section string) (*qsql.DB, error) {
	return qsql.HasCache(section)
}

func CloseCache() {
	qsql.CloseCache()
}

Using the cache package

package main

import (
	"github.com/gwaylib/conf"
	"github.com/gwaylib/errors"
	_ "github.com/go-sql-driver/mysql"

    "model/db"
)

func main() {
    mdb := db.GetCache("main")
    arr := make([]string, 3)
    if err := mdb.QueryElems(&arr, "SELECT id, created_at, updated_at WHERE id=?", 1); err != nil{
        panic(err)
    }
}

Standard sql

*qsql.DB has implements *sql.DB, so you can call qsql.DB like *sql.DB

mdb := db.GetCache("main") 

row := mdb.QueryRow("SELECT * ...")
// ...

rows, err := mdb.Query("SELECT * ...")
// ...

result, err := mdb.Exec("UPDATE ...")
// ...

Insert struct(s) into table

the struct tag format like db:"field", reference to: http://github.com/jmoiron/sqlx

type User struct{
    Id     int64  `db:"id,auto_increment"` // flag "autoincrement", "auto_increment" are supported .
    Name   string `db:"name"`
    Ignore string `db:"-"` // ignore flag: "-"
}

func main() {
    mdb := db.GetCache("main") 

    var u = &User{
        Name:"testing",
    }

    // Insert data with driver.
    if _, err := mdb.InsertStruct(u, "testing"); err != nil {
        // ... 
    }
    // ...

    // Insert structs
    // TODO: qsql.InsertStructs ?
    var us := []User{}
    tx := mdb.Begin()
    txFn := func() error{
        for _, u := range us {
            if err := tx.InsertStruct(u, "testing"); err != nil{
                return errors.As(err)
            }
        }
        return nil
    }
    if err := qsql.Commit(tx, txFn); err != nil {
        // ...
    }
}

Quick sql way

package main

import (
    gErrors "github.com/gwaylib/errors"
)

// Way 1: query result to a struct.
type User struct{
    Id   int64 `db:"id"`
    Name string `db:"name"`
}

func main() {
    mdb := db.GetCache("main") 
    var u = *User{}
    if err := mdb.QueryStruct(u, "SELECT id, name FROM a WHERE id = ?", id); err != nil {
        // sql.ErrNoRows has been replace by gErrors.ErrNoData
        if gErrors.ErrNoData.Equal(err) {
           // no data
        }
        // ...
    }
    // ..

    count := 0
    if err := mdb.QueryElem(&count, "SELECT count(*) FROM a WHERE id = ?", id); err != nil {
        // sql.ErrNoRows has been replace by errors.ErrNoData
        if errors.ErrNoData.Equal(err) {
           // no data
        }
        // ...
    }
}

Make a lazy tx commit

// commit the tx
func main() {
    mdb := qsql.GetCache("main") 
    tx, err := mdb.Begin()
    if err != nil{
        // ...
    }
    fn := func() error {
      if err := tx.Exec("UPDATE testing SET name = ? WHERE id = ?", id); err != nil{
        return err
      }
      return nil
    }
    if err := mdb.Commit(tx, fn); err != nil {
        // ...
    }
}

SqlBuilder

func main() {
    mdb := qsql.GetCache("main") 

    id := 0
    inIds := []interface{}{1,2}

    bd := mdb.NewSqlBuilder() // qsql.NewSqlBuilder(mdb.DriverName())
    bd.Select("id", "created_at")
    bd.Add("FROM")
    bd.AddTab("tmp")
    bd.Add("WHERE")
    bd.AddTab("created_at BETWEEN ? AND ?", time.Now().AddDate(-1,0,0), time.Now())
    bd.AddTabIf(len(inIds)>0, fmt.Sprintf("AND id IN (%s)", bd.AddStmtIn(inIds))) // create the sql params as '?', becareful, it has performance issues when the array is too long.
    titles, data, err := mdb.QueryPageArr(bd.String(), bd.Args()...) 
    if err != nil {
        panic(err)
    }

    updateBD := mdb.NewSqlBuilder()
    updateBD.Add("UPDATE tmp SET")
    updateBD.AddTab("(updated_at=?,name=?)", time.Now())
    updateDB.Add("WHERE")
    updateDB.AddTab("id=?", id)
    if _, err := mdb.Exec(updateDB.String(), updateDB.Args()...); err != nil {
        panic(err)
    }
}

Documentation

Overview

A simple and quick to get started go orm framework if you have experience with SQL language.

the stmt placeholder using '?' for all, it will be replaced by builder.

Index

Constants

View Source
const (
	DRV_NAME_MYSQL     = "mysql"
	DRV_NAME_ORACLE    = "oracle" // or "oci8"
	DRV_NAME_POSTGRES  = "postgres"
	DRV_NAME_SQLITE3   = "sqlite3"
	DRV_NAME_SQLSERVER = "sqlserver" // or "mssql"

)

Variables

This section is empty.

Functions

func Close

func Close(closer io.Closer)

A lazy function to closed the io.Closer

func CloseCache

func CloseCache()

Close all instance in the cache.

func Commit

func Commit(tx *sql.Tx, fn func() error) error

A lazy function to commit the *sql.Tx

func InsertStruct

func InsertStruct(drvName string, exec Execer, obj interface{}, tbName string) (sql.Result, error)

func InsertStructContext

func InsertStructContext(drvName string, exec Execer, ctx context.Context, obj interface{}, tbName string) (sql.Result, error)

func MakeDBData added in v0.0.3

func MakeDBData(l int) []interface{}

func QueryElem

func QueryElem(queryer Queryer, result interface{}, querySql string, args ...interface{}) error

func QueryElemContext

func QueryElemContext(queryer Queryer, ctx context.Context, result interface{}, querySql string, args ...interface{}) error

func QueryElems

func QueryElems(queryer Queryer, result interface{}, querySql string, args ...interface{}) error

func QueryElemsContext

func QueryElemsContext(queryer Queryer, ctx context.Context, result interface{}, querySql string, args ...interface{}) error

func QueryPageArr

func QueryPageArr(queryer Queryer, querySql string, args ...interface{}) (titles []string, result [][]interface{}, err error)

func QueryPageArrContext

func QueryPageArrContext(queryer Queryer, ctx context.Context, querySql string, args ...interface{}) (titles []string, result [][]interface{}, err error)

func QueryPageMap

func QueryPageMap(queryer Queryer, querySql string, args ...interface{}) (titles []string, result []map[string]interface{}, err error)

func QueryPageMapContext

func QueryPageMapContext(queryer Queryer, ctx context.Context, querySql string, args ...interface{}) (titles []string, result []map[string]interface{}, err error)

func QueryStruct

func QueryStruct(queryer Queryer, obj interface{}, querySql string, args ...interface{}) error

func QueryStructContext

func QueryStructContext(queryer Queryer, ctx context.Context, obj interface{}, querySql string, args ...interface{}) error

func QueryStructs

func QueryStructs(queryer Queryer, obj interface{}, querySql string, args ...interface{}) error

func QueryStructsContext

func QueryStructsContext(queryer Queryer, ctx context.Context, obj interface{}, querySql string, args ...interface{}) error

func RegCache

func RegCache(key string, db *DB)

Register a db to the connection pool by manully.

func RegCacheWithIni

func RegCacheWithIni(iniPath string)

func Rollback

func Rollback(tx *sql.Tx)

A lazy function to rollback the *sql.Tx

func ScanStructs

func ScanStructs(rows *sql.Rows, obj interface{}) error

func SetLog added in v0.0.4

func SetLog(l Log)

func StmtIn added in v0.0.3

func StmtIn(paramStartIdx, paramsLen int, drvName ...string) string

Types

type DB

type DB struct {
	*sql.DB
	// contains filtered or unexported fields
}

qsql.DB Extendd sql.DB and implement qsql.QuickQuery interface

func GetCache

func GetCache(key string) *DB

Get the db instance from the cache.

func HasCache

func HasCache(key string) (*DB, error)

Checking the cache does it have a db instance.

func NewDB

func NewDB(drvName string, db *sql.DB) *DB

func Open

func Open(drvName, dsn string) (*DB, error)

Implement the sql.Open

func (*DB) Close

func (db *DB) Close() error

func (*DB) Commit

func (db *DB) Commit(tx *sql.Tx, fn func() error) error

A lazy function to commit the *sql.Tx if will auto commit when the function is nil error, or do a rollback and return the function error.

func (*DB) DriverName

func (db *DB) DriverName() string

func (*DB) InsertStruct

func (db *DB) InsertStruct(structPtr interface{}, tbName string) (sql.Result, error)

Reflect one db data to the struct. the struct tag format like `db:"field_title"`, reference to: http://github.com/jmoiron/sqlx

func (*DB) InsertStructContext

func (db *DB) InsertStructContext(ctx context.Context, structPtr interface{}, tbName string) (sql.Result, error)

func (*DB) IsClose

func (db *DB) IsClose() bool

func (*DB) NewSqlBuilder added in v0.0.4

func (db *DB) NewSqlBuilder() *SqlBuilder

func (*DB) QueryElem

func (db *DB) QueryElem(result interface{}, querySql string, args ...interface{}) error

Query one field to a sql.Scanner.

func (*DB) QueryElemContext

func (db *DB) QueryElemContext(ctx context.Context, result interface{}, querySql string, args ...interface{}) error

func (*DB) QueryElems

func (db *DB) QueryElems(result interface{}, querySql string, args ...interface{}) error

Query one field to a sql.Scanner array.

func (*DB) QueryElemsContext

func (db *DB) QueryElemsContext(ctx context.Context, result interface{}, querySql string, args ...interface{}) error

func (*DB) QueryPageArr

func (db *DB) QueryPageArr(querySql string, args ...interface{}) (titles []string, result [][]interface{}, err error)

Reflect the query result to a string array.

func (*DB) QueryPageArrContext

func (db *DB) QueryPageArrContext(ctx context.Context, querySql string, args ...interface{}) (titles []string, result [][]interface{}, err error)

func (*DB) QueryPageMap

func (db *DB) QueryPageMap(querySql string, args ...interface{}) (titles []string, result []map[string]interface{}, err error)

Reflect the query result to a string map.

func (*DB) QueryPageMapContext

func (db *DB) QueryPageMapContext(ctx context.Context, querySql string, args ...interface{}) (titles []string, result []map[string]interface{}, err error)

func (*DB) QueryStruct

func (db *DB) QueryStruct(structPtr interface{}, querySql string, args ...interface{}) error

Reflect the sql.Query result to a struct.

func (*DB) QueryStructContext

func (db *DB) QueryStructContext(ctx context.Context, structPtr interface{}, querySql string, args ...interface{}) error

func (*DB) QueryStructs

func (db *DB) QueryStructs(structPtr interface{}, querySql string, args ...interface{}) error

Reflect the sql.Query result to a struct array. Return empty array if data not found.

func (*DB) QueryStructsContext

func (db *DB) QueryStructsContext(ctx context.Context, structPtr interface{}, querySql string, args ...interface{}) error

func (*DB) ScanStructs

func (db *DB) ScanStructs(rows *sql.Rows, structsPtr interface{}) error

Reflect the sql.Rows to []struct array. Return empty array if data not found. Refere to: github.com/jmoiron/sqlx DO NOT forget close the rows

func (*DB) StmtIn added in v0.0.3

func (db *DB) StmtIn(paramStartIdx, paramsLen int) string

Return "?,?,?,?..." for default, or "@p1,@p2,@p3..." for mssql, or ":1,:2,:3..." for pgsql. paramStartIdx default is 0, but you need count it when the driver is mssq, pgsql etc. .

type DBData

type DBData string

通用的字符串查询

func (*DBData) Scan

func (d *DBData) Scan(i interface{}) error

func (*DBData) String

func (d *DBData) String() string

type Execer

type Execer interface {
	Exec(query string, args ...interface{}) (sql.Result, error)
	ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
}

type Log added in v0.0.4

type Log interface {
	Println(msg ...interface{})
}

type PageSql

type PageSql struct {
	// contains filtered or unexported fields
}

func NewPageSql

func NewPageSql(countBD, queryBD *SqlBuilder) *PageSql

func (*PageSql) QueryCount

func (p *PageSql) QueryCount(db *DB) (int64, error)

func (*PageSql) QueryPageArr

func (p *PageSql) QueryPageArr(db *DB) ([]string, [][]interface{}, error)

func (*PageSql) QueryPageMap

func (p *PageSql) QueryPageMap(db *DB) ([]string, []map[string]interface{}, error)

type Queryer

type Queryer interface {
	Query(query string, args ...interface{}) (*sql.Rows, error)
	QueryRow(query string, args ...interface{}) *sql.Row

	QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
	QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
}

type QuickSql added in v0.0.3

type QuickSql interface {
	DriverName() string

	// Insert a struct data into tbName
	//
	// Reflect one db data to the struct.
	// the struct tag format like `db:"field_title"`, reference to: http://github.com/jmoiron/sqlx
	//
	InsertStruct(structPtr interface{}, tbName string) (sql.Result, error)
	InsertStructContext(ctx context.Context, structPtr interface{}, tbName string) (sql.Result, error)

	// Scan the rows result to []struct
	// Reflect the sql.Rows to a struct array.
	// Return empty array if data not found.
	// Refere to: github.com/jmoiron/sqlx
	// DOT NOT forget close the rows after called.
	ScanStructs(rows *sql.Rows, structsPtr interface{}) error

	// Query db data to a struct
	QueryStruct(structPrt interface{}, querySql string, args ...interface{}) error
	QueryStructContext(ctx context.Context, structPrt interface{}, querySql string, args ...interface{}) error
	// Query db data to []struct
	QueryStructs(structsPrt interface{}, querySql string, args ...interface{}) error
	QueryStructsContext(ctx context.Context, structsPrt interface{}, querySql string, args ...interface{}) error

	// Query a element data like int, string.
	// Same as row.Scan(&e)
	QueryElem(ePtr interface{}, querySql string, args ...interface{}) error
	QueryElemContext(ctx context.Context, ePtr interface{}, querySql string, args ...interface{}) error
	// Query elements data like []int, []string in result.
	QueryElems(ePtr interface{}, querySql string, args ...interface{}) error
	QueryElemsContext(ctx context.Context, ePtr interface{}, querySql string, args ...interface{}) error

	// Query a page data to array.
	// the result data is [][]*string but no nil *string pointer instance.
	QueryPageArr(querySql string, args ...interface{}) (titles []string, result [][]interface{}, err error)
	QueryPageArrContext(ctx context.Context, querySql string, args ...interface{}) (titles []string, result [][]interface{}, err error)

	// Query a page data to map, NOT RECOMMENED to use when there is a large page data.
	// the result data is []map[string]*string but no nil *string pointer instance.
	QueryPageMap(querySql string, args ...interface{}) (titles []string, result []map[string]interface{}, err error)
	QueryPageMapContext(ctx context.Context, querySql string, args ...interface{}) (titles []string, result []map[string]interface{}, err error)

	// Extend stmt for the where in
	// paramStartIdx default is 0, but you need count it when the driver is mssq, pgsql etc. .
	//
	// Example for the first input:
	// fmt.Sprintf("select * from table_name where in (%s)", qsql.StmtWhereIn(0,len(args))
	// Or
	// fmt.Sprintf("select * from table_name where in (%s)", qsql.StmtWhereIn(0,len(args), qsql.DRV_NAME_MYSQL)
	//
	// Example for the second input:
	// fmt.Sprintf("select * from table_name where id=? in (%s)", qsql.StmtWhereIn(1,len(args))
	//
	// Return "?,?,?,?..." for default, or "@p1,@p2,@p3..." for mssql, or ":1,:2,:3..." for pgsql when paramStartIdx is 0.
	StmtIn(paramStartIdx, paramLen int) string

	// auto commit when the func is return nil, or auto rollback when the func is error
	Commit(tx *sql.Tx, fn func() error) error
}

type SqlBuilder added in v0.0.3

type SqlBuilder struct {
	// contains filtered or unexported fields
}

func NewSqlBuilder added in v0.0.3

func NewSqlBuilder(drvName ...string) *SqlBuilder

func NewSqlBuilderWithIndent added in v0.0.4

func NewSqlBuilderWithIndent(indent string, drvName ...string) *SqlBuilder

func (*SqlBuilder) Add added in v0.0.3

func (b *SqlBuilder) Add(query string, args ...interface{}) *SqlBuilder

add the query to the buffer with indent, and add the args to the argument recorder, call builder.Args() to output the recorder

func (*SqlBuilder) AddIf added in v0.0.3

func (b *SqlBuilder) AddIf(ok bool, query string, args ...interface{}) *SqlBuilder

call AddTab if ok is true

func (*SqlBuilder) AddStmtIn added in v0.0.4

func (b *SqlBuilder) AddStmtIn(inArgs interface{}) string

append the slice to the sql params and return then the stmt string. where in is not a slice kind, it will be panic

func (*SqlBuilder) AddTab added in v0.0.3

func (b *SqlBuilder) AddTab(query string, args ...interface{}) *SqlBuilder

if indent isn't " ", add one tab with two space width to the buffer before adding

func (*SqlBuilder) Args added in v0.0.3

func (b *SqlBuilder) Args() []interface{}

func (*SqlBuilder) Copy added in v0.0.3

func (b *SqlBuilder) Copy() *SqlBuilder

func (*SqlBuilder) DrvName added in v0.0.4

func (b *SqlBuilder) DrvName() string

func (*SqlBuilder) Indent added in v0.0.4

func (b *SqlBuilder) Indent() string

func (*SqlBuilder) Select added in v0.0.3

func (b *SqlBuilder) Select(column ...string) *SqlBuilder

func (*SqlBuilder) SelectStruct added in v0.0.3

func (b *SqlBuilder) SelectStruct(obj interface{}) *SqlBuilder

func (*SqlBuilder) SetDump added in v0.0.4

func (b *SqlBuilder) SetDump(dump bool)

func (*SqlBuilder) Sql added in v0.0.3

func (b *SqlBuilder) Sql() []interface{}

func (*SqlBuilder) String added in v0.0.3

func (b *SqlBuilder) String() string

Directories

Path Synopsis
example module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL