diff --git a/src/modb.c b/src/modb.c new file mode 100644 index 0000000..f8d7926 --- /dev/null +++ b/src/modb.c @@ -0,0 +1,125 @@ +#include +#include +#include +#include + +#include "modb.h" +#include "modb_p.h" +#include "db_query.h" +#include "strext.h" + + +int modbCreate(struct stored_conn_t *sconn, struct modb_t *modb) +{ + if (createSysTable(sconn, modb) == (uint64_t)-1) { + return -1; + } + if (createMetaTable(sconn, modb) == (uint64_t)-1) { + destroyTable(sconn, modb, SYS_TABLE, STR_LEN(SYS_TABLE)); + return -1; + } + if (createObjectsTable(sconn, modb) == (uint64_t)-1) { + destroyTable(sconn, modb, META_TABLE, STR_LEN(META_TABLE)); + destroyTable(sconn, modb, SYS_TABLE, STR_LEN(SYS_TABLE)); + return -1; + } + if (createMDOGroupsTable(sconn, modb) == (uint64_t)-1) { + 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 -1; + } + + return 0; +} +int modbExists(struct stored_conn_t *sconn, struct modb_t *modb) +{ + return tableExists(sconn, modb, META_TABLE, STR_LEN(META_TABLE)); +} +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)); + return err == 0; +} + +int modbAccountingCreate(struct stored_conn_t *sconn, struct modb_t *modb) +{ + if (createOwnersTable(sconn, modb) == (uint64_t)-1) { + return -1; + } + if (createGroupsTable(sconn, modb) == (uint64_t)-1) { + destroyTable(sconn, modb, OWNERS_TABLE, STR_LEN(OWNERS_TABLE)); + return -1; + } + if (createOwnerGroupsTable(sconn, modb) == (uint64_t)-1) { + destroyTable(sconn, modb, GROUPS_TABLE, STR_LEN(GROUPS_TABLE)); + destroyTable(sconn, modb, OWNERS_TABLE, STR_LEN(OWNERS_TABLE)); + return -1; + } + + return 0; +} +int modbAccountingExists(struct stored_conn_t *sconn, struct modb_t *modb) +{ + return tableExists(sconn, modb, OWNERS_TABLE, STR_LEN(OWNERS_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; +} + +int modbMetaExtCreate(struct stored_conn_t *sconn, struct modb_t *modb, + struct column_data_t **col_data, size_t cols) +{ + char *qry; + uint64_t res; + size_t qry_len; + str_builder *sb; + char *colstr; + + if ((sb = strbld_create()) == 0) { + return -1; + } + strbld_str(sb, "CREATE TABLE `", 0); + strbld_str(sb, modb->name, modb->name_len); + strbld_str(sb, META_EXT_TABLE, STR_LEN(META_EXT_TABLE)); + strbld_str(sb, "` ", 2); + strbld_str(sb, "(", 1); + strbld_str(sb, "`mdo_id` INT UNSIGNED NOT NULL", 0); + for (size_t c = 0; c < cols; c++) { + struct column_data_t *col = *(col_data + c); + if ((colstr = createColString(col)) == 0) { + strbld_destroy(&sb); + return -1; + } + strbld_str(sb, colstr, 0); + free(colstr); + } + strbld_str(sb, ", INDEX (`mdo_id`))", 0); + if (strbld_finalize_or_destroy(&sb, &qry, &qry_len) != 0) { + return -1; + } + + res = simpleQuery(sconn, qry, qry_len); + free(qry); + + return (res == (uint64_t)-1) ? -1 : (int)res; +} +int modbMetaExtExists(struct stored_conn_t *sconn, struct modb_t *modb) +{ + return tableExists(sconn, modb, META_EXT_TABLE, STR_LEN(META_EXT_TABLE)); +} +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; +} diff --git a/src/modb.h b/src/modb.h new file mode 100644 index 0000000..db628a4 --- /dev/null +++ b/src/modb.h @@ -0,0 +1,22 @@ +#ifndef H__MODB__ +#define H__MODB__ + +#include "db_connection.h" +#include "db_column.h" +#include "modb_types.h" + + +int modbCreate(struct stored_conn_t *sconn, struct modb_t *modb); +int modbExists(struct stored_conn_t *sconn, struct modb_t *modb); +int modbDestroy(struct stored_conn_t *sconn, struct modb_t *modb); + +int modbAccountingCreate(struct stored_conn_t *sconn, struct modb_t *modb); +int modbAccountingExists(struct stored_conn_t *sconn, struct modb_t *modb); +int modbAccountingDestroy(struct stored_conn_t *sconn, struct modb_t *modb); + +int modbMetaExtCreate(struct stored_conn_t *sconn, struct modb_t *modb, + struct column_data_t **col_data, size_t cols); +int modbMetaExtExists(struct stored_conn_t *sconn, struct modb_t *modb); +int modbMetaExtDestroy(struct stored_conn_t *sconn, struct modb_t *modb); + +#endif // H__MODB__ diff --git a/src/modb_p.c b/src/modb_p.c new file mode 100644 index 0000000..8b9281a --- /dev/null +++ b/src/modb_p.c @@ -0,0 +1,349 @@ +#include +#include +#include +#include + +#include "modb_p.h" +#include "db_query.h" +#include "strext.h" + + +uint64_t createSysTable(struct stored_conn_t *sconn, struct modb_t *modb) +{ + char *qry; + uint64_t res; + size_t qry_len; + str_builder *sb; + + if ((sb = strbld_create()) == 0) { + return (uint64_t)-1; + } + strbld_str(sb, "CREATE TABLE `", 0); + strbld_str(sb, modb->name, modb->name_len); + strbld_str(sb, SYS_TABLE, STR_LEN(SYS_TABLE)); + strbld_str(sb, "` ", 2); + strbld_str(sb, "(" + "`key` VARCHAR(255) NULL, " + "`value` VARCHAR(255) NULL, " + "UNIQUE(`key`)" + ")", 0); + if (strbld_finalize_or_destroy(&sb, &qry, &qry_len) != 0) { + return (uint64_t)-1; + } + + res = simpleQuery(sconn, qry, qry_len); + free(qry); + + return res; +} +uint64_t createMetaTable(struct stored_conn_t *sconn, struct modb_t *modb) +{ + char *qry; + uint64_t res; + size_t qry_len; + str_builder *sb; + + if ((sb = strbld_create()) == 0) { + return (uint64_t)-1; + } + strbld_str(sb, "CREATE TABLE `", 0); + strbld_str(sb, modb->name, modb->name_len); + strbld_str(sb, META_TABLE, STR_LEN(META_TABLE)); + strbld_str(sb, "` ", 2); + strbld_str(sb, "(" + "`mdo_id` INT UNSIGNED NOT NULL AUTO_INCREMENT, " + "`title` VARCHAR(255) NOT NULL, " + "`owner` INT UNSIGNED NOT NULL, " + "`created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, " + "`updated` TIMESTAMP on update CURRENT_TIMESTAMP NULL DEFAULT NULL, " + "`deleted` TIMESTAMP NULL DEFAULT NULL, " + "PRIMARY KEY(`mdo_id`)" + ")", 0); + if (strbld_finalize_or_destroy(&sb, &qry, &qry_len) != 0) { + return (uint64_t)-1; + } + + res = simpleQuery(sconn, qry, qry_len); + free(qry); + + return res; +} +uint64_t createObjectsTable(struct stored_conn_t *sconn, struct modb_t *modb) +{ + char *qry; + uint64_t res; + size_t qry_len; + str_builder *sb; + + if ((sb = strbld_create()) == 0) { + return (uint64_t)-1; + } + strbld_str(sb, "CREATE TABLE `", 0); + strbld_str(sb, modb->name, modb->name_len); + strbld_str(sb, OBJECTS_TABLE, STR_LEN(OBJECTS_TABLE)); + strbld_str(sb, "` ", 2); + strbld_str(sb, "(" + "`mdo_id` INT UNSIGNED NOT NULL, " + "`object` MEDIUMBLOB NOT NULL, " + "PRIMARY KEY (`mdo_id`)" + ")", 0); + if (strbld_finalize_or_destroy(&sb, &qry, &qry_len) != 0) { + return (uint64_t)-1; + } + + res = simpleQuery(sconn, qry, qry_len); + free(qry); + + return res; +} +uint64_t createMDOGroupsTable(struct stored_conn_t *sconn, struct modb_t *modb) +{ + char *qry; + uint64_t res; + size_t qry_len; + str_builder *sb; + + if ((sb = strbld_create()) == 0) { + return (uint64_t)-1; + } + strbld_str(sb, "CREATE TABLE `", 0); + strbld_str(sb, modb->name, modb->name_len); + strbld_str(sb, MDO_GROUPS_TABLE, STR_LEN(MDO_GROUPS_TABLE)); + strbld_str(sb, "` ", 2); + strbld_str(sb, "(" + "`mdo_id` INT UNSIGNED NOT NULL, " + "`group_id` INT UNSIGNED NOT NULL, " + "INDEX(`mdo_id`), " + "INDEX(`group_id`)" + ")", 0); + if (strbld_finalize_or_destroy(&sb, &qry, &qry_len) != 0) { + return (uint64_t)-1; + } + + res = simpleQuery(sconn, qry, qry_len); + free(qry); + + return res; +} + +uint64_t createOwnersTable(struct stored_conn_t *sconn, struct modb_t *modb) +{ + char *qry; + uint64_t res; + size_t qry_len; + str_builder *sb; + + if ((sb = strbld_create()) == 0) { + return (uint64_t)-1; + } + 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, "` ", 2); + strbld_str(sb, "(" + "`id` INT UNSIGNED NOT NULL, " + "`username` VARCHAR(255) NOT NULL, " + "`email` VARCHAR(255) NOT NULL, " + "`created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, " + "`updated` TIMESTAMP on update CURRENT_TIMESTAMP NULL DEFAULT NULL, " + "`deleted` TIMESTAMP NULL DEFAULT NULL, " + "INDEX (`id`)" + ")", 0); + if (strbld_finalize_or_destroy(&sb, &qry, &qry_len) != 0) { + return (uint64_t)-1; + } + + res = simpleQuery(sconn, qry, qry_len); + free(qry); + + return res; +} +uint64_t createGroupsTable(struct stored_conn_t *sconn, struct modb_t *modb) +{ + char *qry; + uint64_t res; + size_t qry_len; + str_builder *sb; + + if ((sb = strbld_create()) == 0) { + return (uint64_t)-1; + } + strbld_str(sb, "CREATE TABLE `", 0); + strbld_str(sb, modb->name, modb->name_len); + strbld_str(sb, GROUPS_TABLE, STR_LEN(GROUPS_TABLE)); + strbld_str(sb, "` ", 2); + strbld_str(sb, "(" + "`id` INT UNSIGNED NOT NULL, " + "`name` VARCHAR(255) NOT NULL, " + "`created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, " + "`updated` TIMESTAMP on update CURRENT_TIMESTAMP NULL DEFAULT NULL, " + "`deleted` TIMESTAMP NULL DEFAULT NULL, " + "INDEX (`id`)" + ")", 0); + if (strbld_finalize_or_destroy(&sb, &qry, &qry_len) != 0) { + return (uint64_t)-1; + } + + res = simpleQuery(sconn, qry, qry_len); + free(qry); + + return res; +} +uint64_t createOwnerGroupsTable(struct stored_conn_t *sconn, struct modb_t *modb) +{ + char *qry; + uint64_t res; + size_t qry_len; + str_builder *sb; + + if ((sb = strbld_create()) == 0) { + return (uint64_t)-1; + } + 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, "` ", 2); + strbld_str(sb, "(" + "`owner_id` INT UNSIGNED NOT NULL, " + "`group_id` INT UNSIGNED NOT NULL, " + "INDEX(`owner_id`), " + "INDEX(`group_id`)" + ")", 0); + if (strbld_finalize_or_destroy(&sb, &qry, &qry_len) != 0) { + return (uint64_t)-1; + } + + res = simpleQuery(sconn, qry, qry_len); + free(qry); + + return res; +} + +int tableExists(struct stored_conn_t *sconn, struct modb_t *modb, + const char *suffix, size_t suffix_len) +{ + char *qry, *res; + size_t qry_len; + str_builder *sb; + int retval = 0; + + if ((sb = strbld_create()) == 0) { + return -errno; + } + retval += strbld_str(sb, "SHOW TABLES LIKE '", 0); + retval += strbld_str(sb, modb->name, modb->name_len); + retval += strbld_str(sb, suffix, suffix_len); + retval += strbld_char(sb, '\''); + if (strbld_finalize_or_destroy(&sb, &qry, &qry_len) != 0) { + return -errno; + } + + res = scalarString(sconn, qry, qry_len, "Z"); + if (res == 0 || strncmp(res, "Z", 1) == 0 || strlen(res) != modb->name_len) { + retval = -1; + } else { + retval = strncmp(res, modb->name, modb->name_len) == 0; + } + + if (res != 0) { + free(res); + } + free(qry); + + return retval; +} + +uint64_t destroyTable(struct stored_conn_t *sconn, struct modb_t *modb, + const char *suffix, size_t suffix_len) +{ + char *qry; + uint64_t res; + size_t qry_len; + str_builder *sb; + + if ((sb = strbld_create()) == 0) { + return (uint64_t)-1; + } + strbld_str(sb, "DROP TABLE `", 0); + strbld_str(sb, modb->name, modb->name_len); + strbld_str(sb, suffix, suffix_len); + strbld_str(sb, "` ", 2); + if (strbld_finalize_or_destroy(&sb, &qry, &qry_len) != 0) { + return (uint64_t)-1; + } + + res = simpleQuery(sconn, qry, qry_len); + free(qry); + + return res; +} + +char *createColString(struct column_data_t *col) +{ + char *colstr; + size_t colstr_len; + str_builder *sb; + + if ((sb = strbld_create()) == 0) { + return 0; + } + strbld_str(sb, ", `", 3); + strbld_str(sb, col->name, col->name_len); + strbld_str(sb, "` ", 2); + + switch(col->type) { + case TYPE_RAW: + strbld_str(sb, "MEDIUMBLOB", 10); + break; + case TYPE_BOOL: + strbld_str(sb, "BOOLEAN", 7); + break; + case TYPE_INT8: + case TYPE_UINT8: + strbld_str(sb, "TINYINT", 7); + break; + case TYPE_INT16: + case TYPE_UINT16: + strbld_str(sb, "SMALLINT", 8); + break; + case TYPE_INT32: + case TYPE_UINT32: + strbld_str(sb, "INT", 3); + break; + case TYPE_INT64: + case TYPE_UINT64: + strbld_str(sb, "BIGINT", 6); + break; + case TYPE_FLOAT: + strbld_str(sb, "FLOAT", 5); + break; + case TYPE_DOUBLE: + strbld_str(sb, "DOUBLE", 6); + break; + case TYPE_STRING: + strbld_str(sb, "VARCHAR(4096)", 13); + break; + case TYPE_BLOB: + strbld_str(sb, "MEDIUMBLOB", 10); + break; + case TYPE_TIMESTAMP: + strbld_str(sb, "TIMESTAMP", 8); + } + + if (col->isUnsigned) { + strbld_str(sb, " UNSIGNED", 0); + } + + if (col->isNullable) { + strbld_str(sb, " NOT NULL", 0); + } else { + strbld_str(sb, " NULL", 0); + } + + if (strbld_finalize_or_destroy(&sb, &colstr, &colstr_len) != 0) { + return 0; + } + + return colstr; +} + diff --git a/src/modb_p.h b/src/modb_p.h new file mode 100644 index 0000000..538b9de --- /dev/null +++ b/src/modb_p.h @@ -0,0 +1,41 @@ +#ifndef H__MODB_P__ +#define H__MODB_P__ + +#include +#include + +#include "db_connection.h" +#include "db_column.h" +#include "modb_types.h" + + +#define SYS_TABLE "_sys" +#define META_TABLE "_meta" +#define OBJECTS_TABLE "_objects" +#define MDO_GROUPS_TABLE "_mdo_groups" + +#define OWNERS_TABLE "_owner" +#define GROUPS_TABLE "_groups" +#define OWNER_GROUPS_TABLE "_owner_groups" + +#define META_EXT_TABLE "_meta_ext" + + +uint64_t createSysTable(struct stored_conn_t *sconn, struct modb_t *modb); +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 createGroupsTable(struct stored_conn_t *sconn, struct modb_t *modb); +uint64_t createOwnerGroupsTable(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); + +uint64_t destroyTable(struct stored_conn_t *sconn, struct modb_t *modb, + const char *suffix, size_t suffix_len); + +char *createColString(struct column_data_t *col); + +#endif // H__MODB_P__ diff --git a/src/modb_types.c b/src/modb_types.c new file mode 100644 index 0000000..7992823 --- /dev/null +++ b/src/modb_types.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +#include "modb_types.h" +#include "strext.h" + + +struct modb_t *modbAlloc(const char *name, size_t name_len) +{ + struct modb_t *modb = (struct modb_t *)malloc(sizeof(struct modb_t)); + if (modb == 0) { + fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno)); + return 0; + } + + if (strmemcpy(name, name_len, &modb->name, &modb->name_len) != 0) { + modbRelease(&modb); + return 0; + } + + return modb; +} +void modbRelease(struct modb_t **modb) +{ + if ((*modb)->name != 0) { + free((*modb)->name); + (*modb)->name = 0; + } + + free(*modb); + *modb = 0; +} diff --git a/src/modb_types.h b/src/modb_types.h new file mode 100644 index 0000000..65f4257 --- /dev/null +++ b/src/modb_types.h @@ -0,0 +1,15 @@ +#ifndef H__MODB_TYPES__ +#define H__MODB_TYPES__ + +#include +#include + +struct modb_t { + char *name; + size_t name_len; +}; + +struct modb_t *modbAlloc(const char *name, size_t name_len); +void modbRelease(struct modb_t **modb); + +#endif // H__MODB_TYPES__