Skip to content

Instantly share code, notes, and snippets.

@greenlion
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save greenlion/ba59d6bb3bf198ad07d2 to your computer and use it in GitHub Desktop.
Save greenlion/ba59d6bb3bf198ad07d2 to your computer and use it in GitHub Desktop.
UDF using RapidJSON to flatten a JSON document to key/value pairs
/*
* 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