diff --git a/internal/storage/driver/module.go b/internal/storage/driver/module.go index 98299e211..f0be31b16 100644 --- a/internal/storage/driver/module.go +++ b/internal/storage/driver/module.go @@ -2,6 +2,7 @@ package driver import ( "context" + ledger "github.com/formancehq/ledger/internal" "github.com/formancehq/ledger/internal/storage/bucket" ledgerstore "github.com/formancehq/ledger/internal/storage/ledger" systemstore "github.com/formancehq/ledger/internal/storage/system" @@ -21,6 +22,15 @@ func NewFXModule() fx.Option { fx.Provide(fx.Annotate(func(tracerProvider trace.TracerProvider) bucket.Factory { return bucket.NewDefaultFactory(bucket.WithTracer(tracerProvider.Tracer("store"))) })), + fx.Invoke(func(db *bun.DB) { + db.Dialect().Tables().Register( + &ledger.Transaction{}, + &ledger.Log{}, + &ledger.Account{}, + &ledger.Move{}, + &ledger.Ledger{}, + ) + }), fx.Provide(func(params struct { fx.In diff --git a/internal/storage/ledger/paginator_column.go b/internal/storage/ledger/paginator_column.go index 1cca2bb10..1e412b31e 100644 --- a/internal/storage/ledger/paginator_column.go +++ b/internal/storage/ledger/paginator_column.go @@ -6,6 +6,7 @@ import ( "github.com/formancehq/go-libs/v2/time" ledgercontroller "github.com/formancehq/ledger/internal/controller/ledger" "github.com/uptrace/bun" + "github.com/uptrace/bun/schema" "math/big" "reflect" "strings" @@ -15,6 +16,7 @@ import ( type columnPaginator[ResourceType, OptionsType any] struct { defaultPaginationColumn string defaultOrder bunpaginate.Order + Table *schema.Table } //nolint:unused @@ -24,6 +26,7 @@ func (o columnPaginator[ResourceType, OptionsType]) paginate(sb *bun.SelectQuery if query.Column != "" { paginationColumn = query.Column } + originalOrder := o.defaultOrder if query.Order != nil { originalOrder = *query.Order @@ -43,19 +46,23 @@ func (o columnPaginator[ResourceType, OptionsType]) paginate(sb *bun.SelectQuery sb = sb.ColumnExpr("row_number() OVER (ORDER BY " + orderExpression + ")") if query.PaginationID != nil { + paginationID := convertPaginationIDToSQLType( + o.Table.FieldMap[paginationColumn].DiscoveredSQLType, + query.PaginationID, + ) if query.Reverse { switch originalOrder { case bunpaginate.OrderAsc: - sb = sb.Where(fmt.Sprintf("%s < ?", paginationColumn), query.PaginationID) + sb = sb.Where(fmt.Sprintf("%s < ?", paginationColumn), paginationID) case bunpaginate.OrderDesc: - sb = sb.Where(fmt.Sprintf("%s > ?", paginationColumn), query.PaginationID) + sb = sb.Where(fmt.Sprintf("%s > ?", paginationColumn), paginationID) } } else { switch originalOrder { case bunpaginate.OrderAsc: - sb = sb.Where(fmt.Sprintf("%s >= ?", paginationColumn), query.PaginationID) + sb = sb.Where(fmt.Sprintf("%s >= ?", paginationColumn), paginationID) case bunpaginate.OrderDesc: - sb = sb.Where(fmt.Sprintf("%s <= ?", paginationColumn), query.PaginationID) + sb = sb.Where(fmt.Sprintf("%s <= ?", paginationColumn), paginationID) } } } @@ -63,6 +70,16 @@ func (o columnPaginator[ResourceType, OptionsType]) paginate(sb *bun.SelectQuery return sb, nil } +//nolint:unused +func convertPaginationIDToSQLType(sqlType string, id *big.Int) any { + switch sqlType { + case "timestamp without time zone", "timestamp": + return libtime.UnixMicro(id.Int64()) + default: + return id + } +} + //nolint:unused func (o columnPaginator[ResourceType, OptionsType]) buildCursor(ret []ResourceType, query ledgercontroller.ColumnPaginatedQuery[OptionsType]) (*bunpaginate.Cursor[ResourceType], error) { diff --git a/internal/storage/ledger/resource.go b/internal/storage/ledger/resource.go index a903a4250..6e734472a 100644 --- a/internal/storage/ledger/resource.go +++ b/internal/storage/ledger/resource.go @@ -306,7 +306,6 @@ func (r *paginatedResourceRepository[ResourceType, OptionsType, PaginationQueryT finalQuery = finalQuery.Order("row_number") ret := make([]ResourceType, 0) - //fmt.Println(finalQuery.Model(&ret).String()) err = finalQuery.Model(&ret).Scan(ctx) if err != nil { return nil, fmt.Errorf("scanning results: %w", err) diff --git a/internal/storage/ledger/store.go b/internal/storage/ledger/store.go index e9efddc63..0c323da5a 100644 --- a/internal/storage/ledger/store.go +++ b/internal/storage/ledger/store.go @@ -65,6 +65,7 @@ func (store *Store) Transactions() ledgercontroller.PaginatedResource[ return newPaginatedResourceRepository(store, store.ledger, &transactionsResourceHandler{}, columnPaginator[ledger.Transaction, any]{ defaultPaginationColumn: "id", defaultOrder: bunpaginate.OrderDesc, + Table: store.db.Dialect().Tables().ByName("transactions"), }) } @@ -75,6 +76,7 @@ func (store *Store) Logs() ledgercontroller.PaginatedResource[ return newPaginatedResourceRepositoryMapper[ledger.Log, Log, any, ledgercontroller.ColumnPaginatedQuery[any]](store, store.ledger, &logsResourceHandler{}, columnPaginator[Log, any]{ defaultPaginationColumn: "id", defaultOrder: bunpaginate.OrderDesc, + Table: store.db.Dialect().Tables().ByName("logs"), }) } diff --git a/test/e2e/api_transactions_list_test.go b/test/e2e/api_transactions_list_test.go index 923546874..24ff4d315 100644 --- a/test/e2e/api_transactions_list_test.go +++ b/test/e2e/api_transactions_list_test.go @@ -219,6 +219,22 @@ var _ = Context("Ledger transactions list API tests", func() { slices.Reverse(page) Expect(rsp.Data).To(Equal(page)) }) + When("using next page", func() { + JustBeforeEach(func(specContext SpecContext) { + rsp, err = ListTransactions( + ctx, + testServer.GetValue(), + operations.V2ListTransactionsRequest{ + Ledger: "default", + Cursor: rsp.Next, + }, + ) + Expect(err).ToNot(HaveOccurred()) + }) + It("Should return next elements", func() { + Expect(rsp.Data).To(HaveLen(int(pageSize))) + }) + }) }) It("Should be ok", func() { Expect(rsp.PageSize).To(Equal(pageSize))