#include #include #include #include "modb_metadata.h" #include "modb_objects.h" #include "modb_metadata_ext.h" #include "modb_users.h" #include "modb_groups.h" #include "modb_p.h" // ##### PRIVATE int tableRowsToMetadataList(column_data **col_data, size_t n_cols, struct metadata_t ***metadata_list, size_t *n_metadatas) { column_data *col_id, *col_title, *col_owner_id, *col_created, *col_updated, *col_deleted; size_t n_rows, idx; struct metadata_t *metadata; column_data **ext_cols; column_data *col; n_rows = (*col_data)->n_values; if (n_rows == 0) { return 0; } col_id = findColumnByName(col_data, n_cols, "mdo_id"); //col_type = findColumnByName(col_data, n_cols, "type"); col_title = findColumnByName(col_data, n_cols, "title"); col_owner_id = findColumnByName(col_data, n_cols, "owner_id"); col_created = findColumnByName(col_data, n_cols, "created"); col_updated = findColumnByName(col_data, n_cols, "updated"); col_deleted = findColumnByName(col_data, n_cols, "deleted"); size_t n_ext_cols = 0; ext_cols = malloc(n_cols * sizeof(column_data *)); if (ext_cols == 0) { fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno)); return -1; } size_t tbl_len = STR_LEN(META_EXT_TABLE); for (idx = 0; idx < n_cols; idx++) { col = *(col_data + idx); if (strncmp(col->table + (col->table_len - tbl_len), META_EXT_TABLE, tbl_len) == 0) { *(ext_cols + n_ext_cols) = col; n_ext_cols++; } } *metadata_list = (struct metadata_t **)malloc(sizeof(struct metadata_t *) * n_rows); if (*metadata_list == 0) { fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno)); free(ext_cols); return -errno; } memset(*metadata_list, 0, sizeof(struct metadata_t *) * n_rows); for (idx = 0; idx < n_rows; idx++) { metadata = allocMetadata(); if (metadata == 0) { freeMetadataList(metadata_list, idx - 1); free(ext_cols); return -1; } metadata->id = *(col_id->data.ptr_uint32 + idx); // if (!moveColumnStrPointer(col_type, idx, 1, &metadata->type, &metadata->type_len)) { // freeMetadataList(metadata_list, idx); // return -1; // } // metadata->type_c = metadata->type; if (!moveColumnStrPointer(col_title, idx, 1, &metadata->title, &metadata->title_len)) { freeMetadataList(metadata_list, idx); free(ext_cols); return -1; } metadata->title_c = metadata->title; metadata->owner_id = *(col_owner_id->data.ptr_uint32 + idx); metadata->created_on = *(col_created->data.ptr_int64 + idx); if (!columnRowIsNull(col_updated, idx)) { metadata->updated_on = *(col_updated->data.ptr_int64 + idx); } if (!columnRowIsNull(col_deleted, idx)) { metadata->deleted_on = *(col_deleted->data.ptr_int64 + idx); } if (tableRowToMetaExt(ext_cols, n_ext_cols, idx, &metadata->ext) != 1) { freeMetadataList(metadata_list, idx); free(ext_cols); return -1; } *(*metadata_list + idx) = metadata; } free(ext_cols); *n_metadatas = n_rows; return 1; } int doMetadataListQuery(stored_conn *sconn, modb_ref *modb, where_builder *wb, struct metadata_t ***metadata_list, size_t *n_metadatas) { char *table, *ext_table; size_t table_len, ext_len; char *qry; size_t qry_len; uint64_t qry_ret; int res; str_builder *sb; column_data **col_data; size_t n_cols; if ((sb = strbld_create()) == 0) { return -1; } modbTableName(&table, &table_len, modb, METADATA_TABLE, strlen(METADATA_TABLE)); modbTableName(&ext_table, &ext_len, modb, META_EXT_TABLE, strlen(META_EXT_TABLE)); strbld_str(sb, "SELECT * FROM ", 0); escapeTableName_sb(sb, table, table_len); joinStr_sb(sb, " LEFT", 5, 1, ext_table, ext_len, "mdo_id", 6, table, table_len, "mdo_id", 6); if (wb != 0) { compileWhereBuilder_sb(sb, wb, 0); } strbld_str(sb, " ORDER BY `updated` DESC, `created` DESC", 0); modbFreeTableName(&ext_table); modbFreeTableName(&table); if (strbld_finalize_or_destroy(&sb, &qry, &qry_len) != 0) { return -1; } qry_ret = tableQuery(sconn, qry, qry_len, 0, &col_data, &n_cols); free(qry); // Query failed if (qry_ret == (uint64_t)-1) { return -1; } // Zero row result if (qry_ret == 0) { freeColumns(col_data, n_cols); *metadata_list = 0; *n_metadatas = 0; return 0; } res = tableRowsToMetadataList(col_data, n_cols, metadata_list, n_metadatas); freeColumns(col_data, n_cols); if (res <= 0) { return res; } return (int)qry_ret; } int doScalarMetadataListQuery(stored_conn *sconn, modb_ref *modb, where_builder *wb, struct metadata_t **metadata) { int res; struct metadata_t **metadata_list; size_t n_metadatas; res = doMetadataListQuery(sconn, modb, wb, &metadata_list, &n_metadatas); if (res <= 0) { return res; } *metadata = *(metadata_list + 0); *(metadata_list + 0) = 0; freeMetadataList(&metadata_list, n_metadatas); return res; } // ##### PUBLIC struct metadata_t *allocMetadata(void) { struct metadata_t *metadata; metadata = malloc(sizeof(struct metadata_t)); if (metadata == 0) { fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno)); } memset(metadata, 0, sizeof(struct metadata_t)); return metadata; } struct metadata_t **allocMetadataList(size_t n_metadatas) { struct metadata_t **metadatas; metadatas = (struct metadata_t **)malloc(sizeof(struct metadata_t *) * n_metadatas); if (metadatas == 0) { fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno)); return 0; } memset(metadatas, 0, sizeof(struct metadata_t *) * n_metadatas); return metadatas; } void freeMetadata(struct metadata_t **metadata_ptr) { struct metadata_t *metadata = *metadata_ptr; if (metadata->ext != 0) { freeMetaExt(&metadata->ext); } if (metadata->object != 0) { freeObject(&metadata->object); } if (metadata->n_groups > 0) { if (metadata->group_ids != 0) { free(metadata->group_ids); metadata->group_ids = 0; } if (metadata->groups != 0) { freeGroups(&metadata->groups, metadata->n_groups); } metadata->n_groups = 0; } if (metadata->owner != 0) { freeUser(&metadata->owner); } if (metadata->title != 0) { free(metadata->title); metadata->title = 0; } free(metadata); *metadata_ptr = 0; } void freeMetadataList(struct metadata_t ***metadata_list_ptr, size_t n_metadatas) { size_t idx; struct metadata_t **metadatas_list= *metadata_list_ptr; for (idx = 0; idx < n_metadatas; idx++) { if (*(metadatas_list + idx) != 0) { freeMetadata((metadatas_list + idx)); } } free(metadatas_list); *metadata_list_ptr = 0; } int modbMetadataById(stored_conn *sconn, modb_ref *modb, unsigned int id, struct metadata_t **metadata) { where_builder *wb = 0; int res; char *table; size_t table_len; modbTableName(&table, &table_len, modb, METADATA_TABLE, strlen(METADATA_TABLE)); wb = where(table, "mdo_id", EQ, TYPE_ID, 1, id); res = doScalarMetadataListQuery(sconn, modb, wb, metadata); free(table); freeWhereBuilder(&wb); return res; } int modbMetadataListByOwnerId(stored_conn *sconn, modb_ref *modb, unsigned int owner_id, int with_deleted, struct metadata_t ***metadata_list, size_t *n_metadatas) { where_builder *wb = 0; int res; wb = where(0, "owner_id", EQ, TYPE_ID, owner_id); if (with_deleted == 0) { wb = whereAnd(wb, where(0, "deleted", IS_NULL, TYPE_RAW, 0, 0)); } res = doMetadataListQuery(sconn, modb, wb, metadata_list, n_metadatas); if (wb != 0) { freeWhereBuilder(&wb); } return res; } int modbMetadataListByGroupId(stored_conn *sconn, modb_ref *modb, unsigned int group_id, int with_deleted, struct metadata_t ***metadata_list, size_t *n_metadatas) { unsigned int *ids = 0; size_t n_ids; size_t idx; where_builder *wb = 0; int res; if (modbFetchGroupMetadataIds(sconn, modb, group_id, &ids, &n_ids) < 0) { return -1; } if (ids == 0) { return 0; } wb = whereIn(0, 0, "mdo_id", TYPE_ID, 0); for (idx = 0; idx < n_ids; idx++) { setWhereValue(wb, TYPE_ID, 1, *(ids + idx)); } if (!with_deleted) { wb = whereAnd(wb, where(0, "deleted", IS_NULL, TYPE_RAW, 0)); } res = doMetadataListQuery(sconn, modb, wb, metadata_list, n_metadatas); freeWhereBuilder(&wb); free(ids); return res; } int modbMetadataQuery(stored_conn *sconn, modb_ref *modb, where_builder *wb, struct metadata_t ***metadata_list, size_t *n_metadatas) { return doMetadataListQuery(sconn, modb, wb, metadata_list, n_metadatas); } int modbMetadataList(stored_conn *sconn, modb_ref *modb, int with_deleted, struct metadata_t ***metadata_list, size_t *n_metadatas) { where_builder *wb = 0; int res; if (with_deleted == 0) { wb = where(0, "deleted", IS_NULL, TYPE_RAW, 0, 0); } res = doMetadataListQuery(sconn, modb, wb, metadata_list, n_metadatas); if (wb != 0) { freeWhereBuilder(&wb); } return res; } unsigned int modbMetadataCreate(stored_conn *sconn, modb_ref *modb, struct metadata_t *metadata) { str_builder *sb; char *table; size_t table_len; char *qry; size_t qry_len; uint64_t qry_ret; // if (metadata->type_c == 0) { // metadata->type_c = metadata->type; // } if (metadata->title_c == 0) { metadata->title_c = metadata->title; } if ((sb = strbld_create()) == 0) { return 0; } modbTableName(&table, &table_len, modb, METADATA_TABLE, strlen(METADATA_TABLE)); strbld_str(sb, "INSERT INTO ", 0); escapeTableName_sb(sb, table, table_len); // strbld_str(sb, " (`mdo_id`, `type`, `title`, `owner_id`) VALUES (", 0); strbld_str(sb, " (`mdo_id`, `title`, `owner_id`) VALUES (", 0); db_value_sb(sb, TYPE_ID, 1, metadata->id); // strbld_char(sb, ','); // db_value_sb(sb, TYPE_STRING, 2, metadata->type_c, metadata->type_len); strbld_char(sb, ','); db_value_sb(sb, TYPE_STRING, 2, metadata->title_c, metadata->title_len); strbld_char(sb, ','); if (metadata->owner != 0) { db_value_sb(sb, TYPE_ID, 1, metadata->owner->id); } else { db_value_sb(sb, TYPE_ID, 1, metadata->owner_id); } strbld_char(sb, ')'); modbFreeTableName(&table); if (strbld_finalize_or_destroy(&sb, &qry, &qry_len) != 0) { return 0; } qry_ret = simpleQuery(sconn, qry, qry_len); free(qry); return (unsigned int)qry_ret; } int64_t modbMetadataReplace(stored_conn *sconn, modb_ref *modb, unsigned int id, struct metadata_t *metadata) { str_builder *sb; char *table, *set; size_t table_len, set_len; int64_t qry_ret; // if (metadata->type_c == 0) { // metadata->type_c = metadata->type; // } if (metadata->title_c == 0) { metadata->title_c = metadata->title; } if ((sb = strbld_create()) == 0) { return 0; } columnSetValueStr_sb(sb, "mdo_id", TYPE_ID, 1, id); if (metadata->id != 0 && metadata->id != id) { strbld_char(sb, ','); columnSetValueStr_sb(sb, "mdo_id", TYPE_ID, 1, metadata->id); } // if (metadata->type_c != 0) { // strbld_char(sb, ','); // columnSetValueStr_sb(sb, "type", TYPE_STRING, 2, metadata->type_c, metadata->type_len); // } if (metadata->title_c != 0) { strbld_char(sb, ','); columnSetValueStr_sb(sb, "title", TYPE_STRING, 2, metadata->title_c, metadata->title_len); } if (metadata->created_on != 0) { strbld_char(sb, ','); columnSetValueStr_sb(sb, "created", TYPE_TIMESTAMP, 1, metadata->created_on); } if (metadata->updated_on != 0) { strbld_char(sb, ','); columnSetValueStr_sb(sb, "updated", TYPE_TIMESTAMP, 1, metadata->updated_on); } if (metadata->deleted_on != 0) { strbld_char(sb, ','); columnSetValueStr_sb(sb, "deleted", TYPE_TIMESTAMP, 1, metadata->deleted_on); } if (metadata->owner != 0) { strbld_char(sb, ','); columnSetValueStr_sb(sb, "owner_id", TYPE_ID, 1, metadata->owner->id); } else if (metadata->owner_id != 0) { strbld_char(sb, ','); columnSetValueStr_sb(sb, "owner_id", TYPE_ID, 1, metadata->owner_id); } if (strbld_finalize_or_destroy(&sb, &set, &set_len) != 0) { return 0; } modbTableName(&table, &table_len, modb, METADATA_TABLE, STR_LEN(METADATA_TABLE)); qry_ret = updateQuery( sconn, table, table_len, set, set_len, where(0, "mdo_id", EQ, TYPE_ID, 1, id) ); modbFreeTableName(&table); free(set); return qry_ret; } int64_t modbMetadataUpdateType(stored_conn *sconn, modb_ref *modb, unsigned int id, const char *type, size_t type_len) { str_builder *sb; char *table, *set; size_t table_len, set_len; int64_t qry_ret; if ((sb = strbld_create()) == 0) { return 0; } columnSetValueStr_sb(sb, "mdo_id", TYPE_ID, 1, id); strbld_char(sb, ','); columnSetValueStr(&set, &set_len, "type", TYPE_STRING, 2, type, type_len); if (strbld_finalize_or_destroy(&sb, &set, &set_len) != 0) { return 0; } modbTableName(&table, &table_len, modb, METADATA_TABLE, STR_LEN(METADATA_TABLE)); qry_ret = updateQuery( sconn, table, table_len, set, set_len, where(0, "mdo_id", EQ, TYPE_ID, 1, id) ); modbFreeTableName(&table); free(set); return qry_ret; } int64_t modbMetadataUpdateTitle(stored_conn *sconn, modb_ref *modb, unsigned int id, const char *title, size_t title_len) { str_builder *sb; char *table, *set; size_t table_len, set_len; int64_t qry_ret; if ((sb = strbld_create()) == 0) { return 0; } columnSetValueStr_sb(sb, "mdo_id", TYPE_ID, 1, id); strbld_char(sb, ','); columnSetValueStr(&set, &set_len, "title", TYPE_STRING, 2, title, title_len); if (strbld_finalize_or_destroy(&sb, &set, &set_len) != 0) { return 0; } modbTableName(&table, &table_len, modb, METADATA_TABLE, STR_LEN(METADATA_TABLE)); qry_ret = updateQuery( sconn, table, table_len, set, set_len, where(0, "mdo_id", EQ, TYPE_ID, 1, id) ); modbFreeTableName(&table); free(set); return qry_ret; } int64_t modbMetadataUpdateOwner(stored_conn *sconn, modb_ref *modb, unsigned int id, struct user_t *owner) { return modbMetadataUpdateOwnerId(sconn, modb, id, owner->id); } int64_t modbMetadataUpdateOwnerId(stored_conn *sconn, modb_ref *modb, unsigned int id, unsigned int owner_id) { str_builder *sb; char *table, *set; size_t table_len, set_len; int64_t qry_ret; if ((sb = strbld_create()) == 0) { return 0; } columnSetValueStr_sb(sb, "mdo_id", TYPE_ID, 1, id); strbld_char(sb, ','); columnSetValueStr(&set, &set_len, "owner_id", TYPE_ID, 1, owner_id); if (strbld_finalize_or_destroy(&sb, &set, &set_len) != 0) { return 0; } modbTableName(&table, &table_len, modb, METADATA_TABLE, STR_LEN(METADATA_TABLE)); qry_ret = updateQuery( sconn, table, table_len, set, set_len, where(0, "mdo_id", EQ, TYPE_ID, 1, id) ); modbFreeTableName(&table); free(set); return qry_ret; } int modbMetadataDelete(stored_conn *sconn, modb_ref *modb, unsigned int id) { char *table; size_t table_len; int64_t qry_ret; modbTableName(&table, &table_len, modb, METADATA_TABLE, STR_LEN(METADATA_TABLE)); qry_ret = softDeleteByIdQuery(sconn, table, table_len, "mdo_id", id); modbFreeTableName(&table); return (int)qry_ret; } int modbMetadataDestroy(stored_conn *sconn, modb_ref *modb, unsigned int id) { char *table; size_t table_len; int64_t qry_ret; modbTableName(&table, &table_len, modb, METADATA_TABLE, STR_LEN(METADATA_TABLE)); qry_ret = deleteByIdQuery(sconn, table, table_len, "mdo_id", id); modbFreeTableName(&table); return (int)qry_ret; } // MODB Metadata -> Owner int64_t modbFetchMetadataOwner(stored_conn *sconn, modb_ref *modb, struct metadata_t *metadata) { return modbUserById(sconn, modb, metadata->owner_id, 0, &metadata->owner); } // MODB Metadata -> Object int64_t modbFetchMetadataObject(stored_conn *sconn, modb_ref *modb, struct metadata_t *metadata) { return modbObjectById(sconn, modb, metadata->id, &metadata->object); } // MODB Metadata -> MetadataExtended int64_t modbFetchMetadataExtended(stored_conn *sconn, modb_ref *modb, struct metadata_t *metadata) { return modbMetaExtById(sconn, modb, metadata->id, &metadata->ext); } // MODB Metadata -> Groups int modbFetchMetadataGroupIds(stored_conn *sconn, modb_ref *modb, struct metadata_t *metadata) { char *table; size_t table_len; int64_t res; modbTableName(&table, &table_len, modb, MDO_GROUPS_TABLE, STR_LEN(MDO_GROUPS_TABLE)); res = getIdMaps(sconn, table, table_len, "mdo_id", "group_id", metadata->id, &metadata->n_groups, &metadata->group_ids); modbFreeTableName(&table); return res <= 0 ? (int)res : 1; } int modbFetchMetadataGroups(stored_conn *sconn, modb_ref *modb, struct metadata_t *metadata, int with_deleted) { int ret; size_t idx; ret = modbFetchMetadataGroupIds(sconn, modb, metadata); if (ret != 1) { return ret; } metadata->groups = allocGroups(metadata->n_groups); if (metadata->groups == 0) { return -1; } for (idx = 0; idx < metadata->n_groups; idx++) { if (modbGroupById( sconn, modb, *(metadata->group_ids + idx), 0, (metadata->groups + idx) ) != 1) { freeGroups(&metadata->groups, metadata->n_groups); return -1; } if (!with_deleted && (*(metadata->groups + idx))->deleted_on != 0) { freeGroup((metadata->groups + idx)); metadata->n_groups--; if (metadata->n_groups == 0) { free(metadata->groups); free(metadata->group_ids); metadata->group_ids = 0; } else { memmove(metadata->group_ids + idx, metadata->group_ids + idx + 1, metadata->n_groups - idx); } idx--; } } return ret; } int modbSyncMetadataGroups(stored_conn *sconn, modb_ref *modb, unsigned int metadata_id, size_t n_groups, unsigned int *group_ids) { char *table; size_t table_len; int64_t qry_ret; modbTableName(&table, &table_len, modb, MDO_GROUPS_TABLE, STR_LEN(MDO_GROUPS_TABLE)); qry_ret = syncIdMap( sconn, table, table_len, "mdo_id", "group_id", metadata_id, n_groups, group_ids ); modbFreeTableName(&table); return (int)qry_ret; } int modbSyncMetadataGroups_va(stored_conn *sconn, modb_ref *modb, unsigned int metadata_id, size_t n_groups, ...) { va_list args; char *table; size_t table_len; int64_t qry_ret; va_start(args, n_groups); modbTableName(&table, &table_len, modb, MDO_GROUPS_TABLE, STR_LEN(MDO_GROUPS_TABLE)); qry_ret = syncIdMap_va( sconn, table, table_len, "mdo_id", "group_id", metadata_id, n_groups, args ); modbFreeTableName(&table); va_end(args); return (int)qry_ret; } int modbIsLinked_Metadata_Group(stored_conn *sconn, modb_ref *modb, unsigned int metadata_id, unsigned int group_id) { char *table; size_t table_len; int64_t qry_ret; modbTableName(&table, &table_len, modb, MDO_GROUPS_TABLE, STR_LEN(MDO_GROUPS_TABLE)); qry_ret = hasIdMap(sconn, table, table_len, "mdo_id", "group_id", metadata_id, group_id); modbFreeTableName(&table); return (int)qry_ret; } int modbLink_Metadata_Group(stored_conn *sconn, modb_ref *modb, unsigned int metadata_id, unsigned int group_id) { char *table; size_t table_len; int64_t qry_ret; modbTableName(&table, &table_len, modb, MDO_GROUPS_TABLE, STR_LEN(MDO_GROUPS_TABLE)); qry_ret = addIdMap(sconn, table, table_len, "mdo_id", "group_id", metadata_id, group_id); modbFreeTableName(&table); return (int)qry_ret; } int modbUnlink_Metadata_Group(stored_conn *sconn, modb_ref *modb, unsigned int metadata_id, unsigned int group_id) { char *table; size_t table_len; int64_t qry_ret; modbTableName(&table, &table_len, modb, MDO_GROUPS_TABLE, STR_LEN(MDO_GROUPS_TABLE)); qry_ret = removeIdMap(sconn, table, table_len, "mdo_id", "group_id", metadata_id, group_id); modbFreeTableName(&table); return (int)qry_ret; } // MODB Group -> Metadatas int modbFetchGroupMetadataIds(stored_conn *sconn, modb_ref *modb, unsigned int group_id, unsigned int **metadata_ids, size_t *n_ids) { char *table; size_t table_len; int64_t res; modbTableName(&table, &table_len, modb, MDO_GROUPS_TABLE, STR_LEN(MDO_GROUPS_TABLE)); res = getIdMaps(sconn, table, table_len, "group_id", "mdo_id", group_id, n_ids, metadata_ids); modbFreeTableName(&table); return res <= 0 ? (int)res : 1; }