From 5419ee25175000d4193632e900dd328fac994d23 Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:43:13 -0600 Subject: [PATCH 01/75] Refactored mongo select to use a static array instead of a list --- include/cmongo/select.h | 34 ++------ src/cmongo/crud.c | 7 +- src/cmongo/select.c | 169 ++++------------------------------------ 3 files changed, 27 insertions(+), 183 deletions(-) diff --git a/include/cmongo/select.h b/include/cmongo/select.h index 55b44a8..6a2d46f 100644 --- a/include/cmongo/select.h +++ b/include/cmongo/select.h @@ -6,6 +6,7 @@ #include "cmongo/config.h" #define CMONGO_SELECT_FIELD_LEN 256 +#define CMONGO_SELECT_FIELDS_SIZE 32 #ifdef __cplusplus extern "C" { @@ -13,49 +14,24 @@ extern "C" { typedef struct CMongoSelectField { - struct CMongoSelectField *prev; - - char value[CMONGO_SELECT_FIELD_LEN]; size_t len; - - struct CMongoSelectField *next; + char value[CMONGO_SELECT_FIELD_LEN]; } CMongoSelectField; -CMONGO_EXPORT CMongoSelectField *cmongo_select_field_create ( - const char *value -); - typedef struct CMongoSelect { - size_t size; - - CMongoSelectField *start; - CMongoSelectField *end; + size_t n_fields; + CMongoSelectField fields[CMONGO_SELECT_FIELDS_SIZE]; } CMongoSelect; -#define cmongo_select_for_each(select) \ - for (CMongoSelectField *field = select->start; field; field = field->next) - -#define cmongo_select_for_each_backwards(select) \ - for (CMongoSelectField *field = select->end; field; field = field->prev) - CMONGO_EXPORT CMongoSelect *cmongo_select_new (void); -CMONGO_EXPORT bool cmongo_select_is_empty ( - const CMongoSelect *select -); - -CMONGO_EXPORT bool cmongo_select_is_not_empty ( - const CMongoSelect *select -); - // adds a new field to the select list // returns 0 on success, 1 on error CMONGO_EXPORT int cmongo_select_insert_field ( - CMongoSelect *select, - CMongoSelectField *field + CMongoSelect *select, const char *field ); CMONGO_EXPORT void cmongo_select_delete ( diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 14b984f..b27a0d0 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -78,9 +78,12 @@ bson_t *mongo_find_generate_opts ( (void) bson_append_bool (&projection_doc, "_id", -1, true); - cmongo_select_for_each (select) { + for (size_t idx = 0; idx < select->n_fields; idx++) { (void) bson_append_bool ( - &projection_doc, field->value, field->len, true + &projection_doc, + select->fields[idx].value, + select->fields[idx].len, + true ); } diff --git a/src/cmongo/select.c b/src/cmongo/select.c index 1094a12..fdc8036 100644 --- a/src/cmongo/select.c +++ b/src/cmongo/select.c @@ -4,159 +4,41 @@ #include "cmongo/select.h" -#pragma region internal - -static CMongoSelectField *cmongo_select_field_new (void) { - - CMongoSelectField *field = (CMongoSelectField *) malloc (sizeof (CMongoSelectField)); - if (field) { - field->prev = NULL; - - (void) memset (field->value, 0, CMONGO_SELECT_FIELD_LEN); - field->len = 0; - - field->next = NULL; - } - - return field; - -} - -static void cmongo_select_field_delete (CMongoSelectField *field) { - - if (field) free (field); - -} - -static void cmongo_select_internal_insert_after ( - CMongoSelect *select, - CMongoSelectField *element, - CMongoSelectField *field -) { - - if (element == NULL) { - if (select->size == 0) select->end = field; - else select->start->prev = field; - - field->next = select->start; - field->prev = NULL; - select->start = field; - } - - else { - if (element->next == NULL) select->end = field; - - field->next = element->next; - field->prev = element; - element->next = field; - } - - select->size++; - -} - -static CMongoSelectField *cmongo_select_internal_remove_element ( - CMongoSelect *select, - CMongoSelectField *element -) { - - CMongoSelectField *old = NULL; - - if (element == NULL) { - old = select->start; - select->start = select->start->next; - if (select->start != NULL) select->start->prev = NULL; - } - - else { - old = element; - - CMongoSelectField *prevElement = element->prev; - CMongoSelectField *nextElement = element->next; - - if (prevElement != NULL && nextElement != NULL) { - prevElement->next = nextElement; - nextElement->prev = prevElement; - } - - else { - // we are at the start of the select - if (prevElement == NULL) { - if (nextElement != NULL) nextElement->prev = NULL; - select->start = nextElement; - } - - // we are at the end of the select - if (nextElement == NULL) { - if (prevElement != NULL) prevElement->next = NULL; - select->end = prevElement; - } - } - } - - return old; - -} - -#pragma endregion - -#pragma region public - -CMongoSelectField *cmongo_select_field_create ( - const char *value -) { - - CMongoSelectField *field = cmongo_select_field_new (); - if (field && value) { - (void) strncpy (field->value, value, CMONGO_SELECT_FIELD_LEN - 1); - field->len = strlen (field->value); - } - - return field; - -} - CMongoSelect *cmongo_select_new (void) { CMongoSelect *select = (CMongoSelect *) malloc (sizeof (CMongoSelect)); if (select) { - select->size = 0; - - select->start = NULL; - select->end = NULL; + (void) memset (select, 0, sizeof (CMongoSelect)); } return select; } -bool cmongo_select_is_empty (const CMongoSelect *select) { - - return select ? (select->size == 0) : false; - -} - -bool cmongo_select_is_not_empty (const CMongoSelect *select) { - - return select ? (select->size > 0) : false; - -} - // adds a new field to the select list // returns 0 on success, 1 on error int cmongo_select_insert_field ( - CMongoSelect *select, - CMongoSelectField *field + CMongoSelect *select, const char *field ) { int retval = 1; if (select && field) { - cmongo_select_internal_insert_after ( - select, select->end, field - ); + if (select->n_fields < CMONGO_SELECT_FIELDS_SIZE) { + (void) strncpy ( + select->fields[select->n_fields].value, + field, + CMONGO_SELECT_FIELD_LEN - 1 + ); + + select->fields[select->n_fields].len = strlen ( + select->fields[select->n_fields].value + ); - retval = 0; + select->n_fields += 1; + + retval = 0; + } } return retval; @@ -166,24 +48,7 @@ int cmongo_select_insert_field ( void cmongo_select_delete (void *cmongo_select_ptr) { if (cmongo_select_ptr) { - CMongoSelect *select = (CMongoSelect *) cmongo_select_ptr; - - while (select->size > 0) { - cmongo_select_field_delete ( - cmongo_select_internal_remove_element ( - select, NULL - ) - ); - - select->size--; - - if (select->size == 0) { - select->start = NULL; - select->end = NULL; - } - } - - free (select); + free (cmongo_select_ptr); } } From 7bde42310a9bf4c09b00bdbe51c8a193fa4f30fb Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:44:14 -0600 Subject: [PATCH 02/75] Updated includes to use cmongo export qualifiers --- include/cmongo/collections.h | 6 ++++-- include/cmongo/crud.h | 30 +++++++++++++++--------------- include/cmongo/mongo.h | 26 ++++++++++++++------------ include/cmongo/types.h | 8 +++++--- include/cmongo/version.h | 8 +++++--- 5 files changed, 43 insertions(+), 35 deletions(-) diff --git a/include/cmongo/collections.h b/include/cmongo/collections.h index d0c8458..dd4fa60 100644 --- a/include/cmongo/collections.h +++ b/include/cmongo/collections.h @@ -3,18 +3,20 @@ #include +#include "cmongo/mongo.h" + #ifdef __cplusplus extern "C" { #endif // opens handle to a mongo collection in the db -extern mongoc_collection_t *mongo_collection_get ( +CMONGO_EXPORT mongoc_collection_t *mongo_collection_get ( const char *coll_name ); // drops a collection deleting all of its data // retuns 0 on success, 1 on error -extern int mongo_collection_drop ( +CMONGO_EXPORT int mongo_collection_drop ( mongoc_collection_t *collection ); diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index 702c6cf..4aeacd0 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -13,18 +13,18 @@ extern "C" { typedef void (*mongo_parser)(void *model, const bson_t *doc); // counts the docs in a collection by a matching query -extern int64_t mongo_count_docs ( +CMONGO_EXPORT int64_t mongo_count_docs ( mongoc_collection_t *collection, bson_t *query ); // returns true if 1 or more documents matches the query, false if no matches -extern bool mongo_check ( +CMONGO_EXPORT bool mongo_check ( mongoc_collection_t *collection, bson_t *query ); // generates an opts doc that can be used to better work with find methods // primarily used to query with projection (select) options -extern bson_t *mongo_find_generate_opts ( +CMONGO_EXPORT bson_t *mongo_find_generate_opts ( const CMongoSelect *select ); @@ -33,7 +33,7 @@ extern bson_t *mongo_find_generate_opts ( // _id is true by default and should not be incldued // returns a cursor (should be destroyed) that can be used to traverse the matching documents // query gets destroyed, select list remains the same -extern mongoc_cursor_t *mongo_find_all_cursor ( +CMONGO_EXPORT mongoc_cursor_t *mongo_find_all_cursor ( mongoc_collection_t *collection, bson_t *query, const CMongoSelect *select, uint64_t *n_docs @@ -41,28 +41,28 @@ extern mongoc_cursor_t *mongo_find_all_cursor ( // uses a query to find all matching docs with the specified options // query gets destroyed, options remain the same -extern mongoc_cursor_t *mongo_find_all_cursor_with_opts ( +CMONGO_EXPORT mongoc_cursor_t *mongo_find_all_cursor_with_opts ( mongoc_collection_t *collection, bson_t *query, const bson_t *opts ); // use a query to find all matching documents // an empty query will return all the docs in a collection -extern const bson_t **mongo_find_all ( +CMONGO_EXPORT const bson_t **mongo_find_all ( mongoc_collection_t *collection, bson_t *query, const CMongoSelect *select, uint64_t *n_docs ); // correctly destroys an array of docs got from mongo_find_all () -extern void mongo_find_all_destroy_docs ( +CMONGO_EXPORT void mongo_find_all_destroy_docs ( bson_t **docs, uint64_t count ); // uses a query to find one doc with the specified options // query gets destroyed, opts are kept the same // returns 0 on success, 1 on error -extern unsigned int mongo_find_one_with_opts ( +CMONGO_EXPORT unsigned int mongo_find_one_with_opts ( mongoc_collection_t *collection, bson_t *query, const bson_t *opts, void *model, const mongo_parser model_parser @@ -73,7 +73,7 @@ extern unsigned int mongo_find_one_with_opts ( // _id is true by default and should not be incldued // query gets destroyed, select structure remains the same // returns 0 on success, 1 on error -extern unsigned int mongo_find_one ( +CMONGO_EXPORT unsigned int mongo_find_one ( mongoc_collection_t *collection, bson_t *query, const CMongoSelect *select, void *model, const mongo_parser model_parser @@ -82,14 +82,14 @@ extern unsigned int mongo_find_one ( // inserts a document into a collection // destroys document // returns 0 on success, 1 on error -extern int mongo_insert_one ( +CMONGO_EXPORT int mongo_insert_one ( mongoc_collection_t *collection, bson_t *doc ); // inserts many documents into a collection // docs are NOT deleted after the operation // returns 0 on success, 1 on error -extern int mongo_insert_many ( +CMONGO_EXPORT int mongo_insert_many ( mongoc_collection_t *collection, const bson_t **docs, size_t n_docs ); @@ -97,7 +97,7 @@ extern int mongo_insert_many ( // updates a doc by a matching query with the new values // destroys query and update documents // returns 0 on success, 1 on error -extern int mongo_update_one ( +CMONGO_EXPORT int mongo_update_one ( mongoc_collection_t *collection, bson_t *query, bson_t *update ); @@ -105,7 +105,7 @@ extern int mongo_update_one ( // updates all the query matching documents // destroys the query and the update documents // returns 0 on success, 1 on error -extern int mongo_update_many ( +CMONGO_EXPORT int mongo_update_many ( mongoc_collection_t *collection, bson_t *query, bson_t *update ); @@ -113,14 +113,14 @@ extern int mongo_update_many ( // deletes one matching document by a query // destroys the query document // returns 0 on success, 1 on error -extern int mongo_delete_one ( +CMONGO_EXPORT int mongo_delete_one ( mongoc_collection_t *collection, bson_t *query ); // deletes all the query matching documents // destroys the query // returns 0 on success, 1 on error -extern int mongo_delete_many ( +CMONGO_EXPORT int mongo_delete_many ( mongoc_collection_t *collection, bson_t *query ); diff --git a/include/cmongo/mongo.h b/include/cmongo/mongo.h index bf2d30e..1005510 100644 --- a/include/cmongo/mongo.h +++ b/include/cmongo/mongo.h @@ -4,6 +4,8 @@ #include #include +#include "cmongo/config.h" + #ifdef __cplusplus extern "C" { #endif @@ -19,37 +21,37 @@ typedef enum MongoStatus { } MongoStatus; -extern MongoStatus mongo_get_status (void); +CMONGO_EXPORT MongoStatus mongo_get_status (void); -extern void mongo_set_host (const char *h); +CMONGO_EXPORT void mongo_set_host (const char *h); -extern void mongo_set_port (const char *p); +CMONGO_EXPORT void mongo_set_port (const char *p); -extern void mongo_set_username (const char *u); +CMONGO_EXPORT void mongo_set_username (const char *u); -extern void mongo_set_password (const char *pswd); +CMONGO_EXPORT void mongo_set_password (const char *pswd); -extern void mongo_set_db_name (const char *name); +CMONGO_EXPORT void mongo_set_db_name (const char *name); -extern void mongo_set_app_name (const char *name); +CMONGO_EXPORT void mongo_set_app_name (const char *name); -extern void mongo_set_uri (const char *uri); +CMONGO_EXPORT void mongo_set_uri (const char *uri); // generates a new uri string with the set values (username, password, host, port & db name) // that can be used to set as the uri for a new connection // returns the newly uri string (that should be freed) on success // returns NULL on error -extern char *mongo_uri_generate (void); +CMONGO_EXPORT char *mongo_uri_generate (void); // pings the db to test for a success connection // returns 0 on success, 1 on error -extern int mongo_ping_db (void); +CMONGO_EXPORT int mongo_ping_db (void); // connect to the mongo db with db name -extern int mongo_connect (void); +CMONGO_EXPORT int mongo_connect (void); // disconnects from the db -extern void mongo_disconnect (void); +CMONGO_EXPORT void mongo_disconnect (void); #ifdef __cplusplus } diff --git a/include/cmongo/types.h b/include/cmongo/types.h index 0bef352..9396094 100644 --- a/include/cmongo/types.h +++ b/include/cmongo/types.h @@ -3,15 +3,17 @@ #include +#include "cmongo/config.h" + #ifdef __cplusplus extern "C" { #endif -extern bson_oid_t *bson_oid_new (void); +CMONGO_PUBLIC bson_oid_t *bson_oid_new (void); -extern void bson_oid_delete (void *bson_oid_t_ptr); +CMONGO_PUBLIC void bson_oid_delete (void *bson_oid_t_ptr); -extern bson_oid_t *bson_oid_create ( +CMONGO_PUBLIC bson_oid_t *bson_oid_create ( const bson_oid_t *original_oid ); diff --git a/include/cmongo/version.h b/include/cmongo/version.h index 6a95120..fc79129 100644 --- a/include/cmongo/version.h +++ b/include/cmongo/version.h @@ -1,6 +1,8 @@ #ifndef _CMONGO_VERSION_H_ #define _CMONGO_VERSION_H_ +#include "cmongo/config.h" + #define CMONGO_VERSION "1.0" #define CMONGO_VERSION_NAME "Release 1.0" #define CMONGO_VERSION_DATE "04/01/2021" @@ -12,13 +14,13 @@ extern "C" { #endif // print full cmongo version information -extern void cmongo_version_print_full (void); +CMONGO_EXPORT void cmongo_version_print_full (void); // print the version id -extern void cmongo_version_print_version_id (void); +CMONGO_EXPORT void cmongo_version_print_version_id (void); // print the version name -extern void cmongo_version_print_version_name (void); +CMONGO_EXPORT void cmongo_version_print_version_name (void); #ifdef __cplusplus } From eff4238058505015647ee9438e89483b9cf80ae5 Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:44:44 -0600 Subject: [PATCH 03/75] Added test header with check macro definitions --- test/test.h | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 test/test.h diff --git a/test/test.h b/test/test.h new file mode 100644 index 0000000..374e37b --- /dev/null +++ b/test/test.h @@ -0,0 +1,176 @@ +#ifndef _CMONGO_TESTS_H_ +#define _CMONGO_TESTS_H_ + +#include +#include + +#define where (void) fprintf (stderr, "%s:%d -> ", __FILE__, __LINE__) + +#define \ + fail(msg) \ + ({ \ + where; \ + (void) fprintf (stderr, "%s\n", msg); \ + exit (1); \ + }) + +#define \ + test_check(result, msg) \ + ({ \ + if ((result) == false) { \ + where; \ + (void) fprintf ( \ + stderr, \ + "Check has failed!\n" \ + ); \ + \ + if (msg) (void) fprintf (stderr, "%s\n", (char *) msg); \ + exit (1); \ + } \ + }) + +#define test_check_ptr_eq(X, Y) test_check (X == Y, NULL) + +#define test_check_ptr_ne(X, Y) test_check (X != Y, NULL) + +#define test_check_int_ne(X, Y) test_check (X != Y, NULL) + +#define test_check_int_gt(X, Y) test_check (X > Y, NULL) + +#define \ + test_check_ptr(ptr) \ + ({ \ + if (!ptr) { \ + where; \ + (void) fprintf (stderr, "Pointer is NULL!"); \ + exit (1); \ + } \ + }) + +#define \ + test_check_null_ptr(ptr) \ + ({ \ + if (ptr) { \ + where; \ + (void) fprintf (stderr, "Pointer is NOT NULL!"); \ + exit (1); \ + } \ + }) + +#define \ + test_check_true(value) \ + ({ \ + if (!value) { \ + where; \ + (void) fprintf (stderr, "Value is NOT true!"); \ + exit (1); \ + } \ + }) + +#define \ + test_check_false(value) \ + ({ \ + if (value) { \ + where; \ + (void) fprintf (stderr, "Value is NOT false!"); \ + exit (1); \ + } \ + }) + +#define \ + test_check_bool_eq(value, expected, msg) \ + ({ \ + if (value != expected) { \ + where; \ + (void) fprintf ( \ + stderr, \ + "BOOL %d does not match %d\n", \ + value, expected \ + ); \ + \ + if (msg) (void) fprintf (stderr, "%s\n", (char *) msg); \ + exit (1); \ + } \ + }) + +#define \ + test_check_unsigned_eq(value, expected, msg) \ + ({ \ + if (value != expected) { \ + where; \ + (void) fprintf ( \ + stderr, \ + "UNSIGNED %d does not match %d\n", \ + value, expected \ + ); \ + \ + if (msg) (void) fprintf (stderr, "%s\n", (char *) msg); \ + exit (1); \ + } \ + }) + +#define \ + test_check_int_eq(value, expected, msg) \ + ({ \ + if (value != expected) { \ + where; \ + (void) fprintf ( \ + stderr, \ + "INTEGER %d does not match %d\n", \ + value, expected \ + ); \ + \ + if (msg) (void) fprintf (stderr, "%s\n", (char *) msg); \ + exit (1); \ + } \ + }) + +#define \ + test_check_long_int_eq(value, expected, msg) \ + ({ \ + if (value != expected) { \ + where; \ + (void) fprintf ( \ + stderr, \ + "INTEGER %ld does not match %ld\n", \ + value, expected \ + ); \ + \ + if (msg) (void) fprintf (stderr, "%s\n", (char *) msg); \ + exit (1); \ + } \ + }) + +#define \ + test_check_str_eq(value, expected, msg) \ + ({ \ + if (strcmp ((char *) value, (char *) expected)) { \ + where; \ + (void) fprintf ( \ + stderr, \ + "STRING %s does not match %s\n", \ + (char *) value, (char *) expected \ + ); \ + \ + if (msg) (void) fprintf (stderr, "%s\n", (char *) msg); \ + exit (1); \ + } \ + }) + +#define \ + test_check_str_len(string, expected, msg) \ + ({ \ + if (strlen ((char *) string) != expected) { \ + where; \ + (void) fprintf ( \ + stderr, \ + "STRING %s LEN does not match %d\n", \ + (char *) string, expected \ + ); \ + \ + if (msg) (void) fprintf (stderr, "%s\n", (char *) msg); \ + exit (1); \ + } \ + }) + +#endif \ No newline at end of file From 34dfd1a75b88c821cf93af07418079febcce8c2b Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:44:56 -0600 Subject: [PATCH 04/75] Added base cmongo select unit tests --- test/select.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 test/select.c diff --git a/test/select.c b/test/select.c new file mode 100644 index 0000000..8162489 --- /dev/null +++ b/test/select.c @@ -0,0 +1,67 @@ +#include +#include +#include + +#include + +#include "test.h" + +static void test_select_create_single (void) { + + CMongoSelect *select = cmongo_select_new (); + + test_check_ptr (select); + test_check_int_eq (select->n_fields, 0, NULL); + + cmongo_select_insert_field (select, "name"); + + test_check_int_eq (select->n_fields, 1, NULL); + test_check_str_eq (select->fields[0].value, "name", NULL); + test_check_str_len (select->fields[0].value, strlen ("name"), NULL); + + cmongo_select_delete (select); + +} + +static void test_select_create_multiple (void) { + + CMongoSelect *select = cmongo_select_new (); + + test_check_ptr (select); + test_check_int_eq (select->n_fields, 0, NULL); + + cmongo_select_insert_field (select, "name"); + + test_check_int_eq (select->n_fields, 1, NULL); + test_check_str_eq (select->fields[0].value, "name", NULL); + test_check_str_len (select->fields[0].value, strlen ("name"), NULL); + + cmongo_select_insert_field (select, "email"); + + test_check_int_eq (select->n_fields, 2, NULL); + test_check_str_eq (select->fields[1].value, "email", NULL); + test_check_str_len (select->fields[1].value, strlen ("email"), NULL); + + cmongo_select_insert_field (select, "username"); + + test_check_int_eq (select->n_fields, 3, NULL); + test_check_str_eq (select->fields[2].value, "username", NULL); + test_check_str_len (select->fields[2].value, strlen ("username"), NULL); + + cmongo_select_delete (select); + +} + +int main (int argc, char **argv) { + + (void) printf ("Testing SELECT...\n"); + + test_select_create_single (); + + test_select_create_multiple (); + + (void) printf ("\nDone with SELECT tests!\n\n"); + + return 0; + +} \ No newline at end of file From 7e640dfaad390264a0239887807baf0e2296ee92 Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:45:54 -0600 Subject: [PATCH 05/75] Refactored makefile to compile tests and handle coverage --- makefile | 123 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 104 insertions(+), 19 deletions(-) diff --git a/makefile b/makefile index 1a1bba5..20f595b 100644 --- a/makefile +++ b/makefile @@ -2,7 +2,21 @@ TYPE := development SLIB := libcmongo.so -MONGOC := -l mongoc-1.0 -l bson-1.0 +all: directories $(SLIB) + +directories: + @mkdir -p $(TARGETDIR) + @mkdir -p $(BUILDDIR) + +install: $(SLIB) + install -m 644 ./bin/libcmongo.so /usr/local/lib/ + cp -R ./include/cmongo /usr/local/include + +uninstall: + rm /usr/local/lib/libcmongo.so + rm -r /usr/local/include/cmongo + +MONGOC := -l bson-1.0 -l mongoc-1.0 MONGOC_INC := -I /usr/local/include/libbson-1.0 -I /usr/local/include/libmongoc-1.0 DEFINES := -D _GNU_SOURCE @@ -13,6 +27,7 @@ GCCVGTEQ8 := $(shell expr `gcc -dumpversion | cut -f1 -d.` \>= 8) SRCDIR := src INCDIR := include + BUILDDIR := objs TARGETDIR := bin @@ -20,6 +35,9 @@ SRCEXT := c DEPEXT := d OBJEXT := o +COVDIR := coverage +COVEXT := gcov + # common flags # -Wconversion COMMON := -march=native \ @@ -58,29 +76,18 @@ endif CFLAGS += -fPIC $(COMMON) LIB := -L /usr/local/lib $(MONGOC) + +ifeq ($(TYPE), test) + LIB += -lgcov --coverage +endif + INC := -I $(INCDIR) -I /usr/local/include $(MONGOC_INC) INCDEP := -I $(INCDIR) SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT))) -all: directories $(SLIB) - -install: $(SLIB) - install -m 644 ./bin/libcmongo.so /usr/local/lib/ - cp -R ./include/cmongo /usr/local/include - -uninstall: - rm /usr/local/lib/libcmongo.so - rm -r /usr/local/include/cmongo - -directories: - @mkdir -p $(TARGETDIR) - @mkdir -p $(BUILDDIR) - -clean: - @$(RM) -rf $(BUILDDIR) - @$(RM) -rf $(TARGETDIR) +SRCCOVS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(SRCEXT).$(COVEXT))) # pull in dependency info for *existing* .o files -include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT)) @@ -98,4 +105,82 @@ $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT) @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp -.PHONY: all clean \ No newline at end of file +# tests +TESTDIR := test +TESTBUILD := $(TESTDIR)/objs +TESTTARGET := $(TESTDIR)/bin +TESTCOVDIR := $(COVDIR)/test + +TESTFLAGS := -g $(DEFINES) -Wall -Wno-unknown-pragmas -Wno-format + +ifeq ($(TYPE), test) + TESTFLAGS += -fprofile-arcs -ftest-coverage +endif + +TESTLIBS := $(PTHREAD) -L ./bin -l cmongo + +ifeq ($(TYPE), test) + TESTLIBS += -lgcov --coverage +endif + +TESTINC := -I $(INCDIR) -I ./$(TESTDIR) + +TESTS := $(shell find $(TESTDIR) -type f -name *.$(SRCEXT)) +TESTOBJS := $(patsubst $(TESTDIR)/%,$(TESTBUILD)/%,$(TESTS:.$(SRCEXT)=.$(OBJEXT))) + +TESTCOVS := $(patsubst $(TESTDIR)/%,$(TESTBUILD)/%,$(TESTS:.$(SRCEXT)=.$(SRCEXT).$(COVEXT))) + +test: $(TESTOBJS) + @mkdir -p ./$(TESTTARGET) + @mkdir -p ./$(TESTTARGET) + $(CC) $(TESTINC) ./$(TESTBUILD)/select.o -o ./$(TESTTARGET)/select $(TESTLIBS) + $(CC) $(TESTINC) ./$(TESTBUILD)/version.o -o ./$(TESTTARGET)/version $(TESTLIBS) + +# compile tests +$(TESTBUILD)/%.$(OBJEXT): $(TESTDIR)/%.$(SRCEXT) + @mkdir -p $(dir $@) + $(CC) $(TESTFLAGS) $(INC) $(TESTLIBS) -c -o $@ $< + @$(CC) $(TESTFLAGS) $(INCDEP) -MM $(TESTDIR)/$*.$(SRCEXT) > $(TESTBUILD)/$*.$(DEPEXT) + @cp -f $(TESTBUILD)/$*.$(DEPEXT) $(TESTBUILD)/$*.$(DEPEXT).tmp + @sed -e 's|.*:|$(TESTBUILD)/$*.$(OBJEXT):|' < $(TESTBUILD)/$*.$(DEPEXT).tmp > $(TESTBUILD)/$*.$(DEPEXT) + @sed -e 's/.*://' -e 's/\\$$//' < $(TESTBUILD)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(TESTBUILD)/$*.$(DEPEXT) + @rm -f $(TESTBUILD)/$*.$(DEPEXT).tmp + +#coverage +COVOBJS := $(SRCCOVS) $(TESTCOVS) + +test-coverage: $(COVOBJS) + +coverage-init: + @mkdir -p ./$(COVDIR) + @mkdir -p ./$(TESTCOVDIR) + +coverage: coverage-init test-coverage + +# get lib coverage reports +$(BUILDDIR)/%.$(SRCEXT).$(COVEXT): $(SRCDIR)/%.$(SRCEXT) + @mkdir -p ./$(COVDIR)/$(dir $<) + gcov -r $< --object-directory $(dir $@) + mv $(notdir $@) ./$(COVDIR)/$<.gcov + +# get tests coverage reports +$(TESTBUILD)/%.$(SRCEXT).$(COVEXT): $(TESTDIR)/%.$(SRCEXT) + gcov -r $< --object-directory $(dir $@) + mv $(notdir $@) ./$(TESTCOVDIR) + +clear: clean-objects clean-tests clean-coverage + +clean: clear + @$(RM) -rf $(TARGETDIR) + +clean-objects: + @$(RM) -rf $(BUILDDIR) + +clean-tests: + @$(RM) -rf $(TESTBUILD) + @$(RM) -rf $(TESTTARGET) + +clean-coverage: + @$(RM) -rf $(COVDIR) + +.PHONY: all clean clear test coverage From 790655ccd24b173eec5f29db579bb08296a720b3 Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:46:06 -0600 Subject: [PATCH 06/75] Added base codecov configuration --- .codecov.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .codecov.yml diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 0000000..23c0459 --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,20 @@ +codecov: + require_ci_to_pass: yes + +coverage: + precision: 2 + round: down + range: "70...100" + +parsers: + gcov: + branch_detection: + conditional: yes + loop: yes + method: no + macro: no + +comment: + layout: "reach,diff,flags,files,footer" + behavior: default + require_changes: no \ No newline at end of file From 21821cb9e59577e7c44660257959759f18f3609b Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:47:08 -0600 Subject: [PATCH 07/75] Added dedicated version file --- version.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 version.txt diff --git a/version.txt b/version.txt new file mode 100644 index 0000000..2100241 --- /dev/null +++ b/version.txt @@ -0,0 +1 @@ +1.0b-1 \ No newline at end of file From 03a3da68851f664356e3626c03847f4da3d966a5 Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:47:46 -0600 Subject: [PATCH 08/75] Added version match check test --- test/version.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 test/version.c diff --git a/test/version.c b/test/version.c new file mode 100644 index 0000000..3b769b9 --- /dev/null +++ b/test/version.c @@ -0,0 +1,60 @@ +#include +#include +#include + +#include + +#include + +// opens and reads a file into a buffer +// sets file size to the amount of bytes read +static char *file_read (const char *filename, size_t *file_size) { + + char *file_contents = NULL; + + if (filename) { + struct stat filestatus = { 0 }; + if (!stat (filename, &filestatus)) { + FILE *fp = fopen (filename, "rt"); + if (fp) { + *file_size = filestatus.st_size; + file_contents = (char *) malloc (filestatus.st_size); + + // read the entire file into the buffer + if (fread (file_contents, filestatus.st_size, 1, fp) != 1) { + (void) fprintf ( + stderr, "Failed to read file (%s) contents!", filename + ); + + free (file_contents); + } + + (void) fclose (fp); + } + } + + + else { + (void) fprintf (stderr, "Unable to open file %s.", filename); + } + } + + return file_contents; + +} + +int main (int argc, char **argv) { + + // get version from file + size_t version_len = 0; + char *version_from_file = file_read ("version.txt", &version_len); + + if (version_from_file) { + if (!strcmp (CMONGO_VERSION, version_from_file)) { + return 0; + } + } + + return 1; + +} \ No newline at end of file From b2c7ddac7cc5299463da67516f54cbdca9ffafe2 Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:48:25 -0600 Subject: [PATCH 09/75] Added dedicated script to run tests --- test/run.sh | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 test/run.sh diff --git a/test/run.sh b/test/run.sh new file mode 100644 index 0000000..36566b5 --- /dev/null +++ b/test/run.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +LD_LIBRARY_PATH=bin ./test/bin/select || { exit 1; } From 8ffcd40e986046d78356c61717abb6d97141218e Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:48:40 -0600 Subject: [PATCH 10/75] Added coverage to .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 8f84944..a6aea71 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ bin objs +coverage + keys data From 53c5a2009b8c8ade5738c511972420679d0be312 Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:49:22 -0600 Subject: [PATCH 11/75] Added dedicated script to build sources --- build.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 build.sh diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..ded10ad --- /dev/null +++ b/build.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# ensure a clean build +make clean + +# gcc +printf "gcc make\n\n" +make -j8 +printf "\n\ngcc test\n\n" +make test -j8 From 7c0e06a07149f6130177c4f3f6919db492a80031 Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:49:34 -0600 Subject: [PATCH 12/75] Added dedicated script to build & generate coverage reports --- coverage.sh | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 coverage.sh diff --git a/coverage.sh b/coverage.sh new file mode 100644 index 0000000..77a0dd6 --- /dev/null +++ b/coverage.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# ensure a clean build +make clean + +# gcc +printf "gcc make\n\n" +make TYPE=test -j8 +printf "\n\ngcc test\n\n" +make TYPE=test test -j8 + +# run +bash test/run.sh + +make coverage From 9536acaa8f85434d128955531e22a4842be80bab Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:50:02 -0600 Subject: [PATCH 13/75] Added base documentation files --- docs/Home.md | 1 + docs/_Footer.md | 1 + 2 files changed, 2 insertions(+) create mode 100644 docs/Home.md create mode 100644 docs/_Footer.md diff --git a/docs/Home.md b/docs/Home.md new file mode 100644 index 0000000..c45998c --- /dev/null +++ b/docs/Home.md @@ -0,0 +1 @@ +Welcome to the cmongo wiki! diff --git a/docs/_Footer.md b/docs/_Footer.md new file mode 100644 index 0000000..6ffc593 --- /dev/null +++ b/docs/_Footer.md @@ -0,0 +1 @@ +Ermiry - Never Stop Creating \ No newline at end of file From 8ddd73ae8937c4fb571d7534f237cc5b31d92308 Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:50:15 -0600 Subject: [PATCH 14/75] Added workflow to push documentation to wiki --- .github/workflows/docs.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/workflows/docs.yml diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..338b88a --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,20 @@ +name: CMongo Documentation + +on: + push: + branches: + - 'main' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout reposistory + uses: actions/checkout@v2 + + - name: Upload Documentation to Wiki + uses: SwiftDocOrg/github-wiki-publish-action@v1 + with: + path: "docs" + env: + GH_PERSONAL_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From f8dc33a0d44abb9dbf598f277c6431fa12da37fd Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:50:32 -0600 Subject: [PATCH 15/75] Added workflow to handle coverage reports --- .github/workflows/coverage.yml | 45 ++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 .github/workflows/coverage.yml diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 0000000..c56f49a --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,45 @@ +name: CMongo Code Coverage + +on: + pull_request: + branches: + - '*' + +jobs: + coverage: + name: CMongo coverage + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + # compile + - name: gcc make + run: make TYPE=test + - name: gcc tests + run: make TYPE=test test + + # run + - name: test + run: bash test/run.sh + + - name: coverage + run: make coverage + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + directory: ./coverage/ + flags: unittests + name: build + fail_ci_if_error: true + # verbose: true + + - name: clean tests + run: make clean-tests + + - name: g++ tests + run: make TYPE=test CC=g++ test + - name: g++ run tests + run: bash test/run.sh \ No newline at end of file From a9703ac80a4089475330e94e8e3d8ca1754d8434 Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:50:44 -0600 Subject: [PATCH 16/75] Added workflows to create beta & production releases --- .github/workflows/pre-release.yml | 39 +++++++++++++++++++++++++++++++ .github/workflows/release.yml | 39 +++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 .github/workflows/pre-release.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml new file mode 100644 index 0000000..4b79d23 --- /dev/null +++ b/.github/workflows/pre-release.yml @@ -0,0 +1,39 @@ +name: CMongo Pre-Release + +on: + push: + branches: + - '*beta' + +jobs: + build: + name: Create Pre-Release + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Read version file + id: get_version + run: echo "::set-output name=version::$(cat version.txt)" + + - name: Read changelog + id: get_changes + run: | + changes=$(cat CHANGELOG.md) + changes="${changes//'%'/'%25'}" + changes="${changes//$'\n'/'%0A'}" + changes="${changes//$'\r'/'%0D'}" + echo "::set-output name=changes::$changes" + + - name: Create Pre-Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ steps.get_version.outputs.version }} + release_name: Beta ${{ steps.get_version.outputs.version }} + body: ${{ steps.get_changes.outputs.changes }} + draft: false + prerelease: true \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..fd083b5 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,39 @@ +name: CMongo Release + +on: + push: + branches: + - 'main' + +jobs: + build: + name: Create Release + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Read version file + id: get_version + run: echo "::set-output name=version::$(cat version.txt)" + + - name: Read changelog + id: get_changes + run: | + changes=$(cat CHANGELOG.md) + changes="${changes//'%'/'%25'}" + changes="${changes//$'\n'/'%0A'}" + changes="${changes//$'\r'/'%0D'}" + echo "::set-output name=changes::$changes" + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ steps.get_version.outputs.version }} + release_name: Release ${{ steps.get_version.outputs.version }} + body: ${{ steps.get_changes.outputs.changes }} + draft: false + prerelease: false \ No newline at end of file From 1ade1786014b6c99fbf46b1d336b89d2ffe84094 Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:50:57 -0600 Subject: [PATCH 17/75] Added dedicated script to compile production like sources --- production.sh | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 production.sh diff --git a/production.sh b/production.sh new file mode 100644 index 0000000..1260a66 --- /dev/null +++ b/production.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# ensure a clean build +make clean + +# main sources +printf "gcc make\n\n" +make TYPE=production -j8 From 191520374f1a95b785459ef4a5f8652405e71c4e Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:51:15 -0600 Subject: [PATCH 18/75] Added dedicated workflow to test version check --- .github/workflows/version.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/version.yml diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml new file mode 100644 index 0000000..61fc2e9 --- /dev/null +++ b/.github/workflows/version.yml @@ -0,0 +1,30 @@ +name: CMongo Version Check + +on: + push: + branches: + - '*beta' + - 'main' + pull_request: + branches: + - '*beta' + - 'main' + +jobs: + build: + name: CMongo build + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Install Dependencies + run: sudo apt-get install libcurl4-openssl-dev + + - name: gcc make + run: make + - name: gcc tests + run: make test + + - name: Check version + run: LD_LIBRARY_PATH=bin ./test/bin/version \ No newline at end of file From d4a35abbbc627aaa6adb951029eb9a4b7b4b0610 Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 11:58:39 -0600 Subject: [PATCH 19/75] Updated version to beta 1.0b-1 --- CHANGELOG.md | 14 ++++++++++++++ include/cmongo/version.h | 8 ++++---- 2 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9283ecc --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,14 @@ +## General +- Refactored mongo select to use a static array instead of a list +- Updated includes to use cmongo export qualifiers +- Refactored makefile to compile tests and handle coverage +- Added base codecov configuration +- Added dedicated version file +- Added version match check test +- Added dedicated script to run tests +- Added workflows to create beta & production releases + +## Tests +- Added test header with check macro definitions +- Added base cmongo select unit tests +- Added dedicated script to run tests \ No newline at end of file diff --git a/include/cmongo/version.h b/include/cmongo/version.h index fc79129..793b84f 100644 --- a/include/cmongo/version.h +++ b/include/cmongo/version.h @@ -3,10 +3,10 @@ #include "cmongo/config.h" -#define CMONGO_VERSION "1.0" -#define CMONGO_VERSION_NAME "Release 1.0" -#define CMONGO_VERSION_DATE "04/01/2021" -#define CMONGO_VERSION_TIME "23:28 CST" +#define CMONGO_VERSION "1.0b-1" +#define CMONGO_VERSION_NAME "Beta 1.0b-1" +#define CMONGO_VERSION_DATE "14/01/2021" +#define CMONGO_VERSION_TIME "11:56 CST" #define CMONGO_VERSION_AUTHOR "Erick Salas" #ifdef __cplusplus From b56cde6b1e3e9c229c7f536efffec23447f70061 Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 12:02:37 -0600 Subject: [PATCH 20/75] Updated coverage and version workflows to use mongo image --- .github/workflows/coverage.yml | 2 ++ .github/workflows/version.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index c56f49a..66671ee 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -9,6 +9,8 @@ jobs: coverage: name: CMongo coverage runs-on: ubuntu-latest + container: + image: ermiry/mongoc:buildev steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml index 61fc2e9..314448b 100644 --- a/.github/workflows/version.yml +++ b/.github/workflows/version.yml @@ -14,6 +14,8 @@ jobs: build: name: CMongo build runs-on: ubuntu-latest + container: + image: ermiry/mongoc:buildev steps: - name: Checkout code uses: actions/checkout@v2 From 97a0ecd92d9db2ffb3a4c063f319cc9057bf0c1e Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 14 Jan 2021 12:04:57 -0600 Subject: [PATCH 21/75] Removed dependencies step for version workflow --- .github/workflows/version.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml index 314448b..450a471 100644 --- a/.github/workflows/version.yml +++ b/.github/workflows/version.yml @@ -20,9 +20,6 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - - name: Install Dependencies - run: sudo apt-get install libcurl4-openssl-dev - - name: gcc make run: make - name: gcc tests From 5ac13f7024f343371249263893e220e4103426e2 Mon Sep 17 00:00:00 2001 From: ermiry Date: Tue, 2 Mar 2021 10:30:23 -0600 Subject: [PATCH 22/75] Added custom mongo structure to hold values --- include/cmongo/mongo.h | 58 ++++++++++++++++------ src/cmongo/mongo.c | 108 ++++++++++++++++++++++------------------- 2 files changed, 100 insertions(+), 66 deletions(-) diff --git a/include/cmongo/mongo.h b/include/cmongo/mongo.h index 1005510..4aed516 100644 --- a/include/cmongo/mongo.h +++ b/include/cmongo/mongo.h @@ -6,14 +6,20 @@ #include "cmongo/config.h" +#define CMONGO_DB_NAME_SIZE 128 +#define CMONGO_HOST_SIZE 128 + +#define CMONGO_USERNAME_SIZE 128 +#define CMONGO_PASSWORD_SIZE 128 + +#define CMONGO_APP_NAME_SIZE 128 + +#define CMONGO_URI_SIZE 1024 + #ifdef __cplusplus extern "C" { #endif -extern mongoc_client_t *client; - -extern char *db_name; - typedef enum MongoStatus { MONGO_STATUS_DISCONNECTED = 0, @@ -21,27 +27,49 @@ typedef enum MongoStatus { } MongoStatus; -CMONGO_EXPORT MongoStatus mongo_get_status (void); +typedef struct Mongo { -CMONGO_EXPORT void mongo_set_host (const char *h); + MongoStatus status; -CMONGO_EXPORT void mongo_set_port (const char *p); + size_t db_name_len; + char db_name[CMONGO_DB_NAME_SIZE]; -CMONGO_EXPORT void mongo_set_username (const char *u); + size_t host_len; + char host[CMONGO_HOST_SIZE]; + unsigned int port; -CMONGO_EXPORT void mongo_set_password (const char *pswd); + size_t username_len; + char username[CMONGO_USERNAME_SIZE]; + size_t password_len; + char password[CMONGO_PASSWORD_SIZE]; + + size_t app_name_len; + char app_name[CMONGO_APP_NAME_SIZE]; -CMONGO_EXPORT void mongo_set_db_name (const char *name); + size_t uri_len; + char uri[CMONGO_URI_SIZE]; + +} Mongo; + +CMONGO_EXPORT void mongo_set_db_name (const char *db_name); + +CMONGO_EXPORT void mongo_set_host (const char *host); + +CMONGO_EXPORT void mongo_set_port (const unsigned int port); + +CMONGO_EXPORT void mongo_set_username (const char *username); + +CMONGO_EXPORT void mongo_set_password (const char *pswd); -CMONGO_EXPORT void mongo_set_app_name (const char *name); +CMONGO_EXPORT void mongo_set_app_name (const char *app_name); CMONGO_EXPORT void mongo_set_uri (const char *uri); -// generates a new uri string with the set values (username, password, host, port & db name) +// generates a new uri string with the set values +// (username, password, host, port & db name) // that can be used to set as the uri for a new connection -// returns the newly uri string (that should be freed) on success -// returns NULL on error -CMONGO_EXPORT char *mongo_uri_generate (void); +// returns 0 on success 1 on error +CMONGO_EXPORT unsigned int mongo_uri_generate (void); // pings the db to test for a success connection // returns 0 on success, 1 on error diff --git a/src/cmongo/mongo.c b/src/cmongo/mongo.c index 68e3972..c0dfceb 100644 --- a/src/cmongo/mongo.c +++ b/src/cmongo/mongo.c @@ -9,105 +9,111 @@ #include "cmongo/mongo.h" -static MongoStatus status = MONGO_STATUS_DISCONNECTED; +static Mongo mongo = { 0 }; -MongoStatus mongo_get_status (void) { return status; } +MongoStatus mongo_get_status (void) { return mongo.status; } -static mongoc_uri_t *uri = NULL; -mongoc_client_t *client = NULL; -static mongoc_database_t *database = NULL; +void mongo_set_db_name (const char *db_name) { -static char *host = NULL; + if (db_name) { + (void) strncpy (mongo.db_name, db_name, CMONGO_DB_NAME_SIZE - 1); + mongo.db_name_len = strlen (mongo.db_name); + } -void mongo_set_host (const char *h) { +} + +void mongo_set_host (const char *host) { - if (h) host = strdup (h); + if (host) { + (void) strncpy (mongo.host, host, CMONGO_HOST_SIZE - 1); + mongo.host_len = strlen (mongo.host); + } } -static char *port = NULL; - -void mongo_set_port (const char *p) { +void mongo_set_port (const unsigned int port) { - if (p) port = strdup (p); + mongo.port = port; } -static char *username = NULL; - -void mongo_set_username (const char *u) { +void mongo_set_username (const char *username) { - if (u) username = strdup (u); + if (username) { + (void) strncpy (mongo.username, username, CMONGO_USERNAME_SIZE - 1); + mongo.username_len = strlen (mongo.username); + } } -static char *password = NULL; - void mongo_set_password (const char *pswd) { - if (pswd) password = strdup (pswd); + if (pswd) { + (void) strncpy (mongo.password, pswd, CMONGO_PASSWORD_SIZE - 1); + mongo.password_len = strlen (mongo.password); + } } -char *db_name = NULL; - -void mongo_set_db_name (const char *name) { - - if (name) db_name = strdup (name); - -} - -static char *app_name = NULL; +void mongo_set_app_name (const char *app_name) { -void mongo_set_app_name (const char *name) { - - if (name) app_name = strdup (name); + if (app_name) { + (void) strncpy (mongo.app_name, app_name, CMONGO_APP_NAME_SIZE - 1); + mongo.app_name_len = strlen (mongo.app_name); + } } -static char *uri_string = NULL; - void mongo_set_uri (const char *uri) { - if (uri) uri_string = strdup (uri); + if (uri) { + (void) strncpy (mongo.uri, uri, CMONGO_URI_SIZE - 1); + mongo.uri_len = strlen (mongo.uri); + } } -// generates a new uri string with the set values (username, password, host, port & db name) +// generates a new uri string with the set values +// (username, password, host, port & db name) // that can be used to set as the uri for a new connection -// returns the newly uri string (that should be freed) on success, NULL on error -char *mongo_uri_generate (void) { +// returns 0 on success 1 on error +unsigned int mongo_uri_generate (void) { - char *retval = NULL; + unsigned int retval = 1; - if (host && port && db_name) { - char buffer[512] = { 0 }; - if (username && password) { + if ( + mongo.host_len + && mongo.port + && mongo.db_name_len + ) { + if (mongo.username_len && mongo.password_len) { (void) snprintf ( - buffer, 512, - "mongodb://%s:%s@%s:%s/%s", - username, password, - host, port, - db_name + mongo.uri, CMONGO_URI_SIZE - 1, + "mongodb://%s:%s@%s:%u/%s", + mongo.username, mongo.password, + mongo.host, mongo.port, + mongo.db_name ); } else { (void) snprintf ( - buffer, 512, + mongo.uri, CMONGO_URI_SIZE - 1, "mongodb://%s:%s/%s", - host, port, - db_name + mongo.host, mongo.port, + mongo.db_name ); } - - retval = strdup (buffer); } return retval; } +static mongoc_uri_t *uri = NULL; +mongoc_client_t *client = NULL; +static mongoc_database_t *database = NULL; + // pings the db to test for a success connection // Possible connection problems -- failed to authenticate to the db // returns 0 on success, 1 on error From 992c7f36a1a81a34054b0258c73ac5d53446b6f1 Mon Sep 17 00:00:00 2001 From: ermiry Date: Tue, 2 Mar 2021 10:59:03 -0600 Subject: [PATCH 23/75] Updated main methods to use new structure Also added a mongo clients pool to handle multi-threaded workflows --- include/cmongo/mongo.h | 10 ++- src/cmongo/mongo.c | 199 ++++++++++++++++++++--------------------- 2 files changed, 102 insertions(+), 107 deletions(-) diff --git a/include/cmongo/mongo.h b/include/cmongo/mongo.h index 4aed516..4baf2b3 100644 --- a/include/cmongo/mongo.h +++ b/include/cmongo/mongo.h @@ -49,6 +49,8 @@ typedef struct Mongo { size_t uri_len; char uri[CMONGO_URI_SIZE]; + mongoc_client_pool_t *pool; + } Mongo; CMONGO_EXPORT void mongo_set_db_name (const char *db_name); @@ -71,12 +73,12 @@ CMONGO_EXPORT void mongo_set_uri (const char *uri); // returns 0 on success 1 on error CMONGO_EXPORT unsigned int mongo_uri_generate (void); +// connect to the mongo db with db name +CMONGO_EXPORT unsigned int mongo_connect (void); + // pings the db to test for a success connection // returns 0 on success, 1 on error -CMONGO_EXPORT int mongo_ping_db (void); - -// connect to the mongo db with db name -CMONGO_EXPORT int mongo_connect (void); +CMONGO_EXPORT unsigned int mongo_ping_db (void); // disconnects from the db CMONGO_EXPORT void mongo_disconnect (void); diff --git a/src/cmongo/mongo.c b/src/cmongo/mongo.c index c0dfceb..96c86db 100644 --- a/src/cmongo/mongo.c +++ b/src/cmongo/mongo.c @@ -23,36 +23,36 @@ void mongo_set_db_name (const char *db_name) { } void mongo_set_host (const char *host) { - + if (host) { (void) strncpy (mongo.host, host, CMONGO_HOST_SIZE - 1); mongo.host_len = strlen (mongo.host); } - + } void mongo_set_port (const unsigned int port) { - + mongo.port = port; - + } void mongo_set_username (const char *username) { - + if (username) { (void) strncpy (mongo.username, username, CMONGO_USERNAME_SIZE - 1); mongo.username_len = strlen (mongo.username); } - + } void mongo_set_password (const char *pswd) { - + if (pswd) { (void) strncpy (mongo.password, pswd, CMONGO_PASSWORD_SIZE - 1); mongo.password_len = strlen (mongo.password); } - + } void mongo_set_app_name (const char *app_name) { @@ -87,22 +87,26 @@ unsigned int mongo_uri_generate (void) { && mongo.db_name_len ) { if (mongo.username_len && mongo.password_len) { - (void) snprintf ( + mongo.uri_len = snprintf ( mongo.uri, CMONGO_URI_SIZE - 1, - "mongodb://%s:%s@%s:%u/%s", - mongo.username, mongo.password, + "mongodb://%s:%s@%s:%u/%s", + mongo.username, mongo.password, mongo.host, mongo.port, mongo.db_name ); + + retval = 0; } else { - (void) snprintf ( + mongo.uri_len = snprintf ( mongo.uri, CMONGO_URI_SIZE - 1, - "mongodb://%s:%s/%s", + "mongodb://%s:%s/%s", mongo.host, mongo.port, mongo.db_name ); + + retval = 0; } } @@ -110,63 +114,25 @@ unsigned int mongo_uri_generate (void) { } -static mongoc_uri_t *uri = NULL; -mongoc_client_t *client = NULL; -static mongoc_database_t *database = NULL; +static unsigned int mongo_connect_internal ( + const mongoc_uri_t *uri +) { -// pings the db to test for a success connection -// Possible connection problems -- failed to authenticate to the db -// returns 0 on success, 1 on error -int mongo_ping_db (void) { - - int retval = 1; - - if (client) { - if (db_name) { - bson_t *command = NULL, reply = { 0 }; - bson_error_t error = { 0 }; - - command = BCON_NEW ("ping", BCON_INT32 (1)); - if (mongoc_client_command_simple ( - client, - db_name, - command, - NULL, - &reply, - &error - )) { - // success - char *str = bson_as_json (&reply, NULL); - if (str) { - (void) fprintf (stdout, "\n%s\n", str); - free (str); - } - - retval = 0; - } + unsigned int retval = 1; - else { - (void) fprintf ( - stderr, "[MONGO][ERROR]: %s\n", error.message - ); - } - } + mongo.pool = mongoc_client_pool_new (uri); + if (mongo.pool) { + mongoc_client_pool_set_error_api (mongo.pool, 2); - else { - (void) fprintf ( - stderr, - "[MONGO][ERROR]: DB name hasn't been set! " - "Use mongo_set_db_name ()\n" + if (mongo.app_name_len) { + mongoc_client_pool_set_appname ( + mongo.pool, mongo.app_name ); } - } - else { - (void) fprintf ( - stderr, - "[MONGO][ERROR]: Not connected to mongo! " - "Call mongo_connect () first\n" - ); + mongo.status = MONGO_STATUS_CONNECTED; + + retval = 0; } return retval; @@ -174,51 +140,44 @@ int mongo_ping_db (void) { } // connect to the mongo db with db name -int mongo_connect (void) { +unsigned int mongo_connect (void) { - int retval = 1; + unsigned int retval = 1; - if (uri_string) { + if (mongo.uri_len) { bson_error_t error = { 0 }; - mongoc_init (); // init mongo internals + mongoc_init (); // init mongo internals // safely create mongo uri object - uri = mongoc_uri_new_with_error (uri_string, &error); - if (uri) { - // create a new client instance - client = mongoc_client_new_from_uri (uri); - if (client) { - // register the app name -> for logging info - mongoc_client_set_appname (client, app_name); - - status = MONGO_STATUS_CONNECTED; + mongoc_uri_t *uri = mongoc_uri_new_with_error ( + mongo.uri, &error + ); - retval = 0; - } + if (uri) { + retval = mongo_connect_internal (uri); - else { - (void) fprintf ( - stderr, "Failed to create a new client instance!\n" - ); - } + mongoc_uri_destroy (uri); } else { (void) fprintf ( stderr, - "failed to parse URI: %s\n" - "error message: %s\n", - uri_string, - error.message + "Failed to parse Mongo URI: %s", + mongo.uri + ); + + (void) fprintf ( + stderr, "Error: %s\n\n", error.message ); } } else { (void) fprintf ( - stderr, "Not uri string! " - "Call mongo_set_uri () before attemting a connection\n" + stderr, + "Not uri string! " + "Call mongo_set_uri () before attempting a connection\n" ); } @@ -226,24 +185,58 @@ int mongo_connect (void) { } +// pings the db to test for a success connection +// returns 0 on success, 1 on error +unsigned int mongo_ping_db (void) { + + unsigned int retval = 1; + + if (mongo.status == MONGO_STATUS_CONNECTED) { + bson_t *command = NULL, reply = { 0 }; + bson_error_t error = { 0 }; + + // get a client from the pool + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + + command = BCON_NEW ("ping", BCON_INT32 (1)); + + if (mongoc_client_command_simple ( + client, + mongo.db_name, + command, + NULL, + &reply, + &error + )) { + // success + char *str = bson_as_json (&reply, NULL); + if (str) { + (void) fprintf (stdout, "\n%s\n", str); + free (str); + } + + retval = 0; + } + + else { + (void) fprintf ( + stderr, "[MONGO][ERROR]: %s\n", error.message + ); + } + } + + return retval; + +} + // disconnects from the db void mongo_disconnect (void) { - mongoc_database_destroy (database); - mongoc_uri_destroy (uri); - mongoc_client_destroy (client); - - if (host) free (host); - if (port) free (port); - if (username) free (username); - if (password) free (password); - - if (app_name) free (app_name); - if (uri_string) free (uri_string); - if (db_name) free (db_name); + mongoc_client_pool_destroy (mongo.pool); + mongo.pool = NULL; mongoc_cleanup (); - status = MONGO_STATUS_DISCONNECTED; + mongo.status = MONGO_STATUS_DISCONNECTED; } \ No newline at end of file From 3536c6b11ab22571612d71f96c9e1b68c03f74f1 Mon Sep 17 00:00:00 2001 From: ermiry Date: Tue, 2 Mar 2021 12:23:05 -0600 Subject: [PATCH 24/75] Added base dedicated model structure & methods --- include/cmongo/model.h | 39 ++++++++++++++++++++++++++++++++++++++ src/cmongo/model.c | 43 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 include/cmongo/model.h create mode 100644 src/cmongo/model.c diff --git a/include/cmongo/model.h b/include/cmongo/model.h new file mode 100644 index 0000000..949edea --- /dev/null +++ b/include/cmongo/model.h @@ -0,0 +1,39 @@ +#ifndef _CMONGO_MODELS_H_ +#define _CMONGO_MODELS_H_ + +#include + +#include + +#include "cmongo/config.h" + +#define CMONGO_COLLNAME_SIZE 128 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*mongo_parser)(void *model, const bson_t *doc); + +typedef struct CMongoModel { + + size_t collname_len; + char collname[CMONGO_COLLNAME_SIZE]; + + mongo_parser model_parser; + +} CMongoModel; + +CMONGO_PUBLIC CMongoModel *cmongo_model_new (void); + +CMONGO_PUBLIC void cmongo_model_delete (void *model_ptr); + +CMONGO_EXPORT CMongoModel *cmongo_model_create ( + const char *collname +); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/src/cmongo/model.c b/src/cmongo/model.c new file mode 100644 index 0000000..0121913 --- /dev/null +++ b/src/cmongo/model.c @@ -0,0 +1,43 @@ +#include +#include + +#include "cmongo/model.h" + +CMongoModel *cmongo_model_new (void) { + + CMongoModel *model = (CMongoModel *) malloc (sizeof (CMongoModel)); + if (model) { + (void) memset (model, 0, sizeof (CMongoModel)); + } + + return model; + +} + +void cmongo_model_delete (void *model_ptr) { + + if (model_ptr) free (model_ptr); + +} + +CMongoModel *cmongo_model_create (const char *collname) { + + CMongoModel *model = cmongo_model_new (); + if (model && collname) { + (void) strncpy (model->collname, collname, CMONGO_COLLNAME_SIZE - 1); + model->collname_len = strlen (model->collname); + } + + return model; + +} + +void cmongo_model_set_parser ( + CMongoModel *model, const mongo_parser model_parser +) { + + if (model) { + model->model_parser = model_parser; + } + +} \ No newline at end of file From c298af3d03b25a1151793df7ca3c68fd42700a41 Mon Sep 17 00:00:00 2001 From: ermiry Date: Tue, 2 Mar 2021 12:23:32 -0600 Subject: [PATCH 25/75] Made main mongo structure accessible from all sources --- include/cmongo/mongo.h | 2 ++ src/cmongo/mongo.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/cmongo/mongo.h b/include/cmongo/mongo.h index 4baf2b3..6f15d84 100644 --- a/include/cmongo/mongo.h +++ b/include/cmongo/mongo.h @@ -53,6 +53,8 @@ typedef struct Mongo { } Mongo; +CMONGO_PRIVATE Mongo mongo; + CMONGO_EXPORT void mongo_set_db_name (const char *db_name); CMONGO_EXPORT void mongo_set_host (const char *host); diff --git a/src/cmongo/mongo.c b/src/cmongo/mongo.c index 96c86db..1e6ecec 100644 --- a/src/cmongo/mongo.c +++ b/src/cmongo/mongo.c @@ -9,7 +9,7 @@ #include "cmongo/mongo.h" -static Mongo mongo = { 0 }; +Mongo mongo = { 0 }; MongoStatus mongo_get_status (void) { return mongo.status; } @@ -101,7 +101,7 @@ unsigned int mongo_uri_generate (void) { else { mongo.uri_len = snprintf ( mongo.uri, CMONGO_URI_SIZE - 1, - "mongodb://%s:%s/%s", + "mongodb://%s:%u/%s", mongo.host, mongo.port, mongo.db_name ); From 4947bcfa59b6dd1a9705e7d0208a6d03808623a4 Mon Sep 17 00:00:00 2001 From: ermiry Date: Tue, 2 Mar 2021 12:24:26 -0600 Subject: [PATCH 26/75] Updated mongo find all methods to use model Also using client pool methods to be thread safe --- include/cmongo/crud.h | 15 ++-- src/cmongo/crud.c | 202 ++++++++++++++++++++++++++++++------------ 2 files changed, 151 insertions(+), 66 deletions(-) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index 4aeacd0..81bed7d 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -1,25 +1,24 @@ #ifndef _CMONGO_CRUD_H_ #define _CMONGO_CRUD_H_ -#include #include +#include +#include "cmongo/model.h" #include "cmongo/select.h" #ifdef __cplusplus extern "C" { #endif -typedef void (*mongo_parser)(void *model, const bson_t *doc); - // counts the docs in a collection by a matching query CMONGO_EXPORT int64_t mongo_count_docs ( - mongoc_collection_t *collection, bson_t *query + const CMongoModel *model, bson_t *query ); // returns true if 1 or more documents matches the query, false if no matches CMONGO_EXPORT bool mongo_check ( - mongoc_collection_t *collection, bson_t *query + const CMongoModel *model, bson_t *query ); // generates an opts doc that can be used to better work with find methods @@ -34,7 +33,7 @@ CMONGO_EXPORT bson_t *mongo_find_generate_opts ( // returns a cursor (should be destroyed) that can be used to traverse the matching documents // query gets destroyed, select list remains the same CMONGO_EXPORT mongoc_cursor_t *mongo_find_all_cursor ( - mongoc_collection_t *collection, + const CMongoModel *model, bson_t *query, const CMongoSelect *select, uint64_t *n_docs ); @@ -42,14 +41,14 @@ CMONGO_EXPORT mongoc_cursor_t *mongo_find_all_cursor ( // uses a query to find all matching docs with the specified options // query gets destroyed, options remain the same CMONGO_EXPORT mongoc_cursor_t *mongo_find_all_cursor_with_opts ( - mongoc_collection_t *collection, + const CMongoModel *model, bson_t *query, const bson_t *opts ); // use a query to find all matching documents // an empty query will return all the docs in a collection CMONGO_EXPORT const bson_t **mongo_find_all ( - mongoc_collection_t *collection, + const CMongoModel *model, bson_t *query, const CMongoSelect *select, uint64_t *n_docs ); diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index b27a0d0..f03b479 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -2,10 +2,12 @@ #include #include -#include #include +#include #include "cmongo/crud.h" +#include "cmongo/model.h" +#include "cmongo/mongo.h" #include "cmongo/select.h" #ifdef __cplusplus @@ -15,23 +17,36 @@ // counts the docs in a collection by a matching query int64_t mongo_count_docs ( - mongoc_collection_t *collection, bson_t *query + const CMongoModel *model, bson_t *query ) { int64_t retval = 0; - if (collection && query) { - bson_error_t error = { 0 }; - retval = mongoc_collection_count_documents ( - collection, query, NULL, NULL, NULL, &error - ); - - if (retval < 0) { - (void) fprintf ( - stderr, "[MONGO][ERROR]: %s", error.message + if (model && query) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname ); - retval = 0; + if (collection) { + bson_error_t error = { 0 }; + retval = mongoc_collection_count_documents ( + collection, query, NULL, NULL, NULL, &error + ); + + if (retval < 0) { + (void) fprintf ( + stderr, "[MONGO][ERROR]: %s", error.message + ); + + retval = 0; + } + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); } bson_destroy (query); @@ -44,16 +59,30 @@ int64_t mongo_count_docs ( // returns true if 1 or more documents matches the query // returns false if no matches bool mongo_check ( - mongoc_collection_t *collection, bson_t *query + const CMongoModel *model, bson_t *query ) { bool retval = false; - if (collection && query) { - bson_error_t error = { 0 }; - retval = mongoc_collection_count_documents ( - collection, query, NULL, NULL, NULL, &error - ); + if (model && query) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + bson_error_t error = { 0 }; + + retval = mongoc_collection_count_documents ( + collection, query, NULL, NULL, NULL, &error + ); + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } bson_destroy (query); } @@ -101,7 +130,7 @@ bson_t *mongo_find_generate_opts ( // returns a cursor (should be destroyed) that can be used to traverse the matching documents // query gets destroyed, select list remains the same mongoc_cursor_t *mongo_find_all_cursor ( - mongoc_collection_t *collection, + const CMongoModel *model, bson_t *query, const CMongoSelect *select, uint64_t *n_docs ) { @@ -109,19 +138,32 @@ mongoc_cursor_t *mongo_find_all_cursor ( mongoc_cursor_t *cursor = NULL; *n_docs = 0; - if (collection && query) { - uint64_t count = mongo_count_docs (collection, bson_copy (query)); - if (count > 0) { - bson_t *opts = mongo_find_generate_opts (select); - - cursor = mongoc_collection_find_with_opts ( - collection, query, opts, NULL + if (model && query) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname ); - *n_docs = count; + if (collection) { + uint64_t count = mongo_count_docs (collection, bson_copy (query)); + if (count > 0) { + bson_t *opts = mongo_find_generate_opts (select); + + cursor = mongoc_collection_find_with_opts ( + collection, query, opts, NULL + ); + + *n_docs = count; - if (opts) bson_destroy (opts); - bson_destroy (query); + if (opts) bson_destroy (opts); + bson_destroy (query); + } + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); } } @@ -132,16 +174,29 @@ mongoc_cursor_t *mongo_find_all_cursor ( // uses a query to find all matching docs with the specified options // query gets destroyed, options remain the same mongoc_cursor_t *mongo_find_all_cursor_with_opts ( - mongoc_collection_t *collection, + const CMongoModel *model, bson_t *query, const bson_t *opts ) { mongoc_cursor_t *cursor = NULL; - if (collection && query) { - cursor = mongoc_collection_find_with_opts ( - collection, query, opts, NULL - ); + if (model && query) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + cursor = mongoc_collection_find_with_opts ( + collection, query, opts, NULL + ); + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } bson_destroy (query); } @@ -150,45 +205,76 @@ mongoc_cursor_t *mongo_find_all_cursor_with_opts ( } -// use a query to find all matching documents -// an empty query will return all the docs in a collection -const bson_t **mongo_find_all ( +const bson_t **mongo_find_all_internal ( mongoc_collection_t *collection, bson_t *query, const CMongoSelect *select, uint64_t *n_docs ) { const bson_t **retval = NULL; - *n_docs = 0; - if (collection && query) { - uint64_t count = mongo_count_docs (collection, bson_copy (query)); - if (count > 0) { - retval = (const bson_t **) calloc (count, sizeof (bson_t *)); - for (uint64_t i = 0; i < count; i++) retval[i] = bson_new (); + uint64_t count = mongo_count_docs (collection, bson_copy (query)); + if (count > 0) { + retval = (const bson_t **) calloc (count, sizeof (bson_t *)); + for (uint64_t i = 0; i < count; i++) retval[i] = bson_new (); - bson_t *opts = mongo_find_generate_opts (select); + bson_t *opts = mongo_find_generate_opts (select); - mongoc_cursor_t *cursor = mongoc_collection_find_with_opts ( - collection, query, opts, NULL - ); + mongoc_cursor_t *cursor = mongoc_collection_find_with_opts ( + collection, query, opts, NULL + ); - uint64_t i = 0; - const bson_t *doc = NULL; - while (mongoc_cursor_next (cursor, &doc)) { - // add the matching doc into our retval array - bson_copy_to (doc, (bson_t *) retval[i]); - i++; - } + uint64_t i = 0; + const bson_t *doc = NULL; + while (mongoc_cursor_next (cursor, &doc)) { + // add the matching doc into our retval array + bson_copy_to (doc, (bson_t *) retval[i]); + i++; + } - *n_docs = count; + *n_docs = count; - mongoc_cursor_destroy (cursor); + mongoc_cursor_destroy (cursor); - if (opts) bson_destroy (opts); + if (opts) bson_destroy (opts); + } + + return retval; - bson_destroy (query); +} + +// use a query to find all matching documents +// an empty query will return all the docs in a collection +const bson_t **mongo_find_all ( + const CMongoModel *model, + bson_t *query, const CMongoSelect *select, + uint64_t *n_docs +) { + + const bson_t **retval = NULL; + *n_docs = 0; + + if (model && query) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + retval = mongo_find_all_internal ( + collection, + query, select, + n_docs + ); + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); } + + bson_destroy (query); } return retval; From af644b9d61d751375bd4fc5beaa7300bcebf158e Mon Sep 17 00:00:00 2001 From: ermiry Date: Tue, 2 Mar 2021 12:24:58 -0600 Subject: [PATCH 27/75] Refactored update & delete methods to be thread safe Also updated methods to use new model structure --- include/cmongo/crud.h | 24 +++--- src/cmongo/crud.c | 174 ++++++++++++++++++++++++++++++------------ 2 files changed, 138 insertions(+), 60 deletions(-) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index 81bed7d..2a741c3 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -81,46 +81,46 @@ CMONGO_EXPORT unsigned int mongo_find_one ( // inserts a document into a collection // destroys document // returns 0 on success, 1 on error -CMONGO_EXPORT int mongo_insert_one ( - mongoc_collection_t *collection, bson_t *doc +CMONGO_EXPORT unsigned int mongo_insert_one ( + const CMongoModel *model, bson_t *doc ); // inserts many documents into a collection // docs are NOT deleted after the operation // returns 0 on success, 1 on error -CMONGO_EXPORT int mongo_insert_many ( - mongoc_collection_t *collection, +CMONGO_EXPORT unsigned int mongo_insert_many ( + const CMongoModel *model, const bson_t **docs, size_t n_docs ); // updates a doc by a matching query with the new values // destroys query and update documents // returns 0 on success, 1 on error -CMONGO_EXPORT int mongo_update_one ( - mongoc_collection_t *collection, +CMONGO_EXPORT unsigned int mongo_update_one ( + const CMongoModel *model, bson_t *query, bson_t *update ); // updates all the query matching documents // destroys the query and the update documents // returns 0 on success, 1 on error -CMONGO_EXPORT int mongo_update_many ( - mongoc_collection_t *collection, +CMONGO_EXPORT unsigned int mongo_update_many ( + const CMongoModel *model, bson_t *query, bson_t *update ); // deletes one matching document by a query // destroys the query document // returns 0 on success, 1 on error -CMONGO_EXPORT int mongo_delete_one ( - mongoc_collection_t *collection, bson_t *query +CMONGO_EXPORT unsigned int mongo_delete_one ( + const CMongoModel *model, bson_t *query ); // deletes all the query matching documents // destroys the query // returns 0 on success, 1 on error -CMONGO_EXPORT int mongo_delete_many ( - mongoc_collection_t *collection, bson_t *query +CMONGO_EXPORT unsigned int mongo_delete_many ( + const CMongoModel *model, bson_t *query ); #ifdef __cplusplus diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index f03b479..5ffb710 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -382,18 +382,31 @@ unsigned int mongo_find_one ( // inserts a document into a collection // destroys document // returns 0 on success, 1 on error -int mongo_insert_one ( - mongoc_collection_t *collection, bson_t *doc +unsigned int mongo_insert_one ( + const CMongoModel *model, bson_t *doc ) { - int retval = 1; + unsigned int retval = 1; - if (collection && doc) { - bson_error_t error = { 0 }; + if (model && doc) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); - retval = mongoc_collection_insert_one ( - collection, doc, NULL, NULL, &error - ) ? 0 : 1; + if (collection) { + bson_error_t error = { 0 }; + + retval = mongoc_collection_insert_one ( + collection, doc, NULL, NULL, &error + ) ? 0 : 1; + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } bson_destroy (doc); } @@ -405,19 +418,32 @@ int mongo_insert_one ( // inserts many documents into a collection // docs are NOT deleted after the operation // returns 0 on success, 1 on error -int mongo_insert_many ( - mongoc_collection_t *collection, +unsigned int mongo_insert_many ( + const CMongoModel *model, const bson_t **docs, size_t n_docs ) { - int retval = 1; + unsigned int retval = 1; - if (collection && docs) { - bson_error_t error = { 0 }; + if (model && docs) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); - retval = mongoc_collection_insert_many ( - collection, docs, n_docs, NULL, NULL, &error - ) ? 0 : 1; + if (collection) { + bson_error_t error = { 0 }; + + retval = mongoc_collection_insert_many ( + collection, docs, n_docs, NULL, NULL, &error + ) ? 0 : 1; + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } } return retval; @@ -428,19 +454,32 @@ int mongo_insert_many ( // updates a doc by a matching query with the new values // destroys query and update documents // returns 0 on success, 1 on error -int mongo_update_one ( - mongoc_collection_t *collection, +unsigned int mongo_update_one ( + const CMongoModel *model, bson_t *query, bson_t *update ) { - int retval = 1; + unsigned int retval = 1; + + if (model && query && update) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + bson_error_t error = { 0 }; + + retval = mongoc_collection_update_one ( + collection, query, update, NULL, NULL, &error + ) ? 0 : 1; - if (collection && query && update) { - bson_error_t error = { 0 }; + mongoc_collection_destroy (collection); + } - retval = mongoc_collection_update_one ( - collection, query, update, NULL, NULL, &error - ) ? 0 : 1; + mongoc_client_pool_push (mongo.pool, client); + } bson_destroy (query); bson_destroy (update); @@ -453,19 +492,32 @@ int mongo_update_one ( // updates all the query matching documents // destroys the query and the update documents // returns 0 on success, 1 on error -int mongo_update_many ( - mongoc_collection_t *collection, +unsigned int mongo_update_many ( + const CMongoModel *model, bson_t *query, bson_t *update ) { - int retval = 0; + unsigned int retval = 0; + + if (model && query && update) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + bson_error_t error = { 0 }; + + retval = mongoc_collection_update_many ( + collection, query, update, NULL, NULL, &error + ) ? 0 : 1; - if (collection && query && update) { - bson_error_t error = { 0 }; + mongoc_collection_destroy (collection); + } - retval = mongoc_collection_update_many ( - collection, query, update, NULL, NULL, &error - ) ? 0 : 1; + mongoc_client_pool_push (mongo.pool, client); + } bson_destroy (query); bson_destroy (update); @@ -478,18 +530,31 @@ int mongo_update_many ( // deletes one matching document by a query // destroys the query document // returns 0 on success, 1 on error -int mongo_delete_one ( - mongoc_collection_t *collection, bson_t *query +unsigned int mongo_delete_one ( + const CMongoModel *model, bson_t *query ) { - int retval = 0; + unsigned int retval = 0; + + if (model && query) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + bson_error_t error = { 0 }; + + retval = mongoc_collection_delete_one ( + collection, query, NULL, NULL, &error + ) ? 0 : 1; - if (collection && query) { - bson_error_t error = { 0 }; + mongoc_collection_destroy (collection); + } - retval = mongoc_collection_delete_one ( - collection, query, NULL, NULL, &error - ) ? 0 : 1; + mongoc_client_pool_push (mongo.pool, client); + } bson_destroy (query); } @@ -501,18 +566,31 @@ int mongo_delete_one ( // deletes all the query matching documents // destroys the query // returns 0 on success, 1 on error -int mongo_delete_many ( - mongoc_collection_t *collection, bson_t *query +unsigned int mongo_delete_many ( + const CMongoModel *model, bson_t *query ) { - int retval = 0; + unsigned int retval = 0; + + if (model && query) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + bson_error_t error = { 0 }; + + retval = mongoc_collection_delete_many ( + collection, query, NULL, NULL, &error + ) ? 0 : 1; - if (collection && query) { - bson_error_t error = { 0 }; + mongoc_collection_destroy (collection); + } - retval = mongoc_collection_delete_many ( - collection, query, NULL, NULL, &error - ) ? 0 : 1; + mongoc_client_pool_push (mongo.pool, client); + } bson_destroy (query); } From 8181d0478d739da81feaad3e5ff9ba3d94faed18 Mon Sep 17 00:00:00 2001 From: ermiry Date: Tue, 2 Mar 2021 12:31:46 -0600 Subject: [PATCH 28/75] Split mongo_count_docs () to be used by other methods --- src/cmongo/crud.c | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 5ffb710..7de2ecd 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -15,6 +15,30 @@ #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif +// counts the docs in a collection by a matching query +static int64_t mongo_count_docs_internal ( + mongoc_collection_t *collection, bson_t *query +) { + + int64_t retval = 0; + + bson_error_t error = { 0 }; + retval = mongoc_collection_count_documents ( + collection, query, NULL, NULL, NULL, &error + ); + + if (retval < 0) { + (void) fprintf ( + stderr, "[MONGO][ERROR]: %s", error.message + ); + + retval = 0; + } + + return retval; + +} + // counts the docs in a collection by a matching query int64_t mongo_count_docs ( const CMongoModel *model, bson_t *query @@ -30,19 +54,10 @@ int64_t mongo_count_docs ( ); if (collection) { - bson_error_t error = { 0 }; - retval = mongoc_collection_count_documents ( - collection, query, NULL, NULL, NULL, &error + retval = mongo_count_docs_internal ( + collection, query ); - if (retval < 0) { - (void) fprintf ( - stderr, "[MONGO][ERROR]: %s", error.message - ); - - retval = 0; - } - mongoc_collection_destroy (collection); } @@ -146,7 +161,10 @@ mongoc_cursor_t *mongo_find_all_cursor ( ); if (collection) { - uint64_t count = mongo_count_docs (collection, bson_copy (query)); + uint64_t count = mongo_count_docs_internal ( + collection, bson_copy (query) + ); + if (count > 0) { bson_t *opts = mongo_find_generate_opts (select); @@ -213,7 +231,7 @@ const bson_t **mongo_find_all_internal ( const bson_t **retval = NULL; - uint64_t count = mongo_count_docs (collection, bson_copy (query)); + uint64_t count = mongo_count_docs_internal (collection, bson_copy (query)); if (count > 0) { retval = (const bson_t **) calloc (count, sizeof (bson_t *)); for (uint64_t i = 0; i < count; i++) retval[i] = bson_new (); From efc10dd3f24daae833ab616d553b3eb578e04c28 Mon Sep 17 00:00:00 2001 From: ermiry Date: Tue, 2 Mar 2021 12:37:58 -0600 Subject: [PATCH 29/75] Updated find one methods to use new model structure --- include/cmongo/crud.h | 8 +++--- src/cmongo/crud.c | 66 ++++++++++++++++++++++++++++++------------- 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index 2a741c3..2ffbacc 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -62,9 +62,9 @@ CMONGO_EXPORT void mongo_find_all_destroy_docs ( // query gets destroyed, opts are kept the same // returns 0 on success, 1 on error CMONGO_EXPORT unsigned int mongo_find_one_with_opts ( - mongoc_collection_t *collection, + const CMongoModel *model, bson_t *query, const bson_t *opts, - void *model, const mongo_parser model_parser + void *output ); // uses a query to find one doc @@ -73,9 +73,9 @@ CMONGO_EXPORT unsigned int mongo_find_one_with_opts ( // query gets destroyed, select structure remains the same // returns 0 on success, 1 on error CMONGO_EXPORT unsigned int mongo_find_one ( - mongoc_collection_t *collection, + const CMongoModel *model, bson_t *query, const CMongoSelect *select, - void *model, const mongo_parser model_parser + void *output ); // inserts a document into a collection diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 7de2ecd..e2ca86c 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -316,7 +316,7 @@ void mongo_find_all_destroy_docs ( static unsigned int mongo_find_one_internal ( mongoc_collection_t *collection, bson_t *query, const bson_t *opts, - void *model, const mongo_parser model_parser + void *output, const mongo_parser model_parser ) { unsigned int retval = 1; @@ -330,7 +330,7 @@ static unsigned int mongo_find_one_internal ( const bson_t *doc = NULL; if (mongoc_cursor_next (cursor, &doc)) { - model_parser (model, doc); + model_parser (output, doc); retval = 0; } @@ -345,19 +345,32 @@ static unsigned int mongo_find_one_internal ( // query gets destroyed, opts are kept the same // returns 0 on success, 1 on error unsigned int mongo_find_one_with_opts ( - mongoc_collection_t *collection, + const CMongoModel *model, bson_t *query, const bson_t *opts, - void *model, const mongo_parser model_parser + void *output ) { unsigned int retval = 1; - if (collection && query && model && model_parser) { - retval = mongo_find_one_internal ( - collection, - query, opts, - model, model_parser - ); + if (model && query && output) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + retval = mongo_find_one_internal ( + collection, + query, opts, + output, model->model_parser + ); + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } bson_destroy (query); } @@ -372,23 +385,36 @@ unsigned int mongo_find_one_with_opts ( // query gets destroyed, select structure remains the same // returns 0 on success, 1 on error unsigned int mongo_find_one ( - mongoc_collection_t *collection, + const CMongoModel *model, bson_t *query, const CMongoSelect *select, - void *model, const mongo_parser model_parser + void *output ) { unsigned int retval = 1; - if (collection && query && model && model_parser) { - bson_t *opts = mongo_find_generate_opts (select); + if (model && query && output) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); - retval = mongo_find_one_internal ( - collection, - query, opts, - model, model_parser - ); + if (collection) { + bson_t *opts = mongo_find_generate_opts (select); - if (opts) bson_destroy (opts); + retval = mongo_find_one_internal ( + collection, + query, opts, + output, model->model_parser + ); + + if (opts) bson_destroy (opts); + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } bson_destroy (query); } From 9f8cdd14dc2af622bf159c1ac8207225f14a501d Mon Sep 17 00:00:00 2001 From: ermiry Date: Tue, 2 Mar 2021 12:38:33 -0600 Subject: [PATCH 30/75] Removed mongo_collection_get () wrapper method --- include/cmongo/collections.h | 5 ----- src/cmongo/collections.c | 7 ------- 2 files changed, 12 deletions(-) diff --git a/include/cmongo/collections.h b/include/cmongo/collections.h index dd4fa60..0e88397 100644 --- a/include/cmongo/collections.h +++ b/include/cmongo/collections.h @@ -9,11 +9,6 @@ extern "C" { #endif -// opens handle to a mongo collection in the db -CMONGO_EXPORT mongoc_collection_t *mongo_collection_get ( - const char *coll_name -); - // drops a collection deleting all of its data // retuns 0 on success, 1 on error CMONGO_EXPORT int mongo_collection_drop ( diff --git a/src/cmongo/collections.c b/src/cmongo/collections.c index b302cdc..404b994 100644 --- a/src/cmongo/collections.c +++ b/src/cmongo/collections.c @@ -5,13 +5,6 @@ #include "cmongo/mongo.h" -// opens handle to a mongo collection in the db -mongoc_collection_t *mongo_collection_get (const char *coll_name) { - - return mongoc_client_get_collection (client, db_name, coll_name); - -} - // drops a collection deleting all of its data // retuns 0 on success, 1 on error int mongo_collection_drop (mongoc_collection_t *collection) { From e5347f2946876d273687ec2d2fe9867818caf657 Mon Sep 17 00:00:00 2001 From: ermiry Date: Tue, 2 Mar 2021 14:13:10 -0600 Subject: [PATCH 31/75] Added missing cmongo_model_set_parser () export --- include/cmongo/model.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/cmongo/model.h b/include/cmongo/model.h index 949edea..aaeea7c 100644 --- a/include/cmongo/model.h +++ b/include/cmongo/model.h @@ -32,6 +32,10 @@ CMONGO_EXPORT CMongoModel *cmongo_model_create ( const char *collname ); +CMONGO_EXPORT void cmongo_model_set_parser ( + CMongoModel *model, const mongo_parser model_parser +); + #ifdef __cplusplus } #endif From 44a2e4853674bab1b01eee075e18ade21887e958 Mon Sep 17 00:00:00 2001 From: ermiry Date: Tue, 2 Mar 2021 14:15:00 -0600 Subject: [PATCH 32/75] Added base client pools example --- examples/pool.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 examples/pool.c diff --git a/examples/pool.c b/examples/pool.c new file mode 100644 index 0000000..66ed23b --- /dev/null +++ b/examples/pool.c @@ -0,0 +1,99 @@ +#include + +#include + +#include + +static pthread_mutex_t mutex; +static bool in_shutdown = false; + +static void *worker (void *data) { + + mongoc_client_pool_t *pool = data; + mongoc_client_t *client; + bson_t ping = BSON_INITIALIZER; + bson_error_t error; + bool r; + + BSON_APPEND_INT32 (&ping, "ping", 1); + + while (true) { + client = mongoc_client_pool_pop (pool); + + r = mongoc_client_command_simple ( + client, "admin", &ping, NULL, NULL, &error + ); + + if (!r) { + fprintf (stderr, "%s\n", error.message); + } + + mongoc_client_pool_push (pool, client); + + pthread_mutex_lock (&mutex); + if (in_shutdown || !r) { + pthread_mutex_unlock (&mutex); + break; + } + + pthread_mutex_unlock (&mutex); + } + + bson_destroy (&ping); + return NULL; + +} + +int main (int argc, char **argv) { + + const char *uri_string = "mongodb://127.0.0.1/?appname=pool-example"; + mongoc_uri_t *uri; + bson_error_t error; + mongoc_client_pool_t *pool; + pthread_t threads[10]; + unsigned i; + void *ret; + + pthread_mutex_init (&mutex, NULL); + mongoc_init (); + + if (argc > 1) { + uri_string = argv[1]; + } + + uri = mongoc_uri_new_with_error (uri_string, &error); + if (!uri) { + fprintf (stderr, + "failed to parse URI: %s\n" + "error message: %s\n", + uri_string, + error.message + ); + + return EXIT_FAILURE; + } + + pool = mongoc_client_pool_new (uri); + mongoc_client_pool_set_error_api (pool, 2); + + for (i = 0; i < 10; i++) { + pthread_create (&threads[i], NULL, worker, pool); + } + + sleep (10); + pthread_mutex_lock (&mutex); + in_shutdown = true; + pthread_mutex_unlock (&mutex); + + for (i = 0; i < 10; i++) { + pthread_join (threads[i], &ret); + } + + mongoc_client_pool_destroy (pool); + mongoc_uri_destroy (uri); + + mongoc_cleanup (); + + return EXIT_SUCCESS; + +} \ No newline at end of file From 08db54ec46b71db0cadaa672599742b4260245e6 Mon Sep 17 00:00:00 2001 From: ermiry Date: Tue, 2 Mar 2021 14:15:48 -0600 Subject: [PATCH 33/75] Updated version to beta 1.0b-2 --- CHANGELOG.md | 19 +++++-------------- include/cmongo/version.h | 8 ++++---- version.txt | 2 +- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9283ecc..3ecc50b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,5 @@ -## General -- Refactored mongo select to use a static array instead of a list -- Updated includes to use cmongo export qualifiers -- Refactored makefile to compile tests and handle coverage -- Added base codecov configuration -- Added dedicated version file -- Added version match check test -- Added dedicated script to run tests -- Added workflows to create beta & production releases - -## Tests -- Added test header with check macro definitions -- Added base cmongo select unit tests -- Added dedicated script to run tests \ No newline at end of file +- Added custom mongo structure to hold values +- Added base dedicated model structure & methods +- Updated CRUD methods to be thread safe +- Split mongo_count_docs () to be used by other methods +- Removed mongo_collection_get () wrapper method \ No newline at end of file diff --git a/include/cmongo/version.h b/include/cmongo/version.h index 793b84f..447de53 100644 --- a/include/cmongo/version.h +++ b/include/cmongo/version.h @@ -3,10 +3,10 @@ #include "cmongo/config.h" -#define CMONGO_VERSION "1.0b-1" -#define CMONGO_VERSION_NAME "Beta 1.0b-1" -#define CMONGO_VERSION_DATE "14/01/2021" -#define CMONGO_VERSION_TIME "11:56 CST" +#define CMONGO_VERSION "1.0b-2" +#define CMONGO_VERSION_NAME "Beta 1.0b-2" +#define CMONGO_VERSION_DATE "02/03/2021" +#define CMONGO_VERSION_TIME "14:15 CST" #define CMONGO_VERSION_AUTHOR "Erick Salas" #ifdef __cplusplus diff --git a/version.txt b/version.txt index 2100241..14689fc 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0b-1 \ No newline at end of file +1.0b-2 \ No newline at end of file From 175579b8e3f3b59f00d7133e99eb2371fe8c54fe Mon Sep 17 00:00:00 2001 From: ermiry Date: Mon, 15 Mar 2021 10:43:07 -0600 Subject: [PATCH 34/75] Added missing mongo_get_status () export --- include/cmongo/mongo.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/cmongo/mongo.h b/include/cmongo/mongo.h index 6f15d84..78ae75d 100644 --- a/include/cmongo/mongo.h +++ b/include/cmongo/mongo.h @@ -55,6 +55,8 @@ typedef struct Mongo { CMONGO_PRIVATE Mongo mongo; +CMONGO_EXPORT MongoStatus mongo_get_status (void); + CMONGO_EXPORT void mongo_set_db_name (const char *db_name); CMONGO_EXPORT void mongo_set_host (const char *host); From acf8be7292f21c3f7bf9b34d9bab8585a1f8abb0 Mon Sep 17 00:00:00 2001 From: ermiry Date: Mon, 15 Mar 2021 10:43:33 -0600 Subject: [PATCH 35/75] Added buffer size definition in types header --- include/cmongo/types.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/cmongo/types.h b/include/cmongo/types.h index 9396094..52b020d 100644 --- a/include/cmongo/types.h +++ b/include/cmongo/types.h @@ -5,6 +5,8 @@ #include "cmongo/config.h" +#define BSON_ARRAY_BUFFER_SIZE 16 + #ifdef __cplusplus extern "C" { #endif From 74fd2aaa4648d7b55675a4b15b8fc414af8a5601 Mon Sep 17 00:00:00 2001 From: ermiry Date: Mon, 15 Mar 2021 10:44:17 -0600 Subject: [PATCH 36/75] Added find methods that return result as json --- include/cmongo/crud.h | 21 +++++++ src/cmongo/crud.c | 134 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index 2ffbacc..aec5e90 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -6,6 +6,7 @@ #include "cmongo/model.h" #include "cmongo/select.h" +#include "cmongo/types.h" #ifdef __cplusplus extern "C" { @@ -45,6 +46,16 @@ CMONGO_EXPORT mongoc_cursor_t *mongo_find_all_cursor_with_opts ( bson_t *query, const bson_t *opts ); +// returns a new string in relaxed extended JSON format +// with all matching objects inside an array +// query gets destroyed, opts are kept the same +// returns 0 on success, 1 on error +CMONGO_EXPORT char *mongo_find_all_cursor_with_opts_to_json ( + const CMongoModel *model, + bson_t *query, const bson_t *opts, + const char *array_name, size_t *json_len +); + // use a query to find all matching documents // an empty query will return all the docs in a collection CMONGO_EXPORT const bson_t **mongo_find_all ( @@ -67,6 +78,16 @@ CMONGO_EXPORT unsigned int mongo_find_one_with_opts ( void *output ); +// works like mongo_find_one_with_opts () +// creates a new string with the result in relaxed extended JSON format +// query gets destroyed, opts are kept the same +// returns 0 on success, 1 on error +CMONGO_EXPORT unsigned int mongo_find_one_with_opts_to_json ( + const CMongoModel *model, + bson_t *query, const bson_t *opts, + char **json, size_t *json_len +); + // uses a query to find one doc // select is a dlist of strings used for document projection, // _id is true by default and should not be incldued diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index e2ca86c..660e749 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -9,6 +9,7 @@ #include "cmongo/model.h" #include "cmongo/mongo.h" #include "cmongo/select.h" +#include "cmongo/types.h" #ifdef __cplusplus #pragma GCC diagnostic push @@ -223,6 +224,72 @@ mongoc_cursor_t *mongo_find_all_cursor_with_opts ( } +static char *mongo_find_all_cursor_with_opts_to_json_internal ( + mongoc_cursor_t *cursor, + const char *array_name, size_t *json_len +) { + + char *json = NULL; + + bson_t *doc = bson_new (); + if (doc) { + char buf[BSON_ARRAY_BUFFER_SIZE] = { 0 }; + const char *key = NULL; + size_t keylen = 0; + + bson_t json_array = BSON_INITIALIZER; + (void) bson_append_array_begin (doc, array_name, (int) strlen (array_name), &json_array); + + int i = 0; + const bson_t *object_doc = NULL; + while (mongoc_cursor_next (cursor, &object_doc)) { + keylen = bson_uint32_to_string (i, &key, buf, BSON_ARRAY_BUFFER_SIZE); + (void) bson_append_document (&json_array, key, (int) keylen, object_doc); + + bson_destroy ((bson_t *) object_doc); + + i++; + } + + (void) bson_append_array_end (doc, &json_array); + + json = bson_as_relaxed_extended_json (doc, json_len); + } + + return json; + +} + +// returns a new string in relaxed extended JSON format +// with all matching objects inside an array +// query gets destroyed, opts are kept the same +// returns 0 on success, 1 on error +char *mongo_find_all_cursor_with_opts_to_json ( + const CMongoModel *model, + bson_t *query, const bson_t *opts, + const char *array_name, size_t *json_len +) { + + char *json = NULL; + + mongoc_cursor_t *cursor = mongo_find_all_cursor_with_opts ( + model, + query, opts + ); + + if (cursor) { + json = mongo_find_all_cursor_with_opts_to_json_internal ( + cursor, + array_name, json_len + ); + + mongoc_cursor_destroy (cursor); + } + + return json; + +} + const bson_t **mongo_find_all_internal ( mongoc_collection_t *collection, bson_t *query, const CMongoSelect *select, @@ -379,6 +446,73 @@ unsigned int mongo_find_one_with_opts ( } +static unsigned int mongo_find_one_internal_to_json ( + mongoc_collection_t *collection, + bson_t *query, const bson_t *opts, + char **json, size_t *json_len +) { + + unsigned int retval = 1; + + mongoc_cursor_t *cursor = mongoc_collection_find_with_opts ( + collection, query, opts, NULL + ); + + if (cursor) { + (void) mongoc_cursor_set_limit (cursor, 1); + + const bson_t *doc = NULL; + if (mongoc_cursor_next (cursor, &doc)) { + *json = bson_as_relaxed_extended_json (doc, json_len); + retval = 0; + } + + mongoc_cursor_destroy (cursor); + } + + return retval; + +} + +// works like mongo_find_one_with_opts () +// creates a new string with the result in relaxed extended JSON format +// query gets destroyed, opts are kept the same +// returns 0 on success, 1 on error +unsigned int mongo_find_one_with_opts_to_json ( + const CMongoModel *model, + bson_t *query, const bson_t *opts, + char **json, size_t *json_len +) { + + unsigned int retval = 1; + + if (model && query && json && json_len) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + retval = mongo_find_one_internal_to_json ( + collection, + query, opts, + json, json_len + ); + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } + + bson_destroy (query); + } + + return retval; + +} + // uses a query to find one doc // select is a dlist of strings used for document projection, // _id is true by default and should not be incldued From 66683cfb13fe34e94f77200230a78a838b0f6729 Mon Sep 17 00:00:00 2001 From: ermiry Date: Mon, 15 Mar 2021 10:54:54 -0600 Subject: [PATCH 37/75] Updated version to beta 1.0b-3 --- CHANGELOG.md | 8 +++----- include/cmongo/version.h | 8 ++++---- version.txt | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ecc50b..f96235d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,3 @@ -- Added custom mongo structure to hold values -- Added base dedicated model structure & methods -- Updated CRUD methods to be thread safe -- Split mongo_count_docs () to be used by other methods -- Removed mongo_collection_get () wrapper method \ No newline at end of file +- Added missing mongo_get_status () export +- Added buffer size definition in types header +- Added find methods that return result as json \ No newline at end of file diff --git a/include/cmongo/version.h b/include/cmongo/version.h index 447de53..3388aca 100644 --- a/include/cmongo/version.h +++ b/include/cmongo/version.h @@ -3,10 +3,10 @@ #include "cmongo/config.h" -#define CMONGO_VERSION "1.0b-2" -#define CMONGO_VERSION_NAME "Beta 1.0b-2" -#define CMONGO_VERSION_DATE "02/03/2021" -#define CMONGO_VERSION_TIME "14:15 CST" +#define CMONGO_VERSION "1.0b-3" +#define CMONGO_VERSION_NAME "Beta 1.0b-3" +#define CMONGO_VERSION_DATE "15/03/2021" +#define CMONGO_VERSION_TIME "10:54 CST" #define CMONGO_VERSION_AUTHOR "Erick Salas" #ifdef __cplusplus diff --git a/version.txt b/version.txt index 14689fc..486b511 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0b-2 \ No newline at end of file +1.0b-3 \ No newline at end of file From 1e1c7b9874fc51901e76bc9ea6c90fdedb175c61 Mon Sep 17 00:00:00 2001 From: ermiry Date: Fri, 26 Mar 2021 23:21:36 -0600 Subject: [PATCH 38/75] Added methods to perform aggregations --- include/cmongo/crud.h | 21 +++++++++++++++++ src/cmongo/crud.c | 55 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index aec5e90..03e32b1 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -144,6 +144,27 @@ CMONGO_EXPORT unsigned int mongo_delete_many ( const CMongoModel *model, bson_t *query ); +#pragma endregion + +#pragma region aggregation + +// performs an aggregation in the model's collection +// returns a cursor with the aggregation's result +CMONGO_EXPORT mongoc_cursor_t *mongo_perform_aggregation_with_opts ( + const CMongoModel *model, + mongoc_query_flags_t flags, + const bson_t *opts, + bson_t *pipeline +); + +// works like mongo_perform_aggregation_with_opts () +// but sets flags to 0 and opts to NULL +CMONGO_EXPORT mongoc_cursor_t *mongo_perform_aggregation ( + const CMongoModel *model, bson_t *pipeline +); + +#pragma endregion + #ifdef __cplusplus } #endif diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 660e749..32c9fd1 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -777,6 +777,61 @@ unsigned int mongo_delete_many ( } +#pragma endregion + +#pragma region aggregation + +// performs an aggregation in the model's collection +// returns a cursor with the aggregation's result +mongoc_cursor_t *mongo_perform_aggregation_with_opts ( + const CMongoModel *model, + mongoc_query_flags_t flags, + const bson_t *opts, + bson_t *pipeline +) { + + mongoc_cursor_t *cursor = NULL; + + if (model && pipeline) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + cursor = mongoc_collection_aggregate ( + collection, + flags, pipeline, opts, NULL + ); + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } + + bson_destroy (pipeline); + } + + return cursor; + +} + +// works like mongo_perform_aggregation_with_opts () +// but sets flags to 0 and opts to NULL +mongoc_cursor_t *mongo_perform_aggregation ( + const CMongoModel *model, bson_t *pipeline +) { + + return mongo_perform_aggregation_with_opts ( + model, 0, NULL, pipeline + ); + +} + +#pragma endregion + #ifdef __cplusplus #pragma GCC diagnostic pop #endif \ No newline at end of file From 19fe5da8f3f0f462ec4b57fd4f5b109d28783a22 Mon Sep 17 00:00:00 2001 From: ermiry Date: Fri, 26 Mar 2021 23:22:28 -0600 Subject: [PATCH 39/75] Added custom method to populate an object's array Ability to convert populate a single's object array into a json string --- include/cmongo/crud.h | 27 ++++++++++++++++++ src/cmongo/crud.c | 64 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index 03e32b1..5abd534 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -12,11 +12,17 @@ extern "C" { #endif +#pragma region count + // counts the docs in a collection by a matching query CMONGO_EXPORT int64_t mongo_count_docs ( const CMongoModel *model, bson_t *query ); +#pragma endregion + +#pragma region find + // returns true if 1 or more documents matches the query, false if no matches CMONGO_EXPORT bool mongo_check ( const CMongoModel *model, bson_t *query @@ -99,6 +105,19 @@ CMONGO_EXPORT unsigned int mongo_find_one ( void *output ); +// returns a new string in relaxed extended JSON format +// created with the result of an aggregation that represents +// how a single object's array gets populated +// pipeline gets destroyed, opts are kept the same +CMONGO_EXPORT char *mongo_find_one_populate_array_to_json ( + const CMongoModel *model, + bson_t *pipeline, size_t *json_len +); + +#pragma endregion + +#pragma region insert + // inserts a document into a collection // destroys document // returns 0 on success, 1 on error @@ -114,6 +133,10 @@ CMONGO_EXPORT unsigned int mongo_insert_many ( const bson_t **docs, size_t n_docs ); +#pragma endregion + +#pragma region update + // updates a doc by a matching query with the new values // destroys query and update documents // returns 0 on success, 1 on error @@ -130,6 +153,10 @@ CMONGO_EXPORT unsigned int mongo_update_many ( bson_t *query, bson_t *update ); +#pragma endregion + +#pragma region delete + // deletes one matching document by a query // destroys the query document // returns 0 on success, 1 on error diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 32c9fd1..9088697 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -16,6 +16,8 @@ #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif +#pragma region count + // counts the docs in a collection by a matching query static int64_t mongo_count_docs_internal ( mongoc_collection_t *collection, bson_t *query @@ -72,6 +74,10 @@ int64_t mongo_count_docs ( } +#pragma endregion + +#pragma region find + // returns true if 1 or more documents matches the query // returns false if no matches bool mongo_check ( @@ -263,7 +269,6 @@ static char *mongo_find_all_cursor_with_opts_to_json_internal ( // returns a new string in relaxed extended JSON format // with all matching objects inside an array // query gets destroyed, opts are kept the same -// returns 0 on success, 1 on error char *mongo_find_all_cursor_with_opts_to_json ( const CMongoModel *model, bson_t *query, const bson_t *opts, @@ -557,6 +562,56 @@ unsigned int mongo_find_one ( } +// returns a new string in relaxed extended JSON format +// created with the result of an aggregation that represents +// how a single object's array gets populated +// pipeline gets destroyed, opts are kept the same +char *mongo_find_one_populate_array_to_json ( + const CMongoModel *model, + bson_t *pipeline, size_t *json_len +) { + + char *json = NULL; + + if (model && pipeline && json_len) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + mongoc_cursor_t *cursor = mongoc_collection_aggregate ( + collection, + 0, pipeline, NULL, NULL + ); + + if (cursor) { + const bson_t *doc = NULL; + if (mongoc_cursor_next (cursor, &doc)) { + json = bson_as_relaxed_extended_json (doc, json_len); + } + + mongoc_cursor_destroy (cursor); + } + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } + + bson_destroy (pipeline); + } + + return json; + +} + +#pragma endregion + +#pragma region insert + // inserts a document into a collection // destroys document // returns 0 on success, 1 on error @@ -628,6 +683,9 @@ unsigned int mongo_insert_many ( } +#pragma endregion + +#pragma region update // updates a doc by a matching query with the new values // destroys query and update documents @@ -705,6 +763,10 @@ unsigned int mongo_update_many ( } +#pragma endregion + +#pragma region delete + // deletes one matching document by a query // destroys the query document // returns 0 on success, 1 on error From c1bfa9478ffd054bac4200807290a6fd2de36463 Mon Sep 17 00:00:00 2001 From: ermiry Date: Sat, 27 Mar 2021 11:37:55 -0600 Subject: [PATCH 40/75] Updated version to beta 1.0b-4 --- CHANGELOG.md | 5 ++--- include/cmongo/version.h | 8 ++++---- version.txt | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f96235d..08d8b97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,2 @@ -- Added missing mongo_get_status () export -- Added buffer size definition in types header -- Added find methods that return result as json \ No newline at end of file +- Added methods to perform aggregations +- Added custom method to populate an object's array into a json \ No newline at end of file diff --git a/include/cmongo/version.h b/include/cmongo/version.h index 3388aca..84d6270 100644 --- a/include/cmongo/version.h +++ b/include/cmongo/version.h @@ -3,10 +3,10 @@ #include "cmongo/config.h" -#define CMONGO_VERSION "1.0b-3" -#define CMONGO_VERSION_NAME "Beta 1.0b-3" -#define CMONGO_VERSION_DATE "15/03/2021" -#define CMONGO_VERSION_TIME "10:54 CST" +#define CMONGO_VERSION "1.0b-4" +#define CMONGO_VERSION_NAME "Beta 1.0b-4" +#define CMONGO_VERSION_DATE "27/03/2021" +#define CMONGO_VERSION_TIME "11:37 CST" #define CMONGO_VERSION_AUTHOR "Erick Salas" #ifdef __cplusplus diff --git a/version.txt b/version.txt index 486b511..b5a2c49 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0b-3 \ No newline at end of file +1.0b-4 \ No newline at end of file From 1c3f13530d3290ba581de2010a8a478e97169da4 Mon Sep 17 00:00:00 2001 From: ermiry Date: Sat, 27 Mar 2021 23:43:17 -0600 Subject: [PATCH 41/75] Added base mongo_find_one_populate_object () --- include/cmongo/crud.h | 11 +++++ src/cmongo/crud.c | 109 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index 5abd534..8e51f5d 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -105,6 +105,17 @@ CMONGO_EXPORT unsigned int mongo_find_one ( void *output ); +// performs an aggregation in the model's collection +// to match an object by its oid and then lookup & undwind +// the selected field using its _id +// returns 0 on success, 1 on error +CMONGO_EXPORT unsigned int mongo_find_one_populate_object ( + const CMongoModel *model, + const bson_oid_t *oid, + const char *from, const char *local_field, + void *output +); + // returns a new string in relaxed extended JSON format // created with the result of an aggregation that represents // how a single object's array gets populated diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 9088697..4e8da75 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -11,6 +11,8 @@ #include "cmongo/select.h" #include "cmongo/types.h" +#define CMONGO_UNWIND_VALUE_SIZE 64 + #ifdef __cplusplus #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" @@ -562,6 +564,113 @@ unsigned int mongo_find_one ( } +static bson_t *mongo_find_one_populate_object_pipeline ( + const bson_oid_t *oid, + const char *from, const char *local_field +) { + + char unwind[CMONGO_UNWIND_VALUE_SIZE] = { 0 }; + (void) snprintf ( + unwind, CMONGO_UNWIND_VALUE_SIZE - 1, + "$%s", local_field + ); + + bson_t *pipeline = BCON_NEW ( + "pipeline", + "[", + "{", + "$match", "{", "store", BCON_OID (oid), "}", + "}", + "{", + "$lookup", "{", + "from", BCON_UTF8 (from), + "localField", BCON_UTF8 (local_field), + "foreignField", BCON_UTF8 ("_id"), + "as", BCON_UTF8 (local_field), + "}", + "}", + + "{", + "$unwind", BCON_UTF8 (unwind), + "}", + "]" + ); + + return pipeline; + +} + +static unsigned int mongo_find_one_aggregate_internal ( + mongoc_collection_t *collection, + const bson_t *pipeline, + void *output, const mongo_parser model_parser +) { + + unsigned int retval = 1; + + mongoc_cursor_t *cursor = mongoc_collection_aggregate ( + collection, 0, pipeline, NULL, NULL + ); + + if (cursor) { + const bson_t *doc = NULL; + if (mongoc_cursor_next (cursor, &doc)) { + model_parser (output, doc); + retval = 0; + } + + mongoc_cursor_destroy (cursor); + } + + return retval; + +} + +// performs an aggregation in the model's collection +// to match an object by its oid and then lookup & undwind +// the selected field using its _id +// returns 0 on success, 1 on error +unsigned int mongo_find_one_populate_object ( + const CMongoModel *model, + const bson_oid_t *oid, + const char *from, const char *local_field, + void *output +) { + + unsigned int retval = 1; + + if (model && oid && from && local_field) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + bson_t *pipeline = mongo_find_one_populate_object_pipeline ( + oid, from, local_field + ); + + if (pipeline) { + retval = mongo_find_one_aggregate_internal ( + collection, pipeline, + output, model->model_parser + ); + + bson_destroy (pipeline); + } + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } + } + + return retval; + +} + // returns a new string in relaxed extended JSON format // created with the result of an aggregation that represents // how a single object's array gets populated From ebd62875c49bb5634d71f2f3ac053f62a516c53a Mon Sep 17 00:00:00 2001 From: ermiry Date: Sat, 27 Mar 2021 23:44:42 -0600 Subject: [PATCH 42/75] Added mongo_find_one_populate_object_to_json () --- include/cmongo/crud.h | 10 +++++++++ src/cmongo/crud.c | 49 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index 8e51f5d..a3a198f 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -116,6 +116,16 @@ CMONGO_EXPORT unsigned int mongo_find_one_populate_object ( void *output ); +// works like mongo_find_one_populate_object () +// but converts the result into a json string +// returns 0 on success, 1 on error +CMONGO_EXPORT unsigned int mongo_find_one_populate_object_to_json ( + const CMongoModel *model, + const bson_oid_t *oid, + const char *from, const char *local_field, + char **json, size_t *json_len +); + // returns a new string in relaxed extended JSON format // created with the result of an aggregation that represents // how a single object's array gets populated diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 4e8da75..cd2c2bd 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -671,6 +671,55 @@ unsigned int mongo_find_one_populate_object ( } +// works like mongo_find_one_populate_object () +// but converts the result into a json string +// returns 0 on success, 1 on error +unsigned int mongo_find_one_populate_object_to_json ( + const CMongoModel *model, + const bson_oid_t *oid, + const char *from, const char *local_field, + char **json, size_t *json_len +) { + + unsigned int retval = 1; + + if (model && oid && from && local_field) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + mongoc_cursor_t *cursor = mongoc_collection_aggregate ( + collection, 0, + mongo_find_one_populate_object_pipeline ( + oid, from, local_field + ), NULL, NULL + ); + + if (cursor) { + const bson_t *doc = NULL; + if (mongoc_cursor_next (cursor, &doc)) { + *json = bson_as_relaxed_extended_json (doc, json_len); + } + + mongoc_cursor_destroy (cursor); + + retval = 0; + } + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } + } + + return retval; + +} + // returns a new string in relaxed extended JSON format // created with the result of an aggregation that represents // how a single object's array gets populated From 902ee5392dbdef42345bdf79943ff85787119891 Mon Sep 17 00:00:00 2001 From: ermiry Date: Sat, 27 Mar 2021 23:46:34 -0600 Subject: [PATCH 43/75] Fixed pipeline bson memory leak in find one populate --- src/cmongo/crud.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index cd2c2bd..b5d307b 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -691,22 +691,27 @@ unsigned int mongo_find_one_populate_object_to_json ( ); if (collection) { - mongoc_cursor_t *cursor = mongoc_collection_aggregate ( - collection, 0, - mongo_find_one_populate_object_pipeline ( - oid, from, local_field - ), NULL, NULL + bson_t *pipeline = mongo_find_one_populate_object_pipeline ( + oid, from, local_field ); - if (cursor) { - const bson_t *doc = NULL; - if (mongoc_cursor_next (cursor, &doc)) { - *json = bson_as_relaxed_extended_json (doc, json_len); - } + if (pipeline) { + mongoc_cursor_t *cursor = mongoc_collection_aggregate ( + collection, 0, pipeline, NULL, NULL + ); - mongoc_cursor_destroy (cursor); + if (cursor) { + const bson_t *doc = NULL; + if (mongoc_cursor_next (cursor, &doc)) { + *json = bson_as_relaxed_extended_json (doc, json_len); + } + + mongoc_cursor_destroy (cursor); - retval = 0; + retval = 0; + } + + bson_destroy (pipeline); } mongoc_collection_destroy (collection); From 7838dc0b647b9309bff58a5184db3743436c158f Mon Sep 17 00:00:00 2001 From: ermiry Date: Sat, 27 Mar 2021 23:50:59 -0600 Subject: [PATCH 44/75] Renamed mongo_find_one_populate_array_to_json () --- src/cmongo/crud.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index b5d307b..90693f8 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -729,7 +729,7 @@ unsigned int mongo_find_one_populate_object_to_json ( // created with the result of an aggregation that represents // how a single object's array gets populated // pipeline gets destroyed, opts are kept the same -char *mongo_find_one_populate_array_to_json ( +char *mongo_find_one_custom_populate_array_to_json ( const CMongoModel *model, bson_t *pipeline, size_t *json_len ) { From a03fcf64199a044f57ff2e1b4cfdb97936ab0581 Mon Sep 17 00:00:00 2001 From: ermiry Date: Sat, 27 Mar 2021 23:54:38 -0600 Subject: [PATCH 45/75] Added new mongo_find_one_populate_array () --- include/cmongo/crud.h | 13 +++++++- src/cmongo/crud.c | 73 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index a3a198f..b804647 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -126,11 +126,22 @@ CMONGO_EXPORT unsigned int mongo_find_one_populate_object_to_json ( char **json, size_t *json_len ); +// performs an aggregation in the model's collection +// to match an object by its oid and then lookup (populate) +// the selected array by searching by the object's oids +// returns 0 on success, 1 on error +CMONGO_EXPORT unsigned int mongo_find_one_populate_array ( + const CMongoModel *model, + const bson_oid_t *oid, + const char *from, const char *local_field, + void *output +); + // returns a new string in relaxed extended JSON format // created with the result of an aggregation that represents // how a single object's array gets populated // pipeline gets destroyed, opts are kept the same -CMONGO_EXPORT char *mongo_find_one_populate_array_to_json ( +CMONGO_EXPORT char *mongo_find_one_custom_populate_array_to_json ( const CMongoModel *model, bson_t *pipeline, size_t *json_len ); diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 90693f8..60e8a14 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -639,7 +639,7 @@ unsigned int mongo_find_one_populate_object ( unsigned int retval = 1; - if (model && oid && from && local_field) { + if (model && oid && from && local_field && output) { mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); if (client) { mongoc_collection_t *collection = mongoc_client_get_collection ( @@ -725,6 +725,77 @@ unsigned int mongo_find_one_populate_object_to_json ( } +static inline bson_t *mongo_find_one_populate_array_pipeline ( + const bson_oid_t *oid, + const char *from, const char *local_field +) { + + bson_t *pipeline = BCON_NEW ( + "pipeline", + "[", + "{", + "$match", "{", "_id", BCON_OID (oid), "}", + "}", + "{", + "$lookup", "{", + "from", BCON_UTF8 (from), + "localField", BCON_UTF8 (local_field), + "foreignField", BCON_UTF8 ("_id"), + "as", BCON_UTF8 (local_field), + "}", + "}", + "]" + ); + + return pipeline; + +} + +// performs an aggregation in the model's collection +// to match an object by its oid and then lookup (populate) +// the selected array by searching by the object's oids +// returns 0 on success, 1 on error +unsigned int mongo_find_one_populate_array ( + const CMongoModel *model, + const bson_oid_t *oid, + const char *from, const char *local_field, + void *output +) { + + unsigned int retval = 1; + + if (model && oid && from && local_field && output) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + bson_t *pipeline = mongo_find_one_populate_array_pipeline ( + oid, from, local_field + ); + + if (pipeline) { + retval = mongo_find_one_aggregate_internal ( + collection, pipeline, + output, model->model_parser + ); + + bson_destroy (pipeline); + } + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } + } + + return retval; + +} + // returns a new string in relaxed extended JSON format // created with the result of an aggregation that represents // how a single object's array gets populated From 22915e9f74137972491fdf21b04fa1b9c616b1bf Mon Sep 17 00:00:00 2001 From: ermiry Date: Sat, 27 Mar 2021 23:56:34 -0600 Subject: [PATCH 46/75] Added mongo_find_one_populate_array_to_json () --- include/cmongo/crud.h | 10 ++++++++ src/cmongo/crud.c | 55 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index b804647..75deaff 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -137,6 +137,16 @@ CMONGO_EXPORT unsigned int mongo_find_one_populate_array ( void *output ); +// works like mongo_find_one_populate_array () +// but converts the result into a json string +// returns 0 on success, 1 on error +CMONGO_EXPORT unsigned int mongo_find_one_populate_array_to_json ( + const CMongoModel *model, + const bson_oid_t *oid, + const char *from, const char *local_field, + char **json, size_t *json_len +); + // returns a new string in relaxed extended JSON format // created with the result of an aggregation that represents // how a single object's array gets populated diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 60e8a14..0f3b6ce 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -796,6 +796,61 @@ unsigned int mongo_find_one_populate_array ( } + +// works like mongo_find_one_populate_array () +// but converts the result into a json string +// returns 0 on success, 1 on error +unsigned int mongo_find_one_populate_array_to_json ( + const CMongoModel *model, + const bson_oid_t *oid, + const char *from, const char *local_field, + char **json, size_t *json_len +) { + + unsigned int retval = 1; + + if (model && oid && from && local_field) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + bson_t *pipeline = mongo_find_one_populate_array_pipeline ( + oid, from, local_field + ); + + if (pipeline) { + mongoc_cursor_t *cursor = mongoc_collection_aggregate ( + collection, 0, pipeline, NULL, NULL + ); + + if (cursor) { + const bson_t *doc = NULL; + if (mongoc_cursor_next (cursor, &doc)) { + *json = bson_as_relaxed_extended_json (doc, json_len); + } + + mongoc_cursor_destroy (cursor); + + retval = 0; + } + + bson_destroy (pipeline); + } + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } + } + + return retval; + +} + // returns a new string in relaxed extended JSON format // created with the result of an aggregation that represents // how a single object's array gets populated From 70e41565f40ca129893718c5c5280922ab06293d Mon Sep 17 00:00:00 2001 From: ermiry Date: Wed, 31 Mar 2021 13:30:56 -0600 Subject: [PATCH 47/75] Refactored compilation flags in makefile --- makefile | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/makefile b/makefile index 20f595b..9ab3880 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,9 @@ TYPE := development +COVERAGE := 0 + +DEBUG := 0 + SLIB := libcmongo.so all: directories $(SLIB) @@ -21,6 +25,8 @@ MONGOC_INC := -I /usr/local/include/libbson-1.0 -I /usr/local/include/libmongoc- DEFINES := -D _GNU_SOURCE +DEVELOPMENT := -D CMONGO_DEBUG + CC := gcc GCCVGTEQ8 := $(shell expr `gcc -dumpversion | cut -f1 -d.` \>= 8) @@ -39,9 +45,8 @@ COVDIR := coverage COVEXT := gcov # common flags -# -Wconversion -COMMON := -march=native \ - -Wall -Wno-unknown-pragmas \ +# -Wconversion -march=native +COMMON := -Wall -Wno-unknown-pragmas \ -Wfloat-equal -Wdouble-promotion -Wint-to-pointer-cast -Wwrite-strings \ -Wtype-limits -Wsign-compare -Wmissing-field-initializers \ -Wuninitialized -Wmaybe-uninitialized -Wempty-body \ @@ -52,9 +57,14 @@ COMMON := -march=native \ CFLAGS := $(DEFINES) ifeq ($(TYPE), development) - CFLAGS += -g -fasynchronous-unwind-tables + CFLAGS += -g -fasynchronous-unwind-tables $(DEVELOPMENT) else ifeq ($(TYPE), test) CFLAGS += -g -fasynchronous-unwind-tables -D_FORTIFY_SOURCE=2 -fstack-protector -O2 + ifeq ($(COVERAGE), 1) + CFLAGS += -fprofile-arcs -ftest-coverage + endif +else ifeq ($(TYPE), beta) + CFLAGS += -g -D_FORTIFY_SOURCE=2 -O2 else CFLAGS += -D_FORTIFY_SOURCE=2 -O2 endif @@ -78,7 +88,9 @@ CFLAGS += -fPIC $(COMMON) LIB := -L /usr/local/lib $(MONGOC) ifeq ($(TYPE), test) - LIB += -lgcov --coverage + ifeq ($(COVERAGE), 1) + LIB += -lgcov --coverage + endif endif INC := -I $(INCDIR) -I /usr/local/include $(MONGOC_INC) @@ -114,13 +126,19 @@ TESTCOVDIR := $(COVDIR)/test TESTFLAGS := -g $(DEFINES) -Wall -Wno-unknown-pragmas -Wno-format ifeq ($(TYPE), test) - TESTFLAGS += -fprofile-arcs -ftest-coverage + ifeq ($(COVERAGE), 1) + TESTFLAGS += -fprofile-arcs -ftest-coverage + endif endif TESTLIBS := $(PTHREAD) -L ./bin -l cmongo +TESTLIBS += -Wl,-rpath=./$(TARGETDIR) -L ./$(TARGETDIR) -l cmongo + ifeq ($(TYPE), test) - TESTLIBS += -lgcov --coverage + ifeq ($(COVERAGE), 1) + TESTLIBS += -lgcov --coverage + endif endif TESTINC := -I $(INCDIR) -I ./$(TESTDIR) @@ -133,6 +151,7 @@ TESTCOVS := $(patsubst $(TESTDIR)/%,$(TESTBUILD)/%,$(TESTS:.$(SRCEXT)=.$(SRCEXT) test: $(TESTOBJS) @mkdir -p ./$(TESTTARGET) @mkdir -p ./$(TESTTARGET) + $(CC) $(TESTINC) ./$(TESTBUILD)/model.o -o ./$(TESTTARGET)/model $(TESTLIBS) $(CC) $(TESTINC) ./$(TESTBUILD)/select.o -o ./$(TESTTARGET)/select $(TESTLIBS) $(CC) $(TESTINC) ./$(TESTBUILD)/version.o -o ./$(TESTTARGET)/version $(TESTLIBS) From 7cf7082874b63b930360d236b640ed43507409f6 Mon Sep 17 00:00:00 2001 From: ermiry Date: Wed, 31 Mar 2021 13:31:14 -0600 Subject: [PATCH 48/75] Added base model unit tests methods --- test/model.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 test/model.c diff --git a/test/model.c b/test/model.c new file mode 100644 index 0000000..1181995 --- /dev/null +++ b/test/model.c @@ -0,0 +1,76 @@ +#include +#include +#include + +#include + +#include "test.h" + +static const char *collname = { "users" }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" + +static void test_model_parser ( + void *model, const bson_t *doc +) { + + // nothing to be done here + +} + +#pragma GCC diagnostic pop + +static void test_model_new_single (void) { + + CMongoModel *model = cmongo_model_new (); + + test_check_unsigned_eq (model->collname_len, 0, NULL); + test_check_null_ptr (model->model_parser); + + cmongo_model_delete (model); + +} + +static void test_model_create_single (void) { + + CMongoModel *model = cmongo_model_create (collname); + + test_check_unsigned_eq (model->collname_len, strlen (collname), NULL); + test_check_str_eq (model->collname, collname, NULL); + test_check_null_ptr (model->model_parser); + + cmongo_model_delete (model); + +} + +static void test_model_set_parser (void) { + + CMongoModel *model = cmongo_model_create (collname); + + test_check_unsigned_eq (model->collname_len, strlen (collname), NULL); + test_check_str_eq (model->collname, collname, NULL); + test_check_null_ptr (model->model_parser); + + cmongo_model_set_parser (model, test_model_parser); + test_check_ptr (model->model_parser); + + cmongo_model_delete (model); + +} + +int main (int argc, char **argv) { + + (void) printf ("Testing MODEL...\n"); + + test_model_new_single (); + + test_model_create_single (); + + test_model_set_parser (); + + (void) printf ("\nDone with MODEL tests!\n\n"); + + return 0; + +} \ No newline at end of file From 74af30f289632727b40e42c4c9dc75161fba618b Mon Sep 17 00:00:00 2001 From: ermiry Date: Wed, 31 Mar 2021 13:31:28 -0600 Subject: [PATCH 49/75] Handling model tests in dedicated test script --- test/run.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/run.sh b/test/run.sh index 36566b5..9f37620 100644 --- a/test/run.sh +++ b/test/run.sh @@ -1,3 +1,5 @@ #!/bin/bash -LD_LIBRARY_PATH=bin ./test/bin/select || { exit 1; } +./test/bin/model || { exit 1; } + +./test/bin/select || { exit 1; } From 08560df4d095e0b1ee4b118e1855c18131fabd06 Mon Sep 17 00:00:00 2001 From: ermiry Date: Wed, 31 Mar 2021 13:49:37 -0600 Subject: [PATCH 50/75] Added workflow to compile & run tests This also uploads coverage after successful tests --- .github/workflows/{coverage.yml => test.yml} | 24 +++++++------------- 1 file changed, 8 insertions(+), 16 deletions(-) rename .github/workflows/{coverage.yml => test.yml} (60%) diff --git a/.github/workflows/coverage.yml b/.github/workflows/test.yml similarity index 60% rename from .github/workflows/coverage.yml rename to .github/workflows/test.yml index 66671ee..a35fc82 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/test.yml @@ -1,4 +1,4 @@ -name: CMongo Code Coverage +name: CMongo Tests on: pull_request: @@ -7,7 +7,7 @@ on: jobs: coverage: - name: CMongo coverage + name: CMongo tests runs-on: ubuntu-latest container: image: ermiry/mongoc:buildev @@ -16,16 +16,16 @@ jobs: uses: actions/checkout@v2 # compile - - name: gcc make - run: make TYPE=test - - name: gcc tests - run: make TYPE=test test + - name: Compile Sources + run: make TYPE=test COVERAGE=1 + - name: Compile Tests + run: make TYPE=test COVERAGE=1 test # run - - name: test + - name: Unit Tests run: bash test/run.sh - - name: coverage + - name: Coverage run: make coverage - name: Upload coverage to Codecov @@ -37,11 +37,3 @@ jobs: name: build fail_ci_if_error: true # verbose: true - - - name: clean tests - run: make clean-tests - - - name: g++ tests - run: make TYPE=test CC=g++ test - - name: g++ run tests - run: bash test/run.sh \ No newline at end of file From 2e86f12d701e3508d406b23488728d2a51c7a30b Mon Sep 17 00:00:00 2001 From: ermiry Date: Wed, 31 Mar 2021 13:55:04 -0600 Subject: [PATCH 51/75] Updated version to beta 1.0b-5 --- CHANGELOG.md | 15 +++++++++++++-- include/cmongo/version.h | 8 ++++---- version.txt | 2 +- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08d8b97..60c6d48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,13 @@ -- Added methods to perform aggregations -- Added custom method to populate an object's array into a json \ No newline at end of file +## General +- Refactored compilation flags in makefile +- Added workflow to compile & run tests + +## CRUD +- Added base mongo_find_one_populate_object () +- Added mongo_find_one_populate_object_to_json () +- Renamed mongo_find_one_populate_array_to_json () +- Added new mongo_find_one_populate_array () +- Added mongo_find_one_populate_array_to_json () + +## Tests +- Added base model unit tests methods \ No newline at end of file diff --git a/include/cmongo/version.h b/include/cmongo/version.h index 84d6270..0854bf1 100644 --- a/include/cmongo/version.h +++ b/include/cmongo/version.h @@ -3,10 +3,10 @@ #include "cmongo/config.h" -#define CMONGO_VERSION "1.0b-4" -#define CMONGO_VERSION_NAME "Beta 1.0b-4" -#define CMONGO_VERSION_DATE "27/03/2021" -#define CMONGO_VERSION_TIME "11:37 CST" +#define CMONGO_VERSION "1.0b-5" +#define CMONGO_VERSION_NAME "Beta 1.0b-5" +#define CMONGO_VERSION_DATE "31/03/2021" +#define CMONGO_VERSION_TIME "13:54 CST" #define CMONGO_VERSION_AUTHOR "Erick Salas" #ifdef __cplusplus diff --git a/version.txt b/version.txt index b5a2c49..7d12d09 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0b-4 \ No newline at end of file +1.0b-5 \ No newline at end of file From 7004f770955151daed88af2dfd7bd69e184f9a7e Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 1 Apr 2021 11:09:52 -0600 Subject: [PATCH 52/75] Added mongo_perform_aggregation_to_json () --- include/cmongo/crud.h | 10 +++++++++ src/cmongo/crud.c | 48 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index 75deaff..f7151e5 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -218,6 +218,7 @@ CMONGO_EXPORT unsigned int mongo_delete_many ( #pragma region aggregation // performs an aggregation in the model's collection +// the pipeline document gets destroyed // returns a cursor with the aggregation's result CMONGO_EXPORT mongoc_cursor_t *mongo_perform_aggregation_with_opts ( const CMongoModel *model, @@ -232,6 +233,15 @@ CMONGO_EXPORT mongoc_cursor_t *mongo_perform_aggregation ( const CMongoModel *model, bson_t *pipeline ); +// works like mongo_perform_aggregation () +// but outputs all the aggregation's result into an array +// returns 0 on success, 1 on error +CMONGO_EXPORT unsigned int mongo_perform_aggregation_to_json ( + const CMongoModel *model, bson_t *pipeline, + const char *array_name, + char **json, size_t *json_len +); + #pragma endregion #ifdef __cplusplus diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 0f3b6ce..fd2a96c 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -1133,6 +1133,7 @@ unsigned int mongo_delete_many ( #pragma region aggregation // performs an aggregation in the model's collection +// the pipeline document gets destroyed // returns a cursor with the aggregation's result mongoc_cursor_t *mongo_perform_aggregation_with_opts ( const CMongoModel *model, @@ -1181,6 +1182,53 @@ mongoc_cursor_t *mongo_perform_aggregation ( } +// works like mongo_perform_aggregation () +// but outputs all the aggregation's result into an array +// returns 0 on success, 1 on error +unsigned int mongo_perform_aggregation_to_json ( + const CMongoModel *model, bson_t *pipeline, + const char *array_name, + char **json, size_t *json_len +) { + + unsigned int retval = 1; + + if (model && pipeline) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + mongoc_cursor_t *cursor = mongoc_collection_aggregate ( + collection, + MONGOC_QUERY_NONE, pipeline, NULL, NULL + ); + + if (cursor) { + *json = mongo_find_all_cursor_with_opts_to_json_internal ( + cursor, array_name, json_len + ); + + mongoc_cursor_destroy (cursor); + + retval = 0; + } + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } + + bson_destroy (pipeline); + } + + return retval; + +} + #pragma endregion #ifdef __cplusplus From c6284c43f3e6a1fe99844bef7e22f579a99ce8d9 Mon Sep 17 00:00:00 2001 From: ermiry Date: Thu, 1 Apr 2021 11:13:12 -0600 Subject: [PATCH 53/75] Updated version to beta 1.0b-6 --- CHANGELOG.md | 14 +------------- include/cmongo/version.h | 8 ++++---- version.txt | 2 +- 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60c6d48..1cee7d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1 @@ -## General -- Refactored compilation flags in makefile -- Added workflow to compile & run tests - -## CRUD -- Added base mongo_find_one_populate_object () -- Added mongo_find_one_populate_object_to_json () -- Renamed mongo_find_one_populate_array_to_json () -- Added new mongo_find_one_populate_array () -- Added mongo_find_one_populate_array_to_json () - -## Tests -- Added base model unit tests methods \ No newline at end of file +- Added mongo_perform_aggregation_to_json () \ No newline at end of file diff --git a/include/cmongo/version.h b/include/cmongo/version.h index 0854bf1..6b7f87a 100644 --- a/include/cmongo/version.h +++ b/include/cmongo/version.h @@ -3,10 +3,10 @@ #include "cmongo/config.h" -#define CMONGO_VERSION "1.0b-5" -#define CMONGO_VERSION_NAME "Beta 1.0b-5" -#define CMONGO_VERSION_DATE "31/03/2021" -#define CMONGO_VERSION_TIME "13:54 CST" +#define CMONGO_VERSION "1.0b-6" +#define CMONGO_VERSION_NAME "Beta 1.0b-6" +#define CMONGO_VERSION_DATE "01/04/2021" +#define CMONGO_VERSION_TIME "11:11 CST" #define CMONGO_VERSION_AUTHOR "Erick Salas" #ifdef __cplusplus diff --git a/version.txt b/version.txt index 7d12d09..89024db 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0b-5 \ No newline at end of file +1.0b-6 \ No newline at end of file From 688814c433156fc48abc575beeef793fca939638 Mon Sep 17 00:00:00 2001 From: ermiry Date: Fri, 2 Apr 2021 21:02:51 -0600 Subject: [PATCH 54/75] Added methods to print oids & documents --- include/cmongo/types.h | 5 +++++ src/cmongo/types.c | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/cmongo/types.h b/include/cmongo/types.h index 52b020d..cdc3b74 100644 --- a/include/cmongo/types.h +++ b/include/cmongo/types.h @@ -5,6 +5,7 @@ #include "cmongo/config.h" +#define BSON_OID_BUFFER_SIZE 32 #define BSON_ARRAY_BUFFER_SIZE 16 #ifdef __cplusplus @@ -19,6 +20,10 @@ CMONGO_PUBLIC bson_oid_t *bson_oid_create ( const bson_oid_t *original_oid ); +CMONGO_PUBLIC void bson_oid_print (const bson_oid_t *oid); + +CMONGO_PUBLIC void bson_print_as_json (const bson_t *document); + #ifdef __cplusplus } #endif diff --git a/src/cmongo/types.c b/src/cmongo/types.c index 857a20a..466558a 100644 --- a/src/cmongo/types.c +++ b/src/cmongo/types.c @@ -1,8 +1,11 @@ #include +#include #include #include +#include "cmongo/types.h" + bson_oid_t *bson_oid_new (void) { bson_oid_t *oid = (bson_oid_t *) malloc (sizeof (bson_oid_t)); @@ -26,4 +29,23 @@ bson_oid_t *bson_oid_create (const bson_oid_t *original_oid) { return oid; +} + +void bson_oid_print (const bson_oid_t *oid) { + + char buffer[BSON_OID_BUFFER_SIZE] = { 0 }; + bson_oid_to_string (oid, buffer); + (void) printf ("%s\n", buffer); + +} + +void bson_print_as_json (const bson_t *document) { + + size_t json_len = 0; + char *json = bson_as_relaxed_extended_json (document, &json_len); + if (json) { + (void) printf ("%s\n", json); + free (json); + } + } \ No newline at end of file From 064bbd0a591f04c66ed9649a421b9a702466740b Mon Sep 17 00:00:00 2001 From: ermiry Date: Mon, 5 Apr 2021 19:30:46 -0500 Subject: [PATCH 55/75] Added mongo_perform_single_aggregation_to_json () --- include/cmongo/crud.h | 10 +++++++++ src/cmongo/crud.c | 49 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index f7151e5..3aa8ae8 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -233,8 +233,18 @@ CMONGO_EXPORT mongoc_cursor_t *mongo_perform_aggregation ( const CMongoModel *model, bson_t *pipeline ); +// works like mongo_perform_aggregation () +// but outputs all the aggregation's result into an object +// useful when aggregation returns just one document +// returns 0 on success, 1 on error +CMONGO_EXPORT unsigned int mongo_perform_single_aggregation_to_json ( + const CMongoModel *model, bson_t *pipeline, + char **json, size_t *json_len +); + // works like mongo_perform_aggregation () // but outputs all the aggregation's result into an array +// useful when aggregation returns many matches // returns 0 on success, 1 on error CMONGO_EXPORT unsigned int mongo_perform_aggregation_to_json ( const CMongoModel *model, bson_t *pipeline, diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index fd2a96c..4112feb 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -1182,8 +1182,57 @@ mongoc_cursor_t *mongo_perform_aggregation ( } +// works like mongo_perform_aggregation () +// but outputs all the aggregation's result into an object +// useful when aggregation returns just one document +// returns 0 on success, 1 on error +unsigned int mongo_perform_single_aggregation_to_json ( + const CMongoModel *model, bson_t *pipeline, + char **json, size_t *json_len +) { + + unsigned int retval = 1; + + if (model && pipeline) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + mongoc_cursor_t *cursor = mongoc_collection_aggregate ( + collection, + MONGOC_QUERY_NONE, pipeline, NULL, NULL + ); + + if (cursor) { + const bson_t *doc = NULL; + if (mongoc_cursor_next (cursor, &doc)) { + *json = bson_as_relaxed_extended_json (doc, json_len); + } + + mongoc_cursor_destroy (cursor); + + retval = 0; + } + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } + + bson_destroy (pipeline); + } + + return retval; + +} + // works like mongo_perform_aggregation () // but outputs all the aggregation's result into an array +// useful when aggregation returns many matches // returns 0 on success, 1 on error unsigned int mongo_perform_aggregation_to_json ( const CMongoModel *model, bson_t *pipeline, From 776a54e4de8c0df78160cca87a3f5efb853e3cc8 Mon Sep 17 00:00:00 2001 From: ermiry Date: Mon, 5 Apr 2021 19:34:12 -0500 Subject: [PATCH 56/75] Updated version to beta 1.0b-7 --- CHANGELOG.md | 3 ++- include/cmongo/version.h | 8 ++++---- version.txt | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cee7d7..5773b07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1 +1,2 @@ -- Added mongo_perform_aggregation_to_json () \ No newline at end of file +- Added methods to print oids & documents +- Added mongo_perform_single_aggregation_to_json () \ No newline at end of file diff --git a/include/cmongo/version.h b/include/cmongo/version.h index 6b7f87a..af7a9e0 100644 --- a/include/cmongo/version.h +++ b/include/cmongo/version.h @@ -3,10 +3,10 @@ #include "cmongo/config.h" -#define CMONGO_VERSION "1.0b-6" -#define CMONGO_VERSION_NAME "Beta 1.0b-6" -#define CMONGO_VERSION_DATE "01/04/2021" -#define CMONGO_VERSION_TIME "11:11 CST" +#define CMONGO_VERSION "1.0b-7" +#define CMONGO_VERSION_NAME "Beta 1.0b-7" +#define CMONGO_VERSION_DATE "05/04/2021" +#define CMONGO_VERSION_TIME "19:33 CST" #define CMONGO_VERSION_AUTHOR "Erick Salas" #ifdef __cplusplus diff --git a/version.txt b/version.txt index 89024db..e8cfa86 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0b-6 \ No newline at end of file +1.0b-7 \ No newline at end of file From 2a3b4ccb82f9fbae75a370e3bd49dd42871e4a3c Mon Sep 17 00:00:00 2001 From: ermiry Date: Mon, 5 Apr 2021 20:20:37 -0500 Subject: [PATCH 57/75] Refactored mongo_find_one_custom_populate_array_to_json () --- include/cmongo/crud.h | 6 ++++-- src/cmongo/crud.c | 16 ++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index 3aa8ae8..83b04ac 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -151,9 +151,11 @@ CMONGO_EXPORT unsigned int mongo_find_one_populate_array_to_json ( // created with the result of an aggregation that represents // how a single object's array gets populated // pipeline gets destroyed, opts are kept the same -CMONGO_EXPORT char *mongo_find_one_custom_populate_array_to_json ( +// returns 0 on success, 1 on error +CMONGO_EXPORT unsigned int mongo_find_one_custom_populate_array_to_json ( const CMongoModel *model, - bson_t *pipeline, size_t *json_len + bson_t *pipeline, + char **json, size_t *json_len ); #pragma endregion diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 4112feb..45b3b79 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -855,12 +855,14 @@ unsigned int mongo_find_one_populate_array_to_json ( // created with the result of an aggregation that represents // how a single object's array gets populated // pipeline gets destroyed, opts are kept the same -char *mongo_find_one_custom_populate_array_to_json ( +// returns 0 on success, 1 on error +unsigned int mongo_find_one_custom_populate_array_to_json ( const CMongoModel *model, - bson_t *pipeline, size_t *json_len + bson_t *pipeline, + char **json, size_t *json_len ) { - char *json = NULL; + unsigned int retval = 1; if (model && pipeline && json_len) { mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); @@ -872,16 +874,18 @@ char *mongo_find_one_custom_populate_array_to_json ( if (collection) { mongoc_cursor_t *cursor = mongoc_collection_aggregate ( collection, - 0, pipeline, NULL, NULL + MONGOC_QUERY_NONE, pipeline, NULL, NULL ); if (cursor) { const bson_t *doc = NULL; if (mongoc_cursor_next (cursor, &doc)) { - json = bson_as_relaxed_extended_json (doc, json_len); + *json = bson_as_relaxed_extended_json (doc, json_len); } mongoc_cursor_destroy (cursor); + + retval = 0; } mongoc_collection_destroy (collection); @@ -893,7 +897,7 @@ char *mongo_find_one_custom_populate_array_to_json ( bson_destroy (pipeline); } - return json; + return retval; } From 30ed2ca1e1568cf06688c6d1ed2928235b968e37 Mon Sep 17 00:00:00 2001 From: ermiry Date: Mon, 12 Apr 2021 14:50:31 -0500 Subject: [PATCH 58/75] Added mongo_find_all_populate_object_to_json () --- include/cmongo/crud.h | 9 +++++ src/cmongo/crud.c | 85 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index 83b04ac..f5a9b62 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -62,6 +62,15 @@ CMONGO_EXPORT char *mongo_find_all_cursor_with_opts_to_json ( const char *array_name, size_t *json_len ); +// works like mongo_find_all_cursor_with_opts_to_json () +// but also populates the specified object +CMONGO_EXPORT unsigned int mongo_find_all_populate_object_to_json ( + const CMongoModel *model, + const char *from, const char *local_field, + const char *array_name, + char **json, size_t *json_len +); + // use a query to find all matching documents // an empty query will return all the docs in a collection CMONGO_EXPORT const bson_t **mongo_find_all ( diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 45b3b79..e039677 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -297,6 +297,90 @@ char *mongo_find_all_cursor_with_opts_to_json ( } +static bson_t *mongo_find_all_populate_object_pipeline ( + const char *from, const char *local_field +) { + + char unwind[CMONGO_UNWIND_VALUE_SIZE] = { 0 }; + (void) snprintf ( + unwind, CMONGO_UNWIND_VALUE_SIZE - 1, + "$%s", local_field + ); + + bson_t *pipeline = BCON_NEW ( + "pipeline", + "[", + "{", + "$lookup", "{", + "from", BCON_UTF8 (from), + "localField", BCON_UTF8 (local_field), + "foreignField", BCON_UTF8 ("_id"), + "as", BCON_UTF8 (local_field), + "}", + "}", + + "{", + "$unwind", BCON_UTF8 (unwind), + "}", + "]" + ); + + return pipeline; + +} + +// works like mongo_find_all_cursor_with_opts_to_json () +// but also populates the specified object +unsigned int mongo_find_all_populate_object_to_json ( + const CMongoModel *model, + const char *from, const char *local_field, + const char *array_name, + char **json, size_t *json_len +) { + + unsigned int retval = 1; + + if (model && from && local_field) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + bson_t *pipeline = mongo_find_all_populate_object_pipeline ( + from, local_field + ); + + if (pipeline) { + mongoc_cursor_t *cursor = mongoc_collection_aggregate ( + collection, 0, pipeline, NULL, NULL + ); + + if (cursor) { + *json = mongo_find_all_cursor_with_opts_to_json_internal ( + cursor, array_name, json_len + ); + + mongoc_cursor_destroy (cursor); + + retval = 0; + } + + bson_destroy (pipeline); + } + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } + } + + return retval; + +} + const bson_t **mongo_find_all_internal ( mongoc_collection_t *collection, bson_t *query, const CMongoSelect *select, @@ -796,7 +880,6 @@ unsigned int mongo_find_one_populate_array ( } - // works like mongo_find_one_populate_array () // but converts the result into a json string // returns 0 on success, 1 on error From 500b3a576c5b26c0cf87130ca0ce2f9041e0bb71 Mon Sep 17 00:00:00 2001 From: ermiry Date: Mon, 12 Apr 2021 14:52:09 -0500 Subject: [PATCH 59/75] Added mongo_find_all_populate_array_to_json () --- src/cmongo/crud.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index e039677..787d739 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -381,6 +381,80 @@ unsigned int mongo_find_all_populate_object_to_json ( } +static inline bson_t *mongo_find_all_populate_array_pipeline ( + const char *from, const char *local_field +) { + + bson_t *pipeline = BCON_NEW ( + "pipeline", + "[", + "{", + "$lookup", "{", + "from", BCON_UTF8 (from), + "localField", BCON_UTF8 (local_field), + "foreignField", BCON_UTF8 ("_id"), + "as", BCON_UTF8 (local_field), + "}", + "}", + "]" + ); + + return pipeline; + +} + +// works like mongo_find_all_cursor_with_opts_to_json () +// but also populates the specified objects array +unsigned int mongo_find_all_populate_array_to_json ( + const CMongoModel *model, + const char *from, const char *local_field, + const char *array_name, + char **json, size_t *json_len +) { + + unsigned int retval = 1; + + if (model && from && local_field) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + bson_t *pipeline = mongo_find_all_populate_array_pipeline ( + from, local_field + ); + + if (pipeline) { + mongoc_cursor_t *cursor = mongoc_collection_aggregate ( + collection, 0, pipeline, NULL, NULL + ); + + if (cursor) { + *json = mongo_find_all_cursor_with_opts_to_json_internal ( + cursor, array_name, json_len + ); + + mongoc_cursor_destroy (cursor); + + retval = 0; + } + + bson_destroy (pipeline); + } + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } + } + + return retval; + +} + const bson_t **mongo_find_all_internal ( mongoc_collection_t *collection, bson_t *query, const CMongoSelect *select, From a5467321b3342f876a189b87f4c47cb7b8243427 Mon Sep 17 00:00:00 2001 From: ermiry Date: Mon, 12 Apr 2021 14:56:00 -0500 Subject: [PATCH 60/75] Updated version to beta 1.0b-8 --- CHANGELOG.md | 5 +++-- include/cmongo/version.h | 8 ++++---- version.txt | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5773b07..63677aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,3 @@ -- Added methods to print oids & documents -- Added mongo_perform_single_aggregation_to_json () \ No newline at end of file +- Refactored mongo_find_one_custom_populate_array_to_json () +- Added mongo_find_all_populate_object_to_json () +- Added mongo_find_all_populate_array_to_json () \ No newline at end of file diff --git a/include/cmongo/version.h b/include/cmongo/version.h index af7a9e0..aa7d0cc 100644 --- a/include/cmongo/version.h +++ b/include/cmongo/version.h @@ -3,10 +3,10 @@ #include "cmongo/config.h" -#define CMONGO_VERSION "1.0b-7" -#define CMONGO_VERSION_NAME "Beta 1.0b-7" -#define CMONGO_VERSION_DATE "05/04/2021" -#define CMONGO_VERSION_TIME "19:33 CST" +#define CMONGO_VERSION "1.0b-8" +#define CMONGO_VERSION_NAME "Beta 1.0b-8" +#define CMONGO_VERSION_DATE "12/04/2021" +#define CMONGO_VERSION_TIME "14:55 CST" #define CMONGO_VERSION_AUTHOR "Erick Salas" #ifdef __cplusplus diff --git a/version.txt b/version.txt index e8cfa86..6b17fd2 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0b-7 \ No newline at end of file +1.0b-8 \ No newline at end of file From 7ec547aec7fa69228fb7282d8ba9c58a0f025eed Mon Sep 17 00:00:00 2001 From: ermiry Date: Mon, 12 Apr 2021 17:32:31 -0500 Subject: [PATCH 61/75] Added missing mongo_find_all_populate_array_to_json export --- include/cmongo/crud.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index f5a9b62..e9363a7 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -71,6 +71,15 @@ CMONGO_EXPORT unsigned int mongo_find_all_populate_object_to_json ( char **json, size_t *json_len ); +// works like mongo_find_all_cursor_with_opts_to_json () +// but also populates the specified objects array +CMONGO_EXPORT unsigned int mongo_find_all_populate_array_to_json ( + const CMongoModel *model, + const char *from, const char *local_field, + const char *array_name, + char **json, size_t *json_len +); + // use a query to find all matching documents // an empty query will return all the docs in a collection CMONGO_EXPORT const bson_t **mongo_find_all ( From 67859cb12246fff9c7db44f535fe6f835066bdd8 Mon Sep 17 00:00:00 2001 From: ermiry Date: Mon, 12 Apr 2021 17:32:44 -0500 Subject: [PATCH 62/75] Changed mongo_find_all_internal () to be private --- src/cmongo/crud.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 787d739..29d129e 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -455,7 +455,7 @@ unsigned int mongo_find_all_populate_array_to_json ( } -const bson_t **mongo_find_all_internal ( +static const bson_t **mongo_find_all_internal ( mongoc_collection_t *collection, bson_t *query, const CMongoSelect *select, uint64_t *n_docs From 227b74fa5887a585e98bb440c9e5c08fc764ccd9 Mon Sep 17 00:00:00 2001 From: ermiry Date: Mon, 12 Apr 2021 17:36:56 -0500 Subject: [PATCH 63/75] Refactored mongo_find_all_to_json () return value Also changed name to be more accurate --- include/cmongo/crud.h | 24 +++---- src/cmongo/crud.c | 143 +++++++++++++++++++++--------------------- 2 files changed, 85 insertions(+), 82 deletions(-) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index e9363a7..b3924a8 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -52,17 +52,7 @@ CMONGO_EXPORT mongoc_cursor_t *mongo_find_all_cursor_with_opts ( bson_t *query, const bson_t *opts ); -// returns a new string in relaxed extended JSON format -// with all matching objects inside an array -// query gets destroyed, opts are kept the same -// returns 0 on success, 1 on error -CMONGO_EXPORT char *mongo_find_all_cursor_with_opts_to_json ( - const CMongoModel *model, - bson_t *query, const bson_t *opts, - const char *array_name, size_t *json_len -); - -// works like mongo_find_all_cursor_with_opts_to_json () +// works like mongo_find_all_to_json () // but also populates the specified object CMONGO_EXPORT unsigned int mongo_find_all_populate_object_to_json ( const CMongoModel *model, @@ -71,7 +61,7 @@ CMONGO_EXPORT unsigned int mongo_find_all_populate_object_to_json ( char **json, size_t *json_len ); -// works like mongo_find_all_cursor_with_opts_to_json () +// works like mongo_find_all_to_json () // but also populates the specified objects array CMONGO_EXPORT unsigned int mongo_find_all_populate_array_to_json ( const CMongoModel *model, @@ -93,6 +83,16 @@ CMONGO_EXPORT void mongo_find_all_destroy_docs ( bson_t **docs, uint64_t count ); +// returns a new string in relaxed extended JSON format +// with all matching objects inside an array +// query gets destroyed, opts are kept the same +CMONGO_EXPORT unsigned int mongo_find_all_to_json ( + const CMongoModel *model, + bson_t *query, const bson_t *opts, + const char *array_name, + char **json, size_t *json_len +); + // uses a query to find one doc with the specified options // query gets destroyed, opts are kept the same // returns 0 on success, 1 on error diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 29d129e..31061c9 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -232,71 +232,6 @@ mongoc_cursor_t *mongo_find_all_cursor_with_opts ( } -static char *mongo_find_all_cursor_with_opts_to_json_internal ( - mongoc_cursor_t *cursor, - const char *array_name, size_t *json_len -) { - - char *json = NULL; - - bson_t *doc = bson_new (); - if (doc) { - char buf[BSON_ARRAY_BUFFER_SIZE] = { 0 }; - const char *key = NULL; - size_t keylen = 0; - - bson_t json_array = BSON_INITIALIZER; - (void) bson_append_array_begin (doc, array_name, (int) strlen (array_name), &json_array); - - int i = 0; - const bson_t *object_doc = NULL; - while (mongoc_cursor_next (cursor, &object_doc)) { - keylen = bson_uint32_to_string (i, &key, buf, BSON_ARRAY_BUFFER_SIZE); - (void) bson_append_document (&json_array, key, (int) keylen, object_doc); - - bson_destroy ((bson_t *) object_doc); - - i++; - } - - (void) bson_append_array_end (doc, &json_array); - - json = bson_as_relaxed_extended_json (doc, json_len); - } - - return json; - -} - -// returns a new string in relaxed extended JSON format -// with all matching objects inside an array -// query gets destroyed, opts are kept the same -char *mongo_find_all_cursor_with_opts_to_json ( - const CMongoModel *model, - bson_t *query, const bson_t *opts, - const char *array_name, size_t *json_len -) { - - char *json = NULL; - - mongoc_cursor_t *cursor = mongo_find_all_cursor_with_opts ( - model, - query, opts - ); - - if (cursor) { - json = mongo_find_all_cursor_with_opts_to_json_internal ( - cursor, - array_name, json_len - ); - - mongoc_cursor_destroy (cursor); - } - - return json; - -} - static bson_t *mongo_find_all_populate_object_pipeline ( const char *from, const char *local_field ) { @@ -329,7 +264,7 @@ static bson_t *mongo_find_all_populate_object_pipeline ( } -// works like mongo_find_all_cursor_with_opts_to_json () +// works like mongo_find_all_to_json () // but also populates the specified object unsigned int mongo_find_all_populate_object_to_json ( const CMongoModel *model, @@ -358,7 +293,7 @@ unsigned int mongo_find_all_populate_object_to_json ( ); if (cursor) { - *json = mongo_find_all_cursor_with_opts_to_json_internal ( + *json = mongo_find_all_to_json_internal ( cursor, array_name, json_len ); @@ -403,7 +338,7 @@ static inline bson_t *mongo_find_all_populate_array_pipeline ( } -// works like mongo_find_all_cursor_with_opts_to_json () +// works like mongo_find_all_to_json () // but also populates the specified objects array unsigned int mongo_find_all_populate_array_to_json ( const CMongoModel *model, @@ -432,7 +367,7 @@ unsigned int mongo_find_all_populate_array_to_json ( ); if (cursor) { - *json = mongo_find_all_cursor_with_opts_to_json_internal ( + *json = mongo_find_all_to_json_internal ( cursor, array_name, json_len ); @@ -545,6 +480,74 @@ void mongo_find_all_destroy_docs ( } +static char *mongo_find_all_to_json_internal ( + mongoc_cursor_t *cursor, + const char *array_name, size_t *json_len +) { + + char *json = NULL; + + bson_t *doc = bson_new (); + if (doc) { + char buf[BSON_ARRAY_BUFFER_SIZE] = { 0 }; + const char *key = NULL; + size_t keylen = 0; + + bson_t json_array = BSON_INITIALIZER; + (void) bson_append_array_begin (doc, array_name, (int) strlen (array_name), &json_array); + + int i = 0; + const bson_t *object_doc = NULL; + while (mongoc_cursor_next (cursor, &object_doc)) { + keylen = bson_uint32_to_string (i, &key, buf, BSON_ARRAY_BUFFER_SIZE); + (void) bson_append_document (&json_array, key, (int) keylen, object_doc); + + bson_destroy ((bson_t *) object_doc); + + i++; + } + + (void) bson_append_array_end (doc, &json_array); + + json = bson_as_relaxed_extended_json (doc, json_len); + } + + return json; + +} + +// returns a new string in relaxed extended JSON format +// with all matching objects inside an array +// query gets destroyed, opts are kept the same +unsigned int mongo_find_all_to_json ( + const CMongoModel *model, + bson_t *query, const bson_t *opts, + const char *array_name, + char **json, size_t *json_len +) { + + unsigned int retval = 1; + + mongoc_cursor_t *cursor = mongo_find_all_cursor_with_opts ( + model, + query, opts + ); + + if (cursor) { + *json = mongo_find_all_to_json_internal ( + cursor, + array_name, json_len + ); + + mongoc_cursor_destroy (cursor); + + retval = 0; + } + + return retval; + +} + static unsigned int mongo_find_one_internal ( mongoc_collection_t *collection, bson_t *query, const bson_t *opts, @@ -1417,7 +1420,7 @@ unsigned int mongo_perform_aggregation_to_json ( ); if (cursor) { - *json = mongo_find_all_cursor_with_opts_to_json_internal ( + *json = mongo_find_all_to_json_internal ( cursor, array_name, json_len ); From 5a5a7d7f3f079fc8ee45c0f52b1cdaeefd044bb3 Mon Sep 17 00:00:00 2001 From: ermiry Date: Mon, 12 Apr 2021 17:38:49 -0500 Subject: [PATCH 64/75] Refactored mongo_find_all methods organization --- include/cmongo/crud.h | 36 ++--- src/cmongo/crud.c | 316 +++++++++++++++++++++--------------------- 2 files changed, 176 insertions(+), 176 deletions(-) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index b3924a8..4bd1352 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -52,24 +52,6 @@ CMONGO_EXPORT mongoc_cursor_t *mongo_find_all_cursor_with_opts ( bson_t *query, const bson_t *opts ); -// works like mongo_find_all_to_json () -// but also populates the specified object -CMONGO_EXPORT unsigned int mongo_find_all_populate_object_to_json ( - const CMongoModel *model, - const char *from, const char *local_field, - const char *array_name, - char **json, size_t *json_len -); - -// works like mongo_find_all_to_json () -// but also populates the specified objects array -CMONGO_EXPORT unsigned int mongo_find_all_populate_array_to_json ( - const CMongoModel *model, - const char *from, const char *local_field, - const char *array_name, - char **json, size_t *json_len -); - // use a query to find all matching documents // an empty query will return all the docs in a collection CMONGO_EXPORT const bson_t **mongo_find_all ( @@ -93,6 +75,24 @@ CMONGO_EXPORT unsigned int mongo_find_all_to_json ( char **json, size_t *json_len ); +// works like mongo_find_all_to_json () +// but also populates the specified object +CMONGO_EXPORT unsigned int mongo_find_all_populate_object_to_json ( + const CMongoModel *model, + const char *from, const char *local_field, + const char *array_name, + char **json, size_t *json_len +); + +// works like mongo_find_all_to_json () +// but also populates the specified objects array +CMONGO_EXPORT unsigned int mongo_find_all_populate_array_to_json ( + const CMongoModel *model, + const char *from, const char *local_field, + const char *array_name, + char **json, size_t *json_len +); + // uses a query to find one doc with the specified options // query gets destroyed, opts are kept the same // returns 0 on success, 1 on error diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 31061c9..ba059b3 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -232,164 +232,6 @@ mongoc_cursor_t *mongo_find_all_cursor_with_opts ( } -static bson_t *mongo_find_all_populate_object_pipeline ( - const char *from, const char *local_field -) { - - char unwind[CMONGO_UNWIND_VALUE_SIZE] = { 0 }; - (void) snprintf ( - unwind, CMONGO_UNWIND_VALUE_SIZE - 1, - "$%s", local_field - ); - - bson_t *pipeline = BCON_NEW ( - "pipeline", - "[", - "{", - "$lookup", "{", - "from", BCON_UTF8 (from), - "localField", BCON_UTF8 (local_field), - "foreignField", BCON_UTF8 ("_id"), - "as", BCON_UTF8 (local_field), - "}", - "}", - - "{", - "$unwind", BCON_UTF8 (unwind), - "}", - "]" - ); - - return pipeline; - -} - -// works like mongo_find_all_to_json () -// but also populates the specified object -unsigned int mongo_find_all_populate_object_to_json ( - const CMongoModel *model, - const char *from, const char *local_field, - const char *array_name, - char **json, size_t *json_len -) { - - unsigned int retval = 1; - - if (model && from && local_field) { - mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); - if (client) { - mongoc_collection_t *collection = mongoc_client_get_collection ( - client, mongo.db_name, model->collname - ); - - if (collection) { - bson_t *pipeline = mongo_find_all_populate_object_pipeline ( - from, local_field - ); - - if (pipeline) { - mongoc_cursor_t *cursor = mongoc_collection_aggregate ( - collection, 0, pipeline, NULL, NULL - ); - - if (cursor) { - *json = mongo_find_all_to_json_internal ( - cursor, array_name, json_len - ); - - mongoc_cursor_destroy (cursor); - - retval = 0; - } - - bson_destroy (pipeline); - } - - mongoc_collection_destroy (collection); - } - - mongoc_client_pool_push (mongo.pool, client); - } - } - - return retval; - -} - -static inline bson_t *mongo_find_all_populate_array_pipeline ( - const char *from, const char *local_field -) { - - bson_t *pipeline = BCON_NEW ( - "pipeline", - "[", - "{", - "$lookup", "{", - "from", BCON_UTF8 (from), - "localField", BCON_UTF8 (local_field), - "foreignField", BCON_UTF8 ("_id"), - "as", BCON_UTF8 (local_field), - "}", - "}", - "]" - ); - - return pipeline; - -} - -// works like mongo_find_all_to_json () -// but also populates the specified objects array -unsigned int mongo_find_all_populate_array_to_json ( - const CMongoModel *model, - const char *from, const char *local_field, - const char *array_name, - char **json, size_t *json_len -) { - - unsigned int retval = 1; - - if (model && from && local_field) { - mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); - if (client) { - mongoc_collection_t *collection = mongoc_client_get_collection ( - client, mongo.db_name, model->collname - ); - - if (collection) { - bson_t *pipeline = mongo_find_all_populate_array_pipeline ( - from, local_field - ); - - if (pipeline) { - mongoc_cursor_t *cursor = mongoc_collection_aggregate ( - collection, 0, pipeline, NULL, NULL - ); - - if (cursor) { - *json = mongo_find_all_to_json_internal ( - cursor, array_name, json_len - ); - - mongoc_cursor_destroy (cursor); - - retval = 0; - } - - bson_destroy (pipeline); - } - - mongoc_collection_destroy (collection); - } - - mongoc_client_pool_push (mongo.pool, client); - } - } - - return retval; - -} - static const bson_t **mongo_find_all_internal ( mongoc_collection_t *collection, bson_t *query, const CMongoSelect *select, @@ -548,6 +390,164 @@ unsigned int mongo_find_all_to_json ( } +static bson_t *mongo_find_all_populate_object_pipeline ( + const char *from, const char *local_field +) { + + char unwind[CMONGO_UNWIND_VALUE_SIZE] = { 0 }; + (void) snprintf ( + unwind, CMONGO_UNWIND_VALUE_SIZE - 1, + "$%s", local_field + ); + + bson_t *pipeline = BCON_NEW ( + "pipeline", + "[", + "{", + "$lookup", "{", + "from", BCON_UTF8 (from), + "localField", BCON_UTF8 (local_field), + "foreignField", BCON_UTF8 ("_id"), + "as", BCON_UTF8 (local_field), + "}", + "}", + + "{", + "$unwind", BCON_UTF8 (unwind), + "}", + "]" + ); + + return pipeline; + +} + +// works like mongo_find_all_to_json () +// but also populates the specified object +unsigned int mongo_find_all_populate_object_to_json ( + const CMongoModel *model, + const char *from, const char *local_field, + const char *array_name, + char **json, size_t *json_len +) { + + unsigned int retval = 1; + + if (model && from && local_field) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + bson_t *pipeline = mongo_find_all_populate_object_pipeline ( + from, local_field + ); + + if (pipeline) { + mongoc_cursor_t *cursor = mongoc_collection_aggregate ( + collection, 0, pipeline, NULL, NULL + ); + + if (cursor) { + *json = mongo_find_all_to_json_internal ( + cursor, array_name, json_len + ); + + mongoc_cursor_destroy (cursor); + + retval = 0; + } + + bson_destroy (pipeline); + } + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } + } + + return retval; + +} + +static inline bson_t *mongo_find_all_populate_array_pipeline ( + const char *from, const char *local_field +) { + + bson_t *pipeline = BCON_NEW ( + "pipeline", + "[", + "{", + "$lookup", "{", + "from", BCON_UTF8 (from), + "localField", BCON_UTF8 (local_field), + "foreignField", BCON_UTF8 ("_id"), + "as", BCON_UTF8 (local_field), + "}", + "}", + "]" + ); + + return pipeline; + +} + +// works like mongo_find_all_to_json () +// but also populates the specified objects array +unsigned int mongo_find_all_populate_array_to_json ( + const CMongoModel *model, + const char *from, const char *local_field, + const char *array_name, + char **json, size_t *json_len +) { + + unsigned int retval = 1; + + if (model && from && local_field) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + bson_t *pipeline = mongo_find_all_populate_array_pipeline ( + from, local_field + ); + + if (pipeline) { + mongoc_cursor_t *cursor = mongoc_collection_aggregate ( + collection, 0, pipeline, NULL, NULL + ); + + if (cursor) { + *json = mongo_find_all_to_json_internal ( + cursor, array_name, json_len + ); + + mongoc_cursor_destroy (cursor); + + retval = 0; + } + + bson_destroy (pipeline); + } + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } + } + + return retval; + +} + static unsigned int mongo_find_one_internal ( mongoc_collection_t *collection, bson_t *query, const bson_t *opts, From d34272a0bbc1c03cd721d9ab801d5cbb11fbe7f1 Mon Sep 17 00:00:00 2001 From: ermiry Date: Mon, 12 Apr 2021 17:40:41 -0500 Subject: [PATCH 65/75] Updated version to beta 1.0b-9 --- CHANGELOG.md | 7 ++++--- include/cmongo/version.h | 6 +++--- version.txt | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63677aa..ebcc13f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ -- Refactored mongo_find_one_custom_populate_array_to_json () -- Added mongo_find_all_populate_object_to_json () -- Added mongo_find_all_populate_array_to_json () \ No newline at end of file +- Added missing mongo_find_all_populate_array_to_json export +- Changed mongo_find_all_internal () to be private +- Refactored mongo_find_all_to_json () return value +- Refactored mongo_find_all methods organization \ No newline at end of file diff --git a/include/cmongo/version.h b/include/cmongo/version.h index aa7d0cc..808eb0e 100644 --- a/include/cmongo/version.h +++ b/include/cmongo/version.h @@ -3,10 +3,10 @@ #include "cmongo/config.h" -#define CMONGO_VERSION "1.0b-8" -#define CMONGO_VERSION_NAME "Beta 1.0b-8" +#define CMONGO_VERSION "1.0b-9" +#define CMONGO_VERSION_NAME "Beta 1.0b-9" #define CMONGO_VERSION_DATE "12/04/2021" -#define CMONGO_VERSION_TIME "14:55 CST" +#define CMONGO_VERSION_TIME "17:40 CST" #define CMONGO_VERSION_AUTHOR "Erick Salas" #ifdef __cplusplus diff --git a/version.txt b/version.txt index 6b17fd2..630d327 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0b-8 \ No newline at end of file +1.0b-9 \ No newline at end of file From aca8481be1f156a988b0e0f2c01d5d64cefcb1f6 Mon Sep 17 00:00:00 2001 From: ermiry Date: Sun, 18 Apr 2021 16:58:29 -0500 Subject: [PATCH 66/75] Added mongo_find_one_populate_array_with_object_to_json () --- include/cmongo/crud.h | 11 ++++++ src/cmongo/crud.c | 90 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index 4bd1352..aae80f5 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -165,6 +165,17 @@ CMONGO_EXPORT unsigned int mongo_find_one_populate_array_to_json ( char **json, size_t *json_len ); +// works like mongo_find_one_populate_array () +// but also populates an object inside an objects array +// and converts the result into a json string +// returns 0 on success, 1 on error +CMONGO_EXPORT unsigned int mongo_find_one_populate_array_with_object_to_json ( + const CMongoModel *model, + const bson_oid_t *oid, + const char *from, const char *local_field, + char **json, size_t *json_len +); + // returns a new string in relaxed extended JSON format // created with the result of an aggregation that represents // how a single object's array gets populated diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index ba059b3..25ecf78 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -1011,6 +1011,96 @@ unsigned int mongo_find_one_populate_array_to_json ( } +static inline bson_t *mongo_find_one_populate_array_with_object_pipeline ( + const bson_oid_t *oid, + const char *from, const char *local_field +) { + + char unwind[CMONGO_UNWIND_VALUE_SIZE] = { 0 }; + (void) snprintf ( + unwind, CMONGO_UNWIND_VALUE_SIZE - 1, + "$%s", local_field + ); + + bson_t *pipeline = BCON_NEW ( + "pipeline", + "[", + "{", + "$match", "{", "_id", BCON_OID (oid), "}", + "}", + "{", + "$unwind", BCON_UTF8 (unwind), + "}", + "{", + "$lookup", "{", + "from", BCON_UTF8 (from), + "localField", BCON_UTF8 (local_field), + "foreignField", BCON_UTF8 ("_id"), + "as", BCON_UTF8 (local_field), + "}", + "}", + "]" + ); + + return pipeline; + +} + +// works like mongo_find_one_populate_array () +// but also populates an object inside an objects array +// and converts the result into a json string +// returns 0 on success, 1 on error +unsigned int mongo_find_one_populate_array_with_object_to_json ( + const CMongoModel *model, + const bson_oid_t *oid, + const char *from, const char *local_field, + char **json, size_t *json_len +) { + + unsigned int retval = 1; + + if (model && oid && from && local_field) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + bson_t *pipeline = mongo_find_one_populate_array_with_object_pipeline ( + oid, from, local_field + ); + + if (pipeline) { + mongoc_cursor_t *cursor = mongoc_collection_aggregate ( + collection, 0, pipeline, NULL, NULL + ); + + if (cursor) { + const bson_t *doc = NULL; + if (mongoc_cursor_next (cursor, &doc)) { + *json = bson_as_relaxed_extended_json (doc, json_len); + } + + mongoc_cursor_destroy (cursor); + + retval = 0; + } + + bson_destroy (pipeline); + } + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } + } + + return retval; + +} + // returns a new string in relaxed extended JSON format // created with the result of an aggregation that represents // how a single object's array gets populated From b63844ab8f14f61a8067c9bf2e6020b7ce39160b Mon Sep 17 00:00:00 2001 From: ermiry Date: Sun, 18 Apr 2021 17:00:42 -0500 Subject: [PATCH 67/75] Updated version to beta 1.0b-10 --- CHANGELOG.md | 5 +---- include/cmongo/version.h | 8 ++++---- version.txt | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebcc13f..dafe372 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1 @@ -- Added missing mongo_find_all_populate_array_to_json export -- Changed mongo_find_all_internal () to be private -- Refactored mongo_find_all_to_json () return value -- Refactored mongo_find_all methods organization \ No newline at end of file +- Added mongo_find_one_populate_array_with_object_to_json () \ No newline at end of file diff --git a/include/cmongo/version.h b/include/cmongo/version.h index 808eb0e..d1b4a96 100644 --- a/include/cmongo/version.h +++ b/include/cmongo/version.h @@ -3,10 +3,10 @@ #include "cmongo/config.h" -#define CMONGO_VERSION "1.0b-9" -#define CMONGO_VERSION_NAME "Beta 1.0b-9" -#define CMONGO_VERSION_DATE "12/04/2021" -#define CMONGO_VERSION_TIME "17:40 CST" +#define CMONGO_VERSION "1.0b-10" +#define CMONGO_VERSION_NAME "Beta 1.0b-10" +#define CMONGO_VERSION_DATE "18/04/2021" +#define CMONGO_VERSION_TIME "17:00 CST" #define CMONGO_VERSION_AUTHOR "Erick Salas" #ifdef __cplusplus diff --git a/version.txt b/version.txt index 630d327..42d1a25 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0b-9 \ No newline at end of file +1.0b-10 \ No newline at end of file From bff7d0a97cdd10a240a949fa4b35188c958e103d Mon Sep 17 00:00:00 2001 From: ermiry Date: Sun, 18 Apr 2021 17:13:02 -0500 Subject: [PATCH 68/75] Added extra array name when populating array with object --- include/cmongo/crud.h | 2 +- src/cmongo/crud.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index aae80f5..bee4eec 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -172,7 +172,7 @@ CMONGO_EXPORT unsigned int mongo_find_one_populate_array_to_json ( CMONGO_EXPORT unsigned int mongo_find_one_populate_array_with_object_to_json ( const CMongoModel *model, const bson_oid_t *oid, - const char *from, const char *local_field, + const char *from, const char *array_name, const char *local_field, char **json, size_t *json_len ); diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 25ecf78..9c6b07b 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -1013,13 +1013,13 @@ unsigned int mongo_find_one_populate_array_to_json ( static inline bson_t *mongo_find_one_populate_array_with_object_pipeline ( const bson_oid_t *oid, - const char *from, const char *local_field + const char *from, const char *array_name, const char *local_field ) { char unwind[CMONGO_UNWIND_VALUE_SIZE] = { 0 }; (void) snprintf ( unwind, CMONGO_UNWIND_VALUE_SIZE - 1, - "$%s", local_field + "$%s", array_name ); bson_t *pipeline = BCON_NEW ( @@ -1053,7 +1053,7 @@ static inline bson_t *mongo_find_one_populate_array_with_object_pipeline ( unsigned int mongo_find_one_populate_array_with_object_to_json ( const CMongoModel *model, const bson_oid_t *oid, - const char *from, const char *local_field, + const char *from, const char *array_name, const char *local_field, char **json, size_t *json_len ) { @@ -1068,7 +1068,7 @@ unsigned int mongo_find_one_populate_array_with_object_to_json ( if (collection) { bson_t *pipeline = mongo_find_one_populate_array_with_object_pipeline ( - oid, from, local_field + oid, from, array_name, local_field ); if (pipeline) { From 82b9c8469ecf66efbb1c6f190bd995c8da2472be Mon Sep 17 00:00:00 2001 From: ermiry Date: Sun, 18 Apr 2021 17:14:33 -0500 Subject: [PATCH 69/75] Updated version to beta 1.0b-11 --- CHANGELOG.md | 2 +- include/cmongo/version.h | 6 +++--- version.txt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dafe372..a48ca95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1 +1 @@ -- Added mongo_find_one_populate_array_with_object_to_json () \ No newline at end of file +- Added extra array name when populating array with object \ No newline at end of file diff --git a/include/cmongo/version.h b/include/cmongo/version.h index d1b4a96..b0b6716 100644 --- a/include/cmongo/version.h +++ b/include/cmongo/version.h @@ -3,10 +3,10 @@ #include "cmongo/config.h" -#define CMONGO_VERSION "1.0b-10" -#define CMONGO_VERSION_NAME "Beta 1.0b-10" +#define CMONGO_VERSION "1.0b-11" +#define CMONGO_VERSION_NAME "Beta 1.0b-11" #define CMONGO_VERSION_DATE "18/04/2021" -#define CMONGO_VERSION_TIME "17:00 CST" +#define CMONGO_VERSION_TIME "17:14 CST" #define CMONGO_VERSION_AUTHOR "Erick Salas" #ifdef __cplusplus diff --git a/version.txt b/version.txt index 42d1a25..1790b46 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0b-10 \ No newline at end of file +1.0b-11 \ No newline at end of file From f0006584a981bd3ca9ff1ac4b13cbac0616c9dde Mon Sep 17 00:00:00 2001 From: ermiry Date: Tue, 20 Apr 2021 13:58:20 -0500 Subject: [PATCH 70/75] Added mongo_perform_single_aggregation () Allows to match a document by its id with a custom aggregation pipeline --- include/cmongo/crud.h | 12 +++++++++--- src/cmongo/crud.c | 40 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/include/cmongo/crud.h b/include/cmongo/crud.h index bee4eec..458e6fc 100644 --- a/include/cmongo/crud.h +++ b/include/cmongo/crud.h @@ -264,9 +264,15 @@ CMONGO_EXPORT mongoc_cursor_t *mongo_perform_aggregation ( const CMongoModel *model, bson_t *pipeline ); -// works like mongo_perform_aggregation () -// but outputs all the aggregation's result into an object -// useful when aggregation returns just one document +// finds one document by matching id with custom pipeline +// usefull when trying to perform custom populate methods +// returns 0 on success, 1 on error +CMONGO_EXPORT unsigned int mongo_perform_single_aggregation ( + const CMongoModel *model, bson_t *pipeline, void *output +); + +// works like mongo_perform_single_aggregation_to_json () +// but outputs the result directly into a json string // returns 0 on success, 1 on error CMONGO_EXPORT unsigned int mongo_perform_single_aggregation_to_json ( const CMongoModel *model, bson_t *pipeline, diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 9c6b07b..ed2fa87 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -1436,9 +1436,43 @@ mongoc_cursor_t *mongo_perform_aggregation ( } -// works like mongo_perform_aggregation () -// but outputs all the aggregation's result into an object -// useful when aggregation returns just one document +// finds one document by matching id with custom pipeline +// usefull when trying to perform custom populate methods +// returns 0 on success, 1 on error +unsigned int mongo_perform_single_aggregation ( + const CMongoModel *model, bson_t *pipeline, void *output +) { + + unsigned int retval = 1; + + if (model && pipeline) { + mongoc_client_t *client = mongoc_client_pool_pop (mongo.pool); + if (client) { + mongoc_collection_t *collection = mongoc_client_get_collection ( + client, mongo.db_name, model->collname + ); + + if (collection) { + retval = mongo_find_one_aggregate_internal ( + collection, pipeline, + output, model->model_parser + ); + + mongoc_collection_destroy (collection); + } + + mongoc_client_pool_push (mongo.pool, client); + } + + bson_destroy (pipeline); + } + + return retval; + +} + +// works like mongo_perform_single_aggregation_to_json () +// but outputs the result directly into a json string // returns 0 on success, 1 on error unsigned int mongo_perform_single_aggregation_to_json ( const CMongoModel *model, bson_t *pipeline, From be55061d46433974d408d180b6a5e5b8682b4f33 Mon Sep 17 00:00:00 2001 From: ermiry Date: Tue, 20 Apr 2021 14:03:22 -0500 Subject: [PATCH 71/75] Updated version to beta 1.0b-12 --- CHANGELOG.md | 2 +- include/cmongo/version.h | 8 ++++---- version.txt | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a48ca95..5fa7c42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1 +1 @@ -- Added extra array name when populating array with object \ No newline at end of file +- Added mongo_perform_single_aggregation () \ No newline at end of file diff --git a/include/cmongo/version.h b/include/cmongo/version.h index b0b6716..10d7e6b 100644 --- a/include/cmongo/version.h +++ b/include/cmongo/version.h @@ -3,10 +3,10 @@ #include "cmongo/config.h" -#define CMONGO_VERSION "1.0b-11" -#define CMONGO_VERSION_NAME "Beta 1.0b-11" -#define CMONGO_VERSION_DATE "18/04/2021" -#define CMONGO_VERSION_TIME "17:14 CST" +#define CMONGO_VERSION "1.0b-12" +#define CMONGO_VERSION_NAME "Beta 1.0b-12" +#define CMONGO_VERSION_DATE "20/04/2021" +#define CMONGO_VERSION_TIME "13:58 CST" #define CMONGO_VERSION_AUTHOR "Erick Salas" #ifdef __cplusplus diff --git a/version.txt b/version.txt index 1790b46..17fc5f4 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0b-11 \ No newline at end of file +1.0b-12 \ No newline at end of file From 855ee406dcefd0afc2deb329264235604951b3ee Mon Sep 17 00:00:00 2001 From: ermiry Date: Sat, 5 Jun 2021 19:03:02 -0500 Subject: [PATCH 72/75] Refactored mongo_count_docs_internal () --- src/cmongo/crud.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index ed2fa87..3142d3a 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -25,22 +25,29 @@ static int64_t mongo_count_docs_internal ( mongoc_collection_t *collection, bson_t *query ) { - int64_t retval = 0; + int64_t count = 0; + #ifdef CMONGO_DEBUG bson_error_t error = { 0 }; - retval = mongoc_collection_count_documents ( + + count = mongoc_collection_count_documents ( collection, query, NULL, NULL, NULL, &error ); - if (retval < 0) { + if (count < 0) { (void) fprintf ( - stderr, "[MONGO][ERROR]: %s", error.message + stderr, "[MONGO][ERROR]: %s\n", error.message ); - retval = 0; + count = 0; } + #else + count = mongoc_collection_count_documents ( + collection, query, NULL, NULL, NULL, NULL + ); + #endif - return retval; + return count; } @@ -96,11 +103,9 @@ bool mongo_check ( ); if (collection) { - bson_error_t error = { 0 }; - - retval = mongoc_collection_count_documents ( - collection, query, NULL, NULL, NULL, &error - ); + if (mongo_count_docs_internal (collection, query) > 0) { + retval = true; + } mongoc_collection_destroy (collection); } From 5cb88eff44c99f54a8684163ef332ecfe8f1965e Mon Sep 17 00:00:00 2001 From: ermiry Date: Sat, 5 Jun 2021 19:03:41 -0500 Subject: [PATCH 73/75] Removed bson_copy (query) in find all methods --- src/cmongo/crud.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 3142d3a..0baabbf 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -175,8 +175,8 @@ mongoc_cursor_t *mongo_find_all_cursor ( ); if (collection) { - uint64_t count = mongo_count_docs_internal ( - collection, bson_copy (query) + uint64_t count = (uint64_t) mongo_count_docs_internal ( + collection, query ); if (count > 0) { @@ -245,7 +245,7 @@ static const bson_t **mongo_find_all_internal ( const bson_t **retval = NULL; - uint64_t count = mongo_count_docs_internal (collection, bson_copy (query)); + uint64_t count = (uint64_t) mongo_count_docs_internal (collection, query); if (count > 0) { retval = (const bson_t **) calloc (count, sizeof (bson_t *)); for (uint64_t i = 0; i < count; i++) retval[i] = bson_new (); From 6e9513e832d903da81920f36883c2116d47f331f Mon Sep 17 00:00:00 2001 From: ermiry Date: Sat, 5 Jun 2021 19:03:57 -0500 Subject: [PATCH 74/75] Refactored crud methods to print errors in dev --- src/cmongo/crud.c | 122 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 109 insertions(+), 13 deletions(-) diff --git a/src/cmongo/crud.c b/src/cmongo/crud.c index 0baabbf..2ab9dca 100644 --- a/src/cmongo/crud.c +++ b/src/cmongo/crud.c @@ -1177,11 +1177,27 @@ unsigned int mongo_insert_one ( ); if (collection) { + #ifdef CMONGO_DEBUG bson_error_t error = { 0 }; - retval = mongoc_collection_insert_one ( + if (mongoc_collection_insert_one ( collection, doc, NULL, NULL, &error - ) ? 0 : 1; + )) { + retval = 0; + } + + else { + (void) fprintf ( + stderr, "[MONGO][ERROR]: %s\n", error.message + ); + } + #else + if (mongoc_collection_insert_one ( + collection, doc, NULL, NULL, NULL + )) { + retval = 0; + } + #endif mongoc_collection_destroy (collection); } @@ -1214,11 +1230,27 @@ unsigned int mongo_insert_many ( ); if (collection) { + #ifdef CMONGO_DEBUG bson_error_t error = { 0 }; - retval = mongoc_collection_insert_many ( + if (mongoc_collection_insert_many ( collection, docs, n_docs, NULL, NULL, &error - ) ? 0 : 1; + )) { + retval = 0; + } + + else { + (void) fprintf ( + stderr, "[MONGO][ERROR]: %s\n", error.message + ); + } + #else + if (mongoc_collection_insert_many ( + collection, docs, n_docs, NULL, NULL, NULL + )) { + retval = 0; + } + #endif mongoc_collection_destroy (collection); } @@ -1253,11 +1285,27 @@ unsigned int mongo_update_one ( ); if (collection) { + #ifdef CMONGO_DEBUG bson_error_t error = { 0 }; - retval = mongoc_collection_update_one ( + if (mongoc_collection_update_one ( collection, query, update, NULL, NULL, &error - ) ? 0 : 1; + )) { + retval = 0; + } + + else { + (void) fprintf ( + stderr, "[MONGO][ERROR]: %s\n", error.message + ); + } + #else + if (mongoc_collection_update_one ( + collection, query, update, NULL, NULL, NULL + )) { + retval = 0; + } + #endif mongoc_collection_destroy (collection); } @@ -1291,11 +1339,27 @@ unsigned int mongo_update_many ( ); if (collection) { + #ifdef CMONGO_DEBUG bson_error_t error = { 0 }; - retval = mongoc_collection_update_many ( + if (mongoc_collection_update_many ( collection, query, update, NULL, NULL, &error - ) ? 0 : 1; + )) { + retval = 0; + } + + else { + (void) fprintf ( + stderr, "[MONGO][ERROR]: %s\n", error.message + ); + } + #else + if (mongoc_collection_update_many ( + collection, query, update, NULL, NULL, NULL + )) { + retval = 0; + } + #endif mongoc_collection_destroy (collection); } @@ -1332,11 +1396,27 @@ unsigned int mongo_delete_one ( ); if (collection) { + #ifdef CMONGO_DEBUG bson_error_t error = { 0 }; - retval = mongoc_collection_delete_one ( + if (mongoc_collection_delete_one ( collection, query, NULL, NULL, &error - ) ? 0 : 1; + )) { + retval = 0; + } + + else { + (void) fprintf ( + stderr, "[MONGO][ERROR]: %s\n", error.message + ); + } + #else + if (mongoc_collection_delete_one ( + collection, query, NULL, NULL, NULL + )) { + retval = 0; + } + #endif mongoc_collection_destroy (collection); } @@ -1368,11 +1448,27 @@ unsigned int mongo_delete_many ( ); if (collection) { + #ifdef CMONGO_DEBUG bson_error_t error = { 0 }; - retval = mongoc_collection_delete_many ( + if (mongoc_collection_delete_many ( collection, query, NULL, NULL, &error - ) ? 0 : 1; + )) { + retval = 0; + } + + else { + (void) fprintf ( + stderr, "[MONGO][ERROR]: %s\n", error.message + ); + } + #else + if (mongoc_collection_delete_many ( + collection, query, NULL, NULL, NULL + )) { + retval = 0; + } + #endif mongoc_collection_destroy (collection); } @@ -1575,4 +1671,4 @@ unsigned int mongo_perform_aggregation_to_json ( #ifdef __cplusplus #pragma GCC diagnostic pop -#endif \ No newline at end of file +#endif From 5e31af2279170d4d581008e947f669716a33c622 Mon Sep 17 00:00:00 2001 From: ermiry Date: Sat, 19 Jun 2021 14:51:28 -0500 Subject: [PATCH 75/75] Updated version to beta 1.0b-13 --- CHANGELOG.md | 4 +++- include/cmongo/version.h | 10 +++++----- version.txt | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fa7c42..dc534c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1 +1,3 @@ -- Added mongo_perform_single_aggregation () \ No newline at end of file +- Refactored mongo_count_docs_internal () +- Removed bson_copy (query) in find all methods +- Refactored crud methods to print errors in dev \ No newline at end of file diff --git a/include/cmongo/version.h b/include/cmongo/version.h index 10d7e6b..009a3a2 100644 --- a/include/cmongo/version.h +++ b/include/cmongo/version.h @@ -3,11 +3,11 @@ #include "cmongo/config.h" -#define CMONGO_VERSION "1.0b-12" -#define CMONGO_VERSION_NAME "Beta 1.0b-12" -#define CMONGO_VERSION_DATE "20/04/2021" -#define CMONGO_VERSION_TIME "13:58 CST" -#define CMONGO_VERSION_AUTHOR "Erick Salas" +#define CMONGO_VERSION "1.0b-13" +#define CMONGO_VERSION_NAME "Beta 1.0b-13" +#define CMONGO_VERSION_DATE "19/06/2021" +#define CMONGO_VERSION_TIME "14:51 CST" +#define CMONGO_VERSION_AUTHOR "Erick Salas" #ifdef __cplusplus extern "C" { diff --git a/version.txt b/version.txt index 17fc5f4..394835b 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0b-12 \ No newline at end of file +1.0b-13 \ No newline at end of file