1
2
3
4
5
6
7
8
9
10
11
12
13 package kivik
14
15 import (
16 "context"
17 "encoding/json"
18 "net/http"
19
20 "github.com/go-kivik/kivik/v4/driver"
21 "github.com/go-kivik/kivik/v4/int/errors"
22 )
23
24
25
26
27
28
29
30
31
32
33
34 func (db *DB) Find(ctx context.Context, query interface{}, options ...Option) *ResultSet {
35 if db.err != nil {
36 return &ResultSet{iter: errIterator(db.err)}
37 }
38 finder, ok := db.driverDB.(driver.Finder)
39 if !ok {
40 return &ResultSet{iter: errIterator(errFindNotImplemented)}
41 }
42
43 jsonQuery, err := toQuery(query, options...)
44 if err != nil {
45 return &ResultSet{iter: errIterator(err)}
46 }
47
48 endQuery, err := db.startQuery()
49 if err != nil {
50 return &ResultSet{iter: errIterator(err)}
51 }
52 rowsi, err := finder.Find(ctx, jsonQuery, multiOptions(options))
53 if err != nil {
54 endQuery()
55 return &ResultSet{iter: errIterator(err)}
56 }
57 return newResultSet(ctx, endQuery, rowsi)
58 }
59
60
61
62 func toQuery(query interface{}, options ...Option) (json.RawMessage, error) {
63 var queryJSON []byte
64 switch t := query.(type) {
65 case string:
66 queryJSON = []byte(t)
67 case []byte:
68 queryJSON = t
69 case json.RawMessage:
70 queryJSON = t
71 default:
72 var err error
73 queryJSON, err = json.Marshal(query)
74 if err != nil {
75 return nil, &errors.Error{Status: http.StatusBadRequest, Err: err}
76 }
77 }
78 var queryObject map[string]interface{}
79 if err := json.Unmarshal(queryJSON, &queryObject); err != nil {
80 return nil, &errors.Error{Status: http.StatusBadRequest, Err: err}
81 }
82
83 opts := map[string]interface{}{}
84 multiOptions(options).Apply(opts)
85
86 for k, v := range opts {
87 queryObject[k] = v
88 }
89
90 return json.Marshal(queryObject)
91 }
92
93
94
95
96
97
98 func (db *DB) CreateIndex(ctx context.Context, ddoc, name string, index interface{}, options ...Option) error {
99 if db.err != nil {
100 return db.err
101 }
102 endQuery, err := db.startQuery()
103 if err != nil {
104 return err
105 }
106 defer endQuery()
107 if finder, ok := db.driverDB.(driver.Finder); ok {
108 return finder.CreateIndex(ctx, ddoc, name, index, multiOptions(options))
109 }
110 return errFindNotImplemented
111 }
112
113
114 func (db *DB) DeleteIndex(ctx context.Context, ddoc, name string, options ...Option) error {
115 if db.err != nil {
116 return db.err
117 }
118 endQuery, err := db.startQuery()
119 if err != nil {
120 return err
121 }
122 defer endQuery()
123 if finder, ok := db.driverDB.(driver.Finder); ok {
124 return finder.DeleteIndex(ctx, ddoc, name, multiOptions(options))
125 }
126 return errFindNotImplemented
127 }
128
129
130 type Index struct {
131 DesignDoc string `json:"ddoc,omitempty"`
132 Name string `json:"name"`
133 Type string `json:"type"`
134 Definition interface{} `json:"def"`
135 }
136
137
138 func (db *DB) GetIndexes(ctx context.Context, options ...Option) ([]Index, error) {
139 if db.err != nil {
140 return nil, db.err
141 }
142 endQuery, err := db.startQuery()
143 if err != nil {
144 return nil, err
145 }
146 defer endQuery()
147 if finder, ok := db.driverDB.(driver.Finder); ok {
148 dIndexes, err := finder.GetIndexes(ctx, multiOptions(options))
149 indexes := make([]Index, len(dIndexes))
150 for i, index := range dIndexes {
151 indexes[i] = Index(index)
152 }
153 return indexes, err
154 }
155 return nil, errFindNotImplemented
156 }
157
158
159
160 type QueryPlan struct {
161 DBName string `json:"dbname"`
162 Index map[string]interface{} `json:"index"`
163 Selector map[string]interface{} `json:"selector"`
164 Options map[string]interface{} `json:"opts"`
165 Limit int64 `json:"limit"`
166 Skip int64 `json:"skip"`
167
168
169
170 Fields []interface{} `json:"fields"`
171 Range map[string]interface{} `json:"range"`
172 }
173
174
175
176 func (db *DB) Explain(ctx context.Context, query interface{}, options ...Option) (*QueryPlan, error) {
177 if db.err != nil {
178 return nil, db.err
179 }
180 if explainer, ok := db.driverDB.(driver.Finder); ok {
181 endQuery, err := db.startQuery()
182 if err != nil {
183 return nil, err
184 }
185 defer endQuery()
186 plan, err := explainer.Explain(ctx, query, multiOptions(options))
187 if err != nil {
188 return nil, err
189 }
190 qp := QueryPlan(*plan)
191 return &qp, nil
192 }
193 return nil, errFindNotImplemented
194 }
195
View as plain text