Skip to content

Commit

Permalink
get basic inserts working
Browse files Browse the repository at this point in the history
  • Loading branch information
goatshriek committed Oct 20, 2023
1 parent 52aecf8 commit 35e665e
Show file tree
Hide file tree
Showing 14 changed files with 188 additions and 56 deletions.
3 changes: 3 additions & 0 deletions docs/examples/sqlite3/sqlite3_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ main( int argc, char **argv ) {
return EXIT_FAILURE;
}

// TODO we're just ignore errors if this fails, assuming it already existed
stumpless_create_default_sqlite3_table( db_target );

stumpless_add_message( db_target, "goes to the sqlite3 database" );
stumpless_add_message( db_target, "this one too" );

Expand Down
15 changes: 11 additions & 4 deletions include/private/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
*/

#ifndef __STUMPLESS_PRIVATE_ERROR_H
# define __STUMPLESS_PRIVATE_ERROR_H
#define __STUMPLESS_PRIVATE_ERROR_H

# include <stddef.h>
# include <stumpless/error.h>
# include "private/config.h"
#include <stddef.h>
#include <stumpless/error.h>
#include "private/config.h"

void
clear_error( void );
Expand Down Expand Up @@ -235,6 +235,13 @@ raise_socket_send_failure( const char *message,
int code,
const char *code_type );

/**
* TODO fill in
*/
COLD_FUNCTION
void
raise_sqlite3_error( const char *message, int code );

COLD_FUNCTION
void
raise_stream_write_failure( void );
Expand Down
2 changes: 1 addition & 1 deletion include/private/target/sqlite3.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct sqlite3_target {
/** A connection to the database this target writes to. */
sqlite3 *db;
/** The SQL command used to insert entries into the database. */
const char *insert_statement;
const char *insert_sql;
#ifdef STUMPLESS_THREAD_SAFETY_SUPPORTED
/**
* Protects db. This mutex must be locked by a thread before it uses the
Expand Down
12 changes: 9 additions & 3 deletions include/stumpless/error.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: Apache-2.0 */

/*
* Copyright 2018-2022 Joel E. Anderson
* Copyright 2018-2023 Joel E. Anderson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,7 +21,7 @@
*/

#ifndef __STUMPLESS_ERROR_H
# define __STUMPLESS_ERROR_H
#define __STUMPLESS_ERROR_H

#include <stdbool.h>
#include <stdio.h>
Expand Down Expand Up @@ -132,7 +132,13 @@ extern "C" {
*
* @since release v2.2.0
*/\
ERROR( STUMPLESS_INVALID_PARAM_STRING, 29 )
ERROR( STUMPLESS_INVALID_PARAM_STRING, 29 ) \
/**
* Sqlite3 encountered a failure.
*
* @since release v2.2.0
*/\
ERROR( STUMPLESS_SQLITE3_FAILURE, 30 )

/**
* An (enum) identifier of the types of errors that might be encountered.
Expand Down
22 changes: 15 additions & 7 deletions include/stumpless/target/sqlite3.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@
*/

#ifndef __STUMPLESS_TARGET_SQLITE3_H
# define __STUMPLESS_TARGET_SQLITE3_H
#define __STUMPLESS_TARGET_SQLITE3_H

# include <stumpless/config.h>
# include <stumpless/target.h>
#include <stumpless/config.h>
#include <stumpless/target.h>

# ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
# endif
#endif

/**
* TODO update
Expand Down Expand Up @@ -70,6 +70,13 @@ STUMPLESS_PUBLIC_FUNCTION
void
stumpless_close_sqlite3_target( struct stumpless_target *target );

/**
* TODO update
*/
STUMPLESS_PUBLIC_FUNCTION
struct stumpless_target *
stumpless_create_default_sqlite3_table( struct stumpless_target *target );

/**
* TODO update
* Opens a file target.
Expand Down Expand Up @@ -101,7 +108,8 @@ STUMPLESS_PUBLIC_FUNCTION
struct stumpless_target *
stumpless_open_sqlite3_target( const char *name );

# ifdef __cplusplus
#ifdef __cplusplus
} /* extern "C" */
# endif
#endif

#endif /* __STUMPLESS_TARGET_SQLITE3_H */
5 changes: 5 additions & 0 deletions src/error.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,11 @@ raise_socket_send_failure( const char *message,
raise_error( STUMPLESS_SOCKET_SEND_FAILURE, message, code, code_type );
}

void
raise_sqlite3_error( const char *message, int code ) {
raise_error( STUMPLESS_SQLITE3_FAILURE, message, code, "the sqlite3 result code" ); // TODO l10n
}

void
raise_stream_write_failure( void ) {
raise_error( STUMPLESS_STREAM_WRITE_FAILURE,
Expand Down
6 changes: 5 additions & 1 deletion src/target.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0

/*
* Copyright 2018-2022 Joel E. Anderson
* Copyright 2018-2023 Joel E. Anderson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -408,6 +408,10 @@ stumpless_close_target( struct stumpless_target *target ) {
config_close_socket_target( target );
break;

case STUMPLESS_SQLITE3_TARGET:
config_close_sqlite3_target( target );
break;

case STUMPLESS_STREAM_TARGET:
stumpless_close_stream_target( target );
break;
Expand Down
132 changes: 105 additions & 27 deletions src/target/sqlite3.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,44 +17,54 @@
*/

#include <sqlite3.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stumpless/entry.h>
#include <stumpless/error.h>
#include <stumpless/target.h>
#include <stumpless/target/sqlite3.h>
#include "private/config/locale/wrapper.h"
#include "private/config/wrapper/thread_safety.h"
#include "private/error.h"
#include "private/inthelper.h"
#include "private/memory.h"
#include "private/target.h"
#include "private/target/sqlite3.h"
#include "private/validate.h"

static sqlite3_stmt *default_statement = NULL;
static const char *default_insert = "INSERT INTO logs (message) VALUES (?)";
static sqlite3_stmt *default_statement = NULL; // TODO needs to be per-target (for multiple target support)
static sqlite3_stmt *default_statements[1];
static const char *default_insert_sql = "INSERT INTO logs (prival, version, timestamp, hostname, app_name, procid, msgid, structured_data, message) VALUES (3, 3, NULL, NULL, NULL, NULL, NULL, NULL, ?);";

// generic pointer here to prevent mandatory public API reliance on sqlite3.h
// this is called while the db mutex is held, so thread safety is not a concern
static
void *
prepare_statments( const struct stumpless_entry *entry, void *data, size_t *count ) {
struct sqlite3_target *target;
int bind_result;

sqlite3_reset( default_statement );

int sql_result;

target = data;
// TODO not thread safe!
bind_result = sqlite3_bind_text( default_statement, 1, entry->message, entry->message_length, SQLITE_STATIC );
printf( "bind result: %d\n", bind_result );
if( !default_statement) {

sql_result = sqlite3_prepare_v2( target->db, target->insert_sql, -1, &default_statement, NULL );
if( sql_result != SQLITE_OK ) {
raise_sqlite3_error( "could not prepare the insert statement", sql_result ); // TODO l10n
return NULL;
}
} else {
sqlite3_reset( default_statement );
}

*count = 1;
return &default_statement;
}
sql_result = sqlite3_bind_text( default_statement, 1, entry->message, entry->message_length, SQLITE_STATIC );
if( sql_result != SQLITE_OK ) {
raise_sqlite3_error( "could not bind the message to the statement", sql_result ); // TODO l10n
return NULL;
}

static
void
after_steps( void *data ) {

*count = 1;
default_statements[0] = default_statement;
return default_statements;
}

void
Expand All @@ -71,6 +81,60 @@ stumpless_close_sqlite3_target( struct stumpless_target *target ) {
clear_error( );
}

struct stumpless_target *
stumpless_create_default_sqlite3_table( struct stumpless_target *target ) {
struct sqlite3_target *db_target;
const char *create_sql = "CREATE TABLE logs (log_id INTEGER PRIMARY KEY, prival INTEGER NOT NULL, version INTEGER NOT NULL, timestamp TEXT, hostname TEXT, app_name TEXT, procid TEXT, msgid TEXT, structured_data TEXT, message TEXT);";
struct sqlite3_stmt *create_statement;
int sql_result;
size_t try_count = 0;
struct stumpless_target *return_result;

VALIDATE_ARG_NOT_NULL( target );

db_target = target->id;
return_result = target;
clear_error();

config_lock_mutex( &db_target->db_mutex );

// TODO assuming that the target is open already
sql_result = sqlite3_prepare_v2( db_target->db, create_sql, -1, &create_statement, NULL );
if( sql_result != SQLITE_OK ) {
raise_sqlite3_error( "sqlite3_prepare_v2 failed on the table creation statement", sql_result ); // TODO l10n
return_result = NULL;
goto cleanup_and_finish;
}

while( true ) {
try_count++;
sql_result = sqlite3_step( create_statement );

if( sql_result == SQLITE_BUSY ) {
if( try_count > 3 ) { // TODO arbitrary retry count ceiling
// TODO make code more specific, STUMPLESS_SQLITE3_BUSY
raise_error(STUMPLESS_SQLITE3_FAILURE, "the database was busy and could not complete the transaction", cap_size_t_to_int(try_count), "the number of attempts made" );
return_result = NULL;
goto cleanup_and_finish;
}
}

if( sql_result == SQLITE_DONE ) {
goto cleanup_and_finish;
}

raise_sqlite3_error( "sqlite3_step failed on the table creation statement", sql_result ); // TODO l10n
return_result = NULL;
goto cleanup_and_finish;
}

sqlite3_finalize( create_statement ); // todo capture errors

cleanup_and_finish:
config_unlock_mutex( &db_target->db_mutex );
return return_result;
}

struct stumpless_target *
stumpless_open_sqlite3_target( const char *db_filename ) {
struct stumpless_target *target;
Expand Down Expand Up @@ -102,6 +166,7 @@ stumpless_open_sqlite3_target( const char *db_filename ) {
void
destroy_sqlite3_target( struct sqlite3_target *target ) {
sqlite3_finalize( default_statement );
default_statement = NULL; // TODO can remove later
// we use v2 here to allow a close to not be blocked by pending transactions
sqlite3_close_v2( target->db );
config_destroy_mutex( &target->db_mutex );
Expand All @@ -111,21 +176,20 @@ destroy_sqlite3_target( struct sqlite3_target *target ) {
struct sqlite3_target *
new_sqlite3_target( const char *db_filename ) {
struct sqlite3_target *target;
int open_result;
int sql_result;

target = alloc_mem( sizeof( *target ) );
if( !target ) {
goto fail;
}

open_result = sqlite3_open( db_filename, &target->db );
if( open_result != SQLITE_OK ) {
// TODO raise appropriate error
sql_result = sqlite3_open( db_filename, &target->db );
if( sql_result != SQLITE_OK ) {
raise_sqlite3_error( "could not open the provided database name", sql_result ); // TODO l10n
goto fail_db;
}

target->insert_statement = default_insert;
sqlite3_prepare_v2( target->db, target->insert_statement, -1, &default_statement, NULL );
target->insert_sql = default_insert_sql;

config_init_mutex( &target->db_mutex );

Expand All @@ -144,18 +208,32 @@ send_entry_to_sqlite3_target( const struct stumpless_target *target,
size_t stmt_count;
size_t i;
sqlite3_stmt **statements;
int result = 1;
int sql_result;

db_target = target->id;

config_lock_mutex( &db_target->db_mutex );

statements = prepare_statments( entry, db_target, &stmt_count );
if( !statements ) {
result = -1;
// TODO create an error for sqlite3 callback failure
// TODO only do this if we didn't use our built-in prepare
raise_sqlite3_error ( "the prepare statements callback failed", 0 ); // TODO make more specific
goto cleanup_and_finish;
}

for( i = 0; i < stmt_count; i++ ) {
sqlite3_step( statements[i] );
sql_result = sqlite3_step( statements[i] );
if( sql_result != SQLITE_DONE ) {
result = -1;
raise_sqlite3_error( "sqlite3_step failed", sql_result ); // TODO l10n
goto cleanup_and_finish;
}
}

printf( "wrote to a sqlite3 target with %zd statements!\n", stmt_count );
cleanup_and_finish:
config_unlock_mutex( &db_target->db_mutex );

return -1;
return result;
}
1 change: 0 additions & 1 deletion test/function/config/sqlite3_unsupported.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
*/

#include <gtest/gtest.h>
#include <stddef.h>
#include <stumpless.h>
#include "test/helper/assert.hpp"
#include "test/helper/fixture.hpp"
Expand Down
Loading

0 comments on commit 35e665e

Please sign in to comment.