Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
124 commits
Select commit Hold shift + click to select a range
8022b74
WIP API
juliannguyen4 Oct 6, 2025
fa886c2
get latest c cl
juliannguyen4 Oct 13, 2025
c5c0c37
Add operate.cdt_select() test case
juliannguyen4 Oct 13, 2025
88ce202
WIP operations.cdt_select() implementation. flags not supported yet
juliannguyen4 Oct 13, 2025
3b2e957
Workaround: surround type hint with quotes to prevent circular refere…
juliannguyen4 Oct 13, 2025
721e4de
rm culprit import
juliannguyen4 Oct 13, 2025
2fa4647
First rough draft implementation of operation cdt_apply(). negative p…
juliannguyen4 Oct 14, 2025
61dd90c
prefix with underscore to mark constants as private
juliannguyen4 Oct 14, 2025
9519804
prefix pyobject var name with py_ to make easier to read
juliannguyen4 Oct 14, 2025
93fadc3
rm dup definition
juliannguyen4 Oct 14, 2025
137707d
Revert "rm dup definition"
juliannguyen4 Oct 14, 2025
0349bf4
Revert "prefix pyobject var name with py_ to make easier to read"
juliannguyen4 Oct 14, 2025
0be5f8e
Merge remote-tracking branch 'origin/dev' into CLIENT-3752-path-expre…
juliannguyen4 Oct 15, 2025
482543f
implement as_cdt_select_flags
juliannguyen4 Oct 15, 2025
2ad1734
fix macro
juliannguyen4 Oct 15, 2025
94dbae0
fix
juliannguyen4 Oct 15, 2025
ce91188
Add some of the missing stubs
juliannguyen4 Oct 15, 2025
eaee895
Op id 3 is now valid. fix test
juliannguyen4 Oct 15, 2025
e4d3df9
Document cdt select flags
juliannguyen4 Oct 15, 2025
1407c76
make less ambiguous
juliannguyen4 Oct 15, 2025
7774423
Move outside of if block
juliannguyen4 Oct 15, 2025
e0f890d
Implement cdt_select ctx
juliannguyen4 Oct 15, 2025
6fd8036
finish test for cdt_select operation
juliannguyen4 Oct 15, 2025
c9ee120
Fix test and code. need to run against server rc
juliannguyen4 Oct 15, 2025
4abaf19
Follow prd examples
juliannguyen4 Oct 15, 2025
f498bf8
fix test case
juliannguyen4 Oct 15, 2025
217010a
Add neg test case
juliannguyen4 Oct 15, 2025
7618495
Stub for testing cdt select flags
juliannguyen4 Oct 15, 2025
5679f37
Move test cases to separate file because the patch is already large e…
juliannguyen4 Oct 15, 2025
ccebaef
Finish cdt_apply op test
juliannguyen4 Oct 16, 2025
b7bdb91
Finish cdt_select + ctx that selects all children with filter. Does n…
juliannguyen4 Oct 16, 2025
55c1293
Properly implement VarBuiltInMap. test before implementing other expr…
juliannguyen4 Oct 16, 2025
ef3bc91
fix test
juliannguyen4 Oct 16, 2025
3eba73e
Just add one class for all the VarBuiltIn expressions
juliannguyen4 Oct 16, 2025
a01797e
Just finish expression cdt_select() and _apply() later. update c client
juliannguyen4 Oct 16, 2025
f924d85
Fix circular import
juliannguyen4 Oct 16, 2025
0dcca1f
Finish cdt modify operation test
juliannguyen4 Oct 16, 2025
d5d7c46
Fix cdt_apply op
juliannguyen4 Oct 17, 2025
f5482d4
Fix tests
juliannguyen4 Oct 17, 2025
0984e90
Add neg test case where expression VarBuiltIn expects the wrong type
juliannguyen4 Oct 17, 2025
3905793
Do cdt select op no fail test
juliannguyen4 Oct 17, 2025
1b548ab
fix test
juliannguyen4 Oct 17, 2025
c1f14db
_cdt_ctx.extra_args is a dict. not class instance
juliannguyen4 Oct 17, 2025
17b20b1
fix
juliannguyen4 Oct 17, 2025
f429500
cdt_apply op uses 'expr' dictionary key, not 'value'
juliannguyen4 Oct 17, 2025
106e9e2
Move no_fail flag test to positive test case
juliannguyen4 Oct 17, 2025
b9acba8
make tests run with expected results for servers less than 8.1.1
juliannguyen4 Oct 17, 2025
231a4a5
fix test
juliannguyen4 Oct 17, 2025
5152d91
fixture probably not being used
juliannguyen4 Oct 17, 2025
07b493f
todo. wip
juliannguyen4 Oct 20, 2025
ad96ee6
fix
juliannguyen4 Oct 21, 2025
931094b
finish
juliannguyen4 Oct 21, 2025
18f8f73
Bin name must be an expr in c
juliannguyen4 Oct 21, 2025
2a830c7
fix test
juliannguyen4 Oct 21, 2025
2bb0625
omit for now so test can run
juliannguyen4 Oct 21, 2025
26b91f5
wip on flag test. suspect that default CDT_SELECT_TREE will yield wro…
juliannguyen4 Oct 21, 2025
78ba26d
Change default cdt select flag for cdt_select and apply operations to…
juliannguyen4 Oct 21, 2025
175284f
Fix test
juliannguyen4 Oct 21, 2025
a23fb01
fix test
juliannguyen4 Oct 21, 2025
6ff5e3d
fix bug
juliannguyen4 Oct 21, 2025
453eae8
real fix
juliannguyen4 Oct 21, 2025
026bb81
APPEND_ARRAY for builtin expression needs to include the 2 arguments …
juliannguyen4 Oct 21, 2025
ba1d5a2
fix
juliannguyen4 Oct 21, 2025
bedb594
Revert "fix"
juliannguyen4 Oct 21, 2025
50b5907
proper fix
juliannguyen4 Oct 21, 2025
c4995ba
in test, expression subtracts an int from iterated value and expects …
juliannguyen4 Oct 21, 2025
a38035f
Cleanup WIP. will break
juliannguyen4 Oct 23, 2025
fa93da6
continue to cleanup. rm default flags for cdt select expr and ops, si…
juliannguyen4 Oct 23, 2025
0fce163
Clean up ops
juliannguyen4 Oct 23, 2025
6c77bbb
missing
juliannguyen4 Oct 23, 2025
e65aed0
no longer used
juliannguyen4 Oct 23, 2025
df5f299
fix
juliannguyen4 Oct 23, 2025
93899f8
fix naming
juliannguyen4 Oct 23, 2025
8af3472
fix naming
juliannguyen4 Oct 23, 2025
ffff0a8
fix naming for cdt ctx
juliannguyen4 Oct 23, 2025
c6182a3
Address TODO
juliannguyen4 Oct 23, 2025
18c82b6
fix test
juliannguyen4 Oct 23, 2025
6fd79ec
bad import
juliannguyen4 Oct 23, 2025
1777b1f
fix test
juliannguyen4 Oct 23, 2025
0d894dc
Change op naming to be consistent with c client
juliannguyen4 Oct 23, 2025
e2f7cd5
Add flags argument to test since it's now required.
juliannguyen4 Oct 23, 2025
da642f7
fix syntax
juliannguyen4 Oct 23, 2025
8ada0fb
fix
juliannguyen4 Oct 23, 2025
ee77386
fix test. fix code
juliannguyen4 Oct 23, 2025
b378c1c
fix
juliannguyen4 Oct 23, 2025
b823b3d
fix test comparing float with int
juliannguyen4 Oct 23, 2025
e46b9bc
fix test
juliannguyen4 Oct 23, 2025
5c6eca0
Finish SELECT_TREE flag test
juliannguyen4 Oct 23, 2025
d41843c
Add flag map key test
juliannguyen4 Oct 23, 2025
a15517e
Add cdt_modify flags. use those in test instead of cdt_select flags
juliannguyen4 Oct 23, 2025
301dcb2
fix stubs
juliannguyen4 Oct 23, 2025
dd54248
Add tests for all LoopVar types
juliannguyen4 Oct 23, 2025
a8d9255
Attempting to test exprs...
juliannguyen4 Oct 23, 2025
6819063
fix syntax
juliannguyen4 Oct 23, 2025
8c7b456
Have both cdt select and apply use the same map key for flags
juliannguyen4 Oct 23, 2025
2cfa250
fix
juliannguyen4 Oct 23, 2025
dcda5e8
For cdt select/apply exprs, pass in bin expr instead of bin name
juliannguyen4 Oct 24, 2025
f74d3c7
Fix cdt modify expr test
juliannguyen4 Oct 24, 2025
6f53e1b
Finish loopvar id enum tests
juliannguyen4 Oct 24, 2025
6ce81da
Add neg test for empty ctx list passed to modify op
juliannguyen4 Oct 24, 2025
5934797
Add neg test for ctx=None. code should be able to handle invalid pyth…
juliannguyen4 Oct 24, 2025
963d196
finish documentation.
juliannguyen4 Oct 24, 2025
2a6e37c
try adding reference to type in param docstring. not letting me click…
juliannguyen4 Oct 24, 2025
b7868a8
fully qualified name
juliannguyen4 Oct 24, 2025
465bedf
Revert "fully qualified name"
juliannguyen4 Oct 24, 2025
091147b
dont need since func signature already has
juliannguyen4 Oct 24, 2025
ad93161
Keyword was changed to make more readable
juliannguyen4 Oct 24, 2025
a16dabf
Rm outdated TODOs
juliannguyen4 Oct 24, 2025
ac603dd
Fix four failing tests...
juliannguyen4 Oct 24, 2025
cf7eaf9
fix spelling
juliannguyen4 Oct 24, 2025
fb61fac
fix mem leak
juliannguyen4 Oct 24, 2025
18665b2
pointer to struct, not struct ref
juliannguyen4 Oct 24, 2025
66de999
most clear
juliannguyen4 Oct 24, 2025
5d34c87
Only 'bottom' number of as_exp_entry entries are actually initialized…
juliannguyen4 Oct 24, 2025
a1d4d20
rm todo for now
juliannguyen4 Oct 24, 2025
52b125b
Make LoopVar public so we can see the init documentation for inheriti…
juliannguyen4 Oct 24, 2025
f6895f9
Show that LoopVar* classes are subclasses of LoopVar class
juliannguyen4 Oct 24, 2025
1e2d5c2
Remove type annotation for expr since it gets expanded in the docs
juliannguyen4 Oct 24, 2025
a157ae1
Make name shorter since the file name is self-explanatory
juliannguyen4 Oct 24, 2025
39d6632
fix confusing comment
juliannguyen4 Oct 24, 2025
e166f24
Clear up why test set up this way
juliannguyen4 Oct 24, 2025
a84e307
confusing spacing
juliannguyen4 Oct 24, 2025
91cbccc
bad spacing
juliannguyen4 Oct 24, 2025
9c15c37
improve var name
juliannguyen4 Oct 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
path = aerospike-client-c
# url = [email protected]:aerospike/aerospike-client-c.git
url = https://github.com/aerospike/aerospike-client-c.git
branch = stage
branch = client-3753-path-expressions-integration
13 changes: 13 additions & 0 deletions aerospike-stubs/aerospike.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,19 @@ TXN_STATE_VERIFIED: Literal[1]
TXN_STATE_COMMITTED: Literal[2]
TXN_STATE_ABORTED: Literal[3]

CDT_SELECT_MATCHING_TREE: Literal[0]
CDT_SELECT_VALUES: Literal[1]
CDT_SELECT_MAP_KEY_VALUES: Literal[1]
CDT_SELECT_MAP_KEYS: Literal[2]
CDT_SELECT_NO_FAIL: Literal[16]

CDT_MODIFY_DEFAULT: Literal[0]
CDT_MODIFY_NO_FAIL: Literal[0x10]

EXP_LOOPVAR_KEY: Literal[0]
EXP_LOOPVAR_VALUE: Literal[1]
EXP_LOOPVAR_INDEX: Literal[2]

@final
class CDTInfinite:
def __init__(self, *args, **kwargs) -> None: ...
Expand Down
26 changes: 26 additions & 0 deletions aerospike_helpers/cdt_ctx.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,29 @@ def cdt_ctx_map_key_create(key: any, order: int = 0) -> _cdt_ctx:
:class:`~aerospike_helpers.cdt_ctx._cdt_ctx`
"""
return _cdt_ctx(id=aerospike.CDT_CTX_MAP_KEY_CREATE, value=key, extra_args={CDT_CTX_ORDER_KEY: order})

def cdt_ctx_all_children() -> _cdt_ctx:
"""
At the current context, causes a query to return a list of all the children
of the current item. For a map, this will recurse into the map elements.
For a list, this will include all the children in the list.

Returns:
:class:`~aerospike_helpers.cdt_ctx._cdt_ctx`
"""
return _cdt_ctx(id=aerospike._CDT_CTX_EXP)

def cdt_ctx_all_children_with_filter(expression: "TypeExpression") -> _cdt_ctx:
"""
All children of the current level will be selected, and then the filter expression
is applied to each item in turn. Items that cause the expression to evaluate to true will be added to the
list of items returned in a query for this level. Items that cause the expression to evaluate to false
will be filtered out

Args:
expression: Compiled expression. This expression must return a boolean.

Returns:
:class:`~aerospike_helpers.cdt_ctx._cdt_ctx`
"""
return _cdt_ctx(id=aerospike._CDT_CTX_EXP, extra_args={aerospike._CDT_CTX_ALL_CHILDREN_WITH_FILTER_EXPR_KEY: expression})
90 changes: 90 additions & 0 deletions aerospike_helpers/expressions/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
from aerospike_helpers.expressions.resources import _ExprOp
from aerospike_helpers.expressions.resources import ResultType
from aerospike_helpers.expressions.resources import _Keys
from aerospike_helpers.cdt_ctx import _cdt_ctx
from abc import ABC

TypeComparisonArg = Union[_BaseExpr, Any]
TypeGeo = Union[_BaseExpr, aerospike.GeoJSON]
Expand Down Expand Up @@ -1069,3 +1071,91 @@ def __init__(self, var_name: str):
exp.LT(exp.Var("x"), 10))).compile()
"""
self._fixed = {_Keys.VALUE_KEY: var_name}


class LoopVar(_BaseExpr, ABC):
"""
Retrieve expression value from a path expression loop variable.
"""
def __init__(self, var_id: int):
"""
Args:
var_id: See :ref:`exp_loopvar_metadata` for possible values.

:return: (value stored in variable)
"""
self._fixed = {_Keys.VALUE_KEY: var_id}


class LoopVarMap(LoopVar):
_op = aerospike._AS_EXP_LOOPVAR_MAP


class LoopVarList(LoopVar):
_op = aerospike._AS_EXP_LOOPVAR_LIST


class LoopVarStr(LoopVar):
_op = aerospike._AS_EXP_LOOPVAR_STR


class LoopVarFloat(LoopVar):
_op = aerospike._AS_EXP_LOOPVAR_FLOAT


class LoopVarInt(LoopVar):
_op = aerospike._AS_EXP_LOOPVAR_INT


class SelectByPath(_BaseExpr):
"""
Constructs a select by path operation. This is used to retrieve a number of
records or fields of records, including those of structured types.
"""
_op = aerospike._AS_EXP_CODE_CALL_SELECT

def __init__(self, ctx: list[_cdt_ctx], return_type: ResultType, flags: int, bin: _BaseExpr):
"""
Args:
ctx: list of CDT contexts. This cannot be None or an empty list.
return_type: Return type specifier.
flags: See :ref:`cdt_select_flags` for possible values.
bin: Bin expression to which this expression applies.

:return: (expression)
"""
self._fixed = {
_Keys.RETURN_TYPE_KEY: return_type,
_Keys.CTX_KEY: ctx,
aerospike._CDT_FLAGS_KEY: flags,
}
self._children = (bin,)


class ModifyByPath(_BaseExpr):
"""
Constructs a CDT apply operation.

The results of the evaluation of the modifying expression will replace the
selected map, and the changes are written back to storage.
"""
_op = aerospike._AS_EXP_CODE_CALL_APPLY

def __init__(self, ctx: list[_cdt_ctx], return_type: ResultType, mod_exp, flags: int, bin: _BaseExpr):
"""
Args:
ctx: list of CDT contexts. This cannot be None or an empty list.
return_type: Return type specifier.
mod_exp: Compiled expression to apply.
flags: See :ref:`cdt_modify_flags` for possible values.
bin: Bin expression to which this expression applies.

:return: (expression)
"""
self._fixed = {
_Keys.RETURN_TYPE_KEY: return_type,
_Keys.CTX_KEY: ctx,
aerospike._CDT_FLAGS_KEY: flags,
aerospike._CDT_APPLY_MOD_EXP_KEY: mod_exp
}
self._children = (bin,)
3 changes: 3 additions & 0 deletions aerospike_helpers/expressions/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class _ExprOp: # TODO replace this with an enum
DEF = 126

_AS_EXP_CODE_AS_VAL = 128

# virtual ops
_AS_EXP_CODE_CALL_VOP_START = 139
_AS_EXP_CODE_CDT_LIST_CRMOD = 140
Expand All @@ -112,6 +113,8 @@ class ReturnType:
MAP_RETURN_INVERTED = 0x10000


# These enum constants must match the values for C client's as_exp_type.
# These are passed as arguments to ModifyByPath and SelectByPath expressions
class ResultType:
"""
Flags used to indicate expression value_type.
Expand Down
43 changes: 43 additions & 0 deletions aerospike_helpers/operations/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import aerospike
from typing import Optional

from aerospike_helpers.cdt_ctx import _cdt_ctx


def read(bin_name):
"""Create a read operation dictionary.
Expand Down Expand Up @@ -131,3 +133,44 @@ def touch(ttl: Optional[int] = None):
warnings.warn("TTL should be specified in the meta dictionary for operate", DeprecationWarning)
op_dict["val"] = ttl
return op_dict


def select_by_path(bin_name: str, ctx: list[_cdt_ctx], flags: int):
"""
Create CDT select operation.
Args:
bin_name: Bin name
ctx: List of contexts to select nodes. It is an error for ctx to be :py:obj:`None` or an empty list.
flags: See :ref:`cdt_select_flags` for the set of valid flags for this function.
Returns:
A dictionary to be passed to operate or operate_ordered.
"""
op_dict = {"op": aerospike._AS_OPERATOR_CDT_READ, "bin": bin_name, "ctx": ctx, aerospike._CDT_FLAGS_KEY: flags}
return op_dict


def modify_by_path(bin_name: str, ctx: list[_cdt_ctx], expr, flags: int):
"""
Create CDT modification operation.
The results of the evaluation of the modifying expression will replace the
selected map, and the changes are written back to storage.
Args:
bin_name: Bin name
ctx: List of contexts to select nodes. It is an error for ctx to be :py:obj:`None` or an empty list.
expr: compiled modifying expression.
flags: See :ref:`cdt_modify_flags` for the set of valid flags for this function.
Returns:
A dictionary to be passed to operate or operate_ordered.
"""
op_dict = {
"op": aerospike._AS_OPERATOR_CDT_MODIFY,
"bin": bin_name,
"ctx": ctx, aerospike._CDT_APPLY_MOD_EXP_KEY: expr,
aerospike._CDT_FLAGS_KEY: flags
}
return op_dict
58 changes: 58 additions & 0 deletions doc/aerospike.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1792,3 +1792,61 @@ Transaction State
.. data:: TXN_STATE_COMMITTED

.. data:: TXN_STATE_ABORTED

.. _cdt_select_flags:

CDT Select Flags
----------------

.. data:: CDT_SELECT_MATCHING_TREE

Return a tree from the root (bin) level to the bottom of the tree, with only non-filtered out nodes.

.. data:: CDT_SELECT_VALUES

Return the list of the values of the nodes finally selected by the context.

.. data:: CDT_SELECT_MAP_KEY_VALUES

Return a list of key-value pairs.

.. data:: CDT_SELECT_MAP_KEYS

For final selected nodes which are elements of maps, return the appropriate map key.

.. data:: CDT_SELECT_NO_FAIL

If the expression in the context hits an invalid type (e.g selects as an integer when the value is a string),
do not fail the operation; just ignore those elements.

.. _cdt_modify_flags:

CDT Modify Flags
----------------

.. data:: CDT_MODIFY_DEFAULT

If the expression in the context hits an invalid type, the operation
will fail. This is the default behavior.

.. data:: CDT_MODIFY_NO_FAIL

If the expression in the context hits an invalid type (e.g., selects as an integer when the value is a string), do
not fail the operation; just ignore those elements.

.. _exp_loopvar_metadata:

Expression Loop Variable Metadata
---------------------------------

.. data:: EXP_LOOPVAR_KEY

The key associated with this value if part of a key-value pair of a map.

.. data:: EXP_LOOPVAR_VALUE

List item, or value from a map key-value pair.

.. data:: EXP_LOOPVAR_INDEX

The index if this element was part of a list.
1 change: 1 addition & 0 deletions doc/aerospike_helpers.expressions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ aerospike\_helpers\.expressions\.base module
.. automodule:: aerospike_helpers.expressions.base
:members:
:special-members:
:show-inheritance:

aerospike\_helpers\.expressions\.list module
--------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions doc/spelling_wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,4 @@ namespaces
yaml
suberror
hardcoded
recurse
20 changes: 20 additions & 0 deletions src/include/policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,28 @@ enum aerospike_hll_operations {
OP_HLL_MAY_CONTAIN
};

enum {
_AS_EXP_CODE_CALL_SELECT = 127,
_AS_EXP_CODE_CALL_APPLY = 129,
};

enum aerospike_expression_operations { OP_EXPR_READ = 2200, OP_EXPR_WRITE };

// Module constants to be used by aerospike_helpers

enum {
_AS_EXP_LOOPVAR_FLOAT = 3000,
_AS_EXP_LOOPVAR_INT,
_AS_EXP_LOOPVAR_LIST,
_AS_EXP_LOOPVAR_MAP,
_AS_EXP_LOOPVAR_STR
};

// Can be either for select or apply
#define _CDT_FLAGS_KEY "cdt_flags"
#define _CDT_APPLY_MOD_EXP_KEY "mod_exp"
#define _CDT_CTX_ALL_CHILDREN_WITH_FILTER_EXPR_KEY "filter_expr"

enum aerospike_regex_constants {
REGEX_NONE = 0,
REGEX_EXTENDED,
Expand Down
Loading