Mercurial > gemma
comparison pkg/controllers/importqueue.go @ 3194:eeff2cc4ff9d
controllers: re-factored the SQL filter to a tree like structure to be of more general use.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Wed, 08 May 2019 13:11:30 +0200 |
parents | 54a3e40cfbed |
children | 4c254651d80b |
comparison
equal
deleted
inserted
replaced
3193:8329c6d3cf2a | 3194:eeff2cc4ff9d |
---|---|
130 return nil | 130 return nil |
131 } | 131 } |
132 return &ta | 132 return &ta |
133 } | 133 } |
134 | 134 |
135 func buildFilters(req *http.Request) (l, b, a *filterBuilder, err error) { | 135 type filledStmt struct { |
136 | 136 stmt strings.Builder |
137 l = new(filterBuilder) | 137 args []interface{} |
138 a = new(filterBuilder) | 138 } |
139 b = new(filterBuilder) | 139 |
140 func buildFilters(req *http.Request) (*filledStmt, *filledStmt, *filledStmt, error) { | |
141 | |
142 var l, a, b filterAnd | |
140 | 143 |
141 var noBefore, noAfter bool | 144 var noBefore, noAfter bool |
142 | 145 |
143 var counting bool | 146 cond := func(format string, args ...interface{}) { |
144 | 147 term := &filterTerm{format: format, args: args} |
145 switch count := strings.ToLower(req.FormValue("count")); count { | 148 l = append(l, term) |
146 case "1", "t", "true": | 149 a = append(l, term) |
147 counting = true | 150 b = append(b, term) |
148 l.stmt.WriteString(selectImportsCountSQL) | |
149 default: | |
150 l.stmt.WriteString(selectImportsSQL) | |
151 } | |
152 a.stmt.WriteString(selectAfterSQL) | |
153 b.stmt.WriteString(selectBeforeSQL) | |
154 | |
155 cond := func(format string, v ...interface{}) { | |
156 l.and(format, v...) | |
157 a.and(format, v...) | |
158 b.and(format, v...) | |
159 } | 151 } |
160 | 152 |
161 if query := req.FormValue("query"); query != "" { | 153 if query := req.FormValue("query"); query != "" { |
162 query = "%" + query + "%" | 154 query = "%" + query + "%" |
163 cond(` (kind ILIKE $%d OR username ILIKE $%d OR signer ILIKE $%d OR `+ | 155 cond(` (kind ILIKE $%d OR username ILIKE $%d OR signer ILIKE $%d OR `+ |
179 ids := toInt8Array(idss) | 171 ids := toInt8Array(idss) |
180 cond(" id = ANY($%d) ", ids) | 172 cond(" id = ANY($%d) ", ids) |
181 } | 173 } |
182 | 174 |
183 if from := req.FormValue("from"); from != "" { | 175 if from := req.FormValue("from"); from != "" { |
184 var fromTime time.Time | 176 fromTime, err := time.Parse(models.ImportTimeFormat, from) |
185 if fromTime, err = time.Parse(models.ImportTimeFormat, from); err != nil { | 177 if err != nil { |
186 return | 178 return nil, nil, nil, err |
187 } | 179 } |
188 l.and(" enqueued >= $%d ", fromTime) | 180 l = append(l, buildFilterTerm("enqueued >= $%d", fromTime)) |
189 b.and(" enqueued < $%d", fromTime) | 181 b = append(b, buildFilterTerm("enqueued < $%d", fromTime)) |
190 } else { | 182 } else { |
191 noBefore = true | 183 noBefore = true |
192 } | 184 } |
193 | 185 |
194 if to := req.FormValue("to"); to != "" { | 186 if to := req.FormValue("to"); to != "" { |
195 var toTime time.Time | 187 toTime, err := time.Parse(models.ImportTimeFormat, to) |
196 if toTime, err = time.Parse(models.ImportTimeFormat, to); err != nil { | 188 if err != nil { |
197 return | 189 return nil, nil, nil, err |
198 } | 190 } |
199 l.and(" enqueued <= $%d ", toTime) | 191 l = append(l, buildFilterTerm("enqueued <= $%d", toTime)) |
200 a.and(" enqueued > $%d", toTime) | 192 a = append(a, buildFilterTerm("enqueued > $%d", toTime)) |
201 } else { | 193 } else { |
202 noAfter = true | 194 noAfter = true |
203 } | 195 } |
204 | 196 |
205 switch warn := strings.ToLower(req.FormValue("warnings")); warn { | 197 switch warn := strings.ToLower(req.FormValue("warnings")); warn { |
206 case "1", "t", "true": | 198 case "1", "t", "true": |
207 cond(" id IN (SELECT id FROM warned) ") | 199 cond(" id IN (SELECT id FROM warned) ") |
208 } | 200 } |
209 | 201 |
210 if !l.hasCond { | 202 fl := &filledStmt{} |
211 l.stmt.WriteString(" TRUE ") | 203 fa := &filledStmt{} |
212 } | 204 fb := &filledStmt{} |
213 if !b.hasCond { | 205 |
214 b.stmt.WriteString(" TRUE ") | 206 fa.stmt.WriteString(selectAfterSQL) |
215 } | 207 fb.stmt.WriteString(selectBeforeSQL) |
216 if !a.hasCond { | 208 |
217 a.stmt.WriteString(" TRUE ") | 209 var counting bool |
210 | |
211 switch count := strings.ToLower(req.FormValue("count")); count { | |
212 case "1", "t", "true": | |
213 counting = true | |
214 fl.stmt.WriteString(selectImportsCountSQL) | |
215 default: | |
216 fl.stmt.WriteString(selectImportsSQL) | |
217 } | |
218 | |
219 if len(l) == 0 { | |
220 fl.stmt.WriteString(" TRUE ") | |
221 } else { | |
222 l.serialize(&fl.stmt, &fl.args) | |
223 } | |
224 | |
225 if len(b) == 0 { | |
226 fb.stmt.WriteString(" TRUE ") | |
227 } else { | |
228 b.serialize(&fb.stmt, &fb.args) | |
229 } | |
230 | |
231 if len(a) == 0 { | |
232 fa.stmt.WriteString(" TRUE ") | |
233 } else { | |
234 a.serialize(&fa.stmt, &fa.args) | |
218 } | 235 } |
219 | 236 |
220 if !counting { | 237 if !counting { |
221 l.stmt.WriteString(" ORDER BY enqueued DESC ") | 238 fl.stmt.WriteString(" ORDER BY enqueued DESC ") |
222 a.stmt.WriteString(" ORDER BY enqueued LIMIT 1") | 239 fa.stmt.WriteString(" ORDER BY enqueued LIMIT 1") |
223 b.stmt.WriteString(" ORDER BY enqueued DESC LIMIT 1") | 240 fb.stmt.WriteString(" ORDER BY enqueued DESC LIMIT 1") |
224 } | 241 } |
225 | 242 |
226 if noBefore { | 243 if noBefore { |
227 b = nil | 244 fb = nil |
228 } | 245 } |
229 if noAfter { | 246 if noAfter { |
230 a = nil | 247 fa = nil |
231 } | 248 } |
232 return | 249 |
233 } | 250 return fl, fb, fa, nil |
234 | 251 } |
235 func neighbored(ctx context.Context, conn *sql.Conn, fb *filterBuilder) *models.ImportTime { | 252 |
253 func neighbored(ctx context.Context, conn *sql.Conn, fb *filledStmt) *models.ImportTime { | |
236 | 254 |
237 var when time.Time | 255 var when time.Time |
238 err := conn.QueryRowContext(ctx, fb.stmt.String(), fb.args...).Scan(&when) | 256 err := conn.QueryRowContext(ctx, fb.stmt.String(), fb.args...).Scan(&when) |
239 switch { | 257 switch { |
240 case err == sql.ErrNoRows: | 258 case err == sql.ErrNoRows: |
250 _ interface{}, | 268 _ interface{}, |
251 req *http.Request, | 269 req *http.Request, |
252 conn *sql.Conn, | 270 conn *sql.Conn, |
253 ) (jr JSONResult, err error) { | 271 ) (jr JSONResult, err error) { |
254 | 272 |
255 var list, before, after *filterBuilder | 273 var list, before, after *filledStmt |
256 | 274 |
257 if list, before, after, err = buildFilters(req); err != nil { | 275 if list, before, after, err = buildFilters(req); err != nil { |
258 return | 276 return |
259 } | 277 } |
260 | 278 |