Documentation
¶
Overview ¶
Package page provides a small, validated value for query paging, shared by the transport (parsing ?page=/?rows= or gRPC fields) and the store (binding :offset / :rows_per_page, e.g. with dbx/dialect.Paginate).
Usage ¶
// REST: parse query params (non-numeric -> error -> 400).
pg, err := page.Parse(r.URL.Query().Get("page"), r.URL.Query().Get("rows"))
// gRPC / programmatic: clamp ints (0/unset -> first default page).
pg := page.New(int(req.GetPage()), int(req.GetPageSize()))
// store: bind the SQL paging parameters.
data := map[string]any{"offset": pg.Offset(), "rows_per_page": pg.RowsPerPage()}
New clamps the number to >= 1 and rows-per-page into [1, MaxRowsPerPage], defaulting non-positive rows to DefaultRowsPerPage. Pair the result with query.Result to return a paginated list envelope.
Cursor paging ¶
Cursor (keyset) paging is also supported via Cursor: an opaque token plus a limit. The SDK owns the token (EncodeCursor / Cursor.Key); the store builds the engine-specific keyset predicate and encodes the boundary row's key into the next cursor. Pair it with query.CursorResult.
c := page.NewCursor(r.URL.Query().Get("cursor"), 50)
key, _ := c.Key() // "" on the first page
// store: WHERE (created_at, id) < decode(key) ORDER BY ... LIMIT c.Limit()
next := page.EncodeCursor(lastRowKey) // "" when the page wasn't full
Index ¶
Constants ¶
const ( // DefaultPageNumber is used when no page number is requested. DefaultPageNumber = 1 // DefaultRowsPerPage is used when no page size is requested. DefaultRowsPerPage = 10 // MaxRowsPerPage caps the page size to bound result sizes. MaxRowsPerPage = 100 )
Variables ¶
This section is empty.
Functions ¶
func EncodeCursor ¶
EncodeCursor packs a store's keyset value (the sort key of the boundary row) into an opaque, URL-safe cursor token. An empty key yields an empty token.
Types ¶
type Cursor ¶
type Cursor struct {
// contains filtered or unexported fields
}
Cursor is a keyset (cursor) paging request: an opaque token marking the last item of the previous page plus a row limit. Cursor paging is stable under concurrent inserts and avoids large OFFSETs, at the cost of random access.
The SDK owns the opaque token (encode/decode); the keyset predicate itself — e.g. WHERE (created_at, id) < (:after_ts, :after_id) — is engine- and entity-specific and stays in the store, which encodes the last row's key into the next cursor via EncodeCursor.
func NewCursor ¶
NewCursor builds a Cursor, clamping the limit into [1, MaxRowsPerPage] (DefaultRowsPerPage when not positive). token is the opaque value from a prior page's next/prev link (empty for the first page).
type Page ¶
type Page struct {
// contains filtered or unexported fields
}
Page represents the requested page and rows per page.
func New ¶
New builds a Page from numeric values for trusted/optional inputs (e.g. gRPC fields where an unset value reads as 0, or programmatic callers). Unlike Parse, it is lenient: a non-positive number or rows-per-page falls back to the default, and rows above MaxRowsPerPage are capped rather than rejected.
func Parse ¶
Parse parses the strings (e.g. ?page= and ?rows= from untrusted client input) and validates the values are in reason. Empty strings fall back to the defaults; out-of-range or non-numeric values are errors a handler should map to a 400.