Remove hard-coded record types #132
@ -3,12 +3,13 @@ package keeper_test
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
"github.com/cerc-io/laconicd/x/registry/client/cli"
|
||||
"github.com/cerc-io/laconicd/x/registry/helpers"
|
||||
"github.com/cerc-io/laconicd/x/registry/keeper"
|
||||
registrytypes "github.com/cerc-io/laconicd/x/registry/types"
|
||||
"os"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestGrpcQueryParams() {
|
||||
|
@ -22,7 +22,10 @@ import (
|
||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
|
||||
cid "github.com/ipfs/go-cid"
|
||||
"github.com/ipld/go-ipld-prime"
|
||||
"github.com/ipld/go-ipld-prime/codec/dagjson"
|
||||
cidlink "github.com/ipld/go-ipld-prime/linking/cid"
|
||||
basicnode "github.com/ipld/go-ipld-prime/node/basic"
|
||||
)
|
||||
|
||||
@ -147,10 +150,20 @@ func (k Keeper) ListRecords(ctx sdk.Context) []types.Record {
|
||||
|
||||
// RecordsFromAttributes gets a list of records whose attributes match all provided values
|
||||
func (k Keeper) RecordsFromAttributes(ctx sdk.Context, attributes []*types.QueryListRecordsRequest_KeyValueInput, all bool) ([]types.Record, error) {
|
||||
log := logger(ctx).With("function", "RecordsFromAttributes")
|
||||
|
||||
resultRecordIds := []string{}
|
||||
for i, attr := range attributes {
|
||||
val := GetAttributeValue(attr.Value)
|
||||
val, err := EncodeAttributeValue2(attr.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attributeIndex := GetAttributesIndexKey(attr.Key, val)
|
||||
log.Debug("attribute index",
|
||||
"key", attr.Key,
|
||||
"value", val,
|
||||
"value_type", fmt.Sprintf("%T", val),
|
||||
"index", attributeIndex)
|
||||
recordIds, err := k.GetAttributeMapping(ctx, attributeIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -178,27 +191,38 @@ func (k Keeper) RecordsFromAttributes(ctx sdk.Context, attributes []*types.Query
|
||||
return records, nil
|
||||
}
|
||||
|
||||
func GetAttributeValue(input *types.QueryListRecordsRequest_ValueInput) interface{} {
|
||||
// TODO non recursive
|
||||
func EncodeAttributeValue2(input *types.QueryListRecordsRequest_ValueInput) ([]byte, error) {
|
||||
np := basicnode.Prototype.Any
|
||||
nb := np.NewBuilder()
|
||||
|
||||
switch value := input.GetValue().(type) {
|
||||
case *types.QueryListRecordsRequest_ValueInput_String_:
|
||||
return value.String_
|
||||
nb.AssignString(value.String_)
|
||||
case *types.QueryListRecordsRequest_ValueInput_Int:
|
||||
return value.Int
|
||||
nb.AssignInt(value.Int)
|
||||
case *types.QueryListRecordsRequest_ValueInput_Float:
|
||||
return value.Float
|
||||
nb.AssignFloat(value.Float)
|
||||
case *types.QueryListRecordsRequest_ValueInput_Boolean:
|
||||
return value.Boolean
|
||||
nb.AssignBool(value.Boolean)
|
||||
case *types.QueryListRecordsRequest_ValueInput_Link:
|
||||
return value.Link
|
||||
link := cidlink.Link{Cid: cid.MustParse(value.Link)}
|
||||
nb.AssignLink(link)
|
||||
case *types.QueryListRecordsRequest_ValueInput_Array:
|
||||
return value.Array
|
||||
// TODO
|
||||
case *types.QueryListRecordsRequest_ValueInput_Map:
|
||||
return value.Map
|
||||
case nil:
|
||||
return nil
|
||||
// TODO
|
||||
default:
|
||||
return fmt.Errorf("Value has unepxpected type %T", value)
|
||||
return nil, fmt.Errorf("Value has unepxpected type %T", value)
|
||||
}
|
||||
|
||||
n := nb.Build()
|
||||
var buf bytes.Buffer
|
||||
if err := dagjson.Encode(n, &buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
value := buf.Bytes()
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func getIntersection(a []string, b []string) []string {
|
||||
@ -341,22 +365,43 @@ func (k Keeper) PutRecord(ctx sdk.Context, record types.Record) {
|
||||
k.updateBlockChangeSetForRecord(ctx, record.Id)
|
||||
}
|
||||
|
||||
func (k Keeper) processAttributes(ctx sdk.Context, attrs map[string]any, id string, prefix string) error {
|
||||
np := basicnode.Prototype.Any // Pick a stle for the in-memory data.
|
||||
nb := np.NewBuilder() // Create a builder.
|
||||
err := dagjson.Decode(nb, bytes.NewReader(content)) // Hand the builder to decoding -- decoding will fill it in!
|
||||
func (k Keeper) processAttributes(ctx sdk.Context, attrs []byte, id string, prefix string) error {
|
||||
np := basicnode.Prototype.Map
|
||||
nb := np.NewBuilder()
|
||||
err := dagjson.Decode(nb, bytes.NewReader(attrs))
|
||||
if err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
n := nb.Build() // Call 'Build' to get the resulting Node. (It's immutable!)
|
||||
n := nb.Build()
|
||||
if n.Kind() != ipld.Kind_Map {
|
||||
return fmt.Errorf("Record attributes must be a map, not %T", n.Kind())
|
||||
}
|
||||
return k.processAttributeMap(ctx, n, id, prefix)
|
||||
}
|
||||
|
||||
for key, value := range attrs {
|
||||
if subRecord, ok := value.(map[string]any); ok {
|
||||
err := k.processAttributes(ctx, subRecord, id, key)
|
||||
func (k Keeper) processAttributeMap(ctx sdk.Context, n ipld.Node, id string, prefix string) error {
|
||||
for it := n.MapIterator(); !it.Done(); {
|
||||
keynode, valuenode, err := it.Next()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
key, err := keynode.AsString()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// for key, value := range attrs {
|
||||
if valuenode.Kind() == ipld.Kind_Map {
|
||||
err := k.processAttributeMap(ctx, valuenode, id, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
var buf bytes.Buffer
|
||||
if err := dagjson.Encode(valuenode, &buf); err != nil {
|
||||
return err
|
||||
}
|
||||
value := buf.Bytes()
|
||||
indexKey := GetAttributesIndexKey(prefix+key, value)
|
||||
if err := k.SetAttributeMapping(ctx, indexKey, id); err != nil {
|
||||
return err
|
||||
|
@ -13,6 +13,16 @@ const (
|
||||
AuthorityUnderAuction = "auction"
|
||||
)
|
||||
|
||||
// TODO if schema records are to be more permissive than allowing a map of fields, this type will
|
||||
// become specific to content records. schema records will either occupy a new message or have new
|
||||
// more general purpose helper types.
|
||||
|
||||
type DagJsonBlob []byte
|
||||
|
||||
func (b DagJsonBlob) MarshalJSON() ([]byte, error) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// ReadablePayload represents a signed record payload that can be serialized from/to YAML.
|
||||
type ReadablePayload struct {
|
||||
Record map[string]interface{} `json:"record"`
|
||||
@ -44,7 +54,6 @@ func (payloadObj *ReadablePayload) ToPayload() Payload {
|
||||
},
|
||||
Signatures: payloadObj.Signatures,
|
||||
}
|
||||
// TODO rm error
|
||||
return payload
|
||||
}
|
||||
|
||||
@ -96,7 +105,7 @@ func (r *ReadableRecord) ToRecordObj() (Record, error) {
|
||||
func (r *ReadableRecord) CanonicalJSON() []byte {
|
||||
bytes, err := canonicalJson.Marshal(r.Attributes)
|
||||
if err != nil {
|
||||
panic("Record marshal error.")
|
||||
panic("Record marshal error: " + err.Error())
|
||||
}
|
||||
|
||||
return bytes
|
||||
|
Loading…
Reference in New Issue
Block a user