-
Notifications
You must be signed in to change notification settings - Fork 1
/
select.go
105 lines (88 loc) · 2.92 KB
/
select.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
package makroud
import (
"context"
"github.com/pkg/errors"
"github.com/ulule/loukoum/v3"
"github.com/ulule/loukoum/v3/builder"
"github.com/ulule/loukoum/v3/stmt"
"github.com/ulule/makroud/reflectx"
)
// Select retrieves the given instance using given arguments as criteria.
// This method accepts loukoum's stmt.Order, stmt.Offet, stmt.Limit and stmt.Expression as arguments.
// For unsupported statement, they will be ignored.
func Select(ctx context.Context, driver Driver, dest interface{}, args ...interface{}) error {
if !reflectx.IsPointer(dest) {
return errors.Wrapf(ErrPointerRequired, "makroud: cannot execute query on %T", dest)
}
if reflectx.IsSlice(dest) {
return selectRows(ctx, driver, dest, args)
}
return selectRow(ctx, driver, dest, args)
}
func selectRow(ctx context.Context, driver Driver, dest interface{}, args []interface{}) error {
model, ok := reflectx.GetFlattenValue(dest).(Model)
if !ok {
return errors.Wrapf(ErrModelRequired, "makroud: cannot execute query on %T", dest)
}
schema, err := GetSchema(driver, model)
if err != nil {
return errors.Wrapf(err, "makroud: cannot fetch schema informations on %T", dest)
}
columns := schema.ColumnPaths()
query, parsed := parseSelectArgs(loukoum.Select(columns.List()).From(model.TableName()), args)
if !parsed.hasLimit {
query = query.Limit(1)
}
if !parsed.hasOrder {
query = query.OrderBy(loukoum.Order(schema.PrimaryKeyName()))
}
if schema.HasDeletedKey() {
query = query.Where(loukoum.Condition(schema.DeletedKeyName()).IsNull(true))
}
return Exec(ctx, driver, query, dest)
}
func selectRows(ctx context.Context, driver Driver, dest interface{}, args []interface{}) error {
model, ok := reflectx.NewSliceValue(dest).(Model)
if !ok {
return errors.Wrapf(ErrModelRequired, "makroud: cannot execute query on %T", dest)
}
schema, err := GetSchema(driver, model)
if err != nil {
return errors.Wrapf(err, "makroud: cannot fetch schema informations on %T", dest)
}
columns := schema.ColumnPaths()
query, parsed := parseSelectArgs(loukoum.Select(columns.List()).From(model.TableName()), args)
if !parsed.hasOrder {
query = query.OrderBy(loukoum.Order(schema.PrimaryKeyName()))
}
if schema.HasDeletedKey() {
query = query.Where(loukoum.Condition(schema.DeletedKeyName()).IsNull(true))
}
return Exec(ctx, driver, query, dest)
}
type parsedSelectArgs struct {
hasLimit bool
hasOffset bool
hasOrder bool
hasExpression bool
}
func parseSelectArgs(query builder.Select, args []interface{}) (builder.Select, parsedSelectArgs) {
result := parsedSelectArgs{}
for i := range args {
switch v := args[i].(type) {
case stmt.Limit:
result.hasLimit = true
query = query.Limit(v)
case stmt.Offset:
result.hasOffset = true
query = query.Offset(v)
case stmt.Order:
result.hasOrder = true
query = query.OrderBy(v)
case stmt.Expression:
result.hasExpression = true
query = query.Where(v)
}
}
return query, result
}