Ejemplo n.º 1
0
void ODBCResult::UV_AfterFetchAll(uv_work_t* work_req, int status)
{
  DEBUG_PRINTF("ODBCResult::UV_AfterFetchAll - Entry\n");
  Nan::HandleScope scope;
  
  fetch_work_data* data = (fetch_work_data *)(work_req->data);
  
  ODBCResult* self = data->objResult->self();
  
  bool doMoreWork = true;
  
  /* Check : to see if there was an ERROR on SQLFetch() call.
   * So before GetColums call we should store the error.
   * Reason : GetColumns internally calls SQLGetDiagField method,
   * and SQLGetDiagField() method retrieves only the diagnostic information of
   * most recent CLI function call, any diagnostic information from a previous call 
   * with the same handle will be lost. - issue253
  */ 
  if (data->result == SQL_ERROR) {
    data->errorCount++;
    data->objError.Reset(ODBC::GetSQLError(
      SQL_HANDLE_STMT,
      self->m_hSTMT,
      (char *) "[node-odbc] Error in ODBCResult::UV_AfterFetchAll"
    ));
  }
  
  if (self->colCount == 0) {
    self->columns = ODBC::GetColumns(self->m_hSTMT, &self->colCount);
    DEBUG_PRINTF("ODBCResult::UV_AfterFetchAll, colcount = %d, columns = %d, stmt = %X\n", 
            self->colCount, self->columns, data->objResult->m_hSTMT);
  }

  /* Check : to see if the result set has columns.
   * Queries like insert into... (which has no actual fetch data),
   * will also return error after SQLFetch call, which is expected here
   * (as we are calling SQLFetch for every SQL query) but not true,
   * hence we should ignore these error.  
  */
  bool noDataFetchQuery = false;

  if (self->colCount == 0) {
    noDataFetchQuery = true;
    doMoreWork = false;
  }
  //check to see if we are at the end of the recordset
  else if (data->result == SQL_NO_DATA) {
    doMoreWork = false;
  }
  //check to see if there was an error
  else if (data->result == SQL_ERROR)  {
    doMoreWork = false;
  }
  
  else {
    Local<Array> rows = Nan::New(data->rows);
    if (data->fetchMode == FETCH_ARRAY) {
      rows->Set(
        Nan::New(data->count), 
        ODBC::GetRecordArray(
          self->m_hSTMT,
          self->columns,
          &self->colCount,
          self->buffer,
          self->bufferLength)
      );
    }
    else {
      rows->Set(
        Nan::New(data->count), 
        ODBC::GetRecordTuple(
          self->m_hSTMT,
          self->columns,
          &self->colCount,
          self->buffer,
          self->bufferLength)
      );
    }
    data->count++;
  }
  if (doMoreWork) {
    //Go back to the thread pool and fetch more data!
    uv_queue_work( uv_default_loop(),
                   work_req,
                   UV_FetchAll,
                   (uv_after_work_cb)UV_AfterFetchAll);
  }
  else {
    DEBUG_PRINTF("ODBCResult::UV_AfterFetchAll Done for stmt %X\n", data->objResult->m_hSTMT);
    
    Local<Value> info[3];
    
    if (data->errorCount > 0) {
      if(noDataFetchQuery) {
        info[0] = Nan::Null();
        noDataFetchQuery = false;
      }
      else {
        info[0] = Nan::New(data->objError);
      }
    }
    else {
      info[0] = Nan::Null();
    }
    
    info[1] = Nan::New(data->rows);
    info[2] = Nan::New(self->colCount);
    Nan::TryCatch try_catch;

    data->cb->Call(3, info);
    ODBC::FreeColumns(self->columns, &self->colCount);
    delete data->cb;
    data->rows.Reset();
    data->objError.Reset();

    if (try_catch.HasCaught()) {
      FatalException(try_catch);
    }

    //TODO: Do we need to free self->rows somehow?
    free(data);
    free(work_req);
    self->Unref(); 
  }
  DEBUG_PRINTF("ODBCResult::UV_AfterFetchAll - Exit\n");
}
Ejemplo n.º 2
0
void ODBCResult::UV_AfterFetchAll(uv_work_t* work_req, int status) {
  DEBUG_PRINTF("ODBCResult::UV_AfterFetchAll\n");
  Nan::HandleScope scope;
  
  fetch_work_data* data = (fetch_work_data *)(work_req->data);
  
  ODBCResult* self = data->objResult->self();
  
  bool doMoreWork = true;
  
  if (self->colCount == 0) {
    self->columns = ODBC::GetColumns(self->m_hSTMT, &self->colCount);
  }
  
  //check to see if the result set has columns
  if (self->colCount == 0) {
    //this most likely means that the query was something like
    //'insert into ....'
    doMoreWork = false;
  }
  //check to see if there was an error
  else if (data->result == SQL_ERROR)  {
    data->errorCount++;
    
    data->objError.Reset(ODBC::GetSQLError(
      SQL_HANDLE_STMT, 
      self->m_hSTMT,
      (char *) "[node-odbc] Error in ODBCResult::UV_AfterFetchAll"
    ));
    
    doMoreWork = false;
  }
  //check to see if we are at the end of the recordset
  else if (data->result == SQL_NO_DATA) {
    doMoreWork = false;
  }
  else {
    //TODO: !important: persistent forces us to set this to a local handle, but do we need to recopy it back to persistent handle?
    Local<Array> rows = Nan::New(data->rows);
    if (data->fetchMode == FETCH_ARRAY) {
      rows->Set(
        Nan::New(data->count), 
        ODBC::GetRecordArray(
          self->m_hSTMT,
          self->columns,
          &self->colCount,
          self->buffer,
          self->bufferLength)
      );
    }
    else {
      rows->Set(
        Nan::New(data->count), 
        ODBC::GetRecordTuple(
          self->m_hSTMT,
          self->columns,
          &self->colCount,
          self->buffer,
          self->bufferLength)
      );
    }
    data->count++;
  }
  
  if (doMoreWork) {
    //Go back to the thread pool and fetch more data!
    uv_queue_work(
      uv_default_loop(),
      work_req, 
      UV_FetchAll, 
      (uv_after_work_cb)UV_AfterFetchAll);
  }
  else {
    ODBC::FreeColumns(self->columns, &self->colCount);
    
    Local<Value> info[2];
    
    if (data->errorCount > 0) {
      info[0] = Nan::New(data->objError);
    }
    else {
      info[0] = Nan::Null();
    }
    
    info[1] = Nan::New(data->rows);

    Nan::TryCatch try_catch;

    data->cb->Call(2, info);
    delete data->cb;
    data->rows.Reset();
    data->objError.Reset();

    if (try_catch.HasCaught()) {
      FatalException(try_catch);
    }

    //TODO: Do we need to free self->rows somehow?
    free(data);
    free(work_req);

    self->Unref(); 
  }
}
Ejemplo n.º 3
0
void ODBCResult::UV_AfterFetchAll(uv_work_t* work_req, int status) {
  DEBUG_PRINTF("ODBCResult::UV_AfterFetchAll\n");
  
  HandleScope scope;
  
  fetch_work_data* data = (fetch_work_data *)(work_req->data);
  
  ODBCResult* self = data->objResult->self();
  
  bool doMoreWork = true;
  
  if (self->colCount == 0) {
    self->columns = ODBC::GetColumns(self->m_hSTMT, &self->colCount);
  }
  
  //check to see if the result set has columns
  if (self->colCount == 0) {
    //this most likely means that the query was something like
    //'insert into ....'
    doMoreWork = false;
  }
  //check to see if there was an error
  else if (data->result == SQL_ERROR)  {
    data->errorCount++;
    
    data->objError = Persistent<Object>::New(ODBC::GetSQLError(
      SQL_HANDLE_STMT, 
      self->m_hSTMT,
      (char *) "[node-odbc] Error in ODBCResult::UV_AfterFetchAll"
    ));
    
    doMoreWork = false;
  }
  //check to see if we are at the end of the recordset
  else if (data->result == SQL_NO_DATA) {
    doMoreWork = false;
  }
  else {
    if (data->fetchMode == FETCH_ARRAY) {
      data->rows->Set(
        Integer::New(data->count), 
        ODBC::GetRecordArray(
          self->m_hSTMT,
          self->columns,
          &self->colCount,
          self->buffer,
          self->bufferLength)
      );
    }
    else {
      data->rows->Set(
        Integer::New(data->count), 
        ODBC::GetRecordTuple(
          self->m_hSTMT,
          self->columns,
          &self->colCount,
          self->buffer,
          self->bufferLength)
      );
    }
    data->count++;
  }
  
  if (doMoreWork) {
    //Go back to the thread pool and fetch more data!
    uv_queue_work(
      uv_default_loop(),
      work_req, 
      UV_FetchAll, 
      (uv_after_work_cb)UV_AfterFetchAll);
  }
  else {
    ODBC::FreeColumns(self->columns, &self->colCount);
    
    Handle<Value> args[2];
    
    if (data->errorCount > 0) {
      args[0] = Local<Object>::New(data->objError);
    }
    else {
      args[0] = Null();
    }
    
    args[1] = Local<Array>::New(data->rows);

    TryCatch try_catch;

    data->cb->Call(Context::GetCurrent()->Global(), 2, args);
    data->cb.Dispose();
    data->rows.Dispose();
    data->objError.Dispose();

    if (try_catch.HasCaught()) {
      FatalException(try_catch);
    }

    //TODO: Do we need to free self->rows somehow?
    free(data);
    free(work_req);

    self->Unref(); 
  }
  
  scope.Close(Undefined());
}