AerospikeQuery * AerospikeQuery_Apply(AerospikeQuery * self, PyObject * args, PyObject * kwds) { // Python function arguments PyObject * py_module = NULL; PyObject * py_function = NULL; PyObject * py_args = NULL; PyObject * py_policy = NULL; PyObject * py_umodule = NULL; PyObject * py_ufunction = NULL; // Python function keyword arguments static char * kwlist[] = {"module", "function", "arguments", "policy", NULL}; if ( PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO:apply", kwlist, &py_module, &py_function, &py_args, &py_policy) == false ){ return NULL; } // Aerospike error object as_error err; // Initialize error object as_error_init(&err); if ( !self || !self->client->as ){ as_error_update(&err, AEROSPIKE_ERR_PARAM, "Invalid query object"); goto CLEANUP; } if (!self->client->is_conn_16) { as_error_update(&err, AEROSPIKE_ERR_CLUSTER, "No connection to aerospike cluster"); goto CLEANUP; } // Aerospike API Arguments char * module = NULL; char * function = NULL; as_arraylist * arglist = NULL; if ( PyUnicode_Check(py_module) ){ py_umodule = PyUnicode_AsUTF8String(py_module); module = PyStr_AsString(py_umodule); } else if ( PyStr_Check(py_module) ) { module = PyStr_AsString(py_module); } else { as_error_update(&err, AEROSPIKE_ERR_CLIENT, "udf module argument must be a string or unicode string"); goto CLEANUP; } if ( PyUnicode_Check(py_function) ){ py_ufunction = PyUnicode_AsUTF8String(py_function); function = PyStr_AsString(py_ufunction); } else if ( PyStr_Check(py_function) ) { function = PyStr_AsString(py_function); } else { as_error_update(&err, AEROSPIKE_ERR_CLIENT, "udf function argument must be a string or unicode string"); goto CLEANUP; } if ( py_args && PyList_Check(py_args) ){ Py_ssize_t size = PyList_Size(py_args); arglist = as_arraylist_new(size, 0); for ( int i = 0; i < size; i++ ) { PyObject * py_val = PyList_GetItem(py_args, (Py_ssize_t)i); as_val * val = NULL; pyobject_to_val(self->client, &err, py_val, &val, &self->static_pool, SERIALIZER_PYTHON); if ( err.code != AEROSPIKE_OK ) { as_error_update(&err, err.code, NULL); goto CLEANUP; } else { as_arraylist_append(arglist, val); } } } as_query_apply(&self->query, module, function, (as_list *) arglist); CLEANUP: if (py_ufunction) { Py_DECREF(py_ufunction); } if (py_umodule) { Py_DECREF(py_umodule); } if ( err.code != AEROSPIKE_OK ) { PyObject * py_err = NULL; error_to_pyobject(&err, &py_err); PyObject *exception_type = raise_exception(&err); if(PyObject_HasAttrString(exception_type, "module")) { PyObject_SetAttrString(exception_type, "module", py_module); } if(PyObject_HasAttrString(exception_type, "func")) { PyObject_SetAttrString(exception_type, "func", py_function); } PyErr_SetObject(exception_type, py_err); Py_DECREF(py_err); return NULL; } Py_INCREF(self); return self; }
AerospikeQuery * AerospikeQuery_Apply(AerospikeQuery * self, PyObject * args, PyObject * kwds) { as_error err; // Initialize error as_error_init(&err); int nargs = (int) PyTuple_Size(args); // Aerospike API Arguments char * module = NULL; char * function = NULL; as_arraylist * arglist = NULL; // too few args if ( nargs < 2 ) { // some error } // Python Arguments PyObject * py_module = PyTuple_GetItem(args, 0); PyObject * py_function = PyTuple_GetItem(args, 1); if ( PyString_Check(py_module) ) { module = PyString_AsString(py_module); } else { as_error_update(&err, AEROSPIKE_ERR_CLIENT, "udf module argument must be a string"); goto CLEANUP; } if ( PyString_Check(py_function) ) { function = PyString_AsString(py_function); } else { as_error_update(&err, AEROSPIKE_ERR_CLIENT, "udf function argument must be a string"); goto CLEANUP; } if ( nargs > 2 ) { arglist = as_arraylist_new(nargs, 0); for ( int i = 2; i < nargs; i++ ) { PyObject * py_val = PyTuple_GetItem(args, i); as_val * val = NULL; pyobject_to_val(&err, py_val, &val); if ( err.code != AEROSPIKE_OK ) { goto CLEANUP; } } } as_query_apply(&self->query, module, function, (as_list *) arglist); CLEANUP: if ( err.code != AEROSPIKE_OK ) { PyObject * py_err = NULL; error_to_pyobject(&err, &py_err); PyErr_SetObject(PyExc_Exception, py_err); return NULL; } Py_INCREF(self); return self; }
int main(int argc, char* argv[]) { // Parse command line arguments. if (! example_get_opts(argc, argv, EXAMPLE_MULTI_KEY_OPTS)) { exit(-1); } // Connect to the aerospike database cluster. aerospike as; example_connect_to_aerospike_with_udf_config(&as, UDF_USER_PATH); // Start clean. example_remove_test_records(&as); example_remove_index(&as, TEST_INDEX_NAME); // Register the UDF in the database cluster. if (! example_register_udf(&as, UDF_FILE_PATH)) { example_cleanup(&as); exit(-1); } // Create a numeric secondary index on test-bin. if (! example_create_integer_index(&as, "test-bin", TEST_INDEX_NAME)) { cleanup(&as); exit(-1); } if (! insert_records(&as)) { cleanup(&as); exit(-1); } if (! example_read_test_records(&as)) { cleanup(&as); exit(-1); } as_error err; // Create an as_query object. as_query query; as_query_init(&query, g_namespace, g_set); // Generate an as_query.where condition. Note that as_query_destroy() takes // care of destroying all the query's member objects if necessary. However // using as_query_where_inita() does avoid internal heap usage. as_query_where_inita(&query, 1); as_query_where(&query, "test-bin", as_integer_range(1, 10)); // Specify the UDF to use on the resulting stream. as_query_apply(&query, UDF_MODULE, "sum_test_bin", NULL); LOG("executing map-reduce query: where test-bin = 1 ... 10"); // Execute the query. This call blocks - callbacks are made in the scope of // this call. if (aerospike_query_foreach(&as, &err, NULL, &query, query_cb, NULL) != AEROSPIKE_OK) { LOG("aerospike_query_foreach() returned %d - %s", err.code, err.message); as_query_destroy(&query); cleanup(&as); exit(-1); } LOG("map-reduce query executed"); // Reuse the as_query object for another query. as_query_destroy(&query); as_query_init(&query, g_namespace, g_set); // Generate an as_query.where condition. as_query_where_inita(&query, 1); as_query_where(&query, "test-bin", as_integer_range(1, 10)); // Specify another UDF to use on the resulting stream. Like the previous UDF // it sums the test-bin values that satisfy the where condition, but does so // in a different, more efficient manner (see query_udf.lua). as_query_apply(&query, UDF_MODULE, "sum_test_bin_2", NULL); LOG("executing aggregate-reduce query: where test-bin = 1 ... 10"); // Execute the query. This call blocks - callbacks are made in the scope of // this call. if (aerospike_query_foreach(&as, &err, NULL, &query, query_cb, NULL) != AEROSPIKE_OK) { LOG("aerospike_query_foreach() returned %d - %s", err.code, err.message); as_query_destroy(&query); cleanup(&as); exit(-1); } LOG("aggregate-reduce query executed"); // Reuse the as_query object for another query. as_query_destroy(&query); as_query_init(&query, g_namespace, g_set); // Generate an as_query.where condition. as_query_where_inita(&query, 1); as_query_where(&query, "test-bin", as_integer_range(1, 10)); // Specify another UDF to use on the resulting stream. Like the previous // UDFs it sums test-bin values that satisfy the where condition, but first // applies a filter to sum only even values (see query_udf.lua). as_query_apply(&query, UDF_MODULE, "sum_test_bin_even", NULL); LOG("executing filter-aggregate-reduce query: where test-bin = 1 ... 10"); // Execute the query. This call blocks - callbacks are made in the scope of // this call. if (aerospike_query_foreach(&as, &err, NULL, &query, query_cb, NULL) != AEROSPIKE_OK) { LOG("aerospike_query_foreach() returned %d - %s", err.code, err.message); as_query_destroy(&query); cleanup(&as); exit(-1); } LOG("filter-aggregate-reduce query executed"); // Reuse the as_query object for another query. as_query_destroy(&query); as_query_init(&query, g_namespace, g_set); // No as_query.where condition in this case, so we include everything. // Specify another UDF to use on the resulting stream. This UDF operates on // the numbers-bin (string) values, and demonstrates a case where the value // returned by the query callback is an as_map (instead of an as_integer). as_query_apply(&query, UDF_MODULE, "count_numbers", NULL); LOG("executing numbers aggregate-reduce query: all records"); // Execute the query. This call blocks - callbacks are made in the scope of // this call. if (aerospike_query_foreach(&as, &err, NULL, &query, query_cb_map, NULL) != AEROSPIKE_OK) { LOG("aerospike_query_foreach() returned %d - %s", err.code, err.message); as_query_destroy(&query); cleanup(&as); exit(-1); } LOG("numbers aggregate-reduce query executed"); as_query_destroy(&query); // Cleanup and disconnect from the database cluster. cleanup(&as); LOG("aggregate query example successfully completed"); return 0; }