/
query.go
128 lines (107 loc) · 2.73 KB
/
query.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package db
import (
"database/sql"
"fmt"
"github.com/jmoiron/sqlx"
)
type Query interface {
One(db Executor, object interface{}) error
All(db Executor, object []interface{}) error
}
// A Simple SQL Select Statement
type SelectStatement struct {
Table string
WhereClause Clause
LimitClause Clause
OrderClause Clause
}
func (c *SelectStatement) Compile() (string, map[string]interface{}) {
outStatement := fmt.Sprintf("SELECT * FROM %s", c.Table)
outObjects := make(map[string]interface{})
if c.WhereClause != nil {
whereStmt, whereObj := c.WhereClause.Compile()
outStatement = fmt.Sprintf("%s WHERE (%s)", outStatement, whereStmt)
outObjects = mapUnion(outObjects, whereObj)
}
if c.OrderClause != nil {
orderStmt, orderObj := c.OrderClause.Compile()
outStatement = fmt.Sprintf("%s ORDER BY %s", outStatement, orderStmt)
outObjects = mapUnion(outObjects, orderObj)
}
if c.LimitClause != nil {
limitStmt, limitObj := c.LimitClause.Compile()
outStatement = fmt.Sprintf("%s LIMIT %s", outStatement, limitStmt)
outObjects = mapUnion(outObjects, limitObj)
}
return outStatement, outObjects
}
func (q *SelectStatement) Order(key string, ascending bool) *SelectStatement {
q.OrderClause = &OrderClause{
Key: key,
Ascending: ascending,
}
return q
}
func (q *SelectStatement) Limit(number int) *SelectStatement {
q.LimitClause = &LimitClause{
Number: number,
}
return q
}
func (q *SelectStatement) WhereClauseAnd(where Clause) *SelectStatement {
if q.WhereClause == nil {
a := make(AndClauses, 1)
a[0] = where
q.WhereClause = a
} else {
obj, ok := q.WhereClause.(AndClauses)
if !ok {
panic("Cannot and to something that isn't an AND Clause.")
}
obj = append(obj, where)
q.WhereClause = obj
}
return q
}
func (q *SelectStatement) Where(key string, value interface{}) *SelectStatement {
return q.WhereClauseAnd(&NamedEquality{
Name: key,
Value: value,
})
}
func (q *SelectStatement) One(db Executor, object interface{}) error {
q.Limit(1)
stmt, obj := q.Compile()
rows, err := db.NamedQuery(stmt, obj)
if err != nil {
return err
}
defer rows.Rows.Close()
if !rows.Next() {
return nil
}
err = rows.StructScan(object)
if err != nil {
return err
}
// Load Relationships
id := int64(-1)
examineObject(object, func(p PrimaryKey, name string) {
id = int64(p)
}, nil, nil, nil)
loadRelationships(object, id)
return nil
}
func (q *SelectStatement) All(db Executor, object interface{}) error {
stmt, obj := q.Compile()
rows, err := db.NamedQuery(stmt, obj)
if err != nil {
return err
}
defer rows.Rows.Close()
return sqlx.StructScan(rows, object)
}
func (c *SelectStatement) Exec(db Executor) (sql.Result, error) {
stmt, obj := c.Compile()
return db.NamedExec(stmt, obj)
}