diff --git a/client/src/com/aerospike/client/cdt/ListOperation.java b/client/src/com/aerospike/client/cdt/ListOperation.java index c40caa425..3b11869c7 100644 --- a/client/src/com/aerospike/client/cdt/ListOperation.java +++ b/client/src/com/aerospike/client/cdt/ListOperation.java @@ -90,9 +90,13 @@ public class ListOperation { /** * Create 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 - * satisfy the context position. + * Server creates list at given context level. + * + * @param binName bin name + * @param order list order + * @param pad if true, context is allowed to be beyond list boundaries and insert nil list entries to + * satisfy the ctx position + * @param ctx optional path to nested list. If not defined, the top-level list is used. */ public static Operation create(String binName, ListOrder order, boolean pad, CTX... ctx) { // If context not defined, the set order for top-level bin list. @@ -100,6 +104,35 @@ public static Operation create(String binName, ListOrder order, boolean pad, CTX return setOrder(binName, order); } + byte[] bytes = packCreate(order, pad, ctx); + return new Operation(Operation.Type.CDT_MODIFY, binName, Value.get(bytes)); + } + + /** + * Create list create operation. + * Server creates list at given context level. + * + * @param binName bin name + * @param order list order + * @param pad if true, context is allowed to be beyond list boundaries and insert nil list entries to + * satisfy the ctx position + * @param persistIndex if true, persist list 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. + * @param ctx optional path to nested list. If not defined, the top-level list is used. + */ + public static Operation create(String binName, ListOrder order, boolean pad, boolean persistIndex, CTX... ctx) { + // If context not defined, the set order for top-level bin list. + if (ctx == null || ctx.length == 0) { + return setOrder(binName, order, persistIndex); + } + + // Create nested list. persistIndex does not apply here, so ignore it. + byte[] bytes = packCreate(order, pad, ctx); + return new Operation(Operation.Type.CDT_MODIFY, binName, Value.get(bytes)); + } + + private static byte[] packCreate(ListOrder order, boolean pad, CTX[] ctx) { Packer packer = new Packer(); // Calculate buffer size. @@ -112,7 +145,7 @@ public static Operation create(String binName, ListOrder order, boolean pad, CTX CDT.init(packer, ctx, SET_TYPE, 1, order.getFlag(pad)); packer.packInt(order.attributes); - return new Operation(Operation.Type.CDT_MODIFY, binName, Value.get(packer.getBuffer())); + return packer.getBuffer(); } /** @@ -124,6 +157,27 @@ public static Operation setOrder(String binName, ListOrder order, CTX... ctx) { return new Operation(Operation.Type.CDT_MODIFY, binName, Value.get(bytes)); } + /** + * Create set list order operation. + * Server sets list order. Server returns null. + * + * @param binName bin name + * @param order list order + * @param persistIndex if true, persist list 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. + * @param ctx optional path to nested list. If not defined, the top-level list is used. + */ + public static Operation setOrder(String binName, ListOrder order, boolean persistIndex, CTX... ctx) { + int attr = order.attributes; + + if (persistIndex) { + attr |= 0x10; + } + byte[] bytes = Pack.pack(ListOperation.SET_TYPE, attr, ctx); + return new Operation(Operation.Type.CDT_MODIFY, binName, Value.get(bytes)); + } + /** * Create default list append operation. * Server appends value to end of list bin. diff --git a/test/src/com/aerospike/test/sync/basic/TestOperateList.java b/test/src/com/aerospike/test/sync/basic/TestOperateList.java index 90a91d149..72603867b 100644 --- a/test/src/com/aerospike/test/sync/basic/TestOperateList.java +++ b/test/src/com/aerospike/test/sync/basic/TestOperateList.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 Aerospike, Inc. + * Copyright 2012-2024 Aerospike, Inc. * * Portions may be licensed to Aerospike, Inc. under one or more contributor * license agreements WHICH ARE COMPATIBLE WITH THE APACHE LICENSE, VERSION 2.0. @@ -1205,4 +1205,51 @@ record = client.operate(null, key, assertEquals(1, list.size()); assertEquals(2, (long)(Long)list.get(0)); } + + @Test + public void operateListCreate() { + Key key = new Key(args.namespace, args.set, "oplkey21"); + + client.delete(null, key); + + List l1 = new ArrayList(); + l1.add(Value.get(3)); + l1.add(Value.get(2)); + l1.add(Value.get(1)); + + WritePolicy wp = new WritePolicy(); + wp.respondAllOps = true; + + // Create list with persisted index. + Record record = client.operate(wp, key, + ListOperation.create(binName, ListOrder.ORDERED, false, true), + ListOperation.appendItems(ListPolicy.Default, binName, l1), + Operation.get(binName) + ); + + assertRecordFound(key, record); + //System.out.println("Record: " + record); + + List results = record.getList(binName); + assertEquals(3, results.size()); // 3 operations equals 3 results. + + int i = 0; + Object obj = results.get(i++); + assertNull(obj); + + long val = (Long)results.get(i++); + assertEquals(3, val); // appendItems returns 3 for number of items appended. + + List list = (List)results.get(i++); + assertEquals(3, list.size()); + + val = (Long)list.get(0); + assertEquals(1, val); // List is returned sorted, so 1 will be the first item. + + val = (Long)list.get(1); + assertEquals(2, val); + + val= (Long)list.get(2); + assertEquals(3, val); + } }