Skip to content

Commit

Permalink
[CLC-19]: \di Command to List Indexes (hazelcast#292)
Browse files Browse the repository at this point in the history
  • Loading branch information
kutluhanmetin authored Aug 29, 2023
1 parent 1acb688 commit a4a16f6
Show file tree
Hide file tree
Showing 16 changed files with 488 additions and 88 deletions.
3 changes: 1 addition & 2 deletions base/commands/map/map_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ import (
"context"
"fmt"

"github.com/hazelcast/hazelcast-go-client"

"github.com/hazelcast/hazelcast-commandline-client/clc"
. "github.com/hazelcast/hazelcast-commandline-client/internal/check"
"github.com/hazelcast/hazelcast-commandline-client/internal/plug"
"github.com/hazelcast/hazelcast-commandline-client/internal/proto/codec"
"github.com/hazelcast/hazelcast-go-client"
)

type MapSetCommand struct{}
Expand Down
57 changes: 3 additions & 54 deletions base/commands/object/object_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import (
"sort"
"strings"

"github.com/hazelcast/hazelcast-go-client/types"

"github.com/hazelcast/hazelcast-commandline-client/base/objects"
"github.com/hazelcast/hazelcast-commandline-client/clc"
. "github.com/hazelcast/hazelcast-commandline-client/internal/check"
"github.com/hazelcast/hazelcast-commandline-client/internal/output"
Expand Down Expand Up @@ -81,7 +80,7 @@ func (cm ObjectListCommand) Exec(ctx context.Context, ec plug.ExecContext) error
typeFilter = ec.Args()[0]
}
showHidden := ec.Props().GetBool(flagShowHidden)
objs, err := getObjects(ctx, ec, typeFilter, showHidden)
objs, err := objects.GetAll(ctx, ec, typeFilter, showHidden)
if err != nil {
return err
}
Expand All @@ -100,7 +99,7 @@ func (cm ObjectListCommand) Exec(ctx context.Context, ec plug.ExecContext) error
output.Column{
Name: "Service Name",
Type: serialization.TypeString,
Value: shortType(o.ServiceName),
Value: objects.ShortType(o.ServiceName),
},
valueCol,
})
Expand All @@ -122,56 +121,6 @@ func objectFilterTypes() string {
return sb.String()
}

func getObjects(ctx context.Context, ec plug.ExecContext, typeFilter string, showHidden bool) ([]types.DistributedObjectInfo, error) {
ci, err := ec.ClientInternal(ctx)
if err != nil {
return nil, err
}
objs, stop, err := ec.ExecuteBlocking(ctx, func(ctx context.Context, sp clc.Spinner) (any, error) {
sp.SetText("Getting distributed objects")
return ci.Client().GetDistributedObjectsInfo(ctx)
})
if err != nil {
return nil, err
}
stop()
var r []types.DistributedObjectInfo
typeFilter = strings.ToLower(typeFilter)
for _, o := range objs.([]types.DistributedObjectInfo) {
if !showHidden && (o.Name == "" || strings.HasPrefix(o.Name, "__")) {
continue
}
if o.Name == "" {
o.Name = "(no name)"
}
if typeFilter == "" {
r = append(r, o)
continue
}
if typeFilter == shortType(o.ServiceName) {
r = append(r, o)
}
}
sort.Slice(r, func(i, j int) bool {
// first sort by type, then name
ri := r[i]
rj := r[j]
if ri.ServiceName < rj.ServiceName {
return true
}
if ri.ServiceName > rj.ServiceName {
return false
}
return ri.Name < rj.Name
})
return r, nil
}

func shortType(svcName string) string {
s := strings.TrimSuffix(strings.TrimPrefix(svcName, "hz:impl:"), "Service")
return strings.ToLower(s)
}

func init() {
// sort objectTypes so they look better in help
sort.Slice(objTypes, func(i, j int) bool {
Expand Down
2 changes: 1 addition & 1 deletion base/commands/script.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func (cm ScriptCommand) Exec(ctx context.Context, ec plug.ExecContext) error {
verbose := ec.Props().GetBool(clc.PropertyVerbose)
ie := ec.Props().GetBool(flagIgnoreErrors)
echo := ec.Props().GetBool(flagEcho)
textFn := makeTextFunc(m, ec, verbose, ie, echo, func(shortcut string) bool {
textFn := makeTextFunc(m, ec, verbose, false, false, func(shortcut string) bool {
// shortcuts are not supported in the script mode
return false
})
Expand Down
1 change: 1 addition & 0 deletions base/commands/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func (cm *ShellCommand) Init(cc plug.InitContext) error {
cc.Hide()
cm.mu.Lock()
cm.shortcuts = map[string]struct{}{
`\di`: {},
`\dm`: {},
`\dm+`: {},
`\exit`: {},
Expand Down
15 changes: 1 addition & 14 deletions base/commands/shell_script_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (

"github.com/hazelcast/hazelcast-commandline-client/clc/cmd"
"github.com/hazelcast/hazelcast-commandline-client/clc/shell"
"github.com/hazelcast/hazelcast-commandline-client/clc/sql"
"github.com/hazelcast/hazelcast-commandline-client/internal/check"
"github.com/hazelcast/hazelcast-commandline-client/internal/plug"
)
Expand Down Expand Up @@ -65,26 +64,14 @@ func makeTextFunc(m *cmd.Main, ec plug.ExecContext, verbose, ignoreErrors, echo
return m.Execute(ctx, args...)
}
}
text, err := shell.ConvertStatement(text)
f, err := shell.ConvertStatement(ctx, ec, text, verbose)
if err != nil {
if errors.Is(err, shell.ErrHelp) {
check.I2(fmt.Fprintln(stdout, shell.InteractiveHelp()))
return nil
}
return err
}
f := func() error {
res, stop, err := sql.ExecSQL(ctx, ec, text)
if err != nil {
return err
}
defer stop()
// TODO: update sql.UpdateOutput to use stdout
if err := sql.UpdateOutput(ctx, ec, res, verbose); err != nil {
return err
}
return nil
}
if w, ok := ec.(plug.ResultWrapper); ok {
return w.WrapResult(f)
}
Expand Down
36 changes: 36 additions & 0 deletions base/commands/sql/sql_it_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import (
"time"

"github.com/hazelcast/hazelcast-go-client"
hz "github.com/hazelcast/hazelcast-go-client"
"github.com/hazelcast/hazelcast-go-client/serialization"
"github.com/hazelcast/hazelcast-go-client/types"
"github.com/stretchr/testify/require"

_ "github.com/hazelcast/hazelcast-commandline-client/base/commands"
Expand Down Expand Up @@ -165,10 +168,43 @@ $ | | %s | | |
$-----------------------------------------------------------------------------------------------------------------------------$`, p1, p2, p1, p2)
tcx.AssertStdoutDollar(target)
})
// di
tcx.WithReset(func() {
mm, err := tcx.Client.GetMap(ctx, "default")
check.Must(err)
check.Must(addIndex(mm))
tcx.WriteStdinf("\\di\n")
tcx.AssertStdoutDollarWithPath("testdata/list_indexes.txt")
})
// di NAME
tcx.WithReset(func() {
mm, err := tcx.Client.GetMap(ctx, "default")
check.Must(err)
check.Must(addIndex(mm))
tcx.WriteStdinf("\\di default\n")
tcx.AssertStdoutDollarWithPath("testdata/list_indexes.txt")
})
})
})
}

func addIndex(m *hz.Map) error {
err := m.Set(context.Background(), "k1", serialization.JSON(`{"A": 10, "B": 40}`))
if err != nil {
return err
}
indexConfig := types.IndexConfig{
Name: "my-index",
Type: types.IndexTypeSorted,
Attributes: []string{"A"},
BitmapIndexOptions: types.BitmapIndexOptions{UniqueKey: "B", UniqueKeyTransformation: types.UniqueKeyTransformationLong},
}
if err = m.AddIndex(context.Background(), indexConfig); err != nil {
return err
}
return nil
}

func sqlSuggestion_Interactive(t *testing.T) {
tcx := it.TestContext{T: t}
tcx.Tester(func(tcx it.TestContext) {
Expand Down
5 changes: 5 additions & 0 deletions base/commands/sql/testdata/list_indexes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
$----------------------------------$
$ Map Name | Name | Attributes $
$----------------------------------$
$ default | my-index | [A] $
$----------------------------------$
4 changes: 3 additions & 1 deletion base/commands/sql/testdata/sql_help.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
$Shortcut Commands:$
$\di List Indexes$
$\di MAPPING List Indexes for a specific mapping$
$\dm List mappings$
$\dm MAPPING Display information about a mapping$
$\dm+ MAPPING Describe a mapping$
$\exit Exit the shell$
$\help Display help for CLC commands$
$\help Display help for CLC commands$
74 changes: 74 additions & 0 deletions base/maps/maps.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package maps

import (
"context"
"fmt"

"github.com/hazelcast/hazelcast-commandline-client/base/commands/object"
"github.com/hazelcast/hazelcast-commandline-client/base/objects"
"github.com/hazelcast/hazelcast-commandline-client/clc"
"github.com/hazelcast/hazelcast-commandline-client/internal/output"
"github.com/hazelcast/hazelcast-commandline-client/internal/plug"
"github.com/hazelcast/hazelcast-commandline-client/internal/proto/codec"
"github.com/hazelcast/hazelcast-commandline-client/internal/serialization"
"github.com/hazelcast/hazelcast-go-client/types"
)

func Indexes(ctx context.Context, ec plug.ExecContext, mapName string) error {
var mapNames []string
if mapName != "" {
mapNames = append(mapNames, mapName)
} else {
maps, err := objects.GetAll(ctx, ec, object.Map, false)
if err != nil {
return err
}
for _, mm := range maps {
mapNames = append(mapNames, mm.Name)
}
}
ci, err := ec.ClientInternal(ctx)
if err != nil {
return err
}
resp, stop, err := ec.ExecuteBlocking(ctx, func(ctx context.Context, sp clc.Spinner) (any, error) {
allIndexes := make(map[string][]types.IndexConfig)
for _, mn := range mapNames {
sp.SetText(fmt.Sprintf("Getting indexes of map %s", mn))
req := codec.EncodeMCGetMapConfigRequest(mn)
// If member configurations are different, this may not work well, however it is nothing to do with CLC
resp, err := ci.InvokeOnRandomTarget(ctx, req, nil)
if err != nil {
return nil, err
}
_, _, _, _, _, _, _, _, _, _, globalIndexes := codec.DecodeMCGetMapConfigResponse(resp)
if err != nil {
return nil, err
}
allIndexes[mn] = globalIndexes
}
return allIndexes, nil
})
stop()
var rows []output.Row
for mn, indexes := range resp.(map[string][]types.IndexConfig) {
for _, index := range indexes {
rows = append(rows,
output.Row{
output.Column{
Name: "Map Name",
Type: serialization.TypeString,
Value: mn,
}, output.Column{
Name: "Name",
Type: serialization.TypeString,
Value: index.Name,
}, output.Column{
Name: "Attributes",
Type: serialization.TypeStringArray,
Value: index.Attributes,
}})
}
}
return ec.AddOutputRows(ctx, rows...)
}
61 changes: 61 additions & 0 deletions base/objects/objects.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package objects

import (
"context"
"sort"
"strings"

"github.com/hazelcast/hazelcast-commandline-client/clc"
"github.com/hazelcast/hazelcast-commandline-client/internal/plug"
"github.com/hazelcast/hazelcast-go-client/types"
)

func GetAll(ctx context.Context, ec plug.ExecContext, typeFilter string, showHidden bool) ([]types.DistributedObjectInfo, error) {
ci, err := ec.ClientInternal(ctx)
if err != nil {
return nil, err
}
objs, stop, err := ec.ExecuteBlocking(ctx, func(ctx context.Context, sp clc.Spinner) (any, error) {
sp.SetText("Getting distributed objects")
return ci.Client().GetDistributedObjectsInfo(ctx)
})
if err != nil {
return nil, err
}
stop()
var r []types.DistributedObjectInfo
typeFilter = strings.ToLower(typeFilter)
for _, o := range objs.([]types.DistributedObjectInfo) {
if !showHidden && (o.Name == "" || strings.HasPrefix(o.Name, "__")) {
continue
}
if o.Name == "" {
o.Name = "(no name)"
}
if typeFilter == "" {
r = append(r, o)
continue
}
if typeFilter == ShortType(o.ServiceName) {
r = append(r, o)
}
}
sort.Slice(r, func(i, j int) bool {
// first sort by type, then name
ri := r[i]
rj := r[j]
if ri.ServiceName < rj.ServiceName {
return true
}
if ri.ServiceName > rj.ServiceName {
return false
}
return ri.Name < rj.Name
})
return r, nil
}

func ShortType(svcName string) string {
s := strings.TrimSuffix(strings.TrimPrefix(svcName, "hz:impl:"), "Service")
return strings.ToLower(s)
}
Loading

0 comments on commit a4a16f6

Please sign in to comment.