# HG changeset patch # User Sascha L. Teichmann # Date 1552580733 -3600 # Node ID 8f3facf902ddcf878d28d0785a5bcc731ff2c156 # Parent d7b1dd25f91fcf4575a08e4d933761391fa211f2 Filter prev/next, too. diff -r d7b1dd25f91f -r 8f3facf902dd pkg/controllers/importqueue.go --- a/pkg/controllers/importqueue.go Thu Mar 14 16:20:16 2019 +0100 +++ b/pkg/controllers/importqueue.go Thu Mar 14 17:25:33 2019 +0100 @@ -51,6 +51,7 @@ summary IS NOT NULL AS has_summary, imports.id IN (SELECT id FROM warned) AS has_warnings FROM import.imports +WHERE ` selectImportSummaySQL = ` SELECT summary FROM import.imports WHERE id = $1` @@ -76,11 +77,13 @@ selectBeforeSQL = ` SELECT enqueued FROM import.imports -WHERE enqueued < $1 ORDER BY enqueued LIMIT 1` +WHERE +` selectAfterSQL = ` SELECT enqueued FROM import.imports -WHERE enqueued > $1 ORDER BY enqueued LIMIT 1` +WHERE +` ) func toInt8Array(txt string) *pgtype.Int8Array { @@ -151,75 +154,95 @@ fb.arg(format, v...) } -func queryImportListStmt( - conn *sql.Conn, - req *http.Request, -) (*sql.Rows, error) { +func buildFilters(req *http.Request) (l, b, a *filterBuilder, err error) { + + l = new(filterBuilder) + a = new(filterBuilder) + b = new(filterBuilder) - var fb filterBuilder + var noBefore, noAfter bool - fb.stmt.WriteString(selectImportsSQL) - - fb.stmt.WriteString(" WHERE ") + l.stmt.WriteString(selectImportsSQL) + a.stmt.WriteString(selectAfterSQL) + b.stmt.WriteString(selectBeforeSQL) if st := req.FormValue("states"); st != "" { states := toTextArray(st, imports.ImportStateNames) - fb.cond(" state = ANY($%d) ", states) + l.cond(" state = ANY($%d) ", states) + a.cond(" state = ANY($%d) ", states) + b.cond(" state = ANY($%d) ", states) } if ks := req.FormValue("kinds"); ks != "" { kinds := toTextArray(ks, imports.ImportKindNames()) - fb.cond(" kind = ANY($%d) ", kinds) + l.cond(" kind = ANY($%d) ", kinds) + a.cond(" kind = ANY($%d) ", kinds) + b.cond(" kind = ANY($%d) ", kinds) } if idss := req.FormValue("ids"); idss != "" { ids := toInt8Array(idss) - fb.cond(" id = ANY($%d) ", ids) + l.cond(" id = ANY($%d) ", ids) + a.cond(" id = ANY($%d) ", ids) + b.cond(" id = ANY($%d) ", ids) } if from := req.FormValue("from"); from != "" { - fromTime, err := time.Parse(models.ImportTimeFormat, from) - if err != nil { - return nil, err + var fromTime time.Time + if fromTime, err = time.Parse(models.ImportTimeFormat, from); err != nil { + return } - fb.cond(" enqueued >= $%d ", fromTime) + l.cond(" enqueued >= $%d ", fromTime) + b.cond(" enqueued < $%d", fromTime) + } else { + noBefore = true } if to := req.FormValue("to"); to != "" { - toTime, err := time.Parse(models.ImportTimeFormat, to) - if err != nil { - return nil, err + var toTime time.Time + if toTime, err = time.Parse(models.ImportTimeFormat, to); err != nil { + return } - fb.cond(" enqueued <= $%d ", toTime) + l.cond(" enqueued <= $%d ", toTime) + a.cond(" enqueued > $%d", toTime) + } else { + noAfter = true } switch warn := strings.ToLower(req.FormValue("warnings")); warn { case "1", "t", "true": - fb.cond(" id IN (SELECT id FROM warned) ") + l.cond(" id IN (SELECT id FROM warned) ") + a.cond(" id IN (SELECT id FROM warned) ") + b.cond(" id IN (SELECT id FROM warned) ") } - if !fb.hasCond { - fb.stmt.WriteString(" TRUE ") + if !l.hasCond { + l.stmt.WriteString(" TRUE ") + } + if !b.hasCond { + b.stmt.WriteString(" TRUE ") + } + if !a.hasCond { + a.stmt.WriteString(" TRUE ") } - fb.stmt.WriteString(" ORDER BY enqueued DESC ") + l.stmt.WriteString(" ORDER BY enqueued DESC ") + a.stmt.WriteString(" ORDER BY enqueued ") + b.stmt.WriteString(" ORDER BY enqueued ") - return conn.QueryContext(req.Context(), fb.stmt.String(), fb.args...) + if noBefore { + b = nil + } + if noAfter { + a = nil + } + return } -func enqueued(ctx context.Context, conn *sql.Conn, what, query string) *models.ImportTime { - if what == "" { - return nil - } - - t, err := time.Parse(models.ImportTimeFormat, what) - if err != nil { - log.Printf("warn: %v\n", err) - return nil - } +func neighbored(ctx context.Context, conn *sql.Conn, fb *filterBuilder) *models.ImportTime { var when time.Time - err = conn.QueryRowContext(ctx, query, t).Scan(&when) + err := conn.QueryRowContext(ctx, fb.stmt.String(), fb.args...).Scan(&when) switch { case err == sql.ErrNoRows: return nil @@ -227,16 +250,8 @@ log.Printf("warn: %v\n", err) return nil } - return &models.ImportTime{when} } -func enqueuedBefore(conn *sql.Conn, req *http.Request) *models.ImportTime { - return enqueued(req.Context(), conn, req.FormValue("from"), selectBeforeSQL) -} - -func enqueuedAfter(conn *sql.Conn, req *http.Request) *models.ImportTime { - return enqueued(req.Context(), conn, req.FormValue("to"), selectAfterSQL) -} func listImports( _ interface{}, @@ -244,9 +259,16 @@ conn *sql.Conn, ) (jr JSONResult, err error) { + var list, before, after *filterBuilder + + if list, before, after, err = buildFilters(req); err != nil { + return + } + + ctx := req.Context() + var rows *sql.Rows - rows, err = queryImportListStmt(conn, req) - if err != nil { + if rows, err = conn.QueryContext(ctx, list.stmt.String(), list.args...); err != nil { return } defer rows.Close() @@ -257,10 +279,11 @@ for rows.Next() { var it models.Import + var enqueued time.Time if err = rows.Scan( &it.ID, &it.State, - &it.Enqueued, + &enqueued, &it.Kind, &it.User, &signer, @@ -272,6 +295,7 @@ if signer.Valid { it.Signer = signer.String } + it.Enqueued = models.ImportTime{enqueued} imports = append(imports, &it) } @@ -279,6 +303,16 @@ return } + var prev, next *models.ImportTime + + if before != nil { + prev = neighbored(ctx, conn, before) + } + + if after != nil { + next = neighbored(ctx, conn, after) + } + jr = JSONResult{ Result: struct { Prev *models.ImportTime `json:"prev,omitempty"` @@ -286,8 +320,8 @@ Imports []*models.Import `json:"imports"` }{ Imports: imports, - Prev: enqueuedBefore(conn, req), - Next: enqueuedAfter(conn, req), + Prev: prev, + Next: next, }, } return