Skip to content

Commit

Permalink
[CLIENT-2767] Support Persistent List Indexes
Browse files Browse the repository at this point in the history
  • Loading branch information
khaf committed Mar 28, 2024
1 parent 50f374f commit 1c2ba46
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 7 deletions.
43 changes: 36 additions & 7 deletions cdt_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

package aerospike

// List operations support negative indexing. If the index is negative, the
// List operations support negative indexing. If the index is negative, the
// resolved index starts backwards from end of list. If an index is out of bounds,
// a parameter error will be returned. If a range is partially out of bounds, the
// valid part of the range will be returned. Index/Range examples:
Expand All @@ -29,7 +29,7 @@ package aerospike
// Index -3 Count 3: Last three items in list.
// Index -5 Count 4: Range between fifth to last item to second to last item inclusive.
//
// Nested CDT operations are supported by optional Ctx context arguments. Examples:
// Nested CDT operations are supported by optional Ctx context arguments. Examples:
//
// bin = [[7,9,5],[1,2,3],[6,5,4,1]]
// Append 11 to last list.
Expand Down Expand Up @@ -151,10 +151,10 @@ const (
// ListReturnTypeExists returns true if count > 0.
ListReturnTypeExists ListReturnType = 13

// ListReturnTypeInverted will invert meaning of list command and return values. For example:
// ListReturnTypeInverted will invert meaning of list command and return values. For example:
// ListOperation.getByIndexRange(binName, index, count, ListReturnType.INDEX | ListReturnType.INVERTED)
// With the INVERTED flag enabled, the items outside of the specified index range will be returned.
// The meaning of the list command can also be inverted. For example:
// The meaning of the list command can also be inverted. For example:
// ListOperation.removeByIndexRange(binName, index, count, ListReturnType.INDEX | ListReturnType.INVERTED);
// With the INVERTED flag enabled, the items outside of the specified index range will be removed and returned.
ListReturnTypeInverted ListReturnType = 0x10000
Expand All @@ -180,7 +180,7 @@ const (
ListWriteFlagsDefault = 0
// ListWriteFlagsAddUnique means: Only add unique values.
ListWriteFlagsAddUnique = 1
// ListWriteFlagsInsertBounded means: Enforce list boundaries when inserting. Do not allow values to be inserted
// ListWriteFlagsInsertBounded means: Enforce list boundaries when inserting. Do not allow values to be inserted
// at index outside current list boundaries.
ListWriteFlagsInsertBounded = 2
// ListWriteFlagsNoFail means: do not raise error if a list item fails due to write flag constraints.
Expand Down Expand Up @@ -425,7 +425,7 @@ func cdtListOrderFlag(order ListOrderType, pad bool) int {

// ListCreateOp creates list create operation.
// Server creates list at given context level. The context is allowed to be beyond list
// boundaries only if pad is set to true. In that case, nil list entries will be inserted to
// boundaries only if pad is set to true. In that case, nil list entries will be inserted to
// satisfy the context position.
func ListCreateOp(binName string, listOrder ListOrderType, pad bool, ctx ...*CDTContext) *Operation {
// If context not defined, the set order for top-level bin list.
Expand All @@ -435,12 +435,41 @@ func ListCreateOp(binName string, listOrder ListOrderType, pad bool, ctx ...*CDT
return &Operation{opType: _CDT_MODIFY, ctx: ctx, binName: binName, binValue: ListValue{_CDT_LIST_SET_TYPE, cdtListOrderFlag(listOrder, pad), IntegerValue(listOrder)}, encoder: cdtCreateOpEncoder}
}

// ListCreateOp creates list create operation with a persisted index.
// A list index improves lookup performance, but requires more storage.
// A list index can be created for a top-level ordered list only.
// Nested and unordered list indexes are not supported.
//
// Server creates list at given context level. The context is allowed to be beyond list
// boundaries only if pad is set to true. In that case, nil list entries will be inserted to
// satisfy the context position.
func ListCreateWithIndexOp(binName string, listOrder ListOrderType, pad bool, ctx ...*CDTContext) *Operation {
// If context not defined, the set order for top-level bin list.
if len(ctx) == 0 {
return ListSetOrderWithIndexOp(binName, listOrder)
}

// Create nested list. persistIndex does not apply here, so ignore it.
return &Operation{opType: _CDT_MODIFY, ctx: ctx, binName: binName, binValue: ListValue{_CDT_LIST_SET_TYPE, cdtListOrderFlag(listOrder, pad), IntegerValue(listOrder)}, encoder: cdtCreateOpEncoder}
}

// ListSetOrderOp creates a set list order operation.
// Server sets list order. Server returns nil.
// Server sets list order. Server returns nil.
func ListSetOrderOp(binName string, listOrder ListOrderType, ctx ...*CDTContext) *Operation {
return &Operation{opType: _CDT_MODIFY, ctx: ctx, binName: binName, binValue: ListValue{_CDT_LIST_SET_TYPE, IntegerValue(listOrder)}, encoder: listGenericOpEncoder}
}

// ListSetOrderWithIndexOp creates a set list order operation with a persisted index.
// A list index improves lookup performance, but requires more storage.
// A list index can be created for a top-level ordered list only.
// Nested and unordered list indexes are not supported.
//
// Server sets list order. Server returns nil.
func ListSetOrderWithIndexOp(binName string, listOrder ListOrderType, ctx ...*CDTContext) *Operation {
listOrder |= 0x10
return &Operation{opType: _CDT_MODIFY, ctx: ctx, binName: binName, binValue: ListValue{_CDT_LIST_SET_TYPE, IntegerValue(listOrder)}, encoder: listGenericOpEncoder}
}

// ListAppendOp creates a list append operation.
// Server appends values to end of list bin.
// Server returns list size on bin name.
Expand Down
13 changes: 13 additions & 0 deletions cdt_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,19 @@ var _ = gg.Describe("CDT List Test", func() {
gm.Expect(sz.Bins[cdtBinName]).To(gm.Equal(100 * 2))
})

gg.It("should create a valid CDT List with persisted index", func() {
cdtBinName := "indexedList"
cdtList, err := client.Operate(wpolicy, key,
as.ListCreateWithIndexOp(cdtBinName, as.ListOrderOrdered, false),
as.ListAppendWithPolicyOp(as.DefaultListPolicy(), cdtBinName, 1, 2, 3, 4),
as.GetBinOp(cdtBinName),
)
gm.Expect(err).ToNot(gm.HaveOccurred())
gm.Expect(cdtList).ToNot(gm.BeNil())
gm.Expect(cdtList.Bins).ToNot(gm.BeNil())
gm.Expect(cdtList.Bins[cdtBinName]).To(gm.Equal([]interface{}{4, []interface{}{1, 2, 3, 4}}))
})

gg.Describe("CDT List Operations", func() {

const listSize = 10
Expand Down

0 comments on commit 1c2ba46

Please sign in to comment.