#include #include "R_modb_manage.h" #include "R_list_item.h" #include "R_helpers_p.h" #include "modb_database.h" SEXP rmodb_connectionInfo(SEXP r_conn_ref) { stored_conn *sconn; SEXP res, conn_name, last_qry, names; if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { return R_NilValue; } conn_name = PROTECT(Rf_allocVector(STRSXP, 1)); SET_STRING_ELT(conn_name, 0, PROTECT(Rf_mkChar(sconn->name))); last_qry = PROTECT(Rf_allocVector(STRSXP, 1)); if (sconn->last_qry != 0) { SET_STRING_ELT(last_qry, 0, PROTECT(Rf_mkChar(sconn->last_qry))); } else { SET_STRING_ELT(last_qry, 0, PROTECT(NA_STRING)); } res = PROTECT(Rf_allocVector(VECSXP, 4)); SET_VECTOR_ELT(res, 0, PROTECT(Rf_ScalarInteger(sconn->conn_id))); SET_VECTOR_ELT(res, 1, conn_name); SET_VECTOR_ELT(res, 2, last_qry); SET_VECTOR_ELT(res, 3, PROTECT(Rf_ScalarInteger((int)sconn->num_queries))); names = PROTECT(Rf_allocVector(STRSXP, 4)); SET_STRING_ELT(names, 0, PROTECT(Rf_mkChar("id"))); SET_STRING_ELT(names, 1, PROTECT(Rf_mkChar("name"))); SET_STRING_ELT(names, 2, PROTECT(Rf_mkChar("num_queries"))); SET_STRING_ELT(names, 3, PROTECT(Rf_mkChar("last_query"))); Rf_setAttrib(res, R_NamesSymbol, names); UNPROTECT(12); return res; } SEXP rmodb_connectToHost(SEXP r_name, SEXP r_host, SEXP r_port, SEXP r_username, SEXP r_password, SEXP r_database) { stored_conn *sconn; const char *name = 0, *host, *user, *pass, *db; unsigned int port; if (!Rf_isNull(r_name)) { name = Rf_translateCharUTF8(STRING_ELT(r_name, 0)); } host = Rf_translateCharUTF8(STRING_ELT(r_host, 0)); port = (unsigned int)Rf_asInteger(r_port); user = Rf_translateCharUTF8(STRING_ELT(r_username, 0)); pass = Rf_translateCharUTF8(STRING_ELT(r_password, 0)); db = Rf_translateCharUTF8(STRING_ELT(r_database, 0)); sconn = createStoredConnection(name); if (sconn == 0) { return R_NilValue; } if (connectToHost(sconn, host, port, user, pass, db) < 0) { destroyStoredConnection(sconn); return R_NilValue; } return Rf_ScalarInteger(sconn->conn_id); } SEXP rmodb_connectToSocket(SEXP r_name, SEXP r_socket, SEXP r_username, SEXP r_password, SEXP r_database) { stored_conn *sconn; const char *name = 0, *sock, *user, *pass, *db; if (!Rf_isNull(r_name)) { name = Rf_translateCharUTF8(STRING_ELT(r_name, 0)); } sock = Rf_translateCharUTF8(STRING_ELT(r_socket, 0)); user = Rf_translateCharUTF8(STRING_ELT(r_username, 0)); pass = Rf_translateCharUTF8(STRING_ELT(r_password, 0)); db = Rf_translateCharUTF8(STRING_ELT(r_database, 0)); sconn = createStoredConnection(name); if (sconn == 0) { return R_NilValue; } if (connectToSocket(sconn, sock, user, pass, db) < 0) { destroyStoredConnection(sconn); return R_NilValue; } return Rf_ScalarInteger(sconn->conn_id); } SEXP rmodb_disconnect(SEXP r_conn_ref) { stored_conn *sconn; int conn_id; if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { return R_NilValue; } conn_id = sconn->conn_id; modbReleaseUse(sconn); closeConnection(sconn); destroyStoredConnection(sconn); return Rf_ScalarInteger(conn_id); } SEXP rmodb_exists(SEXP r_conn_ref, SEXP r_name) { stored_conn *sconn; modb_ref modb; if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { Rf_error("invalid connection reference\n"); } modb.name = Rf_translateCharUTF8(STRING_ELT(r_name, 0)); modb.name_len = strlen(modb.name); return Rf_ScalarLogical(modbExists(sconn, &modb)); } SEXP rmodb_create(SEXP r_conn_ref, SEXP r_name, SEXP r_extra_meta) { stored_conn *sconn; modb_ref modb; struct column_data_t **cols = 0; size_t n_cols = 0; SEXP r_col, r_col_name, r_col_type, r_col_null, r_col_max_len; if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { Rf_error("invalid connection reference\n"); } modb.name = Rf_translateCharUTF8(STRING_ELT(r_name, 0)); modb.name_len = strlen(modb.name); if (modbExists(sconn, &modb)) { Rf_warning("an MODB instance named '%s' already exists\n", modb.name); return Rf_ScalarLogical(FALSE); } if (!Rf_isNull(r_extra_meta)) { n_cols = (size_t)Rf_length(r_extra_meta); cols = (struct column_data_t **)calloc(sizeof(struct column_data_t *), n_cols); if (cols == 0) { rmodb_destroy(r_conn_ref, r_name); Rf_error("failed to create MODB instance"); } for (size_t i = 0; i < n_cols; i++) { r_col = VECTOR_ELT(r_extra_meta, (int)i); r_col_name = STRING_ELT(R_listItem(r_col, "name"), 0); r_col_type = R_listItem(r_col, "type"); r_col_null = R_listItem(r_col, "nullable"); r_col_max_len = R_listItem(r_col, "max_length"); *(cols + i) = initEmptyColumn( (e_column_type)(unsigned int)Rf_asInteger(r_col_type), Rf_asLogical(r_col_null), Rf_translateCharUTF8(r_col_name), 0, 0, 0); if (*(cols + i) == 0) { freeColumns(cols, i); rmodb_destroy(r_conn_ref, r_name); Rf_error("failed to create MODB instance"); } if (r_col_max_len != R_NilValue && (*(cols + i))->type == TYPE_STRING) { (*(cols + i))->max_len = (unsigned int)Rf_asInteger(r_col_max_len); } } } if (!modbCreate(sconn, &modb, cols, n_cols)) { rmodb_destroy(r_conn_ref, r_name); Rf_error("failed to create MODB instance"); } if (n_cols > 0) { freeColumns(cols, n_cols); } return Rf_ScalarLogical(TRUE); } SEXP rmodb_destroy(SEXP r_conn_ref, SEXP r_name) { stored_conn *sconn; modb_ref modb; if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { Rf_error("invalid connection reference\n"); } modb.name = Rf_translateCharUTF8(STRING_ELT(r_name, 0)); modb.name_len = strlen(modb.name); modbDestroy(sconn, &modb); return Rf_ScalarLogical(TRUE); } SEXP rmodb_use(SEXP r_conn_ref, SEXP r_name, SEXP r_override) { stored_conn *sconn; modb_ref modb; if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { Rf_error("invalid connection reference\n"); } modb.name = Rf_translateCharUTF8(STRING_ELT(r_name, 0)); modb.name_len = strlen(modb.name); if (!modbExists(sconn, &modb)) { Rf_error("an MODB instance named '%s' does not exist\n", modb.name); } if (!modbUse(sconn, &modb, Rf_asLogical(r_override))) { return Rf_ScalarLogical(FALSE); } return Rf_ScalarLogical(TRUE); } SEXP rmodb_getLastQuery(SEXP r_conn_ref) { stored_conn *sconn; SEXP r_res; if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { Rf_error("invalid connection reference\n"); } r_res = Rf_allocVector(STRSXP, 1); SET_STRING_ELT(r_res, 0, PROTECT(Rf_mkCharLen(sconn->last_qry, (int)sconn->last_qry_len))); UNPROTECT(2); return r_res; }