feat(count): add QueryCount pagination helpers
Adds CountResult, QueryCount, BuildQueryCountFn, and ReadableTable alias for Jet pagination total counts, with tests and docs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
- `StringKSUID.Equal` / `IsZero`, `BinaryKSUID.Equal` / `IsZero`, and nil sentinel vars for [ApplyInterfacePtr].
|
- `StringKSUID.Equal` / `IsZero`, `BinaryKSUID.Equal` / `IsZero`, and nil sentinel vars for [ApplyInterfacePtr].
|
||||||
- `Query`, `MustQuery`, and `UpdateOne` helpers (+ Context variants).
|
- `Query`, `MustQuery`, and `UpdateOne` helpers (+ Context variants).
|
||||||
- `WithTxValue` for transactional functions that return a value.
|
- `WithTxValue` for transactional functions that return a value.
|
||||||
|
- `QueryCount`, `BuildQueryCountFn`, and `CountResult` for pagination counts.
|
||||||
- Context-aware variants for all query and mutation helpers.
|
- Context-aware variants for all query and mutation helpers.
|
||||||
- `Delete`, `DeleteAffected`, `WithTx`, `ContainsCol`, and `CurrentDialect()`.
|
- `Delete`, `DeleteAffected`, `WithTx`, `ContainsCol`, and `CurrentDialect()`.
|
||||||
- Package documentation (`doc.go`), expanded README, and subpackage docs for `dbxm` / `dbxp`.
|
- Package documentation (`doc.go`), expanded README, and subpackage docs for `dbxm` / `dbxp`.
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ For Postgres, use `dbx.DialectPostgres` and blank-import `dbxp` instead of `dbxm
|
|||||||
| Query | `Fetch`, `MustFetch`, `FetchOne`, `MustFetchOne`, `Query`, `MustQuery` (+ `*Context` variants) |
|
| Query | `Fetch`, `MustFetch`, `FetchOne`, `MustFetchOne`, `Query`, `MustQuery` (+ `*Context` variants) |
|
||||||
| Mutations | `Insert`, `InsertReturning`, `Update`, `UpdateAffected`, `UpdateOne`, `UpdateReturning`, `Delete`, `DeleteAffected` (+ `*Context` variants) |
|
| Mutations | `Insert`, `InsertReturning`, `Update`, `UpdateAffected`, `UpdateOne`, `UpdateReturning`, `Delete`, `DeleteAffected` (+ `*Context` variants) |
|
||||||
| Transactions | `WithTx`, `WithTxValue` |
|
| Transactions | `WithTx`, `WithTxValue` |
|
||||||
| Columns | `NormalCols`, `ContainsCol`, `ExprValues`, `ExprStringers` |
|
| Columns | `NormalCols`, `ContainsCol`, `ExprValues`, `ExprStringers`, `QueryCount`, `BuildQueryCountFn` |
|
||||||
| Partial update | `ApplyPtr`, `ApplyComplexPtr`, `ApplyInterfacePtr`, `ApplyVal` |
|
| Partial update | `ApplyPtr`, `ApplyComplexPtr`, `ApplyInterfacePtr`, `ApplyVal` |
|
||||||
| Pointers | `Ptr`, `Val`, `NowPtr`, `TrimPtr`, `TrimPtrToNil`, `IsZero` |
|
| Pointers | `Ptr`, `Val`, `NowPtr`, `TrimPtr`, `TrimPtrToNil`, `IsZero` |
|
||||||
| Types | `StringKSUID`, `BinaryKSUID`, `JSONB` |
|
| Types | `StringKSUID`, `BinaryKSUID`, `JSONB` |
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package dbx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-jet/jet/v2/mysql"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CountResult holds the count from a Jet COUNT query. Use with a SELECT that
|
||||||
|
// aliases the count as `CountResult.Count`, for example:
|
||||||
|
//
|
||||||
|
// SELECT(mysql.COUNT(col).AS("CountResult.Count"))
|
||||||
|
type CountResult struct {
|
||||||
|
Count int
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryCountFn counts rows matching pre-bound table and condition parameters.
|
||||||
|
type QueryCountFn func(sqlo Queryable) (int, error)
|
||||||
|
|
||||||
|
// QueryCount counts rows in tbl matching conds.
|
||||||
|
func QueryCount(
|
||||||
|
sqlo Queryable,
|
||||||
|
col Column,
|
||||||
|
tbl ReadableTable,
|
||||||
|
conds BoolExpression,
|
||||||
|
) (int, error) {
|
||||||
|
stmt := tbl.SELECT(mysql.COUNT(col).AS("CountResult.Count")).WHERE(conds)
|
||||||
|
var res CountResult
|
||||||
|
if err := stmt.Query(sqlo, &res); err != nil {
|
||||||
|
return 0, fmt.Errorf("query count: %w", err)
|
||||||
|
}
|
||||||
|
return res.Count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildQueryCountFn returns a QueryCountFn with col, tbl, and conds bound.
|
||||||
|
func BuildQueryCountFn(
|
||||||
|
col Column,
|
||||||
|
tbl ReadableTable,
|
||||||
|
conds BoolExpression,
|
||||||
|
) QueryCountFn {
|
||||||
|
return func(sqlo Queryable) (int, error) {
|
||||||
|
return QueryCount(sqlo, col, tbl, conds)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package dbx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCountResult_Scan(t *testing.T) {
|
||||||
|
stmt := mockStatement{
|
||||||
|
queryContextFn: func(_ context.Context, dest any) error {
|
||||||
|
ptr := dest.(*CountResult)
|
||||||
|
ptr.Count = 3
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var scanned CountResult
|
||||||
|
err := stmt.Query(mockQueryable{}, &scanned)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, 3, scanned.Count)
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
//
|
//
|
||||||
// Dialect-neutral type aliases ([Column], [ColumnList]) and helpers for column
|
// Dialect-neutral type aliases ([Column], [ColumnList]) and helpers for column
|
||||||
// lists ([NormalCols], [ContainsCol]) and expression building ([ExprValues]).
|
// lists ([NormalCols], [ContainsCol]) and expression building ([ExprValues]).
|
||||||
|
// [QueryCount] and [BuildQueryCountFn] support pagination total counts.
|
||||||
//
|
//
|
||||||
// Partial-update helpers ([ApplyPtr], [ApplyVal]) track changed fields for
|
// Partial-update helpers ([ApplyPtr], [ApplyVal]) track changed fields for
|
||||||
// repository patch logic.
|
// repository patch logic.
|
||||||
|
|||||||
@@ -13,3 +13,6 @@ type Expression = mysql.Expression
|
|||||||
|
|
||||||
// BoolExpression is a dialect-neutral alias for Jet boolean expressions.
|
// BoolExpression is a dialect-neutral alias for Jet boolean expressions.
|
||||||
type BoolExpression = mysql.BoolExpression
|
type BoolExpression = mysql.BoolExpression
|
||||||
|
|
||||||
|
// ReadableTable is a dialect-neutral alias for Jet readable tables.
|
||||||
|
type ReadableTable = mysql.ReadableTable
|
||||||
|
|||||||
Reference in New Issue
Block a user