Metadata Extended handling implemented

This commit is contained in:
2020-10-15 12:11:51 +01:00
parent a47cb96c84
commit ff218def1b
4 changed files with 572 additions and 54 deletions

View File

@@ -178,7 +178,7 @@ void freeMetadata(struct metadata_t **metadata_ptr)
struct metadata_t *metadata = *metadata_ptr;
if (metadata->ext != 0) {
freeMetadataExt(&metadata->ext);
freeMetaExt(&metadata->ext);
}
if (metadata->object != 0) {
@@ -521,8 +521,7 @@ int64_t modbFetchMetadataObject(stored_conn *sconn, modb_ref *modb, struct metad
// MODB Metadata -> MetadataExtended
int64_t modbFetchMetadataExtended(stored_conn *sconn, modb_ref *modb, struct metadata_t *metadata)
{
// TODO: implement
return -1;
return modbMetaExtById(sconn, modb, metadata->id, &metadata->ext);
}
// MODB Metadata -> Groups

View File

@@ -27,7 +27,7 @@ struct metadata_t {
size_t n_groups;
struct object_t *object;
struct metadata_ext_t *ext;
struct meta_ext_t *ext;
};
struct metadata_t *allocMetadata(void);

View File

@@ -3,52 +3,548 @@
#include <string.h>
#include <errno.h>
#include "database.h"
#include "modb_metadata_ext.h"
#include "modb_p.h"
struct metadata_ext_t *allocMetadataExt(void)
// ##### PRIVATE
int tableRowsToMetaExtList(column_data **col_data, size_t n_cols,
struct meta_ext_t ***ext_list, size_t *n_exts)
{
struct metadata_ext_t *metadata_ext;
column_data *col_id, *col;
size_t n_rows, r_idx, c_idx, v_idx;
struct meta_ext_t *ext;
struct meta_ext_value_t *ext_value;
size_t key_len;
metadata_ext = malloc(sizeof(struct metadata_ext_t));
n_rows = (*col_data)->n_values;
if (n_rows == 0) {
return 0;
}
col_id = findColumnByName(col_data, n_cols, "mdo_id");
if ((*ext_list = allocMetaExtList(n_rows)) == 0) {
fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno));
return -errno;
}
for (r_idx = 0; r_idx < n_rows; r_idx++) {
if ((ext = allocMetaExt()) == 0) {
freeMetaExtList(ext_list, r_idx - 1);
return -1;
}
*((*ext_list) + r_idx) = ext;
ext->id = *(col_id->data.ptr_uint32 + r_idx);
if (n_cols > 0) {
if ((ext->values = allocMetaExtValues(n_cols - 1, 1)) == 0) {
freeMetaExtList(ext_list, r_idx);
return -1;
}
ext->n_values = n_cols - 1;
}
for (c_idx = 0, v_idx = 0; c_idx < n_cols; c_idx++, v_idx++) {
col = *(col_data + c_idx);
if (col == col_id) {
v_idx--;
continue;
}
ext_value = *(ext->values + v_idx);
if (strmemcpy(col->name, col->name_len, &ext_value->key, &key_len) != 0) {
freeMetaExtList(ext_list, r_idx);
return -1;
}
ext_value->key_c = ext_value->key;
switch(col->type) {
case TYPE_RAW:
ext_value->type = VTYPE_RAW;
if (!moveColumnBlobPointer(col, r_idx, 1, (char **)&ext_value->value.raw, &ext_value->value_len)) {
freeMetaExtList(ext_list, r_idx);
return -1;
}
break;
case TYPE_BOOL:
ext_value->type = VTYPE_BOOL;
ext_value->value.int32 = *(col->data.ptr_uint8 + r_idx);
break;
case TYPE_INT8:
ext_value->type = VTYPE_INT32;
ext_value->value.int32 = *(col->data.ptr_int8 + r_idx);
break;
case TYPE_UINT8:
ext_value->type = VTYPE_INT32;
ext_value->value.int32 = *(col->data.ptr_uint8 + r_idx);
break;
case TYPE_INT16:
ext_value->type = VTYPE_INT32;
ext_value->value.int32 = *(col->data.ptr_int16 + r_idx);
break;
case TYPE_UINT16:
ext_value->type = VTYPE_INT32;
ext_value->value.int32 = *(col->data.ptr_uint16 + r_idx);
break;
case TYPE_INT32:
ext_value->type = VTYPE_INT32;
ext_value->value.int32 = *(col->data.ptr_int32 + r_idx);
break;
case TYPE_UINT32:
ext_value->type = VTYPE_INT32;
ext_value->value.dbl = (double)*(col->data.ptr_uint32 + r_idx);
break;
case TYPE_INT64:
ext_value->type = VTYPE_INT32;
ext_value->value.dbl = (double)*(col->data.ptr_int64 + r_idx);
break;
case TYPE_UINT64:
ext_value->type = VTYPE_INT32;
ext_value->value.dbl = (double)*(col->data.ptr_uint64 + r_idx);
break;
case TYPE_FLOAT:
ext_value->type = VTYPE_INT32;
ext_value->value.dbl = (double)*(col->data.ptr_float + r_idx);
break;
case TYPE_DOUBLE:
ext_value->type = VTYPE_DOUBLE;
ext_value->value.dbl = *(col->data.ptr_double + r_idx);
break;
case TYPE_STRING:
ext_value->type = VTYPE_STRING;
if (!moveColumnStrPointer(col, r_idx, 1, &ext_value->value.str, &ext_value->value_len)) {
freeMetaExtList(ext_list, r_idx);
return -1;
}
break;
case TYPE_BLOB:
ext_value->type = VTYPE_RAW;
if (!moveColumnBlobPointer(col, r_idx, 1, (char **)&ext_value->value.raw, &ext_value->value_len)) {
freeMetaExtList(ext_list, r_idx);
return -1;
}
break;
case TYPE_TIMESTAMP:
ext_value->type = VTYPE_TIMESTAMP;
ext_value->value.ts = *(col->data.ptr_int64 + r_idx);
break;
case TYPE_ID:
ext_value->type = VTYPE_ID;
ext_value->value.id = *(col->data.ptr_uint32 + r_idx);
break;
}
}
}
*n_exts = n_rows;
return 1;
}
int doMetaExtListQuery(stored_conn *sconn, modb_ref *modb, where_builder *wb,
struct meta_ext_t ***ext_list, size_t *n_exts)
{
char *tbl_meta, *tbl_ext;
size_t len_meta, len_ext;
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(&tbl_ext, &len_ext, modb, META_EXT_TABLE, strlen(META_EXT_TABLE));
modbTableName(&tbl_meta, &len_meta, modb, METADATA_TABLE, strlen(METADATA_TABLE));
strbld_str(sb, "SELECT ", 0);
escapeColumnName_sb(sb, tbl_ext, len_ext, "*", 0);
strbld_str(sb, " FROM ", 0);
escapeTableName_sb(sb, tbl_ext, len_ext);
joinStr_sb(sb, " LEFT", 5, 1, tbl_meta, len_meta, "mdo_id", 6, tbl_ext, len_ext, "mdo_id", 6);
if (wb != 0) {
compileWhereBuilder_sb(sb, wb, 0);
}
strbld_str(sb, " ORDER BY ", 0);
escapeColumnName_sb(sb, tbl_meta, len_meta, "updated", 0);
strbld_str(sb, " DESC, ", 0);
escapeColumnName_sb(sb, tbl_meta, len_meta, "updated", 0);
strbld_str(sb, " DESC", 0);
modbFreeTableName(&tbl_meta);
modbFreeTableName(&tbl_ext);
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);
*ext_list = 0;
*n_exts = 0;
return 0;
}
res = tableRowsToMetaExtList(col_data, n_cols, ext_list, n_exts);
freeColumns(col_data, n_cols);
if (res <= 0) {
return res;
}
return (int)qry_ret;
}
int doScalarMetaExtListQuery(stored_conn *sconn, modb_ref *modb,
where_builder *wb, struct meta_ext_t **meta_ext)
{
int res;
struct meta_ext_t **meta_ext_list;
size_t n_exts;
res = doMetaExtListQuery(sconn, modb, wb, &meta_ext_list, &n_exts);
if (res <= 0) {
return res;
}
*meta_ext = *(meta_ext_list + 0);
*(meta_ext_list + 0) = 0;
freeMetaExtList(&meta_ext_list, n_exts);
return res;
}
// ##### PUBLIC
struct meta_ext_t *allocMetaExt(void)
{
struct meta_ext_t *metadata_ext;
metadata_ext = malloc(sizeof(struct meta_ext_t));
if (metadata_ext == 0) {
fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno));
}
memset(metadata_ext, 0, sizeof(struct metadata_ext_t));
memset(metadata_ext, 0, sizeof(struct meta_ext_t));
return metadata_ext;
}
struct metadata_ext_t **allocMetadataExts(size_t n_metadata_exts)
void freeMetaExt(struct meta_ext_t **metadata_ext_ptr)
{
struct metadata_ext_t **metadata_exts;
struct meta_ext_t *metadata_ext = *metadata_ext_ptr;
metadata_exts = (struct metadata_ext_t **)malloc(sizeof(struct metadata_ext_t *) * n_metadata_exts);
if (metadata_exts == 0) {
fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno));
return 0;
if (metadata_ext->values != 0) {
freeMetaExtValues(&metadata_ext->values, metadata_ext->n_values);
}
memset(metadata_exts, 0, sizeof(struct metadata_ext_t *) * n_metadata_exts);
return metadata_exts;
}
void freeMetadataExt(struct metadata_ext_t **metadata_ext_ptr)
{
struct metadata_ext_t *metadata_ext = *metadata_ext_ptr;
free(metadata_ext);
*metadata_ext_ptr = 0;
}
void freeMetadataExts(struct metadata_ext_t ***metadata_exts_ptr, size_t n_metadata_exts)
struct meta_ext_t **allocMetaExtList(size_t n_metadata_exts)
{
struct meta_ext_t **metadata_exts;
metadata_exts = (struct meta_ext_t **)malloc(sizeof(struct meta_ext_t *) * n_metadata_exts);
if (metadata_exts == 0) {
fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno));
return 0;
}
memset(metadata_exts, 0, sizeof(struct meta_ext_t *) * n_metadata_exts);
return metadata_exts;
}
void freeMetaExtList(struct meta_ext_t ***metadata_exts_ptr, size_t n_metadata_exts)
{
size_t idx;
struct metadata_ext_t **metadata_exts = *metadata_exts_ptr;
struct meta_ext_t **metadata_exts = *metadata_exts_ptr;
for (idx = 0; idx < n_metadata_exts; idx++) {
if (*(metadata_exts + idx) != 0) {
freeMetadataExt(metadata_exts + idx);
freeMetaExt(metadata_exts + idx);
}
}
free(metadata_exts);
*metadata_exts_ptr = 0;
}
struct meta_ext_value_t *allocMetaExtValue(void)
{
struct meta_ext_value_t *ext_value;
ext_value = malloc(sizeof(struct meta_ext_value_t));
if (ext_value == 0) {
fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno));
}
memset(ext_value, 0, sizeof(struct meta_ext_value_t));
return ext_value;
}
void freeMetaExtValue(struct meta_ext_value_t **ext_value_ptr)
{
struct meta_ext_value_t *ext_value = *ext_value_ptr;
if (ext_value->key != 0) {
free(ext_value->key);
ext_value->key = 0;
}
if (!ext_value->is_null && !ext_value->is_const) {
if (ext_value->type == VTYPE_RAW && ext_value->value.raw != 0) {
free(ext_value->value.raw);
ext_value->value.raw = 0;
}
if (ext_value->type == VTYPE_STRING && ext_value->value.str != 0) {
free(ext_value->value.str);
ext_value->value.str = 0;
}
}
free(ext_value);
*ext_value_ptr = 0;
}
struct meta_ext_value_t **allocMetaExtValues(size_t n_values, int alloc_values)
{
struct meta_ext_value_t **ext_values;
size_t idx;
ext_values = (struct meta_ext_value_t **)malloc(sizeof(struct meta_ext_value_t *) * n_values);
if (ext_values == 0) {
fprintf(stderr, "[%d]malloc: (%d) %s\n", __LINE__, errno, strerror(errno));
return 0;
}
memset(ext_values, 0, sizeof(struct meta_ext_value_t *) * n_values);
if (alloc_values) {
for (idx = 0; idx < n_values; idx++) {
if ((*(ext_values + idx) = allocMetaExtValue()) == 0) {
freeMetaExtValues(&ext_values, idx - 1);
return 0;
}
}
}
return ext_values;
}
void freeMetaExtValues(struct meta_ext_value_t ***ext_values_ptr, size_t n_values)
{
size_t idx;
struct meta_ext_value_t **ext_values = *ext_values_ptr;
for (idx = 0; idx < n_values; idx++) {
if (*(ext_values + idx) != 0) {
freeMetaExtValue(ext_values + idx);
}
}
free(ext_values);
*ext_values_ptr = 0;
}
int modbMetaExtById(stored_conn *sconn, modb_ref *modb, unsigned int id,
struct meta_ext_t **meta_ext)
{
where_builder *wb = 0;
int res;
char *tbl_ext;
size_t len_ext;
modbTableName(&tbl_ext, &len_ext, modb, META_EXT_TABLE, strlen(META_EXT_TABLE));
wb = where(tbl_ext, "mdo_id", EQ, TYPE_UINT32, 1, id);
res = doScalarMetaExtListQuery(sconn, modb, wb, meta_ext);
freeWhereBuilder(&wb);
free(tbl_ext);
return res;
}
int modbMetaExtList(stored_conn *sconn, modb_ref *modb, int with_deleted,
struct meta_ext_t ***meta_exts, size_t *n_meta_exts)
{
where_builder *wb = 0;
int res;
char *tbl_ext = 0;
size_t len_ext;
if (with_deleted == 0) {
modbTableName(&tbl_ext, &len_ext, modb, META_EXT_TABLE, strlen(META_EXT_TABLE));
wb = where(tbl_ext, "deleted", IS_NULL, TYPE_RAW, 0, 0);
}
res = doMetaExtListQuery(sconn, modb, wb, meta_exts, n_meta_exts);
if (wb != 0) {
freeWhereBuilder(&wb);
free(tbl_ext);
}
return res;
}
int64_t modbMetaExtCreate(stored_conn *sconn, modb_ref *modb, struct meta_ext_t *meta_ext)
{
str_builder *sb;
char *table;
size_t table_len;
char *qry;
size_t qry_len;
uint64_t qry_ret;
size_t idx;
struct meta_ext_value_t *ext_value;
if ((sb = strbld_create()) == 0) {
return -1;
}
modbTableName(&table, &table_len, modb, META_EXT_TABLE, strlen(META_EXT_TABLE));
strbld_str(sb, "INSERT INTO ", 0);
escapeTableName_sb(sb, table, table_len);
strbld_str(sb, " (`mdo_id`", 0);
for (idx = 0; idx < meta_ext->n_values; idx++) {
ext_value = (*(meta_ext->values + idx));
strbld_char(sb, ',');
escapeColumnName_sb(sb, 0, 0, ext_value->key_c, 0);
}
strbld_str(sb, ") VALUES (", 0);
db_value_sb(sb, TYPE_ID, 1, meta_ext->id);
for (idx = 0; idx < meta_ext->n_values; idx++) {
ext_value = *(meta_ext->values + idx);
strbld_char(sb, ',');
switch(ext_value->type) {
case VTYPE_RAW:
db_value_sb(sb, TYPE_RAW, 2, ext_value->value.raw, ext_value->value_len);
break;
case VTYPE_BOOL:
db_value_sb(sb, TYPE_BOOL, 1, ext_value->value.bool);
break;
case VTYPE_INT32:
db_value_sb(sb, TYPE_INT32, 1, ext_value->value.int32);
break;
case VTYPE_DOUBLE:
db_value_sb(sb, TYPE_DOUBLE, 1, ext_value->value.dbl);
break;
case VTYPE_STRING:
db_value_sb(sb, TYPE_STRING, 2, ext_value->value.str, ext_value->value_len);
break;
case VTYPE_TIMESTAMP:
db_value_sb(sb, TYPE_TIMESTAMP, 1, ext_value->value.ts);
break;
case VTYPE_ID:
db_value_sb(sb, TYPE_ID, 1, ext_value->value.id);
break;
}
}
strbld_char(sb, ')');
modbFreeTableName(&table);
if (strbld_finalize_or_destroy(&sb, &qry, &qry_len) != 0) {
return -1;
}
qry_ret = simpleQuery(sconn, qry, qry_len);
free(qry);
return qry_ret == 0 ? meta_ext->id : 0;
}
int64_t modbMetaExtReplace(stored_conn *sconn, modb_ref *modb, unsigned int id,
struct meta_ext_t *meta_ext);
int64_t modbMetaExtUpdate(stored_conn *sconn, modb_ref *modb, unsigned int id,
struct meta_ext_t *meta_ext)
{
str_builder *sb;
char *table, *set;
size_t table_len, set_len;
int64_t qry_ret;
size_t idx;
struct meta_ext_value_t *ext_value;
if ((sb = strbld_create()) == 0) {
return 0;
}
columnSetValueStr_sb(sb, "mdo_id", TYPE_ID, 1, id);
for (idx = 0; idx < meta_ext->n_values; idx++) {
ext_value = *(meta_ext->values + idx);
strbld_char(sb, ',');
switch(ext_value->type) {
case VTYPE_RAW:
columnSetValueStr_sb(
sb, ext_value->key_c, TYPE_RAW, 2, ext_value->value.raw, ext_value->value_len
);
break;
case VTYPE_BOOL:
columnSetValueStr_sb(sb, ext_value->key_c, TYPE_BOOL, 1, ext_value->value.bool);
break;
case VTYPE_INT32:
columnSetValueStr_sb(sb, ext_value->key_c, TYPE_INT32, 1, ext_value->value.int32);
break;
case VTYPE_DOUBLE:
columnSetValueStr_sb(sb, ext_value->key_c, TYPE_DOUBLE, 1, ext_value->value.dbl);
break;
case VTYPE_STRING:
columnSetValueStr_sb(
sb, ext_value->key_c, TYPE_STRING, 2, ext_value->value.str, ext_value->value_len
);
break;
case VTYPE_TIMESTAMP:
columnSetValueStr_sb(sb, ext_value->key_c, TYPE_TIMESTAMP, 1, ext_value->value.ts);
break;
case VTYPE_ID:
columnSetValueStr_sb(sb, ext_value->key_c, TYPE_ID, 1, ext_value->value.id);
break;
}
}
if (strbld_finalize_or_destroy(&sb, &set, &set_len) != 0) {
return 0;
}
modbTableName(&table, &table_len, modb, META_EXT_TABLE, strlen(META_EXT_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 modbMetaExtDelete(stored_conn *sconn, modb_ref *modb, unsigned int id)
{
char *table;
size_t table_len;
int64_t qry_ret;
modbTableName(&table, &table_len, modb, META_EXT_TABLE, STR_LEN(META_EXT_TABLE));
qry_ret = softDeleteByIdQuery(sconn, table, table_len, "mdo_id", id);
modbFreeTableName(&table);
return (int)qry_ret;
}
int modbMetaExtDestroy(stored_conn *sconn, modb_ref *modb, unsigned int id)
{
char *table;
size_t table_len;
int64_t qry_ret;
modbTableName(&table, &table_len, modb, META_EXT_TABLE, STR_LEN(META_EXT_TABLE));
qry_ret = deleteByIdQuery(sconn, table, table_len, "mdo_id", id);
modbFreeTableName(&table);
return (int)qry_ret;
}

View File

@@ -1,48 +1,71 @@
#ifndef H__MODB_METADATA_EXT__
#define H__MODB_METADATA_EXT__
#include <stdint.h>
#include "database.h"
#include "modb_ref.h"
// MetadataExtended object
struct metadata_ext_t {
unsigned int id;
// TODO: dynamic extended metadata definition
// struct metadata_ext_value_t **meta_ext;
// size_t n_meta_ext;
enum e_value_type_t {
VTYPE_RAW = 0,
VTYPE_BOOL = 1 << 0,
VTYPE_INT32 = 1 << 1,
VTYPE_DOUBLE = 1 << 2,
VTYPE_STRING = 1 << 3,
VTYPE_TIMESTAMP = 1 << 4,
VTYPE_ID = 1 << 5
};
//struct metadata_ext_value_t {
// char *key;
// enum e_column_type_t type;
// union {
// void *vptr;_ptr
struct meta_ext_t {
unsigned int id;
// int8_t int8;
// uint8_t uint8;
struct meta_ext_value_t **values;
size_t n_values;
};
// int16_t int16;
// uint16_t uint16;
struct meta_ext_value_t {
char *key;
const char *key_c;
enum e_value_type_t type;
union {
void *raw;
int bool;
int32_t int32;
double dbl;
char *str;
const char *str_c;
int64_t ts;
uint32_t id;
} value;
size_t value_len;
// int32_t int32;
// uint32_t uint32;
uint32_t is_null :1;
uint32_t is_const :1;
};
// int64_t int64;
// uint64_t uint64;
struct meta_ext_t *allocMetaExt(void);
void freeMetaExt(struct meta_ext_t **meta_ext);
struct meta_ext_t **allocMetaExtList(size_t n_meta_ext_list);
void freeMetaExtList(struct meta_ext_t ***meta_ext_list_ptr, size_t n_meta_exts);
// float flt;
// double dbl;
struct meta_ext_value_t *allocMetaExtValue(void);
void freeMetaExtValue(struct meta_ext_value_t **meta_ext_value);
struct meta_ext_value_t **allocMetaExtValues(size_t n_values, int alloc_values);
void freeMetaExtValues(struct meta_ext_value_t ***value_list_ptr, size_t n_values);
// char *ptr_str;
// } value;
// size_t value_len;
//};
// MODB Extended Metadata
int modbMetaExtById(stored_conn *sconn, modb_ref *modb, unsigned int id,
struct meta_ext_t **meta_ext);
struct metadata_ext_t *allocMetadataExt(void);
struct metadata_ext_t **allocMetadataExts(size_t n_metadata_exts);
void freeMetadataExt(struct metadata_ext_t **metadata_ext);
void freeMetadataExts(struct metadata_ext_t ***metadata_exts_ptr, size_t n_metadata_exts);
int modbMetaExtList(stored_conn *sconn, modb_ref *modb, int with_deleted,
struct meta_ext_t ***meta_exts, size_t *n_meta_exts);
int64_t modbMetaExtCreate(stored_conn *sconn, modb_ref *modb, struct meta_ext_t *meta_ext);
int64_t modbMetaExtReplace(stored_conn *sconn, modb_ref *modb, unsigned int id,
struct meta_ext_t *meta_ext);
int modbMetaExtDelete(stored_conn *sconn, modb_ref *modb, unsigned int id);
int modbMetaExtDestroy(stored_conn *sconn, modb_ref *modb, unsigned int id);
#endif // H__MODB_METADATA_EXT__