Last active
August 29, 2015 14:16
-
-
Save greenlion/ba59d6bb3bf198ad07d2 to your computer and use it in GitHub Desktop.
UDF using RapidJSON to flatten a JSON document to key/value pairs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Compile with: | |
* g++ -std=c++11 -shared -I `mysql_config --include` `mysql_config --cxxflags` flatten_udf.cpp -o flatten_udf.so | |
*/ | |
#pragma GCC diagnostic ignored "-Wwrite-strings" | |
#include "presto.h" | |
#include <iostream> | |
#include <string> | |
#include "rapidjson/reader.h" | |
#include <mysql.h> | |
#include <sstream> // std::ostringstream | |
#include <plugin.h> | |
#include <unistd.h> | |
/* to remind me of the signatures */ | |
extern "C" { | |
my_bool rapid_flatten_json_init(UDF_INIT *initid, UDF_ARGS *args, char* message); | |
char* rapid_flatten_json(UDF_INIT *initid, UDF_ARGS *args,char *result, long long *length, char *is_null, char *error); | |
void rapid_flatten_json_deinit(UDF_INIT *initid); | |
} | |
#endif | |
using namespace rapidjson; | |
/* This function hooks rewrite related PHP output to the general log*/ | |
void php_log_output(const char *str){ | |
std::cerr << str; | |
} | |
void flatten_json_deinit(UDF_INIT *initid) { | |
delete[] initid->ptr; | |
} | |
my_bool rapid_flatten_json_init(UDF_INIT *initid, UDF_ARGS *args, char* message) { | |
if(args->arg_count != 1 || args->arg_type[0] != STRING_RESULT) { | |
strcpy(message,"Takes one string arg: json_doc"); | |
return 1; | |
} | |
return 0; | |
} | |
char* rapid_flatten_json(UDF_INIT *initid, UDF_ARGS *args,char *result, long long *length, char *is_null, char *error) { | |
if(args->args[0] == NULL) { | |
*is_null = 1; | |
return 0; | |
} | |
std::string json(args->args[0], args->lengths[0]); | |
struct Handler { | |
std::ostringstream oss; | |
std::string key; | |
bool Null() { this->oss << this->key << "=" << "NULL" << "\n"; return true; } | |
bool Bool(bool b) { this->oss << this->key << "=" << std::boolalpha << b << "\n" ; return true; } | |
bool Int(int i) { this->oss << this->key << "=" << i << "\n"; return true; } | |
bool Uint(unsigned u) { this->oss << this->key << "=" << u << "\n"; return true; } | |
bool Int64(int64_t i) { this->oss << this->key << "=" << i << "\n"; return true; } | |
bool Uint64(uint64_t u) { this->oss << this->key << "=" << u << "\n"; return true; } | |
bool Double(double d) { this->oss << this->key << "=" << d << "\n"; return true; } | |
bool String(const char* str, SizeType length, bool copy) { | |
this->oss << this->key << "=" << str << "\n"; | |
return true; | |
} | |
bool Key(const char* str, SizeType length, bool copy) { | |
this->key.assign(str, length); | |
return true; | |
} | |
/* these do nothing */ | |
bool StartObject() { return true; } | |
bool EndObject(SizeType memberCount) { return true; } | |
bool StartArray() { return true; } | |
bool EndArray(SizeType elementCount) { return true; } | |
}; | |
Handler handler; | |
Reader reader; | |
StringStream ss(json.c_str()); | |
reader.Parse<0>(ss, handler); | |
initid->ptr = (char*)malloc(handler.oss.str().length()+1); | |
initid->ptr = strcpy(initid->ptr, handler.oss.str().c_str()); | |
*length = handler.oss.str().length(); | |
return initid->ptr; | |
} | |
void rapid_flatten_json_deinit(UDF_INIT *initid) { | |
delete[] initid->ptr; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment