//#define DEBUG 1 #include #include #include #include "sql_parser.h" #include "../../flydata.h" extern "C" { #ifdef _WIN32 _declspec(dllexport) #endif void Init_dump_parser_ext(); } class InsertParserCallbackHandler : public ParserCallbackHandler { VALUE m_rows; VALUE m_row; VALUE m_value; public: InsertParserCallbackHandler() : ParserCallbackHandler(), m_rows(rb_ary_new()), m_row(rb_ary_new()), m_value(Qnil) { } void value_callback(const char* str, long len, bool end_value) { if (m_value == Qnil) { if (str || len > 0) { m_value = rb_str_new(str, len); int enc = rb_enc_find_index("UTF-8"); rb_enc_associate_index(m_value, enc); debug_print("new value:%s\n", StringValueCStr(m_value)); } else { m_value = Qnil; debug_print("new value:%s\n", "nil"); } } else { rb_str_cat(m_value, str, len); debug_print("value appended:%s\n", StringValueCStr(m_value)); } if (end_value) { rb_ary_push(m_row, m_value); debug_print("value committed:%s\n", m_value == Qnil ? "nil" : StringValueCStr(m_value)); m_value = Qnil; } } void row_end_callback() { if (m_row) { rb_ary_push(m_rows, m_row); debug_print("row pushed\n", 0); m_row = rb_ary_new(); } } VALUE rows() { return m_rows; } }; static VALUE rb_insert_parser_parse2(VALUE self, VALUE sql) { InsertParserCallbackHandler ch; long error_at = -1; if (sql != Qnil) { StringValue(sql); error_at = parse_insert_query(RSTRING_PTR(sql), RSTRING_LEN(sql), ch); } if (error_at > -1) { VALUE mFlydata = rb_define_module("Flydata"); VALUE eAgentError = rb_define_class_under(mFlydata, "AgentError", rb_eStandardError); VALUE eDumpParseError = rb_define_class_under(mFlydata, "DumpParseError", eAgentError); rb_raise(eDumpParseError, "Parse error at %ld", error_at); } return ch.rows(); } void Init_dump_parser_ext() { VALUE mFlydata = rb_define_module("Flydata"); VALUE mSourceMysql = rb_define_module_under(mFlydata, "SourceMysql"); VALUE mParser = rb_define_module_under(mSourceMysql, "Parser"); VALUE cMysqlDumpParser = rb_define_class_under(mParser, "MysqlDumpParser", rb_cObject); VALUE cInsertParser = rb_define_class_under(cMysqlDumpParser, "InsertParser", rb_cObject); rb_define_private_method(cInsertParser, "_parse2", __F(&rb_insert_parser_parse2), 1); }