diff --git a/CMakeLists.txt b/CMakeLists.txt index ba8a752..ddd5f1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,8 +9,6 @@ if (CMAKE_C_COMPILER_ID STREQUAL "MSVC") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4 /WX") else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror") - add_compile_options(-fsanitize=address,undefined) - add_link_options(-fsanitize=address,undefined) endif() add_subdirectory(tests) diff --git a/include/defs.h b/include/defs.h index 19ef591..cc2683c 100644 --- a/include/defs.h +++ b/include/defs.h @@ -1,7 +1,6 @@ // // Created by Seppe Degryse on 31/10/2024. // - #ifndef DEFS_H #define DEFS_H #include diff --git a/include/query.h b/include/query.h index ed8837e..497576e 100644 --- a/include/query.h +++ b/include/query.h @@ -6,6 +6,6 @@ #include "source.h" #include "defs.h" -void execute_query(const query_t *query, source_t *source, sink_t *sink); +void execute_query(const query_t *query, const source_t *source, sink_t *sink); #endif //QUERY_H diff --git a/include/source.h b/include/source.h index df1feb7..e4f7bc0 100644 --- a/include/source.h +++ b/include/source.h @@ -5,13 +5,11 @@ #define SOURCE_H #include "data.h" -#include // Created a source to enable other sources than generator e.g. network typedef struct Source { data_t buffer; - bool has_next; - data_t* (*get_next)(struct Source *self); + data_t* (*get_next)(const struct Source *self); } source_t; typedef struct Sink { diff --git a/include/utils.h b/include/utils.h index 4b9c81e..bf179df 100644 --- a/include/utils.h +++ b/include/utils.h @@ -9,8 +9,10 @@ static int min(const int a, const int b) { return a < b ? a : b; } +/* static int max(const int a, const int b) { return a > b ? a : b; } +*/ #endif //UTILS_H diff --git a/src/generator.c b/src/generator.c index 3d23502..252cd5c 100644 --- a/src/generator.c +++ b/src/generator.c @@ -57,13 +57,15 @@ triple_t triples[] = { #define NUM_TRIPLES (sizeof(triples) / sizeof(triples[0])) +static bool has_next = true; -data_t* get_next_generator(source_t *generator) { - if (!generator->has_next) { +data_t* get_next_generator(const source_t *generator) { + if (!has_next) { return NULL; // Return NULL if there are no items left } - generator->has_next = false; - return &generator->buffer; // Return the current buffer + has_next = false; + + return (data_t*) &generator->buffer; // Return the current buffer } @@ -71,7 +73,6 @@ source_t create_generator_source() { return (source_t) { .buffer = {triples, NUM_TRIPLES, 1}, - .has_next = true, .get_next = get_next_generator }; } diff --git a/src/query.c b/src/query.c index 99500d3..b3960ff 100644 --- a/src/query.c +++ b/src/query.c @@ -17,7 +17,7 @@ /// @param param Join parameters containing a function ptr specifying the join condition void join(const data_t *in1, const data_t *in2, data_t *out, const parameter_t param) { - const uint8_t size = max(in1->size, in2->size) * (in1->width + in2->width); + const uint8_t size = (in1->size * in2->size) * (in1->width + in2->width); out->data = malloc(size * sizeof(triple_t)); assert(out->data); out->size = 0; @@ -121,10 +121,11 @@ void execute_operator(const operator_t *operator_, const data_t *in, data_t *out /// @param query The query to be executed /// @param source The source creating the input stream /// @param sink The sink consuming the output stream -void execute_query(const query_t *query, source_t *source, sink_t *sink) +void execute_query(const query_t *query, const source_t *source, sink_t *sink) { data_t data = {NULL, 0, 1}; data_t* next_data; + while ((next_data = source->get_next(source)) != NULL) { execute_operator(query->root, next_data, &data); sink->push_next(sink, &data); diff --git a/tests/queryTests.cpp b/tests/queryTests.cpp index 60d73ab..ca0385d 100644 --- a/tests/queryTests.cpp +++ b/tests/queryTests.cpp @@ -155,6 +155,48 @@ TEST_F(QueryTestFixture, test_query_filter2) } +bool check_filter7(const triple_t in) +{ + return in.subject == SUBJECT_ALICE; +} + + +TEST_F(QueryTestFixture, test_query_filter3) +{ + filter_check_t conditions1[1] = {check_filter}; + filter_check_t conditions2[1] = {check_filter2}; + filter_check_t conditions3[1] = {check_filter7}; + operator_t filter_op = { + .type = FILTER, + .left = nullptr, + .right = nullptr, + .params = {.filter = {.size = 1, .checks = conditions1}} + }; + + operator_t filter_op2 = { + .type = FILTER, + .left = &filter_op, + .right = nullptr, + .params = {.filter = {.size = 1, .checks = conditions2}} + }; + + operator_t filter_op3 = { + .type = FILTER, + .left = &filter_op2, + .right = nullptr, + .params = {.filter = {.size = 1, .checks = conditions3}} + }; + + query_t query_filter = {.root = &filter_op3}; + + execute_query(&query_filter, &gsource, &gsink); + triple_t expected[1] = { + {SUBJECT_ALICE, PREDICATE_HAS_SKILL, OBJECT_PROGRAMMING}, + }; + ASSERT_TRUE(ARR_EQ(gsink.buffer.data, expected, 1)); +} + + TEST_F(QueryTestFixture, test_query_window) { operator_t window_op = {