130 lines
3 KiB
Go
130 lines
3 KiB
Go
package tables
|
|
|
|
import (
|
|
"context"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/lmika/awstools/internal/dynamo-browse/models"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type Service struct {
|
|
provider TableProvider
|
|
}
|
|
|
|
func NewService(provider TableProvider) *Service {
|
|
return &Service{
|
|
provider: provider,
|
|
}
|
|
}
|
|
|
|
func (s *Service) ListTables(ctx context.Context) ([]string, error) {
|
|
return s.provider.ListTables(ctx)
|
|
}
|
|
|
|
func (s *Service) Describe(ctx context.Context, table string) (*models.TableInfo, error) {
|
|
return s.provider.DescribeTable(ctx, table)
|
|
}
|
|
|
|
func (s *Service) Scan(ctx context.Context, tableInfo *models.TableInfo) (*models.ResultSet, error) {
|
|
results, err := s.provider.ScanItems(ctx, tableInfo.Name, 1000)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "unable to scan table %v", tableInfo.Name)
|
|
}
|
|
|
|
// Get the columns
|
|
seenColumns := make(map[string]int)
|
|
seenColumns[tableInfo.Keys.PartitionKey] = 0
|
|
if tableInfo.Keys.SortKey != "" {
|
|
seenColumns[tableInfo.Keys.SortKey] = 1
|
|
}
|
|
|
|
for _, definedAttribute := range tableInfo.DefinedAttributes {
|
|
if _, seen := seenColumns[definedAttribute]; !seen {
|
|
seenColumns[definedAttribute] = len(seenColumns)
|
|
}
|
|
}
|
|
|
|
otherColsRank := len(seenColumns)
|
|
for _, result := range results {
|
|
for k := range result {
|
|
if _, isSeen := seenColumns[k]; !isSeen {
|
|
seenColumns[k] = otherColsRank
|
|
}
|
|
}
|
|
}
|
|
|
|
columns := make([]string, 0, len(seenColumns))
|
|
for k := range seenColumns {
|
|
columns = append(columns, k)
|
|
}
|
|
sort.Slice(columns, func(i, j int) bool {
|
|
if seenColumns[columns[i]] == seenColumns[columns[j]] {
|
|
return columns[i] < columns[j]
|
|
}
|
|
return seenColumns[columns[i]] < seenColumns[columns[j]]
|
|
})
|
|
|
|
models.Sort(results, tableInfo)
|
|
|
|
resultSet := &models.ResultSet{
|
|
TableInfo: tableInfo,
|
|
Columns: columns,
|
|
}
|
|
resultSet.SetItems(results)
|
|
|
|
return resultSet, nil
|
|
}
|
|
|
|
func (s *Service) Put(ctx context.Context, tableInfo *models.TableInfo, item models.Item) error {
|
|
return s.provider.PutItem(ctx, tableInfo.Name, item)
|
|
}
|
|
|
|
func (s *Service) PutItemAt(ctx context.Context, resultSet *models.ResultSet, index int) error {
|
|
item := resultSet.Items()[index]
|
|
if err := s.provider.PutItem(ctx, resultSet.TableInfo.Name, item); err != nil {
|
|
return err
|
|
}
|
|
|
|
resultSet.SetDirty(index, false)
|
|
resultSet.SetNew(index, false)
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) Delete(ctx context.Context, tableInfo *models.TableInfo, items []models.Item) error {
|
|
for _, item := range items {
|
|
if err := s.provider.DeleteItem(ctx, tableInfo.Name, item.KeyValue(tableInfo)); err != nil {
|
|
return errors.Wrapf(err, "cannot delete item")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// TODO: move into a new service
|
|
func (s *Service) Filter(resultSet *models.ResultSet, filter string) *models.ResultSet {
|
|
for i, item := range resultSet.Items() {
|
|
if filter == "" {
|
|
resultSet.SetHidden(i, false)
|
|
continue
|
|
}
|
|
|
|
var shouldHide = true
|
|
for k := range item {
|
|
str, ok := item.AttributeValueAsString(k)
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
if strings.Contains(str, filter) {
|
|
shouldHide = false
|
|
break
|
|
}
|
|
}
|
|
|
|
resultSet.SetHidden(i, shouldHide)
|
|
}
|
|
|
|
return resultSet
|
|
}
|