mirror of https://github.com/lqs/sqlingo
add documents on all exported functions and interfaces
This commit is contained in:
parent
23f58d61a0
commit
7fea9e30a0
3
case.go
3
case.go
|
|
@ -2,12 +2,14 @@ package sqlingo
|
|||
|
||||
import "strings"
|
||||
|
||||
// CaseExpression indicates the status in a CASE statement
|
||||
type CaseExpression interface {
|
||||
WhenThen(when BooleanExpression, then interface{}) CaseExpression
|
||||
Else(value interface{}) CaseExpressionWithElse
|
||||
End() Expression
|
||||
}
|
||||
|
||||
// CaseExpressionWithElse indicates the status in CASE ... ELSE ... statement
|
||||
type CaseExpressionWithElse interface {
|
||||
End() Expression
|
||||
}
|
||||
|
|
@ -23,6 +25,7 @@ type whenThen struct {
|
|||
then interface{}
|
||||
}
|
||||
|
||||
// Case initiates a CASE statement
|
||||
func Case() CaseExpression {
|
||||
return caseStatus{}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,13 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// Model is the interface of generated model struct
|
||||
type Model interface {
|
||||
GetTable() Table
|
||||
GetValues() []interface{}
|
||||
}
|
||||
|
||||
// Assignment is an assignment statement
|
||||
type Assignment interface {
|
||||
GetSQL(scope scope) (string, error)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strconv"
|
||||
)
|
||||
|
||||
// Cursor is the interface of a row cursor.
|
||||
type Cursor interface {
|
||||
Next() bool
|
||||
Scan(dest ...interface{}) error
|
||||
|
|
|
|||
25
database.go
25
database.go
|
|
@ -6,24 +6,42 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// Database is the interface of a database with underlying sql.DB object.
|
||||
type Database interface {
|
||||
// Get the underlying sql.DB object of the database
|
||||
GetDB() *sql.DB
|
||||
BeginTx(ctx context.Context, opts *sql.TxOptions, f func(tx Transaction) error) error
|
||||
// Executes a query and return the cursor
|
||||
Query(sql string) (Cursor, error)
|
||||
// Executes a query with context and return the cursor
|
||||
QueryContext(ctx context.Context, sqlString string) (Cursor, error)
|
||||
// Executes a statement
|
||||
Execute(sql string) (sql.Result, error)
|
||||
// Executes a statement with context
|
||||
ExecuteContext(ctx context.Context, sql string) (sql.Result, error)
|
||||
// Set the logger function
|
||||
SetLogger(logger func(sql string, durationNano int64))
|
||||
// Set the retry policy function.
|
||||
// The retry policy function returns true if needs retry.
|
||||
SetRetryPolicy(retryPolicy func(err error) bool)
|
||||
// enable or disable caller info
|
||||
EnableCallerInfo(enableCallerInfo bool)
|
||||
// Set a interceptor function
|
||||
SetInterceptor(interceptor InterceptorFunc)
|
||||
|
||||
// Initiate a SELECT statement
|
||||
Select(fields ...interface{}) selectWithFields
|
||||
// Initiate a SELECT DISTINCT statement
|
||||
SelectDistinct(fields ...interface{}) selectWithFields
|
||||
// Initiate a SELECT * FROM statement
|
||||
SelectFrom(tables ...Table) selectWithTables
|
||||
// Initiate a INSERT INTO statement
|
||||
InsertInto(table Table) insertWithTable
|
||||
// Initiate a REPLACE INTO statement
|
||||
ReplaceInto(table Table) insertWithTable
|
||||
// Initiate a UPDATE statement
|
||||
Update(table Table) updateWithSet
|
||||
// Initiate a DELETE FROM statement
|
||||
DeleteFrom(table Table) deleteWithTable
|
||||
}
|
||||
|
||||
|
|
@ -58,6 +76,7 @@ func (d *database) SetInterceptor(interceptor InterceptorFunc) {
|
|||
d.interceptor = interceptor
|
||||
}
|
||||
|
||||
// Open a database, similar to sql.Open
|
||||
func Open(driverName string, dataSourceName string) (db Database, err error) {
|
||||
var sqlDB *sql.DB
|
||||
if dataSourceName != "" {
|
||||
|
|
@ -80,9 +99,8 @@ func (d database) GetDB() *sql.DB {
|
|||
func (d database) getTxOrDB() txOrDB {
|
||||
if d.tx != nil {
|
||||
return d.tx
|
||||
} else {
|
||||
return d.db
|
||||
}
|
||||
return d.db
|
||||
}
|
||||
|
||||
func (d database) Query(sqlString string) (Cursor, error) {
|
||||
|
|
@ -118,6 +136,9 @@ func (d database) queryContextOnce(ctx context.Context, sqlStringWithCallerInfo
|
|||
interceptor := d.interceptor
|
||||
var rows *sql.Rows
|
||||
invoker := func(ctx context.Context, sql string) (err error) {
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
rows, err = d.getTxOrDB().QueryContext(ctx, sql)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,15 +6,23 @@ import (
|
|||
"strconv"
|
||||
)
|
||||
|
||||
// Expression is the interface of a SQL expression.
|
||||
type Expression interface {
|
||||
// get the SQL string
|
||||
GetSQL(scope scope) (string, error)
|
||||
getOperatorPriority() int
|
||||
|
||||
// <> operator
|
||||
NotEquals(other interface{}) BooleanExpression
|
||||
// == operator
|
||||
Equals(other interface{}) BooleanExpression
|
||||
// < operator
|
||||
LessThan(other interface{}) BooleanExpression
|
||||
// <= operator
|
||||
LessThanOrEquals(other interface{}) BooleanExpression
|
||||
// > operator
|
||||
GreaterThan(other interface{}) BooleanExpression
|
||||
// >= operator
|
||||
GreaterThanOrEquals(other interface{}) BooleanExpression
|
||||
|
||||
IsNull() BooleanExpression
|
||||
|
|
@ -29,10 +37,12 @@ type Expression interface {
|
|||
IfNull(altValue interface{}) Expression
|
||||
}
|
||||
|
||||
// Alias is the interface of an table/column alias.
|
||||
type Alias interface {
|
||||
GetSQL(scope scope) (string, error)
|
||||
}
|
||||
|
||||
// BooleanExpression is the interface of a SQL expression with boolean value.
|
||||
type BooleanExpression interface {
|
||||
Expression
|
||||
And(other interface{}) BooleanExpression
|
||||
|
|
@ -40,6 +50,7 @@ type BooleanExpression interface {
|
|||
Not() BooleanExpression
|
||||
}
|
||||
|
||||
// NumberExpression is the interface of a SQL expression with number value.
|
||||
type NumberExpression interface {
|
||||
Expression
|
||||
Add(other interface{}) NumberExpression
|
||||
|
|
@ -55,6 +66,7 @@ type NumberExpression interface {
|
|||
Max() UnknownExpression
|
||||
}
|
||||
|
||||
// StringExpression is the interface of a SQL expression with string value.
|
||||
type StringExpression interface {
|
||||
Expression
|
||||
Min() UnknownExpression
|
||||
|
|
@ -63,6 +75,7 @@ type StringExpression interface {
|
|||
Contains(substring string) BooleanExpression
|
||||
}
|
||||
|
||||
// UnknownExpression is the interface of a SQL expression with unknown value.
|
||||
type UnknownExpression interface {
|
||||
Expression
|
||||
And(other interface{}) BooleanExpression
|
||||
|
|
@ -116,6 +129,7 @@ func falseExpression() expression {
|
|||
}
|
||||
}
|
||||
|
||||
// Raw create a raw SQL statement
|
||||
func Raw(sql string) UnknownExpression {
|
||||
return expression{
|
||||
sql: sql,
|
||||
|
|
@ -123,6 +137,7 @@ func Raw(sql string) UnknownExpression {
|
|||
}
|
||||
}
|
||||
|
||||
// And creates an expression with AND operator.
|
||||
func And(expressions ...BooleanExpression) (result BooleanExpression) {
|
||||
if len(expressions) == 0 {
|
||||
result = trueExpression()
|
||||
|
|
@ -138,6 +153,7 @@ func And(expressions ...BooleanExpression) (result BooleanExpression) {
|
|||
return
|
||||
}
|
||||
|
||||
// Or creates an expression with OR operator.
|
||||
func Or(expressions ...BooleanExpression) (result BooleanExpression) {
|
||||
if len(expressions) == 0 {
|
||||
result = falseExpression()
|
||||
|
|
@ -490,20 +506,20 @@ func (e expression) NotIn(values ...interface{}) BooleanExpression {
|
|||
return expression{builder: builder, priority: 11}
|
||||
}
|
||||
|
||||
type JoinerFunc = func(exprSql, valuesSql string) string
|
||||
type BooleanFunc = func(other interface{}) BooleanExpression
|
||||
type BuilderFunc = func(scope scope) (string, error)
|
||||
type joinerFunc = func(exprSql, valuesSql string) string
|
||||
type booleanFunc = func(other interface{}) BooleanExpression
|
||||
type builderFunc = func(scope scope) (string, error)
|
||||
|
||||
func (e expression) getBuilder(single BooleanFunc, joiner JoinerFunc, values ...interface{}) BuilderFunc {
|
||||
func (e expression) getBuilder(single booleanFunc, joiner joinerFunc, values ...interface{}) builderFunc {
|
||||
return func(scope scope) (string, error) {
|
||||
var valuesSql string
|
||||
var err error
|
||||
|
||||
if len(values) == 1 {
|
||||
value := values[0]
|
||||
if select_, ok := value.(toSelectFinal); ok {
|
||||
if selectStatus, ok := value.(toSelectFinal); ok {
|
||||
// IN subquery
|
||||
valuesSql, err = select_.GetSQL()
|
||||
valuesSql, err = selectStatus.GetSQL()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
|||
11
field.go
11
field.go
|
|
@ -2,18 +2,22 @@ package sqlingo
|
|||
|
||||
import "strings"
|
||||
|
||||
// Field is the interface of a generated field.
|
||||
type Field interface {
|
||||
Expression
|
||||
}
|
||||
|
||||
// NumberField is the interface of a generated field of number type.
|
||||
type NumberField interface {
|
||||
NumberExpression
|
||||
}
|
||||
|
||||
// BooleanField is the interface of a generated field of boolean type.
|
||||
type BooleanField interface {
|
||||
BooleanExpression
|
||||
}
|
||||
|
||||
// StringField is the interface of a generated field of string type.
|
||||
type StringField interface {
|
||||
StringExpression
|
||||
}
|
||||
|
|
@ -41,21 +45,24 @@ func newFieldExpression(tableName string, fieldName string) expression {
|
|||
}
|
||||
}
|
||||
|
||||
// NewNumberField creates a reference to a number field. It should only be called from generated code.
|
||||
func NewNumberField(tableName string, fieldName string) NumberField {
|
||||
return newFieldExpression(tableName, fieldName)
|
||||
}
|
||||
|
||||
// NewBooleanField creates a reference to a boolean field. It should only be called from generated code.
|
||||
func NewBooleanField(tableName string, fieldName string) BooleanField {
|
||||
return newFieldExpression(tableName, fieldName)
|
||||
}
|
||||
|
||||
// NewStringField creates a reference to a string field. It should only be called from generated code.
|
||||
func NewStringField(tableName string, fieldName string) StringField {
|
||||
return newFieldExpression(tableName, fieldName)
|
||||
}
|
||||
|
||||
type FieldList []Field
|
||||
type fieldList []Field
|
||||
|
||||
func (fields FieldList) GetSQL(scope scope) (string, error) {
|
||||
func (fields fieldList) GetSQL(scope scope) (string, error) {
|
||||
isSingleTable := len(scope.Tables) == 1 && scope.lastJoin == nil
|
||||
var sb strings.Builder
|
||||
if len(fields) == 0 {
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ func TestField(t *testing.T) {
|
|||
assertValue(t, NewBooleanField("t1", "f1").Equals(true), "`t1`.`f1` = 1")
|
||||
assertValue(t, NewStringField("t1", "f1").Equals("x"), "`t1`.`f1` = 'x'")
|
||||
|
||||
sql, _ := FieldList{}.GetSQL(scope{
|
||||
sql, _ := fieldList{}.GetSQL(scope{
|
||||
Tables: []Table{
|
||||
&dummyTable{},
|
||||
},
|
||||
|
|
@ -46,7 +46,7 @@ func TestField(t *testing.T) {
|
|||
t.Error(sql)
|
||||
}
|
||||
|
||||
sql, _ = FieldList{}.GetSQL(scope{
|
||||
sql, _ = fieldList{}.GetSQL(scope{
|
||||
Tables: []Table{
|
||||
&dummyTable{},
|
||||
&dummyTable{},
|
||||
|
|
@ -56,7 +56,7 @@ func TestField(t *testing.T) {
|
|||
t.Error(sql)
|
||||
}
|
||||
|
||||
if _, err := (FieldList{
|
||||
if _, err := (fieldList{
|
||||
expression{builder: func(scope scope) (string, error) {
|
||||
return "", errors.New("error")
|
||||
}},
|
||||
|
|
|
|||
|
|
@ -10,26 +10,32 @@ func function(name string, args ...interface{}) expression {
|
|||
}}
|
||||
}
|
||||
|
||||
// Function creates an expression of the call to specified function.
|
||||
func Function(name string, args ...interface{}) Expression {
|
||||
return function(name, args...)
|
||||
}
|
||||
|
||||
// Concat creates an expression of CONCAT function.
|
||||
func Concat(args ...interface{}) StringExpression {
|
||||
return function("CONCAT", args...)
|
||||
}
|
||||
|
||||
// Count creates an expression of COUNT aggregator.
|
||||
func Count(arg interface{}) NumberExpression {
|
||||
return function("COUNT", arg)
|
||||
}
|
||||
|
||||
// If creates an expression of IF function.
|
||||
func If(predicate Expression, trueValue interface{}, falseValue interface{}) (result Expression) {
|
||||
return function("IF", predicate, trueValue, falseValue)
|
||||
}
|
||||
|
||||
// Length creates an expression of LENGTH function.
|
||||
func Length(arg interface{}) NumberExpression {
|
||||
return function("LENGTH", arg)
|
||||
}
|
||||
|
||||
// Sum creates an expression of SUM aggregator.
|
||||
func Sum(arg interface{}) NumberExpression {
|
||||
return function("SUM", arg)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,10 @@ import (
|
|||
"context"
|
||||
)
|
||||
|
||||
// InvokerFunc is the function type of the actual invoker. It should be called in an interceptor.
|
||||
type InvokerFunc = func(ctx context.Context, sql string) error
|
||||
|
||||
// InterceptorFunc is the function type of an interceptor. An interceptor should implement this function to fulfill it's purpose.
|
||||
type InterceptorFunc = func(ctx context.Context, sql string, invoker InvokerFunc) error
|
||||
|
||||
// TODO: add some common interceptors
|
||||
|
|
|
|||
1
order.go
1
order.go
|
|
@ -1,5 +1,6 @@
|
|||
package sqlingo
|
||||
|
||||
// OrderBy indicates the ORDER BY column and the status of descending order.
|
||||
type OrderBy interface {
|
||||
GetSQL(scope scope) (string, error)
|
||||
}
|
||||
|
|
|
|||
24
select.go
24
select.go
|
|
@ -1,7 +1,7 @@
|
|||
package sqlingo
|
||||
|
||||
import (
|
||||
. "context"
|
||||
"context"
|
||||
"errors"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
|
@ -101,7 +101,7 @@ type selectWithLock interface {
|
|||
}
|
||||
|
||||
type toSelectWithContext interface {
|
||||
WithContext(ctx Context) toSelectFinal
|
||||
WithContext(ctx context.Context) toSelectFinal
|
||||
}
|
||||
|
||||
type toSelectFinal interface {
|
||||
|
|
@ -123,14 +123,14 @@ type join struct {
|
|||
type selectStatus struct {
|
||||
scope scope
|
||||
distinct bool
|
||||
fields FieldList
|
||||
fields fieldList
|
||||
where BooleanExpression
|
||||
orderBys []OrderBy
|
||||
groupBys []Expression
|
||||
having BooleanExpression
|
||||
limit *int
|
||||
offset int
|
||||
ctx Context
|
||||
ctx context.Context
|
||||
lock string
|
||||
}
|
||||
|
||||
|
|
@ -263,8 +263,8 @@ func (s selectStatus) ForUpdate() selectWithLock {
|
|||
|
||||
func (s selectStatus) asDerivedTable(name string) Table {
|
||||
return derivedTable{
|
||||
name: name,
|
||||
select_: s,
|
||||
name: name,
|
||||
selectStatus: s,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -364,26 +364,18 @@ func (s selectStatus) GetSQL() (string, error) {
|
|||
return sb.String(), nil
|
||||
}
|
||||
|
||||
func (s selectStatus) WithContext(ctx Context) toSelectFinal {
|
||||
func (s selectStatus) WithContext(ctx context.Context) toSelectFinal {
|
||||
s.ctx = ctx
|
||||
return s
|
||||
}
|
||||
|
||||
func (s selectStatus) getContext() Context {
|
||||
if s.ctx != nil {
|
||||
return s.ctx
|
||||
} else {
|
||||
return Background()
|
||||
}
|
||||
}
|
||||
|
||||
func (s selectStatus) FetchCursor() (Cursor, error) {
|
||||
sqlString, err := s.GetSQL()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cursor, err := s.scope.Database.QueryContext(s.getContext(), sqlString)
|
||||
cursor, err := s.scope.Database.QueryContext(s.ctx, sqlString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
10
table.go
10
table.go
|
|
@ -1,5 +1,6 @@
|
|||
package sqlingo
|
||||
|
||||
// Table is the interface of a generated table.
|
||||
type Table interface {
|
||||
GetName() string
|
||||
GetSQL(scope scope) string
|
||||
|
|
@ -27,13 +28,14 @@ func (t table) getOperatorPriority() int {
|
|||
return 0
|
||||
}
|
||||
|
||||
// NewTable creates a reference to a table. It should only be called from generated code.
|
||||
func NewTable(name string) Table {
|
||||
return table{name: name, sqlDialects: quoteIdentifier(name)}
|
||||
}
|
||||
|
||||
type derivedTable struct {
|
||||
name string
|
||||
select_ selectStatus
|
||||
name string
|
||||
selectStatus selectStatus
|
||||
}
|
||||
|
||||
func (t derivedTable) GetFieldByName(name string) Field {
|
||||
|
|
@ -53,10 +55,10 @@ func (t derivedTable) GetName() string {
|
|||
}
|
||||
|
||||
func (t derivedTable) GetSQL(scope scope) string {
|
||||
sql, _ := t.select_.GetSQL()
|
||||
sql, _ := t.selectStatus.GetSQL()
|
||||
return "(" + sql + ") AS " + t.name
|
||||
}
|
||||
|
||||
func (t derivedTable) GetFields() []Field {
|
||||
return t.select_.fields
|
||||
return t.selectStatus.fields
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ func TestTable(t *testing.T) {
|
|||
func TestDerivedTable(t *testing.T) {
|
||||
dummyFields := []Field{NewNumberField("table", "field")}
|
||||
dt := derivedTable{
|
||||
select_: selectStatus{
|
||||
selectStatus: selectStatus{
|
||||
fields: dummyFields,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"database/sql"
|
||||
)
|
||||
|
||||
// Transaction is the interface of a transaction with underlying sql.Tx object.
|
||||
type Transaction interface {
|
||||
GetDB() *sql.DB
|
||||
GetTx() *sql.Tx
|
||||
|
|
|
|||
Loading…
Reference in New Issue