Add statements debug sql support.
This commit is contained in:
parent
439c9f1ef9
commit
240ddd65e6
27 changed files with 1013 additions and 426 deletions
|
|
@ -2,7 +2,6 @@ package sqlbuilder
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
|
|
@ -13,6 +12,9 @@ type clause interface {
|
|||
type queryData struct {
|
||||
buff bytes.Buffer
|
||||
args []interface{}
|
||||
|
||||
lastChar byte
|
||||
ident int
|
||||
}
|
||||
|
||||
type statementType string
|
||||
|
|
@ -26,48 +28,125 @@ const (
|
|||
lock_statement statementType = "LOCK"
|
||||
)
|
||||
|
||||
const defaultIdent = 5
|
||||
|
||||
func (q *queryData) increaseIdent() {
|
||||
q.ident += defaultIdent
|
||||
}
|
||||
|
||||
func (q *queryData) decreaseIdent() {
|
||||
if q.ident < defaultIdent {
|
||||
q.ident = 0
|
||||
}
|
||||
|
||||
q.ident -= defaultIdent
|
||||
}
|
||||
|
||||
func (q *queryData) writeProjection(statement statementType, projections []projection) error {
|
||||
return serializeProjectionList(statement, projections, q)
|
||||
q.increaseIdent()
|
||||
err := serializeProjectionList(statement, projections, q)
|
||||
q.decreaseIdent()
|
||||
return err
|
||||
}
|
||||
|
||||
func (q *queryData) writeFrom(statement statementType, table tableInterface) error {
|
||||
q.nextLine()
|
||||
q.writeString("FROM")
|
||||
|
||||
q.increaseIdent()
|
||||
err := table.serialize(statement, q)
|
||||
q.decreaseIdent()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (q *queryData) writeWhere(statement statementType, where expression) error {
|
||||
q.writeString(" WHERE ")
|
||||
return where.serialize(statement, q)
|
||||
q.nextLine()
|
||||
q.writeString("WHERE")
|
||||
|
||||
q.increaseIdent()
|
||||
err := where.serialize(statement, q)
|
||||
q.decreaseIdent()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (q *queryData) writeGroupBy(statement statementType, groupBy []groupByClause) error {
|
||||
q.writeString(" GROUP BY ")
|
||||
q.nextLine()
|
||||
q.writeString("GROUP BY")
|
||||
|
||||
return serializeGroupByClauseList(statement, groupBy, q)
|
||||
q.increaseIdent()
|
||||
err := serializeGroupByClauseList(statement, groupBy, q)
|
||||
q.decreaseIdent()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (q *queryData) writeOrderBy(statement statementType, orderBy []orderByClause) error {
|
||||
q.writeString(" ORDER BY ")
|
||||
return serializeOrderByClauseList(statement, orderBy, q)
|
||||
q.nextLine()
|
||||
q.writeString("ORDER BY")
|
||||
|
||||
q.increaseIdent()
|
||||
err := serializeOrderByClauseList(statement, orderBy, q)
|
||||
q.decreaseIdent()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (q *queryData) writeHaving(statement statementType, having expression) error {
|
||||
q.writeString(" HAVING ")
|
||||
return having.serialize(statement, q)
|
||||
q.nextLine()
|
||||
q.writeString("HAVING")
|
||||
|
||||
q.increaseIdent()
|
||||
err := having.serialize(statement, q)
|
||||
q.decreaseIdent()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (q *queryData) nextLine() {
|
||||
q.write([]byte{'\n'})
|
||||
q.write(bytes.Repeat([]byte{' '}, q.ident))
|
||||
}
|
||||
|
||||
func (q *queryData) write(data []byte) {
|
||||
if len(data) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if !isPreSeparator(q.lastChar) && !isPostSeparator(data[0]) && q.buff.Len() > 0 {
|
||||
q.buff.WriteByte(' ')
|
||||
}
|
||||
|
||||
q.buff.Write(data)
|
||||
q.lastChar = data[len(data)-1]
|
||||
}
|
||||
|
||||
func isPreSeparator(b byte) bool {
|
||||
return b == ' ' || b == '.' || b == ',' || b == '(' || b == '\n'
|
||||
}
|
||||
|
||||
func isPostSeparator(b byte) bool {
|
||||
return b == ' ' || b == '.' || b == ',' || b == ')' || b == '\n'
|
||||
}
|
||||
|
||||
func (q *queryData) writeString(str string) {
|
||||
q.buff.WriteString(str)
|
||||
q.write([]byte(str))
|
||||
}
|
||||
|
||||
func (q *queryData) writeByte(b byte) {
|
||||
q.buff.WriteByte(b)
|
||||
q.write([]byte{b})
|
||||
}
|
||||
|
||||
func (q *queryData) finalize() (string, []interface{}) {
|
||||
return q.buff.String() + ";\n", q.args
|
||||
}
|
||||
|
||||
func (q *queryData) insertArgument(arg interface{}) {
|
||||
q.args = append(q.args, arg)
|
||||
argPlaceholder := "$" + strconv.Itoa(len(q.args))
|
||||
|
||||
q.buff.WriteString(argPlaceholder)
|
||||
q.writeString(argPlaceholder)
|
||||
}
|
||||
|
||||
func (q *queryData) reset() {
|
||||
|
|
@ -75,49 +154,49 @@ func (q *queryData) reset() {
|
|||
q.args = []interface{}{}
|
||||
}
|
||||
|
||||
func argToString(value interface{}) (string, error) {
|
||||
func ArgToString(value interface{}) string {
|
||||
switch bindVal := value.(type) {
|
||||
case bool:
|
||||
if bindVal {
|
||||
return "TRUE", nil
|
||||
return "TRUE"
|
||||
} else {
|
||||
return "FALSE", nil
|
||||
return "FALSE"
|
||||
}
|
||||
case int8:
|
||||
return strconv.FormatInt(int64(bindVal), 10), nil
|
||||
return strconv.FormatInt(int64(bindVal), 10)
|
||||
case int:
|
||||
return strconv.FormatInt(int64(bindVal), 10), nil
|
||||
return strconv.FormatInt(int64(bindVal), 10)
|
||||
case int16:
|
||||
return strconv.FormatInt(int64(bindVal), 10), nil
|
||||
return strconv.FormatInt(int64(bindVal), 10)
|
||||
case int32:
|
||||
return strconv.FormatInt(int64(bindVal), 10), nil
|
||||
return strconv.FormatInt(int64(bindVal), 10)
|
||||
case int64:
|
||||
return strconv.FormatInt(int64(bindVal), 10), nil
|
||||
return strconv.FormatInt(int64(bindVal), 10)
|
||||
|
||||
case uint8:
|
||||
return strconv.FormatUint(uint64(bindVal), 10), nil
|
||||
return strconv.FormatUint(uint64(bindVal), 10)
|
||||
case uint:
|
||||
return strconv.FormatUint(uint64(bindVal), 10), nil
|
||||
return strconv.FormatUint(uint64(bindVal), 10)
|
||||
case uint16:
|
||||
return strconv.FormatUint(uint64(bindVal), 10), nil
|
||||
return strconv.FormatUint(uint64(bindVal), 10)
|
||||
case uint32:
|
||||
return strconv.FormatUint(uint64(bindVal), 10), nil
|
||||
return strconv.FormatUint(uint64(bindVal), 10)
|
||||
case uint64:
|
||||
return strconv.FormatUint(uint64(bindVal), 10), nil
|
||||
return strconv.FormatUint(uint64(bindVal), 10)
|
||||
|
||||
case float32:
|
||||
return strconv.FormatFloat(float64(bindVal), 'f', -1, 64), nil
|
||||
return strconv.FormatFloat(float64(bindVal), 'f', -1, 64)
|
||||
case float64:
|
||||
return strconv.FormatFloat(float64(bindVal), 'f', -1, 64), nil
|
||||
return strconv.FormatFloat(float64(bindVal), 'f', -1, 64)
|
||||
|
||||
case string:
|
||||
return bindVal, nil
|
||||
return `'` + bindVal + `'`
|
||||
case []byte:
|
||||
return string(bindVal), nil
|
||||
return string(bindVal)
|
||||
//TODO: implement
|
||||
//case time.Time:
|
||||
// return bindVal.String())
|
||||
default:
|
||||
return "", errors.New("Unsupported literal type. ")
|
||||
return "[Unknown type]"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue