Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 29 additions & 7 deletions src/include/conversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,16 +222,38 @@ PyObject *create_class_instance_from_module(as_error *error_p,
// We return an unsigned long long because it should be able to fit all fixed-width int types up to uint64_t
// Returns -1 on error. Error indicator can be checked to verify if error occurred
// TODO: replace this with new API calls in Python 3.14
unsigned long long
convert_pyobject_to_fixed_width_integer_type(PyObject *pyobject,
unsigned long long max_bound);
uint8_t convert_pyobject_to_uint8_t(PyObject *pyobject);
unsigned long long convert_pyobject_to_unsigned_fixed_width_integer_type(
PyObject *pyobject, unsigned long long max_bound);

uint16_t convert_pyobject_to_uint16_t(PyObject *pyobject);
uint64_t convert_unsigned_long_long_into_uint64_t(as_error *err,
PyObject *pyobject,
const char *component);

uint32_t convert_pyobject_to_uint32_t(PyObject *pyobject);
int64_t convert_long_long_into_int64_t(as_error *err, PyObject *pyobject,
const char *component);

uint64_t convert_pyobject_to_uint64_t(PyObject *pyobject);
uint32_t convert_unsigned_long_into_uint32_t(as_error *err, PyObject *pyobject,
const char *component);

int32_t convert_long_into_int32_t(as_error *err, PyObject *pyobject,
const char *component);

int convert_long_into_int(as_error *err, PyObject *pyobject,
const char *component);

unsigned int convert_unsigned_long_into_enum_value(as_error *err,
PyObject *py_long,
unsigned int max_enum_value,
const char *component);

uint16_t convert_unsigned_long_into_uint16_t(as_error *err, PyObject *pyobject,
const char *component);

int16_t convert_long_into_int16_t(as_error *err, PyObject *pyobject,
const char *component);

uint8_t convert_unsigned_long_into_uint8_t(as_error *err, PyObject *pyobject,
const char *component);

// Returns NULL on error.
const char *convert_pyobject_to_str(PyObject *py_obj);
Expand Down
2 changes: 0 additions & 2 deletions src/include/query.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,6 @@ PyObject *AerospikeQuery_Get_Partitions_status(AerospikeQuery *self);
*/
PyObject *StoreUnicodePyObject(AerospikeQuery *self, PyObject *obj);

int64_t pyobject_to_int64(PyObject *py_obj);

// We need to share this with src/main/client/query.c because this function is no longer assigned
// to the query type's tp_new slot. We are trying to prevent users from using the query type's constructor directly
// to create a query instance.
Expand Down
19 changes: 6 additions & 13 deletions src/main/client/cdt_operation_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,22 +135,15 @@ as_status get_optional_int64_t(as_error *err, const char *key,
if (!py_val) {
return AEROSPIKE_OK;
}

if (!PyLong_Check(py_val)) {
return as_error_update(err, AEROSPIKE_ERR_PARAM,
"%s must be an integer", key);
as_error_update(err, AEROSPIKE_ERR_PARAM,
"Unable to convert Python object %s to int64_t", key);
return err->code;
}

*i64_valptr = (int64_t)PyLong_AsLongLong(py_val);
if (PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
return as_error_update(err, AEROSPIKE_ERR_PARAM, "%s too large",
key);
}
return as_error_update(err, AEROSPIKE_ERR_PARAM, "Failed to convert %s",
key);
*i64_valptr = convert_long_long_into_int64_t(err, py_val, key);
if (err->code != AEROSPIKE_OK) {
return err->code;
}

*found = true;
return AEROSPIKE_OK;
}
Expand Down
30 changes: 18 additions & 12 deletions src/main/client/operate.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ as_status add_op(AerospikeClient *self, as_error *err,
char *bin = NULL;
char *val = NULL;
long offset = 0;
long long long_offset = 0;
long ttl = 0;
double double_offset = 0.0;
int index = 0;
Expand Down Expand Up @@ -544,7 +545,10 @@ as_status add_op(AerospikeClient *self, as_error *err,
goto CLEANUP;
}
if (PyLong_Check(py_index)) {
index = PyLong_AsLong(py_index);
index = convert_long_into_int(err, py_index, "py_index");
if (err->code != AEROSPIKE_OK) {
goto CLEANUP;
}
}
else {
as_error_update(err, AEROSPIKE_ERR_PARAM,
Expand Down Expand Up @@ -573,10 +577,15 @@ as_status add_op(AerospikeClient *self, as_error *err,
as_error_update(err, AEROSPIKE_ERR_CLIENT, "Internal error");
goto CLEANUP;
}

uint32_t flags = convert_pyobject_to_uint32_t(py_flags);
if (!PyLong_Check(py_flags)) {
as_error_update(err, AEROSPIKE_ERR_PARAM,
"CDT operation's flags argument must be a long");
goto CLEANUP;
}
uint32_t flags =
convert_unsigned_long_into_uint32_t(err, py_flags, "path flags");
Py_DECREF(py_flags);
if (PyErr_Occurred()) {
if (err->code != AEROSPIKE_OK) {
as_error_update(err, AEROSPIKE_ERR_PARAM,
"CDT operation's flags argument is invalid");
goto CLEANUP;
Expand Down Expand Up @@ -680,15 +689,12 @@ as_status add_op(AerospikeClient *self, as_error *err,
break;
case AS_OPERATOR_INCR:
if (PyLong_Check(py_value)) {
offset = PyLong_AsLong(py_value);
if (offset == -1 && PyErr_Occurred() && self->strict_types) {
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
as_error_update(err, AEROSPIKE_ERR_PARAM,
"integer value exceeds sys.maxsize");
goto CLEANUP;
}
long_offset = convert_long_long_into_int64_t(err, py_value,
"AS_OPERATOR_INCR");
if (err->code != AEROSPIKE_OK) {
goto CLEANUP;
}
as_operations_add_incr(ops, bin, offset);
as_operations_add_incr(ops, bin, long_offset);
}
else if (PyFloat_Check(py_value)) {
double_offset = PyFloat_AsDouble(py_value);
Expand Down
23 changes: 17 additions & 6 deletions src/main/client/query.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,11 @@ static int query_where_add(as_query **query, as_predicate_type predicate,
"Bin must be a string or unicode");
return 1;
}
int64_t val = pyobject_to_int64(py_val1);

int64_t val = convert_long_long_into_int64_t(err, py_val1,
"query numeric index");
if (err->code != AEROSPIKE_OK) {
return 1;
}
as_query_where_init(*query, 1);
if (index_type == 0) {
as_query_where(*query, bin, as_equals(NUMERIC, val));
Expand Down Expand Up @@ -193,7 +196,11 @@ static int query_where_add(as_query **query, as_predicate_type predicate,
return 1;
}
if (PyLong_Check(py_val1)) {
min = pyobject_to_int64(py_val1);
min = convert_long_long_into_int64_t(err, py_val1,
"predicate max");
if (err->code != AEROSPIKE_OK) {
return 1;
}
}
else {
Py_XDECREF(py_ubin);
Expand All @@ -203,7 +210,11 @@ static int query_where_add(as_query **query, as_predicate_type predicate,
}

if (PyLong_Check(py_val2)) {
max = pyobject_to_int64(py_val2);
max = convert_long_long_into_int64_t(err, py_val2,
"predicate max");
if (err->code != AEROSPIKE_OK) {
return 1;
}
}
else {
Py_XDECREF(py_ubin);
Expand Down Expand Up @@ -405,15 +416,15 @@ static PyObject *AerospikeClient_QueryApply_Invoke(
}

long op = PyLong_AsLong(py_op);
if (op == -1 && PyErr_Occurred()) {
if (PyErr_Occurred()) {
as_error_update(&err, AEROSPIKE_ERR_PARAM,
"unknown predicate type");
goto CLEANUP;
}

as_index_datatype op_data =
(as_index_datatype)PyLong_AsLong(py_op_data);
if (op == -1 && PyErr_Occurred()) {
if (PyErr_Occurred()) {
as_error_update(&err, AEROSPIKE_ERR_PARAM,
"unknown index data type");
goto CLEANUP;
Expand Down
13 changes: 3 additions & 10 deletions src/main/client/remove.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,16 +93,9 @@ PyObject *AerospikeClient_Remove_Invoke(AerospikeClient *self, PyObject *py_key,
if (py_gen) {
if (PyLong_Check(py_gen)) {
remove_policy_p->generation =
(uint16_t)PyLong_AsLong(py_gen);
}
else if (PyLong_Check(py_gen)) {
remove_policy_p->generation =
(uint16_t)PyLong_AsLongLong(py_gen);
if ((uint16_t)-1 == remove_policy_p->generation &&
PyErr_Occurred()) {
as_error_update(
&err, AEROSPIKE_ERR_PARAM,
"integer value for gen exceeds sys.maxsize");
convert_unsigned_long_into_uint16_t(&err, py_gen,
"generation");
if (err.code != AEROSPIKE_OK) {
goto CLEANUP;
}
}
Expand Down
19 changes: 3 additions & 16 deletions src/main/client/truncate.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ PyObject *AerospikeClient_Truncate(AerospikeClient *self, PyObject *args,
PyObject *py_nanos = NULL;
PyObject *py_policy = NULL;
PyObject *ret_val = NULL;
long long temp_long;
as_error err;
uint64_t nanos = 1; // If assignment fails, this will cause an error
char *namespace = NULL;
Expand Down Expand Up @@ -126,21 +125,9 @@ PyObject *AerospikeClient_Truncate(AerospikeClient *self, PyObject *args,

// Start conversion of the nanosecond parameter
if (PyLong_Check(py_nanos)) {

temp_long = PyLong_AsLongLong(py_nanos);
// There was a negative number outside of the range of - 2 ^ 63
if (temp_long < 0 && !PyErr_Occurred()) {
as_error_update(&err, AEROSPIKE_ERR_PARAM,
"Nanoseconds must be a positive value");
goto CLEANUP;
}
// Its possible that this is a valid uint64 between 2 ^ 63 and 2^64 -1
PyErr_Clear();
nanos = (uint64_t)PyLong_AsUnsignedLongLong(py_nanos);

if (PyErr_Occurred()) {
as_error_update(&err, AEROSPIKE_ERR_PARAM,
"Nanoseconds value too large");
nanos = convert_unsigned_long_long_into_uint64_t(&err, py_nanos,
"truncate");
if (err.code != AEROSPIKE_OK) {
goto CLEANUP;
}
}
Expand Down
Loading