Exemple #1
0
SEXP RS_DBI_allocResultSet(SEXP conHandle) {
  RS_DBI_connection *con = RS_DBI_getConnection(conHandle);

  int indx = RS_DBI_newEntry(con->resultSetIds, con->length);
  if (indx < 0) {
    error(
      "cannot allocate a new resultSet -- maximum of %d resultSets already reached",
      con->length
    );
  }
  RS_DBI_resultSet* result = malloc(sizeof(RS_DBI_resultSet));
  if (!result) {
    RS_DBI_freeEntry(con->resultSetIds, indx);
    error("could not malloc dbResultSet");
  }
  result->drvResultSet = (void *) NULL; /* driver's own resultSet (cursor)*/
  result->statement = (char *) NULL;
  result->connectionId = CON_ID(conHandle);
  result->resultSetId = con->counter;
  result->isSelect = (int) -1;
  result->rowsAffected = (int) -1;
  result->rowCount = (int) 0;
  result->completed = (int) -1;
  result->fields = NULL;

  /* update connection's resultSet table */
  int res_id = con->counter;
  con->num_res += (int) 1;
  con->counter += (int) 1;
  con->resultSets[indx] = result;
  con->resultSetIds[indx] = res_id;

  return RS_DBI_asResHandle(MGR_ID(conHandle), CON_ID(conHandle), res_id);
}
s_object *
RS_PostgreSQL_getResult(Con_Handle * conHandle)
{
    S_EVALUATOR RS_DBI_connection * con;
    S_EVALUATOR RS_DBI_resultSet * result;
    PGconn *my_connection;
    Res_Handle *rsHandle;
    Sint res_id;
 
    PGresult *my_result;
   
    con = RS_DBI_getConnection(conHandle);
    my_connection = (PGconn *) con->drvConnection;

    if (con->num_res > 0) {
        res_id = (Sint) con->resultSetIds[0];
        rsHandle = RS_DBI_asResHandle(MGR_ID(conHandle), CON_ID(conHandle), res_id);
        result = RS_DBI_getResultSet(rsHandle);
        if (result->completed == 0) {
            RS_DBI_errorMessage("connection with pending rows, close resultSet before continuing", RS_DBI_ERROR);
        }
        else {
            RS_PostgreSQL_closeResultSet(rsHandle);
        }
    }

    my_result = PQgetResult(my_connection);
    if(my_result == NULL)
       return S_NULL_ENTRY;
    if (strcmp(PQresultErrorMessage(my_result), "") != 0) {
        char *errResultMsg;
        const char *omsg;
        size_t len;
        omsg = PQerrorMessage(my_connection);
        len = strlen(omsg);
        errResultMsg = malloc(len + 80); /* 80 should be larger than the length of "could not ..."*/
        snprintf(errResultMsg, len + 80, "could not Retrieve the result : %s", omsg);
        RS_DBI_errorMessage(errResultMsg, RS_DBI_ERROR);
        free(errResultMsg);

        /*  Frees the storage associated with a PGresult.
         *  void PQclear(PGresult *res);   */

        PQclear(my_result);

    }

    /* we now create the wrapper and copy values */
    PROTECT(rsHandle = RS_DBI_allocResultSet(conHandle));
    result = RS_DBI_getResultSet(rsHandle);
    result->drvResultSet = (void *) my_result;
    result->rowCount = (Sint) 0;
    result->isSelect = 0;
    result->rowsAffected = 0;
    result->completed = 1;
    UNPROTECT(1);
    return rsHandle;
}
Exemple #3
0
/* the invoking (freeing) function must provide a function for
* freeing the conParams, and by setting the (*free_drvConParams)(void *)
* pointer.
*/
void RS_DBI_freeConnection(SEXP conHandle) {
  int indx;

  RS_DBI_connection* con = RS_DBI_getConnection(conHandle);
  MySQLDriver* mgr = rmysql_driver();

  /* Are there open resultSets? If so, free them first */
  if (con->num_res > 0) {
    int  i;
    SEXP rsHandle;

    for(i=0; i < con->num_res; i++){
      rsHandle = RS_DBI_asResHandle(con->managerId,
        con->connectionId,
        (int) con->resultSetIds[i]);
      RS_DBI_freeResultSet(rsHandle);
    }
    warning("opened resultSet(s) forcebly closed");
  }
  if(con->drvConnection) {
    error("internal error in RS_DBI_freeConnection: driver might have left open its connection on the server");
  }
  if(con->conParams){
    error("internal error in RS_DBI_freeConnection: non-freed con->conParams (tiny memory leaked)");
  }
  /* delete this connection from manager's connection table */
  if(con->resultSets) free(con->resultSets);
  if(con->resultSetIds) free(con->resultSetIds);

  /* update the manager's connection table */
  indx = RS_DBI_lookup(mgr->connectionIds, mgr->length, con->connectionId);
  RS_DBI_freeEntry(mgr->connectionIds, indx);
  mgr->connections[indx] = (RS_DBI_connection *) NULL;
  mgr->num_con -= (int) 1;

  free(con);
  con = (RS_DBI_connection *) NULL;

  return;
}
Exemple #4
0
Res_Handle *
RS_PostgreSQL_exec(Con_Handle * conHandle, s_object * statement)
{
    S_EVALUATOR RS_DBI_connection * con;
    Res_Handle *rsHandle;
    RS_DBI_resultSet *result;
    PGconn *my_connection;
    PGresult *my_result;

    Sint res_id, is_select=0;
    char *dyn_statement;

    con = RS_DBI_getConnection(conHandle);
    my_connection = (PGconn *) con->drvConnection;
    dyn_statement = RS_DBI_copyString(CHR_EL(statement, 0));

    /* Do we have a pending resultSet in the current connection?
     * PostgreSQL only allows  one resultSet per connection.
     */
    if (con->num_res > 0) {
        res_id = (Sint) con->resultSetIds[0];   /* recall, PostgreSQL has only 1 res */
        rsHandle = RS_DBI_asResHandle(MGR_ID(conHandle), CON_ID(conHandle), res_id);
        result = RS_DBI_getResultSet(rsHandle);
        if (result->completed == 0) {
            free(dyn_statement);
            RS_DBI_errorMessage("connection with pending rows, close resultSet before continuing", RS_DBI_ERROR);
        }
        else {
            RS_PostgreSQL_closeResultSet(rsHandle);
        }
    }

    /* Here is where we actually run the query */

    /* Example: PGresult *PQexec(PGconn *conn, const char *command); */

    my_result = PQexec(my_connection, dyn_statement);
    if (my_result == NULL) {
        char *errMsg;
        const char *omsg;
        size_t len;
        omsg = PQerrorMessage(my_connection);
        len = strlen(omsg);
        free(dyn_statement);
        errMsg = R_alloc(len + 80, 1); /* 80 should be larger than the length of "could not ..."*/
        snprintf(errMsg, len + 80,  "could not run statement: %s", omsg);
        RS_DBI_errorMessage(errMsg, RS_DBI_ERROR);
    }


    /* ExecStatusType PQresultStatus(const PGresult *res); */

    if (PQresultStatus(my_result) == PGRES_TUPLES_OK) {
        is_select = (Sint) TRUE;
    }
    if (PQresultStatus(my_result) == PGRES_COMMAND_OK) {
        is_select = (Sint) FALSE;
    }

    /* char *PQresultErrorMessage(const PGresult *res); */

    if (strcmp(PQresultErrorMessage(my_result), "") != 0) {
        char *errResultMsg;
        const char *omsg;
        size_t len;
        omsg = PQerrorMessage(my_connection);
        len = strlen(omsg);
        errResultMsg = R_alloc(len + 80, 1); /* 80 should be larger than the length of "could not ..."*/
        snprintf(errResultMsg, len + 80, "could not Retrieve the result : %s", omsg);
        /*  Frees the storage associated with a PGresult.
         *  void PQclear(PGresult *res);   */
        PQclear(my_result);
        free(dyn_statement);
        RS_DBI_errorMessage(errResultMsg, RS_DBI_ERROR);
    }

    /* we now create the wrapper and copy values */
    PROTECT(rsHandle = RS_DBI_allocResultSet(conHandle));
    result = RS_DBI_getResultSet(rsHandle);
    result->statement = RS_DBI_copyString(dyn_statement);
    result->drvResultSet = (void *) my_result;
    result->rowCount = (Sint) 0;
    result->isSelect = is_select;

    /*  Returns the number of rows affected by the SQL command.
     *  char *PQcmdTuples(PGresult *res);
     */

    if (!is_select) {
        result->rowsAffected = (Sint) atoi(PQcmdTuples(my_result));
        result->completed = 1;
    }
    else {
        result->rowsAffected = (Sint) - 1;
        result->completed = 0;
    }

    if (is_select) {
        result->fields = RS_PostgreSQL_createDataMappings(rsHandle);
    }
    free(dyn_statement);
    UNPROTECT(1);
    return rsHandle;
}
Exemple #5
0
/* Execute (currently) one sql statement (INSERT, DELETE, SELECT, etc.),
* set coercion type mappings between the server internal data types and
* S classes.   Returns  an S handle to a resultSet object.
*/
SEXP RS_MySQL_exec(SEXP conHandle, SEXP statement) {
  RS_DBI_connection *con;
  SEXP rsHandle;
  RS_DBI_resultSet  *result;
  MYSQL             *my_connection;
  MYSQL_RES         *my_result;
  int      num_fields, state;
  int     res_id, is_select;
  char     *dyn_statement;

  con = RS_DBI_getConnection(conHandle);
  my_connection = (MYSQL *) con->drvConnection;
  dyn_statement = RS_DBI_copyString(CHR_EL(statement,0));

  /* Do we have a pending resultSet in the current connection?
   * MySQL only allows  one resultSet per connection.
   */
  if(con->num_res>0){
    res_id = (int) con->resultSetIds[0]; /* recall, MySQL has only 1 res */
  rsHandle = RS_DBI_asResHandle(MGR_ID(conHandle),
    CON_ID(conHandle), res_id);
  result = RS_DBI_getResultSet(rsHandle);
  if(result->completed == 0){
    free(dyn_statement);
    error("connection with pending rows, close resultSet before continuing");
  }
  else
    RS_MySQL_closeResultSet(rsHandle);
  }

  /* Here is where we actually run the query */
  state = mysql_query(my_connection, dyn_statement);
  if(state) {
    error("could not run statement: %s", mysql_error(my_connection));
  }

  /* Do we need output column/field descriptors?  Only for SELECT-like
   * statements. The MySQL reference manual suggests invoking
   * mysql_use_result() and if it succeed the statement is SELECT-like
   * that can use a resultSet.  Otherwise call mysql_field_count()
   * and if it returns zero, the sql was not a SELECT-like statement.
   * Finally a non-zero means a failed SELECT-like statement.
   */
  my_result = mysql_use_result(my_connection);
  if(!my_result)
    my_result = (MYSQL_RES *) NULL;

  num_fields = (int) mysql_field_count(my_connection);
  is_select = (int) TRUE;
  if(!my_result){
    if(num_fields>0){
      free(dyn_statement);
      error("error in select/select-like");
    }
    else
      is_select = FALSE;
  }

  /* we now create the wrapper and copy values */
  rsHandle = RS_DBI_allocResultSet(conHandle);
  result = RS_DBI_getResultSet(rsHandle);
  result->statement = RS_DBI_copyString(dyn_statement);
  result->drvResultSet = (void *) my_result;
  result->rowCount = (int) 0;
  result->isSelect = is_select;
  if(!is_select){
    result->rowsAffected = (int) mysql_affected_rows(my_connection);
    result->completed = 1;
  }
  else {
    result->rowsAffected = (int) -1;
    result->completed = 0;
  }

  if(is_select)
    result->fields = RS_MySQL_createDataMappings(rsHandle);

  free(dyn_statement);
  return rsHandle;
}