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"); }
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(); } }
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()); }