diff --git a/scripts/base/frameworks/logging/writers/sqlite.bro b/scripts/base/frameworks/logging/writers/sqlite.bro index 1b19c84ff3..654af93c96 100644 --- a/scripts/base/frameworks/logging/writers/sqlite.bro +++ b/scripts/base/frameworks/logging/writers/sqlite.bro @@ -5,6 +5,9 @@ module LogSQLite; export { ## Separator between set elements. - const set_separator = "," &redef; + const set_separator = Log::set_separator &redef; + + ## String to use for an unset &optional field. + const unset_field = Log::unset_field &redef; } diff --git a/src/AsciiInputOutput.cc b/src/AsciiInputOutput.cc index 28736b9a77..74cabecb1d 100644 --- a/src/AsciiInputOutput.cc +++ b/src/AsciiInputOutput.cc @@ -134,6 +134,7 @@ bool AsciiInputOutput::ValToODesc(ODesc* desc, threading::Value* val, const thre if ( j > 0 ) desc->AddRaw(set_separator); + assert(field != 0); if ( ! ValToODesc(desc, val->val.set_val.vals[j], field) ) { desc->RemoveEscapeSequence(set_separator); @@ -159,6 +160,7 @@ bool AsciiInputOutput::ValToODesc(ODesc* desc, threading::Value* val, const thre if ( j > 0 ) desc->AddRaw(set_separator); + assert(field != 0); if ( ! ValToODesc(desc, val->val.vector_val.vals[j], field) ) { desc->RemoveEscapeSequence(set_separator); diff --git a/src/input/readers/SQLite.cc b/src/input/readers/SQLite.cc index 955e821a53..20559f5664 100644 --- a/src/input/readers/SQLite.cc +++ b/src/input/readers/SQLite.cc @@ -23,13 +23,13 @@ using threading::Field; SQLite::SQLite(ReaderFrontend *frontend) : ReaderBackend(frontend) { - + io = new AsciiInputOutput(this); } SQLite::~SQLite() { DoClose(); - + delete io; } void SQLite::DoClose() @@ -174,7 +174,7 @@ Value* SQLite::EntryToVal(sqlite3_stmt *st, const threading::Field *field, int p int width = atoi(s.substr(pos+1).c_str()); string addr = s.substr(0, pos); - val->val.subnet_val.prefix = StringToAddr(addr); + val->val.subnet_val.prefix = io->StringToAddr(addr); val->val.subnet_val.length = width; break; @@ -183,7 +183,7 @@ Value* SQLite::EntryToVal(sqlite3_stmt *st, const threading::Field *field, int p { const char *text = (const char*) sqlite3_column_text(st, pos); string s(text, sqlite3_column_bytes(st, pos)); - val->val.addr_val = StringToAddr(s); + val->val.addr_val = io->StringToAddr(s); break; } diff --git a/src/input/readers/SQLite.h b/src/input/readers/SQLite.h index 5ed24ce393..1ba528643b 100644 --- a/src/input/readers/SQLite.h +++ b/src/input/readers/SQLite.h @@ -12,8 +12,11 @@ #include #include "../ReaderBackend.h" +#include "../../AsciiInputOutput.h" + #include "sqlite3.h" + namespace input { namespace reader { class SQLite : public ReaderBackend { @@ -48,6 +51,8 @@ private: sqlite3 *db; sqlite3_stmt *st; + AsciiInputOutput* io; + }; diff --git a/src/logging.bif b/src/logging.bif index 487d54a19a..93317e242d 100644 --- a/src/logging.bif +++ b/src/logging.bif @@ -87,6 +87,7 @@ const num_threads: count; module LogSQLite; const set_separator: string; +const unset_field: string; # Options for the ElasticSearch writer. diff --git a/src/logging/writers/SQLite.cc b/src/logging/writers/SQLite.cc index 56e8a23d4e..3157c3f0fc 100644 --- a/src/logging/writers/SQLite.cc +++ b/src/logging/writers/SQLite.cc @@ -24,12 +24,22 @@ using threading::Field; SQLite::SQLite(WriterFrontend* frontend) : WriterBackend(frontend) { - set_separator_len = BifConst::LogSQLite::set_separator->Len(); - set_separator = new char[set_separator_len]; - memcpy(set_separator, BifConst::LogSQLite::set_separator->Bytes(), - set_separator_len); + + set_separator.assign( + (const char*) BifConst::LogSQLite::set_separator->Bytes(), + BifConst::LogAscii::set_separator->Len() + ); + + + unset_field.assign( + (const char*) BifConst::LogSQLite::unset_field->Bytes(), + BifConst::LogAscii::unset_field->Len() + ); + db = 0; + + io = new AsciiInputOutput(this, set_separator, unset_field); } SQLite::~SQLite() @@ -39,6 +49,8 @@ SQLite::~SQLite() sqlite3_close(db); db = 0; } + + delete io; } string SQLite::GetTableType(int arg_type, int arg_subtype) { @@ -226,84 +238,6 @@ char* SQLite::FS(const char* format, ...) { return buf; } -// this one is mainly ripped from Ascii.cc - with some adaptions. -void SQLite::ValToAscii(ODesc* desc, Value* val) - { - if ( ! val->present ) - { - assert(false); - } - - switch ( val->type ) { - - case TYPE_BOOL: - desc->Add(val->val.int_val ? "T" : "F"); - break; - - case TYPE_INT: - desc->Add(val->val.int_val); - break; - - case TYPE_COUNT: - case TYPE_COUNTER: - desc->Add(val->val.uint_val); - break; - - case TYPE_PORT: - desc->Add(val->val.port_val.port); - break; - - case TYPE_SUBNET: - desc->Add(Render(val->val.subnet_val)); - break; - - case TYPE_ADDR: - desc->Add(Render(val->val.addr_val)); - break; - - case TYPE_DOUBLE: - // Rendering via Add() truncates trailing 0s after the - // decimal point. The difference with TIME/INTERVAL is mainly - // to keep the log format consistent. - desc->Add(val->val.double_val); - break; - - case TYPE_INTERVAL: - case TYPE_TIME: - // Rendering via Render() keeps trailing 0s after the decimal - // point. The difference with DOUBLEis mainly to keep the log - // format consistent. - desc->Add(Render(val->val.double_val)); - break; - - case TYPE_ENUM: - case TYPE_STRING: - case TYPE_FILE: - case TYPE_FUNC: - { - int size = val->val.string_val.length; - const char* data = val->val.string_val.data; - - if ( size ) - desc->AddN(data, size); - - break; - } - - case TYPE_TABLE: - case TYPE_VECTOR: - assert(false); - // this would mean that we have a table/vector inside a table/vector. - // that is not possible and should have been caught way earlier. - - default: - // there may not be any types that we do not know here. - assert(false); - } - - } - - int SQLite::AddParams(Value* val, int pos) { @@ -329,13 +263,13 @@ int SQLite::AddParams(Value* val, int pos) case TYPE_SUBNET: { - string out = Render(val->val.subnet_val).c_str(); + string out = io->Render(val->val.subnet_val).c_str(); return sqlite3_bind_text(st, pos, out.data(), out.size(), SQLITE_TRANSIENT); } case TYPE_ADDR: { - string out = Render(val->val.addr_val).c_str(); + string out = io->Render(val->val.addr_val).c_str(); return sqlite3_bind_text(st, pos, out.data(), out.size(), SQLITE_TRANSIENT); } @@ -359,17 +293,19 @@ int SQLite::AddParams(Value* val, int pos) { ODesc desc; desc.Clear(); - desc.AddEscapeSequence(set_separator, set_separator_len); + desc.AddEscapeSequence(set_separator); for ( int j = 0; j < val->val.set_val.size; j++ ) { if ( j > 0 ) - desc.AddRaw(set_separator, set_separator_len); + desc.AddRaw(set_separator); - ValToAscii(&desc, val->val.set_val.vals[j]); + io->ValToODesc(&desc, val->val.set_val.vals[j], NULL); + // yes, giving NULL here is not really really pretty.... + // it works however, because tables cannot contain tables... + // or vectors. } - - + desc.RemoveEscapeSequence(set_separator); return sqlite3_bind_text(st, pos, (const char*) desc.Bytes(), desc.Len(), SQLITE_TRANSIENT); } @@ -377,16 +313,17 @@ int SQLite::AddParams(Value* val, int pos) { ODesc desc; desc.Clear(); - desc.AddEscapeSequence(set_separator, set_separator_len); + desc.AddEscapeSequence(set_separator); for ( int j = 0; j < val->val.vector_val.size; j++ ) { if ( j > 0 ) - desc.AddRaw(set_separator, set_separator_len); + desc.AddRaw(set_separator); - ValToAscii(&desc, val->val.vector_val.vals[j]); + io->ValToODesc(&desc, val->val.vector_val.vals[j], NULL); } + desc.RemoveEscapeSequence(set_separator); return sqlite3_bind_text(st, pos, (const char*) desc.Bytes(), desc.Len(), SQLITE_TRANSIENT); } diff --git a/src/logging/writers/SQLite.h b/src/logging/writers/SQLite.h index 0c8addc9da..f74c2259a5 100644 --- a/src/logging/writers/SQLite.h +++ b/src/logging/writers/SQLite.h @@ -12,6 +12,7 @@ #include "../WriterBackend.h" #include "sqlite3.h" +#include "../../AsciiInputOutput.h" namespace logging { namespace writer { @@ -37,7 +38,6 @@ protected: private: bool checkError(int code); - void ValToAscii(ODesc* desc, threading::Value* val); int AddParams(threading::Value* val, int pos); string GetTableType(int, int); @@ -46,8 +46,11 @@ private: sqlite3 *db; sqlite3_stmt *st; - char* set_separator; - int set_separator_len; + string separator; + string set_separator; + string unset_field; + + AsciiInputOutput* io; }; }