From cb9361fcc92f948e3dbb2bae32155561a43dd7ff Mon Sep 17 00:00:00 2001 From: avsdev-cw Date: Fri, 2 Oct 2020 12:46:21 +0100 Subject: [PATCH] Collection of changes (mostly to db source) - Replaced string malloc()... calls with strmemcpy() from strext.h where appropriate - Added table name to column struct (useful for WHERE's) - Changed the column type enum to powers of 2 (potential for NULLABLE flag by or'ing) - Added last_qry and num_queries to connection struct - Fixed destruct tables stopping on error - Renamed owners to users except in the meta table - Fixed the 'tableExists' query --- src/db_column.c | 29 +++++++++++++++-------------- src/db_column.h | 35 +++++++++++++++++++---------------- src/db_connection.c | 23 +++++++++++------------ src/db_connection.h | 6 ++++++ src/db_query.c | 33 ++++++++++++++++++++++++--------- src/db_value.c | 14 ++------------ src/modb.c | 36 ++++++++++++++++++------------------ src/modb_p.c | 18 +++++++++--------- src/modb_p.h | 8 ++++---- 9 files changed, 108 insertions(+), 94 deletions(-) diff --git a/src/db_column.c b/src/db_column.c index df2137e..98b8c62 100644 --- a/src/db_column.c +++ b/src/db_column.c @@ -5,6 +5,7 @@ #include #include "db_column.h" +#include "strext.h" size_t columnTypeToByteSize(e_column_type type) @@ -111,7 +112,7 @@ e_column_type simplifyFieldType(enum enum_field_types sql_type, int is_unsigned) struct column_data_t *initEmptyColumn(e_column_type type, int nullable, const char *name, - size_t name_len) + size_t name_len, const char *table, size_t table_len) { struct column_data_t *col; @@ -126,15 +127,18 @@ struct column_data_t *initEmptyColumn(e_column_type type, int nullable, const ch } memset(col, 0, sizeof(struct column_data_t)); - col->name_len = name_len; - col->name = (char*)malloc(col->name_len + 1); - if (col->name == NULL) { - fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno)); + if (strmemcpy(name, name_len, &col->name, &col->name_len) != 0) { free(col); return 0; } - memcpy(col->name, name, col->name_len); - *(col->name + col->name_len) = '\0'; + + if (table != 0) { + if (strmemcpy(table, table_len, &col->table, &col->table_len) != 0) { + free(col->name); + free(col); + return 0; + } + } col->type = type; col->type_bytes = columnTypeToByteSize(col->type); @@ -174,7 +178,9 @@ struct column_data_t *columnFromResult(struct stored_conn_t *sconn, MYSQL_RES *r simplifyFieldType(field->type, (field->flags & UNSIGNED_FLAG) > 0), (field->flags & NOT_NULL_FLAG) == 0, field->name, - field->name_length + field->name_length, + field->table, + field->table_length ); if (col == 0 || num_rows == 0) { @@ -342,14 +348,9 @@ int setColumnValue(struct column_data_t *col, uint64_t row, const char *value, s case TYPE_BLOB: case TYPE_RAW: { - *(col->data.ptr_str + row) = (char *)malloc(value_size + 1); - if (*(col->data.ptr_str + row) == 0) { - fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno)); + if (strmemcpy(value, value_size, (col->data.ptr_str + row), (col->data_lens + row)) != 0) { return -1; } - memcpy(*(col->data.ptr_str + row), value, value_size); - *(*(col->data.ptr_str + row) + value_size) = '\0'; - *(col->data_lens + row) = value_size; break; } } diff --git a/src/db_column.h b/src/db_column.h index 779b29e..5a96641 100644 --- a/src/db_column.h +++ b/src/db_column.h @@ -8,25 +8,28 @@ #include "db_connection.h" enum e_column_type_t { - TYPE_RAW, - TYPE_BOOL, - TYPE_INT8, - TYPE_UINT8, - TYPE_INT16, - TYPE_UINT16, - TYPE_INT32, - TYPE_UINT32, - TYPE_INT64, - TYPE_UINT64, - TYPE_FLOAT, - TYPE_DOUBLE, - TYPE_STRING, - TYPE_BLOB, - TYPE_TIMESTAMP + TYPE_RAW = 0 << 0, + TYPE_BOOL = 1 << 0, + TYPE_INT8 = 1 << 1, + TYPE_UINT8 = 1 << 2, + TYPE_INT16 = 1 << 3, + TYPE_UINT16 = 1 << 4, + TYPE_INT32 = 1 << 5, + TYPE_UINT32 = 1 << 6, + TYPE_INT64 = 1 << 7, + TYPE_UINT64 = 1 << 8, + TYPE_FLOAT = 1 << 9, + TYPE_DOUBLE = 1 << 10, + TYPE_STRING = 1 << 11, + TYPE_BLOB = 1 << 12, + TYPE_TIMESTAMP = 1 << 13 }; typedef enum e_column_type_t e_column_type; struct column_data_t { + char *table; + size_t table_len; + char *name; size_t name_len; @@ -86,7 +89,7 @@ static inline void columnRowClearNull(struct column_data_t *col, uint64_t row) } struct column_data_t *initEmptyColumn(e_column_type type, int nullable, const char *name, - size_t name_len); + size_t name_len, const char *table, size_t table_len); struct column_data_t *columnFromResult(struct stored_conn_t *sconn, MYSQL_RES *result, uint64_t num_rows); void freeColumn(struct column_data_t *col); diff --git a/src/db_connection.c b/src/db_connection.c index d9c1992..3873106 100644 --- a/src/db_connection.c +++ b/src/db_connection.c @@ -7,6 +7,7 @@ #include "db_connection.h" #include "db_timeout.h" #include "db_transaction.h" +#include "strext.h" static struct stored_conn_t *storedConnections = 0; @@ -72,16 +73,11 @@ struct stored_conn_t *createStoredConnection(const char *name) fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno)); return 0; } + memset(sconn, 0, sizeof(struct stored_conn_t)); sconn->conn_id = nextConnId++; - sconn->name = 0; sconn->conn = (MYSQL *)malloc(sizeof(MYSQL)); - sconn->isOpen = 0; - sconn->inTransaction = 0; - sconn->needsReset = 0; sconn->timeout = (unsigned int)-1; - sconn->prev = 0; - sconn->next = 0; if (sconn->conn == 0) { fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno)); @@ -90,15 +86,10 @@ struct stored_conn_t *createStoredConnection(const char *name) } if (name && strlen(name) > 0) { - sconn->name_len = sizeof(char) * strlen(name); - sconn->name = (char *)malloc(sconn->name_len + 1); - if (sconn->name == 0) { - fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno)); + if (strmemcpy(name, strlen(name), &sconn->name, &sconn->name_len) != 0) { destroyStoredConnection(sconn); return 0; } - memcpy(sconn->name, name, sconn->name_len); - sconn->name[sconn->name_len] = '\0'; } if (mysql_init(SQCONN(sconn)) == 0) { @@ -157,9 +148,17 @@ void destroyStoredConnection(struct stored_conn_t *sconn) closeConnection(sconn); } + if (sconn->last_qry) { + free(sconn->last_qry); + sconn->last_qry = 0; + sconn->last_qry_alloc = 0; + sconn->last_qry_len = 0; + } + if (sconn->name) { free(sconn->name); sconn->name = 0; + sconn->name_len = 0; } if (sconn->conn) { diff --git a/src/db_connection.h b/src/db_connection.h index fe46936..1e61ea6 100644 --- a/src/db_connection.h +++ b/src/db_connection.h @@ -13,6 +13,12 @@ struct stored_conn_t { void *conn; + char *last_qry; + size_t last_qry_len; + size_t last_qry_alloc; + + uint32_t num_queries; + uint8_t isOpen :1; uint8_t inTransaction :1; uint8_t needsReset :1; diff --git a/src/db_query.c b/src/db_query.c index b1075c0..a15e872 100644 --- a/src/db_query.c +++ b/src/db_query.c @@ -3,8 +3,10 @@ #include #include #include + #include "db_connection.h" #include "db_column.h" +#include "strext.h" uint64_t simpleQuery(struct stored_conn_t *sconn, const char *qry, size_t qry_len) @@ -13,6 +15,8 @@ uint64_t simpleQuery(struct stored_conn_t *sconn, const char *qry, size_t qry_le printf("QRY: %s\n", qry); #endif + char *old_ptr; + if (mysql_real_query(SQCONN(sconn), qry, qry_len) != 0) { fprintf( stderr, "[%d]mysql_real_query: (%d) %s\n", @@ -21,6 +25,22 @@ uint64_t simpleQuery(struct stored_conn_t *sconn, const char *qry, size_t qry_le return (uint64_t)-1; } + if (sconn->last_qry_alloc < qry_len + 1) { + old_ptr = sconn->last_qry; + sconn->last_qry = realloc(sconn->last_qry, qry_len + 1); + if (sconn->last_qry == 0) { + sconn->last_qry = old_ptr; + fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno)); + return (uint64_t)-1; + } + sconn->last_qry_alloc = qry_len + 1; + } + + memcpy(sconn->last_qry, qry, qry_len); + sconn->last_qry[qry_len] = '\0'; + sconn->last_qry_len = qry_len; + sconn->num_queries++; + return mysql_insert_id(SQCONN(sconn)); } @@ -50,8 +70,6 @@ uint64_t tableQuery(struct stored_conn_t *sconn, const char *qry, size_t qry_len (*n_cols) = 1; } if (*n_cols == 0) { - // insert/update query - // TODO: res = makeInt64() // lastInsertId return insertId; } @@ -75,7 +93,8 @@ uint64_t tableQuery(struct stored_conn_t *sconn, const char *qry, size_t qry_len n_rows = mysql_num_rows(result); if (scalar_result && n_rows > 1) { - // TODO: throw warning due to column sizing issue + fprintf(stderr, "[%d]tableQuery: WARN: scalar_result expects 1 row, " + "%llu rows returned from query. Using first result only\n", __LINE__, n_rows); n_rows = 1; } @@ -236,7 +255,7 @@ char *scalarString(struct stored_conn_t *sconn, const char *qry, size_t qry_len, char *default_value) { struct column_data_t **col_data; - size_t n_cols; + size_t n_cols, len; char *retval = NULL; uint64_t n_rows = tableQuery(sconn, qry, qry_len, 1, &col_data, &n_cols); @@ -246,15 +265,11 @@ char *scalarString(struct stored_conn_t *sconn, const char *qry, size_t qry_len, if (n_rows > 0) { if (!((*col_data)->isNullable && columnRowIsNull(*col_data, 0))) { - retval = (char *)malloc((*col_data)->data_lens[0] + 1); - if (retval == 0) { - fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno)); + if (strmemcpy(*((*col_data)->data.ptr_str), (*col_data)->data_lens[0], &retval, &len) != 0) { freeColumn(*col_data); free(col_data); return NULL; } - memcpy(retval, *((*col_data)->data.ptr_str), (*col_data)->data_lens[0]); - retval[(*col_data)->data_lens[0]] = '\0'; } } diff --git a/src/db_value.c b/src/db_value.c index 2f58384..6c0feed 100644 --- a/src/db_value.c +++ b/src/db_value.c @@ -114,14 +114,9 @@ char *db_value_va(char **str, size_t *len, e_column_type type, uint32_t n_args, } if (tmp_str == 0) { - esc_str = (char *)malloc(5); - if (esc_str == 0) { - fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno)); + if (strmemcpy("NULL", 4, &esc_str, &esc_len) != 0) { return 0; } - memcpy(esc_str, "NULL", 4); - esc_str[4] = '\0'; - esc_len = 4; break; } @@ -161,14 +156,9 @@ char *db_value_va(char **str, size_t *len, e_column_type type, uint32_t n_args, tmp_str = va_arg(args, char *); tmp_len = va_arg(args, size_t); - esc_str = (char *)malloc(tmp_len + 1); - if (esc_str == 0) { - fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno)); + if (strmemcpy(tmp_str, tmp_len, &esc_str, &esc_len) != 0) { return 0; } - memcpy(esc_str, tmp_str, tmp_len); - esc_str[tmp_len] = '\0'; - break; } } diff --git a/src/modb.c b/src/modb.c index f8d7926..49c4f16 100644 --- a/src/modb.c +++ b/src/modb.c @@ -38,26 +38,26 @@ int modbExists(struct stored_conn_t *sconn, struct modb_t *modb) } int modbDestroy(struct stored_conn_t *sconn, struct modb_t *modb) { - int err = 0 - || destroyTable(sconn, modb, MDO_GROUPS_TABLE, STR_LEN(MDO_GROUPS_TABLE)) - || destroyTable(sconn, modb, OBJECTS_TABLE, STR_LEN(OBJECTS_TABLE)) - || destroyTable(sconn, modb, META_TABLE, STR_LEN(META_TABLE)) - || destroyTable(sconn, modb, SYS_TABLE, STR_LEN(SYS_TABLE)); + uint64_t err = 0 + | destroyTable(sconn, modb, MDO_GROUPS_TABLE, STR_LEN(MDO_GROUPS_TABLE)) + | destroyTable(sconn, modb, OBJECTS_TABLE, STR_LEN(OBJECTS_TABLE)) + | destroyTable(sconn, modb, META_TABLE, STR_LEN(META_TABLE)) + | destroyTable(sconn, modb, SYS_TABLE, STR_LEN(SYS_TABLE)); return err == 0; } int modbAccountingCreate(struct stored_conn_t *sconn, struct modb_t *modb) { - if (createOwnersTable(sconn, modb) == (uint64_t)-1) { + if (createUsersTable(sconn, modb) == (uint64_t)-1) { return -1; } if (createGroupsTable(sconn, modb) == (uint64_t)-1) { - destroyTable(sconn, modb, OWNERS_TABLE, STR_LEN(OWNERS_TABLE)); + destroyTable(sconn, modb, USERS_TABLE, STR_LEN(USERS_TABLE)); return -1; } - if (createOwnerGroupsTable(sconn, modb) == (uint64_t)-1) { + if (createUserGroupsTable(sconn, modb) == (uint64_t)-1) { destroyTable(sconn, modb, GROUPS_TABLE, STR_LEN(GROUPS_TABLE)); - destroyTable(sconn, modb, OWNERS_TABLE, STR_LEN(OWNERS_TABLE)); + destroyTable(sconn, modb, USERS_TABLE, STR_LEN(USERS_TABLE)); return -1; } @@ -65,15 +65,15 @@ int modbAccountingCreate(struct stored_conn_t *sconn, struct modb_t *modb) } int modbAccountingExists(struct stored_conn_t *sconn, struct modb_t *modb) { - return tableExists(sconn, modb, OWNERS_TABLE, STR_LEN(OWNERS_TABLE)); + return tableExists(sconn, modb, USERS_TABLE, STR_LEN(USERS_TABLE)); } int modbAccountingDestroy(struct stored_conn_t *sconn, struct modb_t *modb) { - int err = 0 - || destroyTable(sconn, modb, OWNER_GROUPS_TABLE, STR_LEN(OWNER_GROUPS_TABLE)) - || destroyTable(sconn, modb, GROUPS_TABLE, STR_LEN(GROUPS_TABLE)) - || destroyTable(sconn, modb, OWNERS_TABLE, STR_LEN(OWNERS_TABLE)); - return err; + uint64_t err = 0 + | destroyTable(sconn, modb, USER_GROUPS_TABLE, STR_LEN(USER_GROUPS_TABLE)) + | destroyTable(sconn, modb, GROUPS_TABLE, STR_LEN(GROUPS_TABLE)) + | destroyTable(sconn, modb, USERS_TABLE, STR_LEN(USERS_TABLE)); + return err == 0; } int modbMetaExtCreate(struct stored_conn_t *sconn, struct modb_t *modb, @@ -119,7 +119,7 @@ int modbMetaExtExists(struct stored_conn_t *sconn, struct modb_t *modb) } int modbMetaExtDestroy(struct stored_conn_t *sconn, struct modb_t *modb) { - int err = 0 - || destroyTable(sconn, modb, META_EXT_TABLE, STR_LEN(META_EXT_TABLE)); - return err; + uint64_t err = 0 + | destroyTable(sconn, modb, META_EXT_TABLE, STR_LEN(META_EXT_TABLE)); + return err == 0; } diff --git a/src/modb_p.c b/src/modb_p.c index 8b9281a..0a967fa 100644 --- a/src/modb_p.c +++ b/src/modb_p.c @@ -126,7 +126,7 @@ uint64_t createMDOGroupsTable(struct stored_conn_t *sconn, struct modb_t *modb) return res; } -uint64_t createOwnersTable(struct stored_conn_t *sconn, struct modb_t *modb) +uint64_t createUsersTable(struct stored_conn_t *sconn, struct modb_t *modb) { char *qry; uint64_t res; @@ -138,7 +138,7 @@ uint64_t createOwnersTable(struct stored_conn_t *sconn, struct modb_t *modb) } strbld_str(sb, "CREATE TABLE `", 0); strbld_str(sb, modb->name, modb->name_len); - strbld_str(sb, OWNERS_TABLE, STR_LEN(OWNERS_TABLE)); + strbld_str(sb, USERS_TABLE, STR_LEN(USERS_TABLE)); strbld_str(sb, "` ", 2); strbld_str(sb, "(" "`id` INT UNSIGNED NOT NULL, " @@ -189,7 +189,7 @@ uint64_t createGroupsTable(struct stored_conn_t *sconn, struct modb_t *modb) return res; } -uint64_t createOwnerGroupsTable(struct stored_conn_t *sconn, struct modb_t *modb) +uint64_t createUserGroupsTable(struct stored_conn_t *sconn, struct modb_t *modb) { char *qry; uint64_t res; @@ -201,12 +201,12 @@ uint64_t createOwnerGroupsTable(struct stored_conn_t *sconn, struct modb_t *modb } strbld_str(sb, "CREATE TABLE `", 0); strbld_str(sb, modb->name, modb->name_len); - strbld_str(sb, OWNER_GROUPS_TABLE, STR_LEN(OWNER_GROUPS_TABLE)); + strbld_str(sb, USER_GROUPS_TABLE, STR_LEN(USER_GROUPS_TABLE)); strbld_str(sb, "` ", 2); strbld_str(sb, "(" - "`owner_id` INT UNSIGNED NOT NULL, " + "`user_id` INT UNSIGNED NOT NULL, " "`group_id` INT UNSIGNED NOT NULL, " - "INDEX(`owner_id`), " + "INDEX(`user_id`), " "INDEX(`group_id`)" ")", 0); if (strbld_finalize_or_destroy(&sb, &qry, &qry_len) != 0) { @@ -239,7 +239,7 @@ int tableExists(struct stored_conn_t *sconn, struct modb_t *modb, } res = scalarString(sconn, qry, qry_len, "Z"); - if (res == 0 || strncmp(res, "Z", 1) == 0 || strlen(res) != modb->name_len) { + if (res == 0 || strlen(res) != (modb->name_len + suffix_len)) { retval = -1; } else { retval = strncmp(res, modb->name, modb->name_len) == 0; @@ -335,9 +335,9 @@ char *createColString(struct column_data_t *col) } if (col->isNullable) { - strbld_str(sb, " NOT NULL", 0); - } else { strbld_str(sb, " NULL", 0); + } else { + strbld_str(sb, " NOT NULL", 0); } if (strbld_finalize_or_destroy(&sb, &colstr, &colstr_len) != 0) { diff --git a/src/modb_p.h b/src/modb_p.h index 538b9de..7e081cb 100644 --- a/src/modb_p.h +++ b/src/modb_p.h @@ -14,9 +14,9 @@ #define OBJECTS_TABLE "_objects" #define MDO_GROUPS_TABLE "_mdo_groups" -#define OWNERS_TABLE "_owner" +#define USERS_TABLE "_users" #define GROUPS_TABLE "_groups" -#define OWNER_GROUPS_TABLE "_owner_groups" +#define USER_GROUPS_TABLE "_user_groups" #define META_EXT_TABLE "_meta_ext" @@ -26,9 +26,9 @@ uint64_t createMetaTable(struct stored_conn_t *sconn, struct modb_t *modb); uint64_t createObjectsTable(struct stored_conn_t *sconn, struct modb_t *modb); uint64_t createMDOGroupsTable(struct stored_conn_t *sconn, struct modb_t *modb); -uint64_t createOwnersTable(struct stored_conn_t *sconn, struct modb_t *modb); +uint64_t createUsersTable(struct stored_conn_t *sconn, struct modb_t *modb); uint64_t createGroupsTable(struct stored_conn_t *sconn, struct modb_t *modb); -uint64_t createOwnerGroupsTable(struct stored_conn_t *sconn, struct modb_t *modb); +uint64_t createUserGroupsTable(struct stored_conn_t *sconn, struct modb_t *modb); int tableExists(struct stored_conn_t *sconn, struct modb_t *modb, const char *suffix, size_t suffix_len);