static boolean reinit_results(TDSSOCKET * tds, size_t num_cols, const struct metadata_t meta[]) { TDSRESULTINFO *info; int i; assert(tds); assert(num_cols); assert(meta); tds_free_all_results(tds); tds->rows_affected = TDS_NO_COUNT; if ((info = alloc_results(num_cols)) == NULL) return false; tds_set_current_results(tds, info); if (tds->cur_cursor) { tds_free_results(tds->cur_cursor->res_info); tds->cur_cursor->res_info = info; tdsdump_log(TDS_DBG_INFO1, "set current_results to cursor->res_info\n"); } else { tds->res_info = info; tdsdump_log(TDS_DBG_INFO1, "set current_results (%u column%s) to tds->res_info\n", (unsigned) num_cols, (num_cols==1? "":"s")); } tdsdump_log(TDS_DBG_INFO1, "setting up %u columns\n", (unsigned) num_cols); for (i = 0; i < num_cols; i++) { set_result_column(tds, info->columns[i], meta[i].name, &meta[i].col); info->columns[i]->bcp_terminator = (char*) meta[i].pacross; /* overload available pointer */ } if (num_cols > 0) { static char dashes[31] = "------------------------------"; tdsdump_log(TDS_DBG_INFO1, " %-20s %-15s %-15s %-7s\n", "name", "size/wsize", "type/wtype", "utype"); tdsdump_log(TDS_DBG_INFO1, " %-20s %15s %15s %7s\n", dashes+10, dashes+30-15, dashes+30-15, dashes+30-7); } for (i = 0; i < num_cols; i++) { TDSCOLUMN *curcol = info->columns[i]; tdsdump_log(TDS_DBG_INFO1, " %-20s %7d/%-7d %7d/%-7d %7d\n", tds_dstr_cstr(&curcol->column_name), curcol->column_size, curcol->on_server.column_size, curcol->column_type, curcol->on_server.column_type, curcol->column_usertype); } #if 1 /* all done now allocate a row for tds_process_row to use */ if (TDS_FAILED(tds_alloc_row(info))) return false; #endif return true; }
/** * Set state of TDS connection, with logging and checking. * \param tds state information for the socket and the TDS protocol * \param state the new state of the connection, cf. TDS_STATE. * \return the new state, which might not be \a state. */ TDS_STATE tds_set_state(TDSSOCKET * tds, TDS_STATE state) { const TDS_STATE prior_state = tds->state; static const char state_names[][10] = { "IDLE", "QUERYING", "PENDING", "READING", "DEAD" }; assert(state < TDS_VECTOR_SIZE(state_names)); assert(tds->state < TDS_VECTOR_SIZE(state_names)); if (state == tds->state) return state; switch(state) { /* transition to READING are valid only from PENDING */ case TDS_PENDING: if (tds->state != TDS_READING && tds->state != TDS_QUERYING) { tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", state_names[prior_state], state_names[state]); return tds->state; } tds->state = state; break; case TDS_READING: if (tds->state != TDS_PENDING) { tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", state_names[prior_state], state_names[state]); return tds->state; } tds->state = state; break; case TDS_IDLE: if (tds->state == TDS_DEAD && TDS_IS_SOCKET_INVALID(tds_get_s(tds))) { tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", state_names[prior_state], state_names[state]); return tds->state; } case TDS_DEAD: tds->state = state; break; case TDS_QUERYING: CHECK_TDS_EXTRA(tds); if (tds->state == TDS_DEAD) { tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", state_names[prior_state], state_names[state]); tdserror(tds_get_ctx(tds), tds, TDSEWRIT, 0); break; } else if (tds->state != TDS_IDLE) { tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", state_names[prior_state], state_names[state]); tdserror(tds_get_ctx(tds), tds, TDSERPND, 0); break; } /* TODO check this code, copied from tds_submit_prepare */ tds_free_all_results(tds); tds->rows_affected = TDS_NO_COUNT; tds_release_cursor(tds, tds->cur_cursor); tds->cur_cursor = NULL; tds->internal_sp_called = 0; tds->state = state; break; default: assert(0); break; } tdsdump_log(TDS_DBG_ERROR, "Changed query state from %s to %s\n", state_names[prior_state], state_names[state]); CHECK_TDS_EXTRA(tds); return tds->state; }
/* * TDS 5 style result sets */ static int read_result(TDS_POOL_MEMBER * pmbr, const unsigned char *buf, int maxlen, int *bytes_read) { TDS_SMALLINT hdrsize; int pos = 0; int namelen; int col; TDSSOCKET *tds = pmbr->tds; int num_cols; TDSCOLUMN *curcol; TDSRESULTINFO *info; if (bytes_left(pmbr, buf, pos, maxlen, 3)) { *bytes_read = maxlen; return 0; } /* FIX ME -- endian */ hdrsize = buf[1] + buf[2] * 256; pos += 3; /* read number of columns and allocate the columns structure */ num_cols = buf[pos] + buf[pos+1] * 256; pos += 2; tds_free_all_results(tds); tds->res_info = tds_alloc_results(num_cols); info = pmbr->tds->res_info; /* * loop through the columns populating COLINFO struct from * server response */ for (col = 0; col < info->num_cols; col++) { curcol = info->columns[col]; namelen = buf[pos++]; strncpy(curcol->column_name, (char *) &buf[pos], namelen); curcol->column_name[namelen] = '\0'; pos += namelen; curcol->column_namelen = namelen; pos++; /* flags */ pos += 4; /* user type */ tds_set_column_type(tds->conn, curcol, (int)buf[pos]); switch(curcol->column_varint_size) { /* FIX ME - endian */ case 2: curcol->column_size = buf[pos] + buf[pos+1]*256; break; case 1: curcol->column_size = buf[pos]; break; case 0: break; } pos+=curcol->column_varint_size; if (is_numeric_type(curcol->column_type)) pos+=2; /* skip locale information */ pos += buf[pos]; } return tds_alloc_row(info); }
static int read_col_name(TDS_POOL_MEMBER * pmbr, const unsigned char *buf, int maxlen, int *bytes_read) { TDS_SMALLINT hdrsize; int pos = 0; int num_cols = 0; int namelen; struct tmp_col_struct *head = NULL, *cur = NULL, *prev; int col; TDSCOLUMN *curcol; TDSRESULTINFO *info; /* header size */ if (bytes_left(pmbr, buf, pos, maxlen, 3)) { *bytes_read = maxlen; return 0; } /* FIXME -- endian */ hdrsize = buf[1] + buf[2] * 256; pos += 3; for (;;) { prev = cur; cur = (struct tmp_col_struct *) malloc(sizeof(struct tmp_col_struct)); cur->next = NULL; cur->column_name = NULL; if (prev) prev->next = cur; if (!head) head = cur; if (bytes_left(pmbr, buf, pos, maxlen, 1)) { *bytes_read = maxlen; free_col_struct(head); return 0; } namelen = buf[pos++]; if (bytes_left(pmbr, buf, pos, maxlen, namelen)) { *bytes_read = maxlen; free_col_struct(head); return 0; } cur->column_name = (char *) malloc(namelen + 1); strncpy(cur->column_name, (char *) &buf[pos], namelen); cur->column_name[namelen] = '\0'; pos += namelen; num_cols++; if (pos >= hdrsize) break; } tds_free_all_results(pmbr->tds); pmbr->tds->res_info = tds_alloc_results(num_cols); info = pmbr->tds->res_info; cur = head; for (col = 0; col < info->num_cols; col++) { curcol = info->columns[col]; strncpy(curcol->column_name, cur->column_name, sizeof(curcol->column_name)); /* FIXME ucs2 client and others */ curcol->column_name[sizeof(curcol->column_name) - 1] = 0; curcol->column_namelen = strlen(curcol->column_name); prev = cur; cur = cur->next; free(prev->column_name); free(prev); } *bytes_read = pos; return 1; }
void TdsDatabaseLayer::FreeAllocatedResultSets() { //fprintf(stderr, "In FreeAllocatedResultSets\n"); int rc; int result_type; /* */ //while ((rc = tds_process_tokens(m_pDatabase, &result_type, NULL, TDS_TOKEN_RESULTS)) == TDS_SUCCEED) //while ((rc = tds_process_tokens(m_pDatabase, &result_type, NULL, TDS_RETURN_ROW|TDS_TOKEN_RESULTS|TDS_RETURN_COMPUTE)) == TDS_SUCCEED) while ((rc = tds_process_tokens(m_pDatabase, &result_type, NULL, TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE)) == TDS_SUCCEED) { switch (result_type) { case TDS_DONE_RESULT: case TDS_DONEPROC_RESULT: case TDS_DONEINPROC_RESULT: case TDS_STATUS_RESULT: break; case TDS_ROWFMT_RESULT: case TDS_COMPUTEFMT_RESULT: case TDS_DESCRIBE_RESULT: break; case TDS_ROW_RESULT: //fprintf(stderr, "Warning (%d): TdsDatabaseLayer query should not return results. Type: %d\n", result_type, result_type); if (m_pDatabase->current_results && m_pDatabase->current_results->num_cols > 0) { while (tds_process_tokens(m_pDatabase, &result_type, NULL, TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW) == TDS_SUCCEED) { //fprintf(stderr, "Warning: TdsDatabaseLayer TDS_ROW_RESULT query should not return results. Type: %d\n", result_type); if (result_type != TDS_ROW_RESULT) break; if (!m_pDatabase->current_results) continue; } } if (m_pDatabase != NULL) tds_free_all_results(m_pDatabase); return; break; default: //fprintf(stderr, "Error: TdsDatabaseLayer query should not return results. Type: %d\n", result_type); return; //break; } } /* while (tds_process_tokens(m_pDatabase, &result_type, NULL, TDS_TOKEN_RESULTS) == TDS_SUCCEED) { switch (result_type) { case TDS_ROWFMT_RESULT: break; case TDS_ROW_RESULT: while (tds_process_tokens(m_pDatabase, &result_type, NULL, TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW) == TDS_SUCCEED) { if (result_type != TDS_ROW_RESULT) break; if (!m_pDatabase->current_results) continue; TDSCOLUMN* col = m_pDatabase->current_results->columns[0]; int ctype = tds_get_conversion_type(col->column_type, col->column_size); unsigned char* src = col->column_data; int srclen = col->column_cur_size; CONV_RESULT dres; tds_convert(m_pDatabase->tds_ctx, ctype, (TDS_CHAR *) src, srclen, SYBINT4, &dres); int optionval = dres.i; } break; default: break; } } */ // Make sure to clean up after ourselves if (m_pDatabase != NULL) tds_free_all_results(m_pDatabase); if (rc == TDS_FAIL) { ThrowDatabaseException(); //fprintf(stderr, "tds_process_tokens() returned TDS_FAIL\n"); return; } else if (rc != TDS_NO_MORE_RESULTS) { ThrowDatabaseException(); //fprintf(stderr, "tds_process_tokens() unexpected return\n"); return; } }
void TdsPreparedStatement::FreeAllocatedResultSets() { //fprintf(stderr, "In FreeAllocatedResultSets\n"); int rc; int result_type; while ((rc = tds_process_tokens(m_pDatabase, &result_type, NULL, TDS_TOKEN_RESULTS)) == TDS_SUCCEED) { switch (result_type) { case TDS_DONE_RESULT: case TDS_DONEPROC_RESULT: case TDS_DONEINPROC_RESULT: /* ignore possible spurious result (TDS7+ send it) */ case TDS_STATUS_RESULT: break; case TDS_ROWFMT_RESULT: case TDS_COMPUTEFMT_RESULT: case TDS_DESCRIBE_RESULT: break; case TDS_ROW_RESULT: //fprintf(stderr, "Warning: TdsPreparedStatement query should not return results. Type: %d\n", result_type); if (m_pDatabase->current_results && m_pDatabase->current_results->num_cols > 0) { while (tds_process_tokens(m_pDatabase, &result_type, NULL, TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW) == TDS_SUCCEED) { //fprintf(stderr, "Warning: TdsPreparedStatement TDS_ROW_RESULT query should not return results. Type: %d\n", result_type); if (result_type != TDS_ROW_RESULT) break; if (!m_pDatabase->current_results) continue; } } return; break; default: //fprintf(stderr, "Error: TdsPreparedStatement query should not return results. Type: %d\n", result_type); return; //break; } } // Clean up after ourselves if (m_pDatabase != NULL) tds_free_all_results(m_pDatabase); if (rc == TDS_FAIL) { //fprintf(stderr, "tds_process_tokens() returned TDS_FAIL\n"); SetErrorInformationFromDatabaseLayer(); ThrowDatabaseException(); return; } else if (rc != TDS_NO_MORE_RESULTS) { //fprintf(stderr, "tds_process_tokens() unexpected return\n"); SetErrorInformationFromDatabaseLayer(); ThrowDatabaseException(); return; } }
/** * Set state of TDS connection, with logging and checking. * \param tds state information for the socket and the TDS protocol * \param state the new state of the connection, cf. TDS_STATE. * \return the new state, which might not be \a state. */ TDS_STATE tds_set_state(TDSSOCKET * tds, TDS_STATE state) { TDS_STATE prior_state; static const char state_names[][8] = { "IDLE", "WRITING", "SENDING", "PENDING", "READING", "DEAD" }; assert(state < TDS_VECTOR_SIZE(state_names)); assert(tds->state < TDS_VECTOR_SIZE(state_names)); prior_state = tds->state; if (state == prior_state) return state; switch(state) { case TDS_PENDING: if (prior_state == TDS_READING || prior_state == TDS_WRITING) { tds->state = TDS_PENDING; tds_mutex_unlock(&tds->wire_mtx); break; } tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", state_names[prior_state], state_names[state]); break; case TDS_READING: /* transition to READING are valid only from PENDING */ if (tds_mutex_trylock(&tds->wire_mtx)) return tds->state; if (tds->state != TDS_PENDING) { tds_mutex_unlock(&tds->wire_mtx); tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", state_names[prior_state], state_names[state]); break; } tds->state = state; break; case TDS_SENDING: if (prior_state != TDS_READING && prior_state != TDS_WRITING) { tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", state_names[prior_state], state_names[state]); break; } if (tds->state == TDS_READING) { /* TODO check this code, copied from tds_submit_prepare */ tds_free_all_results(tds); tds->rows_affected = TDS_NO_COUNT; tds_release_cursor(&tds->cur_cursor); tds_release_cur_dyn(tds); tds->current_op = TDS_OP_NONE; } tds_mutex_unlock(&tds->wire_mtx); tds->state = state; break; case TDS_IDLE: if (prior_state == TDS_DEAD && TDS_IS_SOCKET_INVALID(tds_get_s(tds))) { tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", state_names[prior_state], state_names[state]); break; } case TDS_DEAD: if (prior_state == TDS_READING || prior_state == TDS_WRITING) tds_mutex_unlock(&tds->wire_mtx); tds->state = state; break; case TDS_WRITING: CHECK_TDS_EXTRA(tds); if (tds_mutex_trylock(&tds->wire_mtx)) return tds->state; if (tds->state == TDS_DEAD) { tds_mutex_unlock(&tds->wire_mtx); tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", state_names[prior_state], state_names[state]); tdserror(tds_get_ctx(tds), tds, TDSEWRIT, 0); break; } else if (tds->state != TDS_IDLE && tds->state != TDS_SENDING) { tds_mutex_unlock(&tds->wire_mtx); tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", state_names[prior_state], state_names[state]); tdserror(tds_get_ctx(tds), tds, TDSERPND, 0); break; } if (tds->state == TDS_IDLE) { /* TODO check this code, copied from tds_submit_prepare */ tds_free_all_results(tds); tds->rows_affected = TDS_NO_COUNT; tds_release_cursor(&tds->cur_cursor); tds_release_cur_dyn(tds); tds->current_op = TDS_OP_NONE; } tds->state = state; break; default: assert(0); break; } state = tds->state; tdsdump_log(TDS_DBG_ERROR, "Changed query state from %s to %s\n", state_names[prior_state], state_names[state]); CHECK_TDS_EXTRA(tds); return state; }