builder

package
v1.3.1 Latest Latest
Warning

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

Go to latest
Published: Aug 5, 2019 License: Apache-2.0 Imports: 10 Imported by: 0

README

Builder

It's only a tool helping you build your queries.You should also use the database/sql to operate database

complex sql always need special optimization,which is hard to do it here.So, for very comlex sql, I suggest you write it manually, Exported WhereIn Helper will be added soon

QuickStart

example_1

package main

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
    qb "github.com/didi/gendry/builder"
)

func main() {
    db,err := sql.Open("mysql", "xxxxxxxxxxx")
    if nil != err {
        panic(err)
    }
    mp := map[string]interface{}{
    	"country": "China",
    	"role": "driver",
    	"age >": 45,
        "_groupby": "name",
        "_having": map[string]interface{}{
            "total >": 1000,
            "total <=": 50000,
        },
    	"_orderby": "age desc",
    }
    cond,vals,err := qb.BuildSelect("tableName", where, []string{"name", "count(price) as total", "age"})
    
    //cond: SELECT name,count(price) as total,age FROM tableName WHERE (age>? AND country=? AND role=?) GROUP BY name HAVING (total>? AND total<=?) ORDER BY age DESC
    //vals: []interface{}{45, "China", "driver", 1000, 50000}

	if nil != err {
		panic(err)
	}	
	
    rows,err := db.Query(cond, vals...)
    if nil != err {
        panic(err)
    }
    defer rows.Close()
    for rows.Next() {
        var id int
        var name,phone string
        rows.Scan(&id, &name, &phone)
        fmt.Println(id, name, phone)
    }

    //have fun !!
}

API

BuildSelect

sign: BuildSelect(table string, where map[string]interface{}, field []string) (string,[]interface{},error)

operators supported:

  • =
  • >
  • <
  • =
  • <=
  • >=
  • !=
  • <>
  • in
  • not in
  • like
  • not like
  • between
  • not between
where := map[string]interface{}{
	"foo <>": "aha",
	"bar <=": 45,
	"sex in": []interface{}{"girl", "boy"},
	"name like": "%James",
}

others supported:

  • _orderby
  • _groupby
  • _having
  • _limit
where := map[string]interface{}{
	"age >": 100,
	"_orderby": "fieldName asc",
	"_groupby": "fieldName",
	"_having": map[string]interface{}{"foo":"bar",},
	"_limit": []uint{offset, row_count},
}

Note:

  • _having will be ignored if _groupby isn't setted
  • value of _limit could be:
    • "_limit": []uint{a,b} => LIMIT a,b
    • "_limit": []uint{a} => LIMIT 0,a

Aggregate

sign: AggregateQuery(ctx context.Context, db *sql.DB, table string, where map[string]interface{}, aggregate AggregateSymbleBuilder) (ResultResolver, error)

Aggregate is a helper function to help executing some aggregate queries such as:

  • sum
  • avg
  • max
  • min
  • count

example:

where := map[string]interface{}{
    "score > ": 100,
    "city in": []interface{}{"Beijing", "Shijiazhuang",}
}
// supported: AggregateSum,AggregateMax,AggregateMin,AggregateCount,AggregateAvg
result, err := AggregateQuery(ctx, db, "tableName", where, AggregateSum("age"))
sumAge := result.Int64()

result,err = AggregateQuery(ctx, db, "tableName", where, AggregateCount("*")) 
numberOfRecords := result.Int64()

result,err = AggregateQuery(ctx, db, "tableName", where, AggregateAvg("score"))
averageScore := result.Float64()

BuildUpdate

sign: BuildUpdate(table string, where map[string]interface{}, update map[string]interface{}) (string, []interface{}, error)

BuildUpdate is very likely to BuildSelect but it doesn't support:

  • _orderby
  • _groupby
  • _limit
  • _having
where := map[string]interface{}{
	"foo <>": "aha",
	"bar <=": 45,
	"sex in": []interface{}{"girl", "boy"},
}
update := map[string]interface{}{
	"role": "primaryschoolstudent",
	"rank": 5,
}
cond,vals,err := qb.BuildUpdate("table_name", where, update)

db.Exec(cond, vals...)

BuildInsert

sign: BuildInsert(table string, data []map[string]interface{}) (string, []interface{}, error)

data is a slice and every element(map) in it must have the same keys:

var data []map[string]interface{}
data = append(data, map[string]interface{}{
    "name": "deen",
    "age":  23,
})
data = append(data, map[string]interface{}{
    "name": "Tony",
    "age":  30,
})
cond, vals, err := qb.BuildInsert(table, data)
db.Exec(cond, vals...)

BuildInsertIgnore

sign: BuildInsertIgnore(table string, data []map[string]interface{}) (string, []interface{}, error)

data is a slice and every element(map) in it must have the same keys:

var data []map[string]interface{}
data = append(data, map[string]interface{}{
    "name": "deen",
    "age":  23,
})
data = append(data, map[string]interface{}{
    "name": "Tony",
    "age":  30,
})
cond, vals, err := qb.BuildInsertIgnore(table, data)
db.Exec(cond, vals...)

BuildReplaceInsert

sign: BuildReplaceInsert(table string, data []map[string]interface{}) (string, []interface{}, error)

data is a slice and every element(map) in it must have the same keys:

var data []map[string]interface{}
data = append(data, map[string]interface{}{
    "name": "deen",
    "age":  23,
})
data = append(data, map[string]interface{}{
    "name": "Tony",
    "age":  30,
})
cond, vals, err := qb.BuildReplaceInsert(table, data)
db.Exec(cond, vals...)

NamedQuery

sign: func NamedQuery(sql string, data map[string]interface{}) (string, []interface{}, error)

For very complex query, this might be helpful. And for critical system, this is recommended.

cond, vals, err := builder.NamedQuery("select * from tb where name={{name}} and id in (select uid from anothertable where score in {{m_score}})", map[string]interface{}{
	"name": "caibirdme",
	"m_score": []float64{3.0, 5.8, 7.9},
})

assert.Equal("select * from tb where name=? and id in (select uid from anothertable where score in (?,?,?))", cond)
assert.Equal([]interface{}{"caibirdme", 3.0, 5.8, 7.9}, vals)

BuildDelete

sign: BuildDelete(table string, where map[string]interface{}) (string, []interface{}, error)


Safety

If you use Prepare && stmt.SomeMethods then You have no need to worry about the safety. Prepare is a safety mechanism backed by mysql, it makes sql injection out of work.

So builder doesn't escape the string values it recieved -- it's unnecessary

If you call db.Query(cond, vals...) directly, and you don't set interpolateParams which is one of the driver's variables to true, the driver actually will still prepare a stmt.So it's safe.

Remember:

  • don't assemble raw sql yourself,use builder instead.
  • don't set interpolateParams to true(default false) if you're not aware of the consequence.

Obey instructions above there's no safety issues for most cases.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (

	// ErrUnsupportedOperator reports there's unsupported operators in where-condition
	ErrUnsupportedOperator = errors.New("[builder] unsupported operator")
)

Functions

func BuildDelete

func BuildDelete(table string, where map[string]interface{}) (string, []interface{}, error)

BuildDelete work as its name says

func BuildInsert

func BuildInsert(table string, data []map[string]interface{}) (string, []interface{}, error)

BuildInsert work as its name says

func BuildInsertIgnore added in v1.1.0

func BuildInsertIgnore(table string, data []map[string]interface{}) (string, []interface{}, error)

BuildInsertIgnore work as its name says

func BuildReplaceInsert added in v1.1.0

func BuildReplaceInsert(table string, data []map[string]interface{}) (string, []interface{}, error)

BuildReplaceInsert work as its name says

func BuildSelect

func BuildSelect(table string, where map[string]interface{}, selectField []string) (cond string, vals []interface{}, err error)

BuildSelect work as its name says. supported operators including: =,in,>,>=,<,<=,<>,!=. key without operator will be regarded as =. special key begin with _: _orderby,_groupby,_limit,_having. the value of _orderby must be a string separated by a space(ie:map[string]interface{}{"_orderby": "fieldName desc"}). the value of _limit must be a slice whose type should be []uint and must contain two uints(ie: []uint{0, 100}). the value of _having must be a map just like where but only support =,in,>,>=,<,<=,<>,!= for more examples,see README.md or open a issue.

func BuildUpdate

func BuildUpdate(table string, where map[string]interface{}, update map[string]interface{}) (string, []interface{}, error)

BuildUpdate work as its name says

func NamedQuery

func NamedQuery(sql string, data map[string]interface{}) (string, []interface{}, error)

NamedQuery is used for expressing complex query

func OmitEmpty

func OmitEmpty(where map[string]interface{}, omitKey []string) map[string]interface{}

OmitEmpty is a helper function to clear where map zero value

Types

type AggregateSymbleBuilder

type AggregateSymbleBuilder interface {
	Symble() string
}

AggregateSymbleBuilder need to be implemented so that executor can get what should be put into `select Symble() from xxx where yyy`

func AggregateAvg

func AggregateAvg(col string) AggregateSymbleBuilder

AggregateAvg avg(col)

func AggregateCount

func AggregateCount(col string) AggregateSymbleBuilder

AggregateCount count(col)

func AggregateMax

func AggregateMax(col string) AggregateSymbleBuilder

AggregateMax max(col)

func AggregateMin

func AggregateMin(col string) AggregateSymbleBuilder

AggregateMin min(col)

func AggregateSum

func AggregateSum(col string) AggregateSymbleBuilder

AggregateSum sum(col)

type Between added in v1.2.0

type Between map[string][]interface{}

func (Between) Build added in v1.2.0

func (bt Between) Build() ([]string, []interface{})

type Comparable

type Comparable interface {
	Build() ([]string, []interface{})
}

Comparable requires type implements the Build method

type Eq

type Eq map[string]interface{}

Eq means equal(=)

func (Eq) Build

func (e Eq) Build() ([]string, []interface{})

Build implements the Comparable interface

type Gt

type Gt map[string]interface{}

Gt means greater than(>)

func (Gt) Build

func (g Gt) Build() ([]string, []interface{})

Build implements the Comparable interface

type Gte

type Gte map[string]interface{}

Gte means greater than or equal(>=)

func (Gte) Build

func (g Gte) Build() ([]string, []interface{})

Build implements the Comparable interface

type In

type In map[string][]interface{}

In means in

func (In) Build

func (i In) Build() ([]string, []interface{})

Build implements the Comparable interface

type Like

type Like map[string]interface{}

Like means like

func (Like) Build

func (l Like) Build() ([]string, []interface{})

Build implements the Comparable interface

type Lt

type Lt map[string]interface{}

Lt means less than(<)

func (Lt) Build

func (l Lt) Build() ([]string, []interface{})

Build implements the Comparable interface

type Lte

type Lte map[string]interface{}

Lte means less than or equal(<=)

func (Lte) Build

func (l Lte) Build() ([]string, []interface{})

Build implements the Comparable interface

type Ne

type Ne map[string]interface{}

Ne means Not Equal(!=)

func (Ne) Build

func (n Ne) Build() ([]string, []interface{})

Build implements the Comparable interface

type NotBetween added in v1.2.0

type NotBetween map[string][]interface{}

func (NotBetween) Build added in v1.2.0

func (nbt NotBetween) Build() ([]string, []interface{})

type NotIn

type NotIn map[string][]interface{}

NotIn means not in

func (NotIn) Build

func (i NotIn) Build() ([]string, []interface{})

Build implements the Comparable interface

type NotLike added in v1.2.1

type NotLike map[string]interface{}

func (NotLike) Build added in v1.2.1

func (l NotLike) Build() ([]string, []interface{})

Build implements the Comparable interface

type NullType

type NullType byte

NullType is the NULL type in mysql

const (

	// IsNull the same as `is null`
	IsNull NullType
	// IsNotNull the same as `is not null`
	IsNotNull
)

func (NullType) String

func (nt NullType) String() string

type ResultResolver

type ResultResolver interface {
	Int64() int64
	Float64() float64
}

ResultResolver is a helper for retrieving data caller should know the type and call the responding method

func AggregateQuery

func AggregateQuery(ctx context.Context, db *sql.DB, table string, where map[string]interface{}, aggregate AggregateSymbleBuilder) (ResultResolver, error)

AggregateQuery is a helper function to execute the aggregate query and return the result

Jump to

Keyboard shortcuts

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