Add support for pagination to netquery module

This commit is contained in:
Patrick Pacher
2022-05-10 10:04:21 +02:00
parent 25aceaf103
commit bef911e925
2 changed files with 34 additions and 2 deletions

View File

@@ -59,6 +59,8 @@ type (
OrderBy OrderBys `json:"orderBy"`
GroupBy []string `json:"groupBy"`
Pagination
selectedFields []string
whitelistedFields []string
paramMap map[string]interface{}
@@ -74,6 +76,11 @@ type (
}
OrderBys []OrderBy
Pagination struct {
PageSize int `json:"pageSize"`
Page int `json:"page"`
}
)
func (query *Query) UnmarshalJSON(blob []byte) error {
@@ -156,6 +163,30 @@ func (query *Query) UnmarshalJSON(blob []byte) error {
return nil
}
// TODO(ppacher): right now we only support LIMIT and OFFSET for pagination but that
// has an issue that loading the same page twice might yield different results due to
// new records shifting the result slice. To overcome this, return a "PageToken" to the
// user that includes the time the initial query was created so paginated queries can
// ensure new records don't end up in the result set.
func (page *Pagination) toSQLLimitOffsetClause() string {
limit := page.PageSize
// default and cap the limit to at most 100 items
// per page to avoid out-of-memory conditions when loading
// thousands of results at once.
if limit <= 0 || limit > 100 {
limit = 100
}
sql := fmt.Sprintf("LIMIT %d", limit)
if page.Page > 0 {
sql += fmt.Sprintf(" OFFSET %d", page.Page*limit)
}
return sql
}
func parseMatcher(raw json.RawMessage) (*Matcher, error) {
var m Matcher
if err := json.Unmarshal(raw, &m); err != nil {

View File

@@ -181,9 +181,10 @@ func (req *QueryRequestPayload) generateSQL(ctx context.Context, schema *orm.Tab
if whereClause != "" {
query += " WHERE " + whereClause
}
query += " " + groupByClause + " " + orderByClause
return query, req.paramMap, nil
query += " " + groupByClause + " " + orderByClause + " " + req.Pagination.toSQLLimitOffsetClause()
return strings.TrimSpace(query), req.paramMap, nil
}
func (req *QueryRequestPayload) prepareSelectedFields(ctx context.Context, schema *orm.TableSchema) error {