diff --git a/backend/pkg/api/data_access/general.go b/backend/pkg/api/data_access/general.go index e22b8dccb..3bbebc355 100644 --- a/backend/pkg/api/data_access/general.go +++ b/backend/pkg/api/data_access/general.go @@ -7,7 +7,6 @@ import ( "github.com/doug-martin/goqu/v9/exp" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/gobitfly/beaconchain/pkg/api/types" - t "github.com/gobitfly/beaconchain/pkg/api/types" "github.com/gobitfly/beaconchain/pkg/commons/db" ) @@ -53,9 +52,9 @@ func (d *DataAccessService) GetNamesAndEnsForAddresses(ctx context.Context, addr // helper function to sort and apply pagination to a query // 1st param is the list of all columns necessary to sort the table deterministically; it defines their precedence and sort direction // 2nd param is the requested sort column; it may or may not be part of the default columns -func applySortAndPagination(defaultColumns []t.SortColumn, primary t.SortColumn, cursor t.GenericCursor) ([]exp.OrderedExpression, exp.Expression) { +func applySortAndPagination(defaultColumns []types.SortColumn, primary types.SortColumn, cursor types.GenericCursor) ([]exp.OrderedExpression, exp.Expression) { // prepare ordering columns; always need all columns to ensure consistent ordering - queryOrderColumns := make([]t.SortColumn, 0, len(defaultColumns)) + queryOrderColumns := make([]types.SortColumn, 0, len(defaultColumns)) queryOrderColumns = append(queryOrderColumns, primary) // secondary sorts according to default for _, column := range defaultColumns { @@ -66,10 +65,11 @@ func applySortAndPagination(defaultColumns []t.SortColumn, primary t.SortColumn, // apply ordering queryOrder := []exp.OrderedExpression{} - for _, column := range queryOrderColumns { + for i := range queryOrderColumns { if cursor.IsReverse() { - column.Desc = !column.Desc + queryOrderColumns[i].Desc = !queryOrderColumns[i].Desc } + column := queryOrderColumns[i] colOrder := goqu.C(column.Column).Asc() if column.Desc { colOrder = goqu.C(column.Column).Desc() @@ -83,17 +83,18 @@ func applySortAndPagination(defaultColumns []t.SortColumn, primary t.SortColumn, // reverse order to nest conditions for i := len(queryOrderColumns) - 1; i >= 0; i-- { column := queryOrderColumns[i] - colWhere := goqu.C(column.Column).Gt(column.Offset) if column.Desc { colWhere = goqu.C(column.Column).Lt(column.Offset) } - if i == len(queryOrderColumns)-1 { - queryWhere = colWhere + equal := goqu.C(column.Column).Eq(column.Offset) + if queryWhere == nil { + queryWhere = equal } else { - queryWhere = goqu.Or(colWhere, goqu.And(goqu.C(column.Column).Eq(column.Offset), queryWhere)) + queryWhere = goqu.And(equal, queryWhere) } + queryWhere = goqu.Or(colWhere, queryWhere) } } diff --git a/backend/pkg/api/data_access/notifications.go b/backend/pkg/api/data_access/notifications.go index a68c74b49..aec3bbbb9 100644 --- a/backend/pkg/api/data_access/notifications.go +++ b/backend/pkg/api/data_access/notifications.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "regexp" + "slices" "strings" "github.com/doug-martin/goqu/v9" @@ -64,11 +65,15 @@ func (d *DataAccessService) GetDashboardNotifications(ctx context.Context, userI goqu.I("uvd.name").As("dashboard_name"), goqu.I("uvdg.id").As("group_id"), goqu.I("uvdg.name").As("group_name"), - goqu.SUM("vnh.event_count"), + goqu.SUM("vnh.event_count").As("entity_count"), goqu.L("ARRAY_AGG(DISTINCT event_type)").As("event_types"), ). - InnerJoin(goqu.T("users_val_dashboards").As("uvd"), goqu.On(goqu.Ex{"uvd.id": goqu.I("vnh.dashboard_id")})). - InnerJoin(goqu.T("users_val_dashboards_groups").As("uvdg"), goqu.On(goqu.Ex{"uvdg.id": goqu.I("vnh.group_id")})). + InnerJoin(goqu.T("users_val_dashboards").As("uvd"), goqu.On( + goqu.Ex{"uvd.id": goqu.I("vnh.dashboard_id")})). + InnerJoin(goqu.T("users_val_dashboards_groups").As("uvdg"), goqu.On( + goqu.Ex{"uvdg.id": goqu.I("vnh.group_id")}, + goqu.Ex{"uvdg.dashboard_id": goqu.I("uvd.id")}, + )). Where( goqu.Ex{"uvd.user_id": userId}, goqu.L("uvd.network = ANY(?)", pq.Array(chainIds)), @@ -92,11 +97,16 @@ func (d *DataAccessService) GetDashboardNotifications(ctx context.Context, userI goqu.I("uad.name").As("dashboard_name"), goqu.I("uadg.id").As("group_id"), goqu.I("uadg.name").As("group_name"), - goqu.SUM("anh.event_count"), + goqu.SUM("anh.event_count").As("entity_count"), goqu.L("ARRAY_AGG(DISTINCT event_type)").As("event_types"), ). - InnerJoin(goqu.T("users_acc_dashboards").As("uad"), goqu.On(goqu.Ex{"uad.id": goqu.I("anh.dashboard_id")})). - InnerJoin(goqu.T("users_acc_dashboards_groups").As("uadg"), goqu.On(goqu.Ex{"uadg.id": goqu.I("anh.group_id")})). + InnerJoin(goqu.T("users_acc_dashboards").As("uad"), goqu.On( + goqu.Ex{"uad.id": goqu.I("anh.dashboard_id"), + })). + InnerJoin(goqu.T("users_acc_dashboards_groups").As("uadg"), goqu.On( + goqu.Ex{"uadg.id": goqu.I("anh.group_id"), + goqu.Ex{"uadg.dashboard_id": goqu.I("uad.id")}, + })). Where( goqu.Ex{"uad.user_id": userId}, goqu.L("anh.network = ANY(?)", pq.Array(chainIds)), @@ -134,7 +144,9 @@ func (d *DataAccessService) GetDashboardNotifications(ctx context.Context, userI } order, directions := applySortAndPagination(defaultColumns, t.SortColumn{Column: colSort.Column.ToString(), Desc: colSort.Desc, Offset: offset}, currentCursor.GenericCursor) unionQuery = unionQuery.Order(order...) - unionQuery = unionQuery.Where(directions) + if directions != nil { + unionQuery = unionQuery.Where(directions) + } // search searchName := regexp.MustCompile(`^[a-zA-Z0-9_\-.\ ]+$`).MatchString(search) @@ -152,15 +164,38 @@ func (d *DataAccessService) GetDashboardNotifications(ctx context.Context, userI if err != nil { return nil, nil, err } - err = d.alloyReader.GetContext(ctx, &response, query, args...) + //err = d.alloyReader.SelectContext(ctx, &response, query, args...) + rows, err := d.alloyReader.QueryContext(ctx, query, args...) if err != nil { return nil, nil, err } + defer rows.Close() + for rows.Next() { + var row t.NotificationDashboardsTableRow + err = rows.Scan( + &row.IsAccountDashboard, + &row.ChainId, + &row.Epoch, + &row.DashboardId, + &row.DashboardName, + &row.GroupId, + &row.GroupName, + &row.EntityCount, + pq.Array(&row.EventTypes), + ) + if err != nil { + return nil, nil, err + } + response = append(response, row) + } moreDataFlag := len(response) > int(limit) if moreDataFlag { response = response[:len(response)-1] } + if currentCursor.IsReverse() { + slices.Reverse(response) + } if !moreDataFlag && !currentCursor.IsValid() { // No paging required return response, &t.Paging{}, nil