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
This commit is contained in:
2020-10-02 12:46:21 +01:00
parent 6c8bab8da6
commit cb9361fcc9
9 changed files with 108 additions and 94 deletions

View File

@@ -5,6 +5,7 @@
#include <mysql.h> #include <mysql.h>
#include "db_column.h" #include "db_column.h"
#include "strext.h"
size_t columnTypeToByteSize(e_column_type type) 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, 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; 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)); memset(col, 0, sizeof(struct column_data_t));
col->name_len = name_len; if (strmemcpy(name, name_len, &col->name, &col->name_len) != 0) {
col->name = (char*)malloc(col->name_len + 1);
if (col->name == NULL) {
fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno));
free(col); free(col);
return 0; 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 = type;
col->type_bytes = columnTypeToByteSize(col->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), simplifyFieldType(field->type, (field->flags & UNSIGNED_FLAG) > 0),
(field->flags & NOT_NULL_FLAG) == 0, (field->flags & NOT_NULL_FLAG) == 0,
field->name, field->name,
field->name_length field->name_length,
field->table,
field->table_length
); );
if (col == 0 || num_rows == 0) { 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_BLOB:
case TYPE_RAW: case TYPE_RAW:
{ {
*(col->data.ptr_str + row) = (char *)malloc(value_size + 1); if (strmemcpy(value, value_size, (col->data.ptr_str + row), (col->data_lens + row)) != 0) {
if (*(col->data.ptr_str + row) == 0) {
fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno));
return -1; 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; break;
} }
} }

View File

@@ -8,25 +8,28 @@
#include "db_connection.h" #include "db_connection.h"
enum e_column_type_t { enum e_column_type_t {
TYPE_RAW, TYPE_RAW = 0 << 0,
TYPE_BOOL, TYPE_BOOL = 1 << 0,
TYPE_INT8, TYPE_INT8 = 1 << 1,
TYPE_UINT8, TYPE_UINT8 = 1 << 2,
TYPE_INT16, TYPE_INT16 = 1 << 3,
TYPE_UINT16, TYPE_UINT16 = 1 << 4,
TYPE_INT32, TYPE_INT32 = 1 << 5,
TYPE_UINT32, TYPE_UINT32 = 1 << 6,
TYPE_INT64, TYPE_INT64 = 1 << 7,
TYPE_UINT64, TYPE_UINT64 = 1 << 8,
TYPE_FLOAT, TYPE_FLOAT = 1 << 9,
TYPE_DOUBLE, TYPE_DOUBLE = 1 << 10,
TYPE_STRING, TYPE_STRING = 1 << 11,
TYPE_BLOB, TYPE_BLOB = 1 << 12,
TYPE_TIMESTAMP TYPE_TIMESTAMP = 1 << 13
}; };
typedef enum e_column_type_t e_column_type; typedef enum e_column_type_t e_column_type;
struct column_data_t { struct column_data_t {
char *table;
size_t table_len;
char *name; char *name;
size_t name_len; 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, 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, struct column_data_t *columnFromResult(struct stored_conn_t *sconn, MYSQL_RES *result,
uint64_t num_rows); uint64_t num_rows);
void freeColumn(struct column_data_t *col); void freeColumn(struct column_data_t *col);

View File

@@ -7,6 +7,7 @@
#include "db_connection.h" #include "db_connection.h"
#include "db_timeout.h" #include "db_timeout.h"
#include "db_transaction.h" #include "db_transaction.h"
#include "strext.h"
static struct stored_conn_t *storedConnections = 0; 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)); fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno));
return 0; return 0;
} }
memset(sconn, 0, sizeof(struct stored_conn_t));
sconn->conn_id = nextConnId++; sconn->conn_id = nextConnId++;
sconn->name = 0;
sconn->conn = (MYSQL *)malloc(sizeof(MYSQL)); sconn->conn = (MYSQL *)malloc(sizeof(MYSQL));
sconn->isOpen = 0;
sconn->inTransaction = 0;
sconn->needsReset = 0;
sconn->timeout = (unsigned int)-1; sconn->timeout = (unsigned int)-1;
sconn->prev = 0;
sconn->next = 0;
if (sconn->conn == 0) { if (sconn->conn == 0) {
fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno)); 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) { if (name && strlen(name) > 0) {
sconn->name_len = sizeof(char) * strlen(name); if (strmemcpy(name, strlen(name), &sconn->name, &sconn->name_len) != 0) {
sconn->name = (char *)malloc(sconn->name_len + 1);
if (sconn->name == 0) {
fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno));
destroyStoredConnection(sconn); destroyStoredConnection(sconn);
return 0; return 0;
} }
memcpy(sconn->name, name, sconn->name_len);
sconn->name[sconn->name_len] = '\0';
} }
if (mysql_init(SQCONN(sconn)) == 0) { if (mysql_init(SQCONN(sconn)) == 0) {
@@ -157,9 +148,17 @@ void destroyStoredConnection(struct stored_conn_t *sconn)
closeConnection(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) { if (sconn->name) {
free(sconn->name); free(sconn->name);
sconn->name = 0; sconn->name = 0;
sconn->name_len = 0;
} }
if (sconn->conn) { if (sconn->conn) {

View File

@@ -13,6 +13,12 @@ struct stored_conn_t {
void *conn; 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 isOpen :1;
uint8_t inTransaction :1; uint8_t inTransaction :1;
uint8_t needsReset :1; uint8_t needsReset :1;

View File

@@ -3,8 +3,10 @@
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <mysql.h> #include <mysql.h>
#include "db_connection.h" #include "db_connection.h"
#include "db_column.h" #include "db_column.h"
#include "strext.h"
uint64_t simpleQuery(struct stored_conn_t *sconn, const char *qry, size_t qry_len) 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); printf("QRY: %s\n", qry);
#endif #endif
char *old_ptr;
if (mysql_real_query(SQCONN(sconn), qry, qry_len) != 0) { if (mysql_real_query(SQCONN(sconn), qry, qry_len) != 0) {
fprintf( fprintf(
stderr, "[%d]mysql_real_query: (%d) %s\n", 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; 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)); 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; (*n_cols) = 1;
} }
if (*n_cols == 0) { if (*n_cols == 0) {
// insert/update query
// TODO: res = makeInt64() // lastInsertId
return insertId; 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); n_rows = mysql_num_rows(result);
if (scalar_result && n_rows > 1) { 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; n_rows = 1;
} }
@@ -236,7 +255,7 @@ char *scalarString(struct stored_conn_t *sconn, const char *qry, size_t qry_len,
char *default_value) char *default_value)
{ {
struct column_data_t **col_data; struct column_data_t **col_data;
size_t n_cols; size_t n_cols, len;
char *retval = NULL; char *retval = NULL;
uint64_t n_rows = tableQuery(sconn, qry, qry_len, 1, &col_data, &n_cols); 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 (n_rows > 0) {
if (!((*col_data)->isNullable && columnRowIsNull(*col_data, 0))) { if (!((*col_data)->isNullable && columnRowIsNull(*col_data, 0))) {
retval = (char *)malloc((*col_data)->data_lens[0] + 1); if (strmemcpy(*((*col_data)->data.ptr_str), (*col_data)->data_lens[0], &retval, &len) != 0) {
if (retval == 0) {
fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno));
freeColumn(*col_data); freeColumn(*col_data);
free(col_data); free(col_data);
return NULL; return NULL;
} }
memcpy(retval, *((*col_data)->data.ptr_str), (*col_data)->data_lens[0]);
retval[(*col_data)->data_lens[0]] = '\0';
} }
} }

View File

@@ -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) { if (tmp_str == 0) {
esc_str = (char *)malloc(5); if (strmemcpy("NULL", 4, &esc_str, &esc_len) != 0) {
if (esc_str == 0) {
fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno));
return 0; return 0;
} }
memcpy(esc_str, "NULL", 4);
esc_str[4] = '\0';
esc_len = 4;
break; 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_str = va_arg(args, char *);
tmp_len = va_arg(args, size_t); tmp_len = va_arg(args, size_t);
esc_str = (char *)malloc(tmp_len + 1); if (strmemcpy(tmp_str, tmp_len, &esc_str, &esc_len) != 0) {
if (esc_str == 0) {
fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno));
return 0; return 0;
} }
memcpy(esc_str, tmp_str, tmp_len);
esc_str[tmp_len] = '\0';
break; break;
} }
} }

View File

@@ -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 modbDestroy(struct stored_conn_t *sconn, struct modb_t *modb)
{ {
int err = 0 uint64_t err = 0
|| destroyTable(sconn, modb, MDO_GROUPS_TABLE, STR_LEN(MDO_GROUPS_TABLE)) | destroyTable(sconn, modb, MDO_GROUPS_TABLE, STR_LEN(MDO_GROUPS_TABLE))
|| destroyTable(sconn, modb, OBJECTS_TABLE, STR_LEN(OBJECTS_TABLE)) | destroyTable(sconn, modb, OBJECTS_TABLE, STR_LEN(OBJECTS_TABLE))
|| destroyTable(sconn, modb, META_TABLE, STR_LEN(META_TABLE)) | destroyTable(sconn, modb, META_TABLE, STR_LEN(META_TABLE))
|| destroyTable(sconn, modb, SYS_TABLE, STR_LEN(SYS_TABLE)); | destroyTable(sconn, modb, SYS_TABLE, STR_LEN(SYS_TABLE));
return err == 0; return err == 0;
} }
int modbAccountingCreate(struct stored_conn_t *sconn, struct modb_t *modb) 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; return -1;
} }
if (createGroupsTable(sconn, modb) == (uint64_t)-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; 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, 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; 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) 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 modbAccountingDestroy(struct stored_conn_t *sconn, struct modb_t *modb)
{ {
int err = 0 uint64_t err = 0
|| destroyTable(sconn, modb, OWNER_GROUPS_TABLE, STR_LEN(OWNER_GROUPS_TABLE)) | destroyTable(sconn, modb, USER_GROUPS_TABLE, STR_LEN(USER_GROUPS_TABLE))
|| destroyTable(sconn, modb, GROUPS_TABLE, STR_LEN(GROUPS_TABLE)) | 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 err; return err == 0;
} }
int modbMetaExtCreate(struct stored_conn_t *sconn, struct modb_t *modb, 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 modbMetaExtDestroy(struct stored_conn_t *sconn, struct modb_t *modb)
{ {
int err = 0 uint64_t err = 0
|| destroyTable(sconn, modb, META_EXT_TABLE, STR_LEN(META_EXT_TABLE)); | destroyTable(sconn, modb, META_EXT_TABLE, STR_LEN(META_EXT_TABLE));
return err; return err == 0;
} }

View File

@@ -126,7 +126,7 @@ uint64_t createMDOGroupsTable(struct stored_conn_t *sconn, struct modb_t *modb)
return res; 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; char *qry;
uint64_t res; 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, "CREATE TABLE `", 0);
strbld_str(sb, modb->name, modb->name_len); 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, "` ", 2);
strbld_str(sb, "(" strbld_str(sb, "("
"`id` INT UNSIGNED NOT NULL, " "`id` INT UNSIGNED NOT NULL, "
@@ -189,7 +189,7 @@ uint64_t createGroupsTable(struct stored_conn_t *sconn, struct modb_t *modb)
return res; 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; char *qry;
uint64_t res; 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, "CREATE TABLE `", 0);
strbld_str(sb, modb->name, modb->name_len); 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, "` ", 2);
strbld_str(sb, "(" strbld_str(sb, "("
"`owner_id` INT UNSIGNED NOT NULL, " "`user_id` INT UNSIGNED NOT NULL, "
"`group_id` INT UNSIGNED NOT NULL, " "`group_id` INT UNSIGNED NOT NULL, "
"INDEX(`owner_id`), " "INDEX(`user_id`), "
"INDEX(`group_id`)" "INDEX(`group_id`)"
")", 0); ")", 0);
if (strbld_finalize_or_destroy(&sb, &qry, &qry_len) != 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"); 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; retval = -1;
} else { } else {
retval = strncmp(res, modb->name, modb->name_len) == 0; retval = strncmp(res, modb->name, modb->name_len) == 0;
@@ -335,9 +335,9 @@ char *createColString(struct column_data_t *col)
} }
if (col->isNullable) { if (col->isNullable) {
strbld_str(sb, " NOT NULL", 0);
} else {
strbld_str(sb, " NULL", 0); strbld_str(sb, " NULL", 0);
} else {
strbld_str(sb, " NOT NULL", 0);
} }
if (strbld_finalize_or_destroy(&sb, &colstr, &colstr_len) != 0) { if (strbld_finalize_or_destroy(&sb, &colstr, &colstr_len) != 0) {

View File

@@ -14,9 +14,9 @@
#define OBJECTS_TABLE "_objects" #define OBJECTS_TABLE "_objects"
#define MDO_GROUPS_TABLE "_mdo_groups" #define MDO_GROUPS_TABLE "_mdo_groups"
#define OWNERS_TABLE "_owner" #define USERS_TABLE "_users"
#define GROUPS_TABLE "_groups" #define GROUPS_TABLE "_groups"
#define OWNER_GROUPS_TABLE "_owner_groups" #define USER_GROUPS_TABLE "_user_groups"
#define META_EXT_TABLE "_meta_ext" #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 createObjectsTable(struct stored_conn_t *sconn, struct modb_t *modb);
uint64_t createMDOGroupsTable(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 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, int tableExists(struct stored_conn_t *sconn, struct modb_t *modb,
const char *suffix, size_t suffix_len); const char *suffix, size_t suffix_len);