mirror of
https://github.com/zeek/zeek.git
synced 2025-10-13 12:08:20 +00:00
make sqlite-writer more stable.
This actually looks quite good...
This commit is contained in:
parent
96aa8776d3
commit
d843297a97
1 changed files with 30 additions and 39 deletions
|
@ -1,20 +1,16 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef USE_SQLITE
|
||||
|
||||
#include <string>
|
||||
#include <errno.h>
|
||||
#include <vector>
|
||||
|
||||
#include "../../NetVar.h"
|
||||
|
||||
#include "../../threading/SerialTypes.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "SQLite.h"
|
||||
|
||||
using namespace logging;
|
||||
|
@ -24,19 +20,16 @@ using threading::Field;
|
|||
|
||||
SQLite::SQLite(WriterFrontend* frontend) : WriterBackend(frontend)
|
||||
{
|
||||
|
||||
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, AsciiInputOutput::SeparatorInfo(set_separator, unset_field));
|
||||
|
@ -54,11 +47,9 @@ SQLite::~SQLite()
|
|||
}
|
||||
|
||||
string SQLite::GetTableType(int arg_type, int arg_subtype) {
|
||||
|
||||
string type;
|
||||
|
||||
switch ( arg_type ) {
|
||||
|
||||
case TYPE_BOOL:
|
||||
type = "boolean";
|
||||
break;
|
||||
|
@ -66,16 +57,10 @@ string SQLite::GetTableType(int arg_type, int arg_subtype) {
|
|||
case TYPE_INT:
|
||||
case TYPE_COUNT:
|
||||
case TYPE_COUNTER:
|
||||
case TYPE_PORT:
|
||||
case TYPE_PORT: // note that we do not save the protocol at the moment. Just like in the case of the ascii-writer
|
||||
type = "integer";
|
||||
break;
|
||||
|
||||
/*
|
||||
case TYPE_PORT:
|
||||
type = "VARCHAR(10)";
|
||||
break;
|
||||
*/
|
||||
|
||||
case TYPE_SUBNET:
|
||||
case TYPE_ADDR:
|
||||
type = "text"; // sqlite3 does not have a type for internet addresses
|
||||
|
@ -96,19 +81,18 @@ string SQLite::GetTableType(int arg_type, int arg_subtype) {
|
|||
|
||||
case TYPE_TABLE:
|
||||
case TYPE_VECTOR:
|
||||
type = "text"; // dirty - but sqlite does not directly support arrays. so - we just roll it into a ","-separated string I guess.
|
||||
//type = GetTableType(arg_subtype, 0) + "[]";
|
||||
type = "text"; // dirty - but sqlite does not directly support arrays. so - we just roll it into a ","-separated string.
|
||||
break;
|
||||
|
||||
default:
|
||||
Error(Fmt("unsupported field format %d ", arg_type));
|
||||
return "";
|
||||
return ""; // not the cleanest way to abort. But sqlite will complain on create table...
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
// returns true true in case of error
|
||||
bool SQLite::checkError( int code )
|
||||
{
|
||||
if ( code != SQLITE_OK && code != SQLITE_DONE )
|
||||
|
@ -123,6 +107,10 @@ bool SQLite::checkError( int code )
|
|||
bool SQLite::DoInit(const WriterInfo& info, int num_fields,
|
||||
const Field* const * fields)
|
||||
{
|
||||
if ( sqlite3_threadsafe() == 0 ) {
|
||||
Error("SQLite reports that it is not threadsafe. Bro needs a threadsafe version of SQLite. Aborting");
|
||||
return false;
|
||||
}
|
||||
|
||||
string fullpath(info.path);
|
||||
fullpath.append(".sqlite");
|
||||
|
@ -157,9 +145,15 @@ bool SQLite::DoInit(const WriterInfo& info, int num_fields,
|
|||
if ( i != 0 )
|
||||
create += ",\n";
|
||||
|
||||
string fieldname = fields[i]->name;
|
||||
replace( fieldname.begin(), fieldname.end(), '.', '_' ); // sqlite does not like "." in row names.
|
||||
// sadly sqlite3 has no other method for escaping stuff. That I know of.
|
||||
char* fieldname = sqlite3_mprintf("%Q", fields[i]->name);
|
||||
if ( fieldname == 0 )
|
||||
{
|
||||
InternalError("Could not malloc memory");
|
||||
return false;
|
||||
}
|
||||
create += fieldname;
|
||||
sqlite3_free(fieldname);
|
||||
|
||||
string type = GetTableType(field->type, field->subtype);
|
||||
|
||||
|
@ -167,19 +161,15 @@ bool SQLite::DoInit(const WriterInfo& info, int num_fields,
|
|||
/* if ( !field->optional ) {
|
||||
create += " NOT NULL";
|
||||
} */
|
||||
|
||||
}
|
||||
|
||||
create += "\n);";
|
||||
|
||||
//printf("Create: %s\n", create.c_str());
|
||||
|
||||
{
|
||||
char *errorMsg = 0;
|
||||
int res = sqlite3_exec(db, create.c_str(), NULL, NULL, &errorMsg);
|
||||
if ( res != SQLITE_OK )
|
||||
{
|
||||
//printf("Error executing table creation statement: %s", errorMsg);
|
||||
Error(Fmt("Error executing table creation statement: %s", errorMsg));
|
||||
sqlite3_free(errorMsg);
|
||||
return false;
|
||||
|
@ -206,16 +196,20 @@ bool SQLite::DoInit(const WriterInfo& info, int num_fields,
|
|||
|
||||
insert += "?";
|
||||
|
||||
string fieldname = fields[i]->name;
|
||||
replace( fieldname.begin(), fieldname.end(), '.', '_' ); // sqlite does not like "." in row names.
|
||||
names += fieldname;
|
||||
|
||||
char* fieldname = sqlite3_mprintf("%Q", fields[i]->name);
|
||||
printf("Fieldname: %s\n", fieldname);
|
||||
if ( fieldname == 0 )
|
||||
{
|
||||
InternalError("Could not malloc memory");
|
||||
return false;
|
||||
}
|
||||
names.append(fieldname);
|
||||
sqlite3_free(fieldname);
|
||||
}
|
||||
insert += ");";
|
||||
names += ") ";
|
||||
|
||||
insert = names + insert;
|
||||
//printf("Prepared insert: %s\n\n", insert.c_str());
|
||||
|
||||
if ( checkError(sqlite3_prepare_v2( db, insert.c_str(), insert.size()+1, &st, NULL )) )
|
||||
return false;
|
||||
|
@ -242,12 +236,9 @@ int SQLite::AddParams(Value* val, int pos)
|
|||
{
|
||||
|
||||
if ( ! val->present )
|
||||
{
|
||||
return sqlite3_bind_null(st, pos);
|
||||
}
|
||||
|
||||
switch ( val->type ) {
|
||||
|
||||
case TYPE_BOOL:
|
||||
return sqlite3_bind_int(st, pos, val->val.int_val ? 1 : 0 );
|
||||
|
||||
|
@ -263,13 +254,13 @@ int SQLite::AddParams(Value* val, int pos)
|
|||
|
||||
case TYPE_SUBNET:
|
||||
{
|
||||
string out = io->Render(val->val.subnet_val).c_str();
|
||||
string out = io->Render(val->val.subnet_val);
|
||||
return sqlite3_bind_text(st, pos, out.data(), out.size(), SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
case TYPE_ADDR:
|
||||
{
|
||||
string out = io->Render(val->val.addr_val).c_str();
|
||||
string out = io->Render(val->val.addr_val);
|
||||
return sqlite3_bind_text(st, pos, out.data(), out.size(), SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue