jet/sqlbuilder/clause.go
2019-05-03 12:51:57 +02:00

155 lines
3.1 KiB
Go

package sqlbuilder
import (
"bytes"
"errors"
"strconv"
)
type serializeOption int
const (
SKIP_DEFAULT_ALIASING = iota
FOR_PROJECTION
UNION_ORDER_BY
NO_TABLE_NAME
)
type Clause interface {
Serialize(out *queryData, options ...serializeOption) error
}
type queryData struct {
buff bytes.Buffer
args []interface{}
statementType int
clauseType int
}
const (
select_statement = iota
insert_statement
update_statement
delete_statement
set_statement
)
const (
projection_clause = iota
where_clause
order_by_clause
group_by_clause
having_clause
)
func (q *queryData) WriteProjection(projections []Projection) error {
q.clauseType = projection_clause
return serializeProjectionList(projections, q)
}
func (q *queryData) WriteWhere(where Expression) error {
q.clauseType = where_clause
q.WriteString(" WHERE ")
return where.Serialize(q)
}
func (q *queryData) WriteGroupBy(groupBy []Clause) error {
q.clauseType = group_by_clause
q.WriteString(" GROUP BY ")
return serializeClauseList(groupBy, q)
}
func (q *queryData) WriteOrderBy(orderBy []OrderByClause) error {
q.clauseType = order_by_clause
q.WriteString(" ORDER BY ")
return serializeOrderByClauseList(orderBy, q)
}
func (q *queryData) WriteHaving(having Expression) error {
q.clauseType = having_clause
q.WriteString(" HAVING ")
return having.Serialize(q)
}
func (q *queryData) Write(data []byte) {
q.buff.Write(data)
}
func (q *queryData) WriteString(str string) {
q.buff.WriteString(str)
}
func (q *queryData) WriteByte(b byte) {
q.buff.WriteByte(b)
}
func (q *queryData) InsertArgument(arg interface{}) {
q.args = append(q.args, arg)
argPlaceholder := "$" + strconv.Itoa(len(q.args))
q.buff.WriteString(argPlaceholder)
}
func (q *queryData) Reset() {
q.buff.Reset()
q.args = []interface{}{}
}
func argToString(value interface{}) (string, error) {
switch bindVal := value.(type) {
case bool:
if bindVal {
return "TRUE", nil
} else {
return "FALSE", nil
}
case int8:
return strconv.FormatInt(int64(bindVal), 10), nil
case int:
return strconv.FormatInt(int64(bindVal), 10), nil
case int16:
return strconv.FormatInt(int64(bindVal), 10), nil
case int32:
return strconv.FormatInt(int64(bindVal), 10), nil
case int64:
return strconv.FormatInt(int64(bindVal), 10), nil
case uint8:
return strconv.FormatUint(uint64(bindVal), 10), nil
case uint:
return strconv.FormatUint(uint64(bindVal), 10), nil
case uint16:
return strconv.FormatUint(uint64(bindVal), 10), nil
case uint32:
return strconv.FormatUint(uint64(bindVal), 10), nil
case uint64:
return strconv.FormatUint(uint64(bindVal), 10), nil
case float32:
return strconv.FormatFloat(float64(bindVal), 'f', -1, 64), nil
case float64:
return strconv.FormatFloat(float64(bindVal), 'f', -1, 64), nil
case string:
return bindVal, nil
case []byte:
return string(bindVal), nil
//TODO: implement
//case time.Time:
// return bindVal.String())
default:
return "", errors.New("Unsupported literal type. ")
}
}
func contains(s []serializeOption, e serializeOption) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}