129: Index multivalued attributes. (#128)
Some checks failed
Pull Request Labeler / triage (push) Successful in 6s
Lint / Run flake8 on python integration tests (push) Failing after 15s
Tests / cleanup-runs (push) Has been skipped
CodeQL / Analyze (go) (push) Failing after 2m16s
Lint / Run golangci-lint (push) Successful in 5m57s
Run Gosec / Gosec (push) Failing after 9m59s
Tests / test-unit-cover (push) Failing after 10m7s
Tests / test-rpc (push) Failing after 4m27s
Tests / sdk_tests (push) Failing after 2m45s
Tests / test-importer (push) Successful in 11m36s
Some checks failed
Pull Request Labeler / triage (push) Successful in 6s
Lint / Run flake8 on python integration tests (push) Failing after 15s
Tests / cleanup-runs (push) Has been skipped
CodeQL / Analyze (go) (push) Failing after 2m16s
Lint / Run golangci-lint (push) Successful in 5m57s
Run Gosec / Gosec (push) Failing after 9m59s
Tests / test-unit-cover (push) Failing after 10m7s
Tests / test-rpc (push) Failing after 4m27s
Tests / sdk_tests (push) Failing after 2m45s
Tests / test-importer (push) Successful in 11m36s
This fixes #129, by indexing each value of a multivalued attribute. This handles at least the most common use case, so that we can search on a single value of the attribute. ``` ❯ laconic -c ~/.laconic/local.yml cns record list --all --type ApplicationDeploymentRequest --tags b [ { "id": "bafyreidrp4pylixp44rkxu5il72qhwwc4ir5ctdnssps5rnelstloxivwm", "names": null, "owners": [ "FCCE01FCC2472AEDBCF33902907F33262445AC2C" ], "bondId": "4ef470a9207f00fc07663623d092a14c310794b616eb53b085cfe6976e82f56d", "createTime": "2023-12-18T22:13:23Z", "expiryTime": "2024-12-17T22:13:23Z", "attributes": { "type": "ApplicationDeploymentRequest", "version": "1.0.6", "application": "crn://cerc-io/applications/test-progressive-web-app@0.1.1", "config": { "env": { "CERC_WEBAPP_DEBUG": "57588a9d" } }, "tags": [ "a", "b", "c" ] } } ] ``` Reviewed-on: cerc-io/laconicd#128 Co-authored-by: Thomas E Lackey <telackey@bozemanpass.com> Co-committed-by: Thomas E Lackey <telackey@bozemanpass.com>
This commit is contained in:
parent
588c52c0b2
commit
ae07fc0147
7
x/registry/helpers/examples/general_record_example.yml
Normal file
7
x/registry/helpers/examples/general_record_example.yml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
record:
|
||||||
|
type: GeneralRecord
|
||||||
|
name: foo
|
||||||
|
version: 1.0.0
|
||||||
|
tags:
|
||||||
|
- tagA
|
||||||
|
- tagB
|
@ -3,12 +3,12 @@ package keeper_test
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/cerc-io/laconicd/x/registry/client/cli"
|
"github.com/cerc-io/laconicd/x/registry/client/cli"
|
||||||
"github.com/cerc-io/laconicd/x/registry/helpers"
|
"github.com/cerc-io/laconicd/x/registry/helpers"
|
||||||
"github.com/cerc-io/laconicd/x/registry/keeper"
|
"github.com/cerc-io/laconicd/x/registry/keeper"
|
||||||
registrytypes "github.com/cerc-io/laconicd/x/registry/types"
|
registrytypes "github.com/cerc-io/laconicd/x/registry/types"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) TestGrpcQueryParams() {
|
func (suite *KeeperTestSuite) TestGrpcQueryParams() {
|
||||||
@ -39,6 +39,7 @@ func (suite *KeeperTestSuite) TestGrpcGetRecordLists() {
|
|||||||
examples := []string{
|
examples := []string{
|
||||||
"/../helpers/examples/service_provider_example.yml",
|
"/../helpers/examples/service_provider_example.yml",
|
||||||
"/../helpers/examples/website_registration_example.yml",
|
"/../helpers/examples/website_registration_example.yml",
|
||||||
|
"/../helpers/examples/general_record_example.yml",
|
||||||
}
|
}
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
msg string
|
msg string
|
||||||
@ -59,7 +60,7 @@ func (suite *KeeperTestSuite) TestGrpcGetRecordLists() {
|
|||||||
®istrytypes.QueryListRecordsRequest{},
|
®istrytypes.QueryListRecordsRequest{},
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
2,
|
3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Filter with type",
|
"Filter with type",
|
||||||
@ -79,6 +80,42 @@ func (suite *KeeperTestSuite) TestGrpcGetRecordLists() {
|
|||||||
false,
|
false,
|
||||||
1,
|
1,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Filter with tag (extant) (https://git.vdb.to/cerc-io/laconicd/issues/129)",
|
||||||
|
®istrytypes.QueryListRecordsRequest{
|
||||||
|
Attributes: []*registrytypes.QueryListRecordsRequest_KeyValueInput{
|
||||||
|
{
|
||||||
|
Key: "tags",
|
||||||
|
Value: ®istrytypes.QueryListRecordsRequest_ValueInput{
|
||||||
|
Type: "string",
|
||||||
|
String_: "tagA",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
All: true,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Filter with tag (non-existent) (https://git.vdb.to/cerc-io/laconicd/issues/129)",
|
||||||
|
®istrytypes.QueryListRecordsRequest{
|
||||||
|
Attributes: []*registrytypes.QueryListRecordsRequest_KeyValueInput{
|
||||||
|
{
|
||||||
|
Key: "tags",
|
||||||
|
Value: ®istrytypes.QueryListRecordsRequest_ValueInput{
|
||||||
|
Type: "string",
|
||||||
|
String_: "NOEXIST",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
All: true,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Filter test for key collision (https://git.vdb.to/cerc-io/laconicd/issues/122)",
|
"Filter test for key collision (https://git.vdb.to/cerc-io/laconicd/issues/122)",
|
||||||
®istrytypes.QueryListRecordsRequest{
|
®istrytypes.QueryListRecordsRequest{
|
||||||
@ -151,10 +188,25 @@ func (suite *KeeperTestSuite) TestGrpcGetRecordLists() {
|
|||||||
sr.NoError(err)
|
sr.NoError(err)
|
||||||
recAttr := helpers.UnMarshalMapFromJSONBytes(bz)
|
recAttr := helpers.UnMarshalMapFromJSONBytes(bz)
|
||||||
for _, attr := range test.req.GetAttributes() {
|
for _, attr := range test.req.GetAttributes() {
|
||||||
if attr.Key[:4] == "x500" {
|
av := keeper.GetAttributeValue(attr.Value)
|
||||||
sr.Equal(keeper.GetAttributeValue(attr.Value), recAttr["x500"].(map[string]interface{})[attr.Key[4:]])
|
if nil != av && nil != recAttr[attr.Key] &&
|
||||||
|
reflect.Slice == reflect.TypeOf(recAttr[attr.Key]).Kind() &&
|
||||||
|
reflect.Slice != reflect.TypeOf(av).Kind() {
|
||||||
|
found := false
|
||||||
|
allValues := recAttr[attr.Key].([]interface{})
|
||||||
|
for i := range allValues {
|
||||||
|
if av == allValues[i] {
|
||||||
|
fmt.Printf("Found %s in %s", allValues[i], recAttr[attr.Key])
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sr.Equal(true, found, fmt.Sprintf("Unable to find %s in %s", av, recAttr[attr.Key]))
|
||||||
} else {
|
} else {
|
||||||
sr.Equal(keeper.GetAttributeValue(attr.Value), recAttr[attr.Key])
|
if attr.Key[:4] == "x500" {
|
||||||
|
sr.Equal(av, recAttr["x500"].(map[string]interface{})[attr.Key[4:]])
|
||||||
|
} else {
|
||||||
|
sr.Equal(av, recAttr[attr.Key])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -349,11 +350,22 @@ func (k Keeper) ProcessAttributes(ctx sdk.Context, record types.RecordType) erro
|
|||||||
{
|
{
|
||||||
// #nosec G705
|
// #nosec G705
|
||||||
for key := range record.Attributes {
|
for key := range record.Attributes {
|
||||||
indexKey := GetAttributesIndexKey(key, record.Attributes[key])
|
attr := record.Attributes[key]
|
||||||
|
if reflect.Slice == reflect.TypeOf(attr).Kind() {
|
||||||
|
av := attr.([]interface{})
|
||||||
|
for i := range av {
|
||||||
|
indexKey := GetAttributesIndexKey(key, av[i])
|
||||||
if err := k.SetAttributeMapping(ctx, indexKey, record.ID); err != nil {
|
if err := k.SetAttributeMapping(ctx, indexKey, record.ID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
indexKey := GetAttributesIndexKey(key, attr)
|
||||||
|
if err := k.SetAttributeMapping(ctx, indexKey, record.ID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported record type %s", record.Attributes["type"])
|
return fmt.Errorf("unsupported record type %s", record.Attributes["type"])
|
||||||
|
Loading…
Reference in New Issue
Block a user