From 5b6784c07a80311ace622c6e38da4f59f377626b Mon Sep 17 00:00:00 2001 From: avsdev-cw Date: Mon, 9 Nov 2020 12:40:20 +0000 Subject: [PATCH] R->modb handling of objects coded roughly --- R/Metaobject.R | 178 ++++++++++- src/R_modb_metaobjects.c | 625 ++++++++++++++++++++++++++++++++++++--- src/R_modb_metaobjects.h | 8 +- 3 files changed, 769 insertions(+), 42 deletions(-) diff --git a/R/Metaobject.R b/R/Metaobject.R index be15122..231d27d 100644 --- a/R/Metaobject.R +++ b/R/Metaobject.R @@ -1,13 +1,58 @@ -metaobject_ids <- function(title, ...) { - checkmate::assert_string(title) +#' @export +metaobject_ids <- function(query = list(), withDeleted = FALSE, ...) { + checkmate::assert_list(query) + checkmate::assert_logical(withDeleted) conn_ref <- modb_conn_ref(args = list(...)) - res <- .Call(c_rmodb_metaobjectId, conn_ref, title) + res <- .Call(c_rmodb_metaobjectIds, conn_ref, query, withDeleted) + + return(res) +} +#' @export +metaobject_query <- function(query = list(), withDeleted = FALSE, restrict_owner = 0, ...) { + checkmate::assert_list(query) + checkmate::assert_logical(withDeleted) + checkmate::assert_int(restrict_owner) + conn_ref <- modb_conn_ref(args = list(...)) + + res <- .Call( + c_rmodb_metaobjectQuery, conn_ref, + query, withDeleted, as.integer(restrict_owner) + ) + + return(res) +} +#' @export +metadata_query <- function(query = list(), withDeleted = FALSE, restrict_owner = 0, ...) { + checkmate::assert_list(query) + checkmate::assert_logical(withDeleted) + checkmate::assert_int(restrict_owner) + conn_ref <- modb_conn_ref(args = list(...)) + + res <- .Call( + c_rmodb_metadataQuery, conn_ref, + query, withDeleted, as.integer(restrict_owner) + ) + + return(res) +} +#' @export +object_query <- function(query = list(), withDeleted = FALSE, restrict_owner = 0, ...) { + checkmate::assert_list(query) + checkmate::assert_logical(withDeleted) + checkmate::assert_int(restrict_owner) + conn_ref <- modb_conn_ref(args = list(...)) + + res <- .Call( + c_rmodb_metadataQuery, conn_ref, + query, withDeleted, as.integer(restrict_owner) + ) return(res) } +#' @export metaobject_create <- function(meta, obj, id = NULL, ...) { if (!checkmate::test_null(id)) { checkmate::assert_int(id) @@ -61,17 +106,87 @@ metaobject_create <- function(meta, obj, id = NULL, ...) { "created_on", "updated_on", "deleted_on" ) ext <- meta[!(names(meta) %in% meta_fields)] - meta <- meta[names(meta) %in% c("title", "owner_id", "group_ids")] + meta <- meta[names(meta) %in% meta_fields] + + + # utils::str(meta) + # utils::str(ext) + # utils::str(obj) + + res <- .Call(c_rmodb_createMetaobject, conn_ref, as.integer(id), meta, obj, ext) + + return(res) +} + +#' @export +metaobject_update <- function(id, meta, obj, ...) { + checkmate::assert_int(id) + + # TODO: validate meta and obj + # checkmate::assert_list(meta) + # checkmate::assert_names(names(meta), must.include = c("title")) + # assert_namesInclude(names(meta), one.of = c("owner", "owner_id")) + # if (test_namesInclude(names(meta), all.of = c("owner"))) { + # checkmate::assert_class(meta$owner, "modb_user") + # meta$owner_id <- meta$owner$id + # } else { + # checkmate::assert_int(meta$owner_id) + # } + # meta$owner_id <- as.integer(meta$owner_id) + + # assert_namesInclude(names(meta), one.of = c("groups", "group_ids")) + # if (checkmate::test_null(meta$group_ids)) { + # meta$group_ids <- list() + # } else if (test_namesInclude(names(meta), all.of = c("groups"))) { + # meta$group_ids <- list() + # for (g in meta$groups) { + # checkmate::assert_class(g, "modb_group") + # meta$group_ids <- c(meta$group_ids, g$id) + # } + # } else if (checkmate::test_list(meta$group_ids)) { + # if (length(meta$group_ids) > 0) { + # checkmate::assert_integerish(unlist(meta$group_ids)) + # } + # } else { + # checkmate::assert_integerish(meta$group_ids) + # } + # meta$group_ids <- c(as.integer(meta$group_ids)) + + + conn_ref <- modb_conn_ref(args = list(...)) + + if (!missing(meta)) { + meta_fields <- c( + "id", "title", "owner_id", "owner", "groups", "group_ids", + "created_on", "updated_on", "deleted_on" + ) + ext <- meta[!(names(meta) %in% meta_fields)] + meta <- meta[names(meta) %in% meta_fields[-1]] + if (length(meta) == 0) { + meta <- list(NULL) + } + if (length(ext) == 0) { + ext <- list(NULL) + } + } else { + meta <- list(NULL) + ext <- list(NULL) + } + + if (missing(obj)) { + obj <- list(NULL) + } utils::str(meta) utils::str(ext) utils::str(obj) - res <- .Call(c_rmodb_createMetaobject, conn_ref, as.integer(id), meta, obj, ext) + res <- .Call(c_rmodb_updateMetaobject, conn_ref, as.integer(id), meta, obj, ext) return(res) } +#' @export metaobject_delete <- function(id, ...) { checkmate::assert_int(id) conn_ref <- modb_conn_ref(args = list(...)) @@ -79,6 +194,8 @@ metaobject_delete <- function(id, ...) { res <- .Call(c_rmodb_deleteMetaobject, conn_ref, as.integer(id)) return(res) } + +#' @export metaobject <- function(id, ...) { checkmate::assert_int(id) conn_ref <- modb_conn_ref(args = list(...)) @@ -87,7 +204,8 @@ metaobject <- function(id, ...) { return(res) } -metaobjects <- function(withDeleted = FALSE, ...) +#' @export +metaobjects <- function(id_list = NULL, withDeleted = FALSE, ...) { checkmate::assert_logical(withDeleted) conn_ref <- modb_conn_ref(args = list(...)) @@ -97,4 +215,52 @@ metaobjects <- function(withDeleted = FALSE, ...) ) return(res) +} + +#' @export +metadata <- function(id, ...) { + checkmate::assert_int(id) + conn_ref <- modb_conn_ref(args = list(...)) + + res <- .Call(c_rmodb_metaobject, conn_ref, as.integer(id)) + res[names(res) %in% c("object")] <- NULL + + return(res) +} +#' @export +metadatas <- function(id_list = NULL, withDeleted = FALSE, ...) { + if (!checkmate::test_null(id_list)) { + return(lapply( + id_list, rmodb:::metadata, conn_ref = conn_id, withDeleted = withDeleted + )) + } + conn_ref <- modb_conn_ref(args = list(...)) + + res <- .Call(c_rmodb_metadatas, conn_ref, as.logical(withDeleted)) + + return(res) +} + +#' @export +object <- function(id, ...) { + checkmate::assert_int(id) + conn_ref <- modb_conn_ref(args = list(...)) + + res <- .Call(c_rmodb_metaobject, conn_ref, as.integer(id)) + + return(res$object) +} +#' @export +objects <- function(id_list = NULL, withDeleted = FALSE, ...) { + if (!checkmate::test_null(id_list)) { + return(lapply( + id_list, rmodb:::object, conn_ref = conn_id, withDeleted = withDeleted + )) + } + + conn_ref <- modb_conn_ref(args = list(...)) + + res <- .Call(c_rmodb_metaobjects, conn_ref, as.logical(withDeleted)) + + return(res$object) } \ No newline at end of file diff --git a/src/R_modb_metaobjects.c b/src/R_modb_metaobjects.c index 533d8a7..6310cc3 100644 --- a/src/R_modb_metaobjects.c +++ b/src/R_modb_metaobjects.c @@ -3,6 +3,7 @@ #include "modb_database.h" #include "modb_ref.h" +#include "modb_users.h" #include "R_helpers_p.h" #include "R_list_item.h" #include "R_timestamp.h" @@ -12,6 +13,8 @@ #include "R_memory-object.h" #include "R_magic.h" +#include "modb_p.h" // ARGH! + SEXP metadataToR(struct metadata_t *metadata) @@ -121,41 +124,68 @@ SEXP metadataExtToR(struct meta_ext_t *ext) struct meta_ext_value_t *ext_value; - r_ext = PROTECT(Rf_allocVector(VECSXP, 1 + (int)ext->n_values)); + r_ext = PROTECT(Rf_allocVector(VECSXP, 0 + (int)ext->n_values)); n_protect++; - r_attrib_names = PROTECT(Rf_allocVector(STRSXP, 1 + (int)ext->n_values)); + r_attrib_names = PROTECT(Rf_allocVector(STRSXP, 0 + (int)ext->n_values)); n_protect++; + //printf("MAKING EXT\n"); + for (idx = 0; idx < ext->n_values; idx++) { ext_value = *(ext->values + idx); + //printf("%d, %s, %d, %p\n", ext_value->is_null, ext_value->key_c, ext_value->type, ext_value->value.raw); switch(ext_value->type) { case VTYPE_RAW: - r_tmp = PROTECT(objectToR(ext_value->value.raw)); + r_tmp = PROTECT(objectToR(ext_value->value.raw)); break; case VTYPE_BOOL: - r_tmp = PROTECT(Rf_ScalarLogical(ext_value->value.bool)); + if (ext_value->is_null) { + r_tmp = PROTECT(Rf_ScalarLogical(R_NaInt)); + } else { + r_tmp = PROTECT(Rf_ScalarLogical(ext_value->value.boolVal)); + } break; case VTYPE_INT32: - r_tmp = PROTECT(Rf_ScalarInteger(ext_value->value.int32)); + if (ext_value->is_null) { + r_tmp = PROTECT(Rf_ScalarInteger(R_NaInt)); + } else { + r_tmp = PROTECT(Rf_ScalarInteger(ext_value->value.int32)); + } break; case VTYPE_DOUBLE: - r_tmp = PROTECT(Rf_ScalarReal(ext_value->value.dbl)); + if (ext_value->is_null) { + r_tmp = PROTECT(Rf_ScalarReal(R_NaReal)); + } else { + r_tmp = PROTECT(Rf_ScalarReal(ext_value->value.dbl)); + } break; case VTYPE_STRING: r_tmp = PROTECT(Rf_allocVector(STRSXP, 1)); n_protect++; - SET_STRING_ELT(r_tmp, 0, PROTECT(Rf_mkChar(ext_value->value.str))); + if (ext_value->is_null) { + SET_STRING_ELT(r_tmp, 0, PROTECT(R_NaString)); + } else { + SET_STRING_ELT(r_tmp, 0, PROTECT(Rf_mkChar(ext_value->value.str))); + } break; case VTYPE_TIMESTAMP: - r_tmp = PROTECT(R_Timestamp(ext_value->value.ts)); + if (ext_value->is_null) { + r_tmp = PROTECT(Rf_ScalarReal(R_NaReal)); + } else { + r_tmp = PROTECT(R_Timestamp(ext_value->value.ts)); + } break; case VTYPE_ID: - r_tmp = PROTECT(Rf_ScalarInteger((int)ext_value->value.id)); + if (ext_value->is_null) { + r_tmp = PROTECT(Rf_ScalarInteger(R_NaInt)); + } else { + r_tmp = PROTECT(Rf_ScalarInteger((int)ext_value->value.id)); + } break; } - SET_VECTOR_ELT(r_ext, 1 + (int)idx, r_tmp); - SET_STRING_ELT(r_attrib_names, 1 + (int)idx, PROTECT(Rf_mkChar(ext_value->key_c))); + SET_VECTOR_ELT(r_ext, 0 + (int)idx, r_tmp); + SET_STRING_ELT(r_attrib_names, 0 + (int)idx, PROTECT(Rf_mkChar(ext_value->key_c))); n_protect += 2; } @@ -165,9 +195,367 @@ SEXP metadataExtToR(struct meta_ext_t *ext) return r_ext; } -SEXP rmodb_metaobjectId(SEXP r_conn_ref, SEXP r_query) +SEXP rmodb_metaobjectQuery(SEXP r_conn_ref, SEXP r_query, SEXP r_with_deleted, + SEXP r_owner_restrict) { - return R_NilValue; + stored_conn *sconn; + modb_ref modb; + SEXP r_query_names; + SEXP r_tmp; + SEXP r_metadatas; + int i; + const char *col; + const char *tmp_str; + where_builder *wb = 0, *wb_in = 0; + struct user_t user; + struct metadata_t *metadata; + struct metadata_t **metadata_list; + size_t n_metadatas; + size_t idx, n_ids, m_idx; + unsigned int *ids; + char *table; + size_t table_len; + + if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { + Rf_error("invalid connection reference\n"); + } + + if (!modbFindUse(sconn, &modb)) { + Rf_error("invalid modb reference\n"); + } + + bzero(&user, sizeof(struct user_t)); + user.id = (unsigned int)Rf_asInteger(r_owner_restrict); + if (user.id > 0) { + wb = where(0, "owner_id", EQ, TYPE_ID, 1, user.id); + + if (!modbFetchUserGroupIds(sconn, &modb, &user)) { + Rf_error("invalid user id\n"); + } + if (user.n_groups > 0) { + for (idx = 0; idx < user.n_groups; idx++) { + if (modbFetchGroupMetadataIds(sconn, &modb, *(user.group_ids + idx), &ids, &n_ids) < 0) { + free(user.groups); + return R_NilValue; + } + for (m_idx = 0; m_idx < n_ids; m_idx++) { + if (wb_in == 0) { + modbTableName(&table, &table_len, &modb, METADATA_TABLE, STR_LEN(METADATA_TABLE)); + wb_in = whereIn(0, table, "mdo_id", TYPE_ID, 0); + modbFreeTableName(&table); + } + setWhereValue(wb_in, TYPE_ID, 1, *(ids + m_idx)); + } + free(ids); + } + free(user.groups); + + if (wb_in != 0) { + wb = createWhereBuilder(wb); + wb = whereAnd(0, whereOr(wb, wb_in)); + } + } + } + + if (Rf_asLogical(r_with_deleted) == 0) { + wb = whereAnd(wb, where(0, "deleted", IS_NULL, TYPE_RAW, 0)); + } + r_query_names = Rf_getAttrib(r_query, R_NamesSymbol); + for (i = 0; i < LENGTH(r_query); i++) { + col = Rf_translateCharUTF8(STRING_ELT(r_query_names, i)); + r_tmp = VECTOR_ELT(r_query, i); + if (Rf_isNull(r_tmp)) { + wb = whereAnd(wb, where(0, col, IS_NULL, TYPE_RAW, 0)); + } else { + switch(TYPEOF(r_tmp)) { + case LGLSXP:/* logical vectors */ + wb = whereAnd(wb, where(0, col, EQ, TYPE_BOOL, 1, Rf_asLogical(r_tmp))); + break; + case INTSXP:/* integer vectors */ + wb = whereAnd(wb, where(0, col, EQ, TYPE_INT32, 1, Rf_asInteger(r_tmp))); + break; + case REALSXP:/* real variables */ + wb = whereAnd(wb, where(0, col, EQ, TYPE_DOUBLE, 1, Rf_asReal(r_tmp))); + break; + case STRSXP:/* string vectors */ + r_tmp = STRING_ELT(r_tmp, 0); + if (r_tmp == R_NaString) { + wb = whereAnd(wb, where(0, col, IS_NULL, TYPE_RAW, 0)); + } else { + tmp_str = Rf_translateCharUTF8(r_tmp); + wb = whereAnd(wb, where(0, col, EQ, TYPE_STRING, 2, tmp_str, strlen(tmp_str))); + } + break; + case VECSXP:/* generic vectors */ + break; + default: + break; + // Screwed if I know how to handle this... + } + } + } + + if (modbMetadataQuery(sconn, &modb, wb, &metadata_list, &n_metadatas) <= 0) { + freeWhereBuilder(&wb); + return R_NilValue; + } + freeWhereBuilder(&wb); + + r_metadatas = PROTECT(Rf_allocVector(VECSXP, (int)n_metadatas)); + for (idx = 0; idx < n_metadatas; idx++) { + metadata = *(metadata_list + idx); + + if (modbFetchMetadataOwner(sconn, &modb, metadata) < 0) { + freeMetadata(&metadata); + UNPROTECT(1 + (int)idx); + return R_NilValue; + } + if (modbFetchMetadataGroups(sconn, &modb, metadata, 0) < 0) { + freeMetadataList(&metadata_list, n_metadatas); + UNPROTECT(1 + (int)idx); + return R_NilValue; + } +// if (modbFetchMetadataExtended(sconn, &modb, metadata) < 0) { +// freeMetadataList(&metadata_list, n_metadatas); +// UNPROTECT(1 + (int)idx); +// return R_NilValue; +// } + if (modbFetchMetadataObject(sconn, &modb, metadata) < 0) { + freeMetadataList(&metadata_list, n_metadatas); + UNPROTECT(1 + (int)idx); + return R_NilValue; + } + + SET_VECTOR_ELT(r_metadatas, (int)idx, PROTECT(metadataToR(metadata))); + } + freeMetadataList(&metadata_list, n_metadatas); + + UNPROTECT((int)(1 + n_metadatas)); + return r_metadatas; +} + +SEXP rmodb_metadataQuery(SEXP r_conn_ref, SEXP r_query, SEXP r_with_deleted, SEXP r_owner_restrict) +{ + stored_conn *sconn; + modb_ref modb; + SEXP r_query_names; + SEXP r_tmp; + SEXP r_metadatas; + int i; + const char *col; + const char *tmp_str; + where_builder *wb = 0, *wb_in = 0; + struct user_t user; + struct metadata_t *metadata; + struct metadata_t **metadata_list; + size_t n_metadatas; + size_t idx, n_ids, m_idx; + unsigned int *ids; + char *table; + size_t table_len; + + if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { + Rf_error("invalid connection reference\n"); + } + + if (!modbFindUse(sconn, &modb)) { + Rf_error("invalid modb reference\n"); + } + + bzero(&user, sizeof(struct user_t)); + user.id = (unsigned int)Rf_asInteger(r_owner_restrict); + if (user.id > 0) { + wb = where(0, "owner_id", EQ, TYPE_ID, 1, user.id); + + if (!modbFetchUserGroupIds(sconn, &modb, &user)) { + Rf_error("invalid user id\n"); + } + if (user.n_groups > 0) { + for (idx = 0; idx < user.n_groups; idx++) { + if (modbFetchGroupMetadataIds(sconn, &modb, *(user.group_ids + idx), &ids, &n_ids) < 0) { + free(user.groups); + return R_NilValue; + } + for (m_idx = 0; m_idx < n_ids; m_idx++) { + if (wb_in == 0) { + modbTableName(&table, &table_len, &modb, METADATA_TABLE, STR_LEN(METADATA_TABLE)); + wb_in = whereIn(0, table, "mdo_id", TYPE_ID, 0); + modbFreeTableName(&table); + } + setWhereValue(wb_in, TYPE_ID, 1, *(ids + m_idx)); + } + free(ids); + } + free(user.groups); + + if (wb_in != 0) { + wb = whereAnd(0, whereOr(wb, wb_in)); + } + } + } + + if (Rf_asLogical(r_with_deleted) == 0) { + wb = whereAnd(wb, where(0, "deleted", IS_NULL, TYPE_RAW, 0)); + } + + r_query_names = Rf_getAttrib(r_query, R_NamesSymbol); + for (i = 0; i < LENGTH(r_query); i++) { + col = Rf_translateCharUTF8(STRING_ELT(r_query_names, i)); + r_tmp = VECTOR_ELT(r_query, i); + if (Rf_isNull(r_tmp)) { + wb = whereAnd(wb, where(0, col, IS_NULL, TYPE_RAW, 0)); + } else { + switch(TYPEOF(r_tmp)) { + case LGLSXP:/* logical vectors */ + wb = whereAnd(wb, where(0, col, EQ, TYPE_BOOL, 1, Rf_asLogical(r_tmp))); + break; + case INTSXP:/* integer vectors */ + wb = whereAnd(wb, where(0, col, EQ, TYPE_INT32, 1, Rf_asInteger(r_tmp))); + break; + case REALSXP:/* real variables */ + wb = whereAnd(wb, where(0, col, EQ, TYPE_DOUBLE, 1, Rf_asReal(r_tmp))); + break; + case STRSXP:/* string vectors */ + r_tmp = STRING_ELT(r_tmp, 0); + if (r_tmp == R_NaString) { + wb = whereAnd(wb, where(0, col, IS_NULL, TYPE_RAW, 0)); + } else { + tmp_str = Rf_translateCharUTF8(r_tmp); + wb = whereAnd(wb, where(0, col, EQ, TYPE_STRING, 2, tmp_str, strlen(tmp_str))); + } + break; + case VECSXP:/* generic vectors */ + break; + default: + break; + // Screwed if I know how to handle this... + } + } + } + + if (modbMetadataQuery(sconn, &modb, wb, &metadata_list, &n_metadatas) <= 0) { + freeWhereBuilder(&wb); + return R_NilValue; + } + freeWhereBuilder(&wb); + + r_metadatas = PROTECT(Rf_allocVector(VECSXP, (int)n_metadatas)); + for (idx = 0; idx < n_metadatas; idx++) { + metadata = *(metadata_list + idx); + + if (modbFetchMetadataOwner(sconn, &modb, metadata) < 0) { + freeMetadata(&metadata); + UNPROTECT(1 + (int)idx); + return R_NilValue; + } + if (modbFetchMetadataGroups(sconn, &modb, metadata, 0) < 0) { + freeMetadataList(&metadata_list, n_metadatas); + UNPROTECT(1 + (int)idx); + return R_NilValue; + } +// if (modbFetchMetadataExtended(sconn, &modb, metadata) < 0) { +// freeMetadataList(&metadata_list, n_metadatas); +// UNPROTECT(1 + (int)idx); +// return R_NilValue; +// } + + SET_VECTOR_ELT(r_metadatas, (int)idx, PROTECT(metadataToR(metadata))); + } + freeMetadataList(&metadata_list, n_metadatas); + + UNPROTECT((int)(1 + n_metadatas)); + return r_metadatas; +} + +SEXP rmodb_metaobjectIds(SEXP r_conn_ref, SEXP r_query, SEXP r_with_deleted) +{ + stored_conn *sconn; + modb_ref modb; + SEXP r_query_names; + SEXP r_tmp; + SEXP r_ids; + int i; + const char *col; + const char *tmp_str; + where_builder *wb = 0; + struct metadata_t *metadata; + struct metadata_t **metadata_list; + size_t n_metadatas; + size_t idx; + + if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { + Rf_error("invalid connection reference\n"); + } + + if (!modbFindUse(sconn, &modb)) { + Rf_error("invalid modb reference\n"); + } + + if (Rf_asLogical(r_with_deleted) == 0) { + wb = where(0, "deleted", IS_NULL, TYPE_RAW, 0); + } + r_query_names = Rf_getAttrib(r_query, R_NamesSymbol); + for (i = 0; i < LENGTH(r_query); i++) { + col = Rf_translateCharUTF8(STRING_ELT(r_query_names, i)); + r_tmp = VECTOR_ELT(r_query, i); + if (Rf_isNull(r_tmp)) { + wb = whereAnd(wb, where(0, col, IS_NULL, TYPE_RAW, 0)); + } else { + switch(TYPEOF(r_tmp)) { + case LGLSXP:/* logical vectors */ + if (R_IsNA(Rf_asLogical(r_tmp))) { + wb = whereAnd(wb, where(0, col, IS_NULL, TYPE_RAW, 0)); + } else { + wb = whereAnd(wb, where(0, col, EQ, TYPE_BOOL, 1, Rf_asLogical(r_tmp))); + } + break; + case INTSXP:/* integer vectors */ + if (R_IsNA(Rf_asInteger(r_tmp))) { + wb = whereAnd(wb, where(0, col, IS_NULL, TYPE_RAW, 0)); + } else { + wb = whereAnd(wb, where(0, col, EQ, TYPE_INT32, 1, Rf_asInteger(r_tmp))); + } + break; + case REALSXP:/* real variables */ + if (R_IsNA(Rf_asReal(r_tmp))) { + wb = whereAnd(wb, where(0, col, IS_NULL, TYPE_RAW, 0)); + } else { + wb = whereAnd(wb, where(0, col, EQ, TYPE_DOUBLE, 1, Rf_asReal(r_tmp))); + } + break; + case STRSXP:/* string vectors */ + r_tmp = STRING_ELT(r_tmp, 0); + if (r_tmp == R_NaString) { + wb = whereAnd(wb, where(0, col, IS_NULL, TYPE_RAW, 0)); + } else { + tmp_str = Rf_translateCharUTF8(r_tmp); + wb = whereAnd(wb, where(0, col, EQ, TYPE_STRING, 2, tmp_str, strlen(tmp_str))); + } + break; + case VECSXP:/* generic vectors */ + break; + default: + break; + // Screwed if I know how to handle this... + } + } + } + + if (modbMetadataQuery(sconn, &modb, wb, &metadata_list, &n_metadatas) <= 0) { + freeWhereBuilder(&wb); + return R_NilValue; + } + freeWhereBuilder(&wb); + + r_ids = PROTECT(Rf_allocVector(INTSXP, (int)n_metadatas)); + for (idx = 0; idx < n_metadatas; idx++) { + metadata = *(metadata_list + idx); + SET_INTEGER_ELT(r_ids, (int)idx, (int)metadata->id); + } + freeMetadataList(&metadata_list, n_metadatas); + + UNPROTECT(1); + return r_ids; } SEXP rmodb_metaobject(SEXP r_conn_ref, SEXP r_id) @@ -195,15 +583,15 @@ SEXP rmodb_metaobject(SEXP r_conn_ref, SEXP r_id) freeMetadata(&metadata); return R_NilValue; } - if (modbFetchMetadataGroups(sconn, &modb, metadata, 0) <= 0) { + if (modbFetchMetadataGroups(sconn, &modb, metadata, 0) < 0) { freeMetadata(&metadata); return R_NilValue; } - if (modbFetchMetadataExtended(sconn, &modb, metadata) <= 0) { + if (modbFetchMetadataExtended(sconn, &modb, metadata) < 0) { freeMetadata(&metadata); return R_NilValue; } - if (modbFetchMetadataObject(sconn, &modb, metadata) <= 0) { + if (modbFetchMetadataObject(sconn, &modb, metadata) < 0) { freeMetadata(&metadata); return R_NilValue; } @@ -234,15 +622,15 @@ SEXP rmodb_metadata(SEXP r_conn_ref, SEXP r_id) if (modbMetadataById(sconn, &modb, mo_id, &metadata) <= 0) { return R_NilValue; } - if (modbFetchMetadataOwner(sconn, &modb, metadata) <= 0) { + if (modbFetchMetadataOwner(sconn, &modb, metadata) < 0) { freeMetadata(&metadata); return R_NilValue; } - if (modbFetchMetadataGroups(sconn, &modb, metadata, 0) <= 0) { + if (modbFetchMetadataGroups(sconn, &modb, metadata, 0) < 0) { freeMetadata(&metadata); return R_NilValue; } - if (modbFetchMetadataExtended(sconn, &modb, metadata) <= 0) { + if (modbFetchMetadataExtended(sconn, &modb, metadata) < 0) { freeMetadata(&metadata); return R_NilValue; } @@ -320,11 +708,11 @@ SEXP rmodb_metaobjects(SEXP r_conn_ref, SEXP r_with_deleted) UNPROTECT(1 + (int)idx); return R_NilValue; } - if (modbFetchMetadataExtended(sconn, &modb, metadata) < 0) { - freeMetadataList(&metadata_list, n_metadatas); - UNPROTECT(1 + (int)idx); - return R_NilValue; - } +// if (modbFetchMetadataExtended(sconn, &modb, metadata) < 0) { +// freeMetadataList(&metadata_list, n_metadatas); +// UNPROTECT(1 + (int)idx); +// return R_NilValue; +// } if (modbFetchMetadataObject(sconn, &modb, metadata) < 0) { freeMetadataList(&metadata_list, n_metadatas); UNPROTECT(1 + (int)idx); @@ -375,11 +763,11 @@ SEXP rmodb_metadatas(SEXP r_conn_ref, SEXP r_with_deleted) UNPROTECT(1 + (int)idx); return R_NilValue; } - if (modbFetchMetadataExtended(sconn, &modb, metadata) < 0) { - freeMetadataList(&metadata_list, n_metadatas); - UNPROTECT(1 + (int)idx); - return R_NilValue; - } +// if (modbFetchMetadataExtended(sconn, &modb, metadata) < 0) { +// freeMetadataList(&metadata_list, n_metadatas); +// UNPROTECT(1 + (int)idx); +// return R_NilValue; +// } SET_VECTOR_ELT(r_metadatas, (int)idx, PROTECT(metadataToR(metadata))); } @@ -485,20 +873,34 @@ SEXP rmodb_createMetaobject(SEXP r_conn_ref, SEXP r_id, switch(TYPEOF(r_tmp)) { case LGLSXP:/* logical vectors */ ext_value->type = VTYPE_BOOL; - ext_value->value.bool = Rf_asLogical(r_tmp); + ext_value->value.boolVal = Rf_asLogical(r_tmp); + if (R_IsNA(Rf_asReal(r_tmp))) { + ext_value->is_null = 1; + } break; case INTSXP:/* integer vectors */ ext_value->type = VTYPE_INT32; ext_value->value.int32 = Rf_asInteger(r_tmp); + if (R_IsNA(Rf_asReal(r_tmp))) { + ext_value->is_null = 1; + } break; case REALSXP:/* real variables */ ext_value->type = VTYPE_DOUBLE; ext_value->value.dbl = Rf_asReal(r_tmp); + if (R_IsNA(Rf_asReal(r_tmp))) { + ext_value->is_null = 1; + } break; case STRSXP:/* string vectors */ ext_value->type = VTYPE_STRING; - ext_value->value.str_c = Rf_translateCharUTF8(STRING_ELT(r_tmp, 0)); - ext_value->is_const = 1; + r_tmp = STRING_ELT(r_tmp, 0); + if (r_tmp == R_NaString) { + ext_value->is_null = 1; + } else { + ext_value->value.str_c = Rf_translateCharUTF8(r_tmp); + ext_value->is_const = 1; + } break; case VECSXP:/* generic vectors */ break; @@ -519,9 +921,164 @@ SEXP rmodb_createMetaobject(SEXP r_conn_ref, SEXP r_id, return Rf_ScalarReal((double)metadata.id); } -SEXP rmodb_updateMetaobject(SEXP r_conn_ref, SEXP r_id, SEXP r_metaobject) +SEXP rmodb_updateMetaobject(SEXP r_conn_ref, SEXP r_id, + SEXP r_metadata, SEXP r_object, SEXP r_extendedMeta) { - return R_NilValue; + stored_conn *sconn; + modb_ref modb; + struct metadata_t metadata; + struct object_t object; + struct meta_ext_t *metadata_ext; + struct meta_ext_value_t *ext_value; + struct r_memoryobject_t *memObj; + SEXP r_tmp, r_names; + int i; + + if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { + Rf_error("invalid connection reference\n"); + } + + if (!modbFindUse(sconn, &modb)) { + Rf_error("invalid modb reference\n"); + } + + memset(&metadata, 0, sizeof(struct metadata_t)); + metadata.id = (unsigned int)Rf_asInteger(r_id); + + if (!Rf_isNull(r_metadata) && TYPEOF(r_metadata) == VECSXP && LENGTH(r_metadata) == 1 && Rf_isNull(VECTOR_ELT(r_metadata, 0))) { + // Nothing to do here + } else { + r_tmp = R_listItem(r_metadata, "title"); + if (r_tmp != R_NilValue) { + metadata.title_c = Rf_translateCharUTF8(STRING_ELT(r_tmp, 0)); + } + + r_tmp = R_listItem(r_metadata, "owner_id"); + if (r_tmp != R_NilValue) { + metadata.owner_id = (unsigned int)Rf_asInteger(r_tmp); + } + + r_tmp = R_listItem(r_metadata, "created_on"); + if (r_tmp != R_NilValue) { + metadata.created_on = R_TimestampUnix(r_tmp); + } + r_tmp = R_listItem(r_metadata, "updated_on"); + if (r_tmp != R_NilValue) { + metadata.updated_on = R_TimestampUnix(r_tmp); + } + r_tmp = R_listItem(r_metadata, "deleted_on"); + if (r_tmp != R_NilValue) { + metadata.deleted_on = R_TimestampUnix(r_tmp); + } + + if (!modbMetadataReplace(sconn, &modb, metadata.id, &metadata)) { + return Rf_ScalarLogical(FALSE); + } + + r_tmp = R_listItem(r_metadata, "group_ids"); + if (r_tmp != R_NilValue) { + if (LENGTH(r_tmp) == 1 && TYPEOF(r_tmp) != VECSXP) { + if (modbLink_Metadata_Group( + sconn, &modb, metadata.id, + (unsigned int)Rf_asInteger(r_tmp)) <= 0) { + return Rf_ScalarLogical(FALSE); + } + } else { + for (i = 0; i < LENGTH(r_tmp); i++) { + if (modbLink_Metadata_Group( + sconn, &modb, metadata.id, + (unsigned int)Rf_asInteger(VECTOR_ELT(r_tmp, i))) <= 0) { + return Rf_ScalarLogical(FALSE); + } + } + } + } + } + + if (!Rf_isNull(r_object) && TYPEOF(r_object) == VECSXP && LENGTH(r_object) == 1 && Rf_isNull(VECTOR_ELT(r_object, 0))) { + } else { + memObj = robjectToMemory(r_object, R_MAGIC_XDR_V3); + object.id = metadata.id; + object.data_c = memObj->buf; + object.data_len = memObj->buf_size; + if (modbObjectUpdate(sconn, &modb, metadata.id, &object) <= 0) { + free(memObj->buf); + free(memObj); + return Rf_ScalarLogical(FALSE); + } + free(memObj->buf); + free(memObj); + } + + if (!Rf_isNull(r_extendedMeta) && TYPEOF(r_extendedMeta) == VECSXP && LENGTH(r_extendedMeta) == 1 && Rf_isNull(VECTOR_ELT(r_extendedMeta, 0))) { + + } else { + if ((metadata_ext = allocMetaExt()) == 0) { + return Rf_ScalarLogical(FALSE); + } + metadata_ext->id = metadata.id; + metadata_ext->n_values = (size_t)LENGTH(r_extendedMeta); + metadata_ext->values = allocMetaExtValues(metadata_ext->n_values, 1); + if (metadata_ext->values == 0) { + freeMetaExt(&metadata_ext); + return Rf_ScalarLogical(FALSE); + } + r_names = Rf_getAttrib(r_extendedMeta, R_NamesSymbol); + for (i = 0; i < LENGTH(r_extendedMeta); i++) { + ext_value = *(metadata_ext->values + i); + ext_value->key_c = Rf_translateCharUTF8(STRING_ELT(r_names, i)); + r_tmp = VECTOR_ELT(r_extendedMeta, i); + if (Rf_isNull(r_tmp)) { + ext_value->type = VTYPE_RAW; + ext_value->is_null = 1; + } else { + switch(TYPEOF(r_tmp)) { + case LGLSXP:/* logical vectors */ + ext_value->type = VTYPE_BOOL; + ext_value->value.boolVal = Rf_asLogical(r_tmp); + if (R_IsNA(Rf_asReal(r_tmp))) { + ext_value->is_null = 1; + } + break; + case INTSXP:/* integer vectors */ + ext_value->type = VTYPE_INT32; + ext_value->value.int32 = Rf_asInteger(r_tmp); + if (R_IsNA(Rf_asReal(r_tmp))) { + ext_value->is_null = 1; + } + break; + case REALSXP:/* real variables */ + ext_value->type = VTYPE_DOUBLE; + ext_value->value.dbl = Rf_asReal(r_tmp); + if (R_IsNA(Rf_asReal(r_tmp))) { + ext_value->is_null = 1; + } + break; + case STRSXP:/* string vectors */ + ext_value->type = VTYPE_STRING; + r_tmp = STRING_ELT(r_tmp, 0); + if (r_tmp == R_NaString) { + ext_value->is_null = 1; + } else { + ext_value->value.str_c = Rf_translateCharUTF8(r_tmp); + ext_value->is_const = 1; + } + break; + case VECSXP:/* generic vectors */ + break; + default: + break; + // Screwed if I know how to handle this... + } + } + } + if (modbMetaExtReplace(sconn, &modb, metadata.id, metadata_ext) <= 0) { + freeMetaExt(&metadata_ext); + return Rf_ScalarLogical(FALSE); + } + } + + return Rf_ScalarLogical(TRUE); } SEXP rmodb_deleteMetaobject(SEXP r_conn_ref, SEXP r_id) { diff --git a/src/R_modb_metaobjects.h b/src/R_modb_metaobjects.h index 1349161..1f14468 100644 --- a/src/R_modb_metaobjects.h +++ b/src/R_modb_metaobjects.h @@ -10,7 +10,10 @@ SEXP metadataToR(struct metadata_t *metadata); SEXP objectToR(struct object_t *object); SEXP metadataExtToR(struct meta_ext_t *ext); -SEXP rmodb_metaobjectId(SEXP r_conn_ref, SEXP r_query); +SEXP rmodb_metaobjectIds(SEXP r_conn_ref, SEXP r_query, SEXP with_deleted); +SEXP rmodb_metaobjectQuery(SEXP r_conn_ref, SEXP r_query, SEXP r_with_deleted, + SEXP r_owner_restrict); +SEXP rmodb_metadataQuery(SEXP r_conn_ref, SEXP r_query, SEXP r_with_deleted, SEXP r_owner_restrict); SEXP rmodb_metaobject(SEXP r_conn_ref, SEXP r_id); SEXP rmodb_metadata(SEXP r_conn_ref, SEXP r_id); @@ -21,7 +24,8 @@ SEXP rmodb_metadatas(SEXP r_conn_ref, SEXP r_with_deleted); SEXP rmodb_createMetaobject(SEXP r_conn_ref, SEXP r_id, SEXP r_metadata, SEXP r_object, SEXP r_extendedMeta); -SEXP rmodb_updateMetaobject(SEXP r_conn_ref, SEXP r_id, SEXP r_metaobject); +SEXP rmodb_updateMetaobject(SEXP r_conn_ref, SEXP r_id, + SEXP r_metadata, SEXP r_object, SEXP r_extendedMeta); SEXP rmodb_deleteMetaobject(SEXP r_conn_ref, SEXP r_id);