Commit 31bd6d11 authored by Matthieu Dorier's avatar Matthieu Dorier
Browse files

added test for jx9 version of execute

parent c79e79d8
......@@ -13,12 +13,12 @@ namespace sonata {
typedef std::function<void(unqlite_context*, bool)> RequestCompletionFn;
#define LOG_ERROR()\
unqlite_context_throw_error_format(pCtx, UNQLITE_CTX_WARNING,\
unqlite_context_output_format(pCtx,\
"%s threw an exception: %s", unqlite_result_null(pCtx), ex.what());
#define CHECK_ARGS(__num__) do {\
if(argc != __num__) {\
unqlite_context_throw_error_format(pCtx, UNQLITE_CTX_ERR,\
unqlite_context_output_format(pCtx,\
"%s: unexpected number of aruments (%d, expected %d)",\
unqlite_function_name(pCtx), argc, __num__);\
unqlite_result_null(pCtx);\
......@@ -27,7 +27,7 @@ typedef std::function<void(unqlite_context*, bool)> RequestCompletionFn;
#define CHECK_ARGS2(__num1__, __num2__) do {\
if(argc != (__num1__) && argc != (__num2__)) {\
unqlite_context_throw_error_format(pCtx, UNQLITE_CTX_ERR,\
unqlite_context_output_format(pCtx,\
"%s: unexpected number of aruments (%d, expected %d or %d)",\
unqlite_function_name(pCtx), argc, (__num1__), (__num2__));\
unqlite_result_null(pCtx);\
......@@ -36,7 +36,7 @@ typedef std::function<void(unqlite_context*, bool)> RequestCompletionFn;
#define CATCH_AND_ABORT()\
catch(const Exception& ex) {\
unqlite_context_throw_error_format(pCtx, UNQLITE_CTX_ERR,\
unqlite_context_output_format(pCtx,\
"%s threw an exception: %s", unqlite_function_name(pCtx), ex.what());\
unqlite_result_null(pCtx);\
return UNQLITE_OK;\
......@@ -304,29 +304,31 @@ int UnQLiteVM::sntd_execute(unqlite_context *pCtx, int argc, unqlite_value **arg
try {
database_info db_info(argv[0]);
Database db = vm->m_backend->m_client.open(db_info.address, db_info.provider_id, db_info.db_name, false);
// getting the code
std::string code;
if(unqlite_value_is_callable(argv[1])) {
std::string function_name = unqlite_value_to_string(argv[1], nullptr);
code = vm->extract_function_code(function_name.c_str());
code = vm->extract_function_code(function_name.c_str(), false);
if(code.empty()) {
throw Exception("Could not find source code for function "s+function_name);
}
code += "\n"s + function_name + "();\n";
} else if(unqlite_value_is_string(argv[1])) {
code = unqlite_value_to_string(argv[1], nullptr);
} else {
throw Exception("Invalid 2nd argument type (expected function or string)");
}
// listing variables that should be returned
std::unordered_set<std::string> vars;
if(argc == 3) {
std::vector<std::string> variables = UnQLiteValue(argv[2], nullptr, nullptr, true);
for(auto& v : variables) {
for(auto& v : variables) {
vars.insert(v);
}
}
// executing
std::unordered_map<std::string,std::string> result;
db.execute(code, vars, &result);
unqlite_value* result_dict = unqlite_context_new_scalar(pCtx);
unqlite_value* result_dict = unqlite_context_new_array(pCtx);
for(auto it = result.begin(); it != result.end(); it++) {
unqlite_value* v = unqlite_context_new_scalar(pCtx);
unqlite_value_string(v, it->second.c_str(), -1);
......
......@@ -122,9 +122,10 @@ class UnQLiteVM {
if(ret != UNQLITE_OK) parse_and_throw_error();
}
std::string extract_function_code(const char* function_name) {
std::string extract_function_code(const char* function_name, bool include_fun_decl=true) {
const char* tmp = m_code;
const char* function_beginning = nullptr;
const char* function_body_beginning = nullptr;
size_t fun_name_len = strlen(function_name);
while((tmp = strstr(tmp, "function")) != NULL) {
function_beginning = tmp;
......@@ -152,8 +153,10 @@ class UnQLiteVM {
}
if(isalnum(*(tmp+fun_name_len)) || *(tmp+fun_name_len) == '_')
continue; // the function name is longer than we are looking for
// of we know we passed the function's name
// find the '{' character
while(*tmp != '{') tmp += 1;
function_body_beginning = tmp+1;
unsigned b = 1; // track opened {
do {
tmp += 1;
......@@ -162,8 +165,13 @@ class UnQLiteVM {
if(*tmp == '\0') break;
} while(b != 0);
if(*tmp == '\0') return std::string();
const char* function_body_end = tmp;
const char* function_end = tmp+1;
return std::string(function_beginning, (size_t)(function_end-function_beginning));
if(include_fun_decl) {
return std::string(function_beginning, (size_t)(function_end-function_beginning));
} else {
return std::string(function_body_beginning, (size_t)(function_body_end-function_body_beginning));
}
}
return std::string();
}
......
......@@ -526,10 +526,45 @@ class UnQLiteValue {
template<typename Stream>
Stream& printToStream(Stream& os) const {
if(is<std::string>()) {
os << "\"" << unqlite_value_to_string(m_value, nullptr) << "\"";
} else {
os << unqlite_value_to_string(m_value, nullptr);
if(is<int64_t>()) {
os << as<int64_t>();
} else if(is<double>()) {
os << as<double>();
} else if(is<bool>()) {
bool b = as<bool>();
if(b) os << "true";
else os << "false";
} else if(is<UnQLiteValue::Null>()) {
os << "null";
} else if(is<std::string>()) {
os << "\"" << as<std::string>() << "\"";
} else if(unqlite_value_is_json_array(m_value)
&& !unqlite_value_is_json_object(m_value)) {
os << "[ ";
size_t size = unqlite_array_count(m_value);
size_t i = 0;
const_cast<UnQLiteValue*>(this)->foreach([&os, size, &i](unsigned index, const UnQLiteValue& val) {
val.printToStream(os);
if(i < size-1)
os << ", ";
i += 1;
});
os << "]";
} else if(unqlite_value_is_json_object(m_value)) {
os << "{ ";
size_t size = unqlite_array_count(m_value);
size_t i = 0;
const_cast<UnQLiteValue*>(this)->foreach([&os, size, &i](const std::string& key, const UnQLiteValue& val) {
os << "\"" << key << "\" : ";
val.printToStream(os);
if(i < size-1)
os << ", ";
i += 1;
});
os << "}";
} else if(unqlite_value_is_resource) {
os << "\"resource@" << std::hex
<< (intptr_t)unqlite_value_to_resource(m_value) << "\"";
}
return os;
}
......
$rc = TRUE;
print "Executing test on address ", $addr, "\n";
$ret = snta_db_create($addr, 0, "dbFromJx9", "unqlite", { path : "dbFromJx9" });
if($ret != TRUE) {
print "snta_db_create failed\n";
print db_errlog();
$rc = FALSE;
return;
}
$db = { database_name : "dbFromJx9",
address : $addr,
provider_id : 0 };
print "Executing code on remote database... ";
function myfunction() {
$a = 42;
print "blabla";
}
$results = sntd_execute($db, myfunction, ["a","__output__"]);
if($results == NULL) {
print "sntd_execute failed\n";
print db_errlog();
snta_db_destroy($addr, 0, "dbFromJx9");
$rc = FALSE;
return;
}
print "OK\n";
$fcode = "\$a = 42; print \"blabla\";";
$results = sntd_execute($db, $fcode, ["a","__output__"]);
if($results == NULL) {
print "sntd_execute failed\n";
print db_errlog();
snta_db_destroy($addr, 0, "dbFromJx9");
$rc = FALSE;
return;
}
print "OK\n";
print "Destroying database dbFromJx9\n";
$rc = snta_db_destroy($addr, 0, "dbFromJx9");
if($rc != TRUE) {
print db_errlog();
print "snta_db_destroy failed\n";
$rc = FALSE;
return;
}
print "All done!";
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment