void tds_send_result(TDSSOCKET * tds, TDSRESULTINFO * resinfo) { TDSCOLUMN *curcol; int i, totlen; size_t len; tds_put_byte(tds, TDS_RESULT_TOKEN); totlen = 2; for (i = 0; i < resinfo->num_cols; i++) { curcol = resinfo->columns[i]; len = tds_dstr_len(&curcol->column_name); totlen += 8; totlen += len; curcol = resinfo->columns[i]; if (!is_fixed_type(curcol->column_type)) { totlen++; } } tds_put_smallint(tds, totlen); tds_put_smallint(tds, resinfo->num_cols); for (i = 0; i < resinfo->num_cols; i++) { curcol = resinfo->columns[i]; len = tds_dstr_len(&curcol->column_name); tds_put_byte(tds, tds_dstr_len(&curcol->column_name)); tds_put_n(tds, tds_dstr_cstr(&curcol->column_name), len); tds_put_byte(tds, '0'); tds_put_int(tds, curcol->column_usertype); tds_put_byte(tds, curcol->column_type); if (!is_fixed_type(curcol->column_type)) { tds_put_byte(tds, curcol->column_size); } tds_put_byte(tds, 0); } }
void tds_send_eed(TDSSOCKET * tds, int msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line) { int totsize; tds_put_byte(tds, TDS_EED_TOKEN); totsize = 7 + strlen(procname) + 5 + strlen(msgtext) + 2 + strlen(srvname) + 3; tds_put_smallint(tds, totsize); tds_put_smallint(tds, msgno); tds_put_smallint(tds, 0); /* unknown */ tds_put_byte(tds, msgstate); tds_put_byte(tds, severity); tds_put_byte(tds, strlen(procname)); tds_put_n(tds, procname, strlen(procname)); tds_put_byte(tds, 0); /* unknown */ tds_put_byte(tds, 1); /* unknown */ tds_put_byte(tds, 0); /* unknown */ tds_put_smallint(tds, strlen(msgtext) + 1); tds_put_n(tds, msgtext, strlen(msgtext)); tds_put_byte(tds, severity); tds_put_byte(tds, strlen(srvname)); tds_put_n(tds, srvname, strlen(srvname)); tds_put_byte(tds, 0); /* unknown */ tds_put_byte(tds, 1); /* unknown */ tds_put_byte(tds, 0); /* unknown */ }
void tds7_send_result(TDSSOCKET * tds, TDSRESULTINFO * resinfo) { int i, j; TDSCOLUMN *curcol; /* TDS7+ uses TDS7_RESULT_TOKEN to send column names and info */ tds_put_byte(tds, TDS7_RESULT_TOKEN); /* send the number of columns */ tds_put_smallint(tds, resinfo->num_cols); /* send info about each column */ for (i = 0; i < resinfo->num_cols; i++) { /* usertype, flags, and type */ curcol = resinfo->columns[i]; tds_put_smallint(tds, curcol->column_usertype); tds_put_smallint(tds, curcol->column_flags); tds_put_byte(tds, curcol->column_type); /* smallint? */ /* bytes in "size" field varies */ if (is_blob_type(curcol->column_type)) { tds_put_int(tds, curcol->column_size); } else if (curcol->column_type>=128) { /*is_large_type*/ tds_put_smallint(tds, curcol->column_size); } else { tds_put_tinyint(tds, curcol->column_size); } /* some types have extra info */ if (is_numeric_type(curcol->column_type)) { tds_put_tinyint(tds, curcol->column_prec); tds_put_tinyint(tds, curcol->column_scale); } else if (is_blob_type(curcol->column_type)) { size_t len = tds_dstr_len(&curcol->table_name); const char *name = tds_dstr_cstr(&curcol->table_name); tds_put_smallint(tds, 2 * len); for (j = 0; name[j] != '\0'; j++){ tds_put_byte(tds, name[j]); tds_put_byte(tds, 0); } } /* finally the name, in UCS16 format */ assert(strlen(curcol->column_name) == curcol->column_namelen); tds_put_byte(tds, curcol->column_namelen); for (j = 0; j < curcol->column_namelen; j++) { tds_put_byte(tds, curcol->column_name[j]); tds_put_byte(tds, 0); } } }
/** * Send a "done" token, marking the end of a table, stored procedure, or query. * \param tds Where the token will be written to. * \param token The appropriate type of "done" token for this context: * TDS_DONE_TOKEN outside a stored procedure, * TDS_DONEINPROC_TOKEN inside a stored procedure, or * TDS_DONEPROC_TOKEN at the end of a stored procedure. * \param flags Bitwise-OR of flags in the "enum tds_end" data type. * TDS_DONE_FINAL for the last statement in a query, * TDS_DONE_MORE_RESULTS if not the last statement, * TDS_DONE_ERROR if the statement had an error, * TDS_DONE_INXACT if a transaction is pending, * TDS_DONE_PROC inside a stored procedure, * TDS_DONE_COUNT if a table was sent (and rows counted) * TDS_DONE_CANCELLED if the query was canceled, and * TDS_DONE_EVENT if the token marks an event. * \param numrows Number of rows, if flags has TDS_DONE_COUNT. */ void tds_send_done(TDSSOCKET * tds, int token, TDS_SMALLINT flags, TDS_INT numrows) { tds_put_byte(tds, token); tds_put_smallint(tds, flags); tds_put_smallint(tds, 2); /* are these two bytes the transaction status? */ if (IS_TDS72_PLUS(tds->conn)) tds_put_int8(tds, numrows); else tds_put_int(tds, numrows); }
void tds_env_change(TDSSOCKET * tds, int type, const char *oldvalue, const char *newvalue) { TDS_SMALLINT totsize; /* If oldvalue is NULL, treat it like "" */ if (oldvalue == NULL) oldvalue = ""; /* * NOTE: I don't know why each type of environment value has a different * format. According to the TDS5 specifications, they should all use * the same format. The code for the TDS_ENV_CHARSET case *should* * work for all environment values. -- Steve Kirkendall */ switch (type) { case TDS_ENV_DATABASE: case TDS_ENV_LANG: case TDS_ENV_PACKSIZE: case TDS_ENV_CHARSET: tds_put_byte(tds, TDS_ENVCHANGE_TOKEN); /* totsize = type + newlen + newvalue + oldlen + oldvalue */ /* FIXME ucs2 */ totsize = (IS_TDS7_PLUS(tds->conn) ? 2 : 1) * (strlen(oldvalue) + strlen(newvalue)) + 3; tds_put_smallint(tds, totsize); tds_put_byte(tds, type); tds_put_byte(tds, strlen(newvalue)); /* FIXME this assume singlebyte -> ucs2 for mssql */ tds_put_string(tds, newvalue, strlen(newvalue)); tds_put_byte(tds, strlen(oldvalue)); /* FIXME this assume singlebyte -> ucs2 for mssql */ tds_put_string(tds, oldvalue, strlen(oldvalue)); break; case TDS_ENV_LCID: case TDS_ENV_SQLCOLLATION: #if 1 tds_put_byte(tds, TDS_ENVCHANGE_TOKEN); /* totsize = type + len + oldvalue + len + newvalue */ totsize = 3 + strlen(newvalue) + strlen(oldvalue); tds_put_smallint(tds, totsize); tds_put_byte(tds, type); tds_put_byte(tds, strlen(newvalue)); tds_put_n(tds, newvalue, strlen(newvalue)); tds_put_byte(tds, strlen(oldvalue)); tds_put_n(tds, oldvalue, strlen(oldvalue)); break; #endif default: tdsdump_log(TDS_DBG_WARN, "tds_env_change() ignoring unsupported environment code #%d", type); } }
void tds_send_login_ack(TDSSOCKET * tds, const char *progname) { TDS_UINT ui, version; tds_put_byte(tds, TDS_LOGINACK_TOKEN); tds_put_smallint(tds, 10 + (IS_TDS7_PLUS(tds->conn)? 2 : 1) * strlen(progname)); /* length of message */ if (IS_TDS50(tds->conn)) { tds_put_byte(tds, 5); version = 0x05000000u; } else { tds_put_byte(tds, 1); /* see src/tds/token.c */ if (IS_TDS73_PLUS(tds->conn)) { version = 0x730B0003u; } else if (IS_TDS72_PLUS(tds->conn)) { version = 0x72090002u; } else if (IS_TDS71_PLUS(tds->conn)) { version = tds->conn->tds71rev1 ? 0x07010000u : 0x71000001u; } else { version = (TDS_MAJOR(tds->conn) << 24) | (TDS_MINOR(tds->conn) << 16); } } TDS_PUT_A4BE(&ui, version); tds_put_n(tds, &ui, 4); tds_put_byte(tds, strlen(progname)); /* FIXME ucs2 */ tds_put_string(tds, progname, strlen(progname)); /* server version, always big endian */ TDS_PUT_A4BE(&ui, tds->conn->product_version & 0x7fffffffu); tds_put_n(tds, &ui, 4); }
void tds_send_col_info(TDSSOCKET * tds, TDSRESULTINFO * resinfo) { int col, hdrsize = 0; TDSCOLUMN *curcol; tds_put_byte(tds, TDS_COLFMT_TOKEN); for (col = 0; col < resinfo->num_cols; col++) { curcol = resinfo->columns[col]; hdrsize += 5; if (!is_fixed_type(curcol->column_type)) { hdrsize++; } } tds_put_smallint(tds, hdrsize); for (col = 0; col < resinfo->num_cols; col++) { curcol = resinfo->columns[col]; tds_put_n(tds, "\0\0\0\0", 4); tds_put_byte(tds, curcol->column_type); if (!is_fixed_type(curcol->column_type)) { tds_put_byte(tds, curcol->column_size); } } }
void tds_send_login_ack(TDSSOCKET * tds, const char *progname) { tds_put_byte(tds, TDS_LOGINACK_TOKEN); tds_put_smallint(tds, 10 + (IS_TDS7_PLUS(tds->conn)? 2 : 1) * strlen(progname)); /* length of message */ if (IS_TDS50(tds->conn)) { tds_put_byte(tds, 5); tds_put_byte(tds, 5); tds_put_byte(tds, 0); } else { tds_put_byte(tds, 1); tds_put_byte(tds, TDS_MAJOR(tds->conn)); tds_put_byte(tds, TDS_MINOR(tds->conn)); } tds_put_byte(tds, 0); /* unknown */ tds_put_byte(tds, 0); /* unknown */ tds_put_byte(tds, strlen(progname)); /* FIXME ucs2 */ tds_put_string(tds, progname, strlen(progname)); /* server version, for mssql 1.0.1 */ tds_put_byte(tds, 1); /* unknown */ tds_put_byte(tds, 0); /* unknown */ tds_put_byte(tds, 0); /* unknown */ tds_put_byte(tds, 1); /* unknown */ }
static void tds5_send_msg(TDSSOCKET *tds, TDS_USMALLINT msg_type) { tds_put_tinyint(tds, TDS_MSG_TOKEN); tds_put_tinyint(tds, 3); tds_put_tinyint(tds, 1); tds_put_smallint(tds, msg_type); }
static void unfinished_query_test(TDSSOCKET *tds) { int char_len; char *buf, *p; int i, len; union { TDS_USMALLINT si; TDS_UINT i; TDS_INT8 i8; char buf[8]; } conv; if (IS_TDS72_PLUS(tds->conn)) return; tds_init_write_buf(tds); /* try to build an invalid (unfinished) query split in two packets */ char_len = IS_TDS7_PLUS(tds->conn) ? 2 : 1; buf = calloc(1, tds->out_buf_max + 200); memset(buf, '-', tds->out_buf_max + 200); strcpy(buf + (tds->out_buf_max - 8) / char_len - strlen(select_query) + 1, select_query); memset(strchr(buf, 0), 0, 16); /* convert if needed */ len = strlen(buf); for (i = len; --i >= 0; ) { char c = buf[i]; buf[i * char_len + 0] = c; if (IS_TDS7_PLUS(tds->conn)) buf[i * char_len + 1] = 0; } len *= char_len; /* send the query using tds_put_int8, non allineati */ tds->out_flag = TDS_QUERY; if (tds_set_state(tds, TDS_WRITING) != TDS_WRITING) exit(1); p = buf; memcpy(conv.buf, p, 2); tds_put_smallint(tds, conv.si); p += 2; for (; p < buf + len; p += 8) { CHECK_TDS_EXTRA(tds); memcpy(conv.buf, p, 8); tds_put_int8(tds, conv.i8); } tds_flush_packet(tds); tds_set_state(tds, TDS_PENDING); /* check result was fine */ if (TDS_FAILED(tds_process_simple_query(tds))) { fprintf(stderr, "Error in prepared query\n"); exit(1); } free(buf); }
void tds_send_control_token(TDSSOCKET * tds, TDS_SMALLINT numcols) { int i; tds_put_byte(tds, TDS_CONTROL_FEATUREEXTACK_TOKEN); tds_put_smallint(tds, numcols); for (i = 0; i < numcols; i++) { tds_put_byte(tds, 0); } }
void tds_send_msg(TDSSOCKET * tds, int msgno, int msgstate, int severity, const char *msgtext, const char *srvname, const char *procname, int line) { int msgsz; size_t len; tds_put_byte(tds, TDS_INFO_TOKEN); if (!procname) procname = ""; len = strlen(procname); msgsz = 4 /* msg no */ + 1 /* msg state */ + 1 /* severity */ /* FIXME ucs2 */ + 4 + (IS_TDS7_PLUS(tds->conn) ? 2 : 1) * (strlen(msgtext) + strlen(srvname) + len) + (IS_TDS72_PLUS(tds->conn) ? 4 : 2); /* line number */ tds_put_smallint(tds, msgsz); tds_put_int(tds, msgno); tds_put_byte(tds, msgstate); tds_put_byte(tds, severity); tds_put_smallint(tds, strlen(msgtext)); /* FIXME ucs2 */ tds_put_string(tds, msgtext, strlen(msgtext)); tds_put_byte(tds, strlen(srvname)); /* FIXME ucs2 */ tds_put_string(tds, srvname, strlen(srvname)); if (len) { tds_put_byte(tds, len); /* FIXME ucs2 */ tds_put_string(tds, procname, len); } else { tds_put_byte(tds, 0); } if (IS_TDS72_PLUS(tds->conn)) tds_put_int(tds, line); else tds_put_smallint(tds, line); }
void tds_send_col_name(TDSSOCKET * tds, TDSRESULTINFO * resinfo) { int col, hdrsize = 0; TDSCOLUMN *curcol; tds_put_byte(tds, TDS_COLNAME_TOKEN); for (col = 0; col < resinfo->num_cols; col++) { curcol = resinfo->columns[col]; hdrsize += tds_dstr_len(&curcol->column_name) + 1; } tds_put_smallint(tds, hdrsize); for (col = 0; col < resinfo->num_cols; col++) { curcol = resinfo->columns[col]; tds_put_byte(tds, tds_dstr_len(&curcol->column_name)); /* exclude the null */ tds_put_n(tds, tds_dstr_cstr(&curcol->column_name), tds_dstr_len(&curcol->column_name)); } }
void tds_send_col_name(TDSSOCKET * tds, TDSRESULTINFO * resinfo) { int col, hdrsize = 0; TDSCOLUMN *curcol; tds_put_byte(tds, TDS_COLNAME_TOKEN); for (col = 0; col < resinfo->num_cols; col++) { curcol = resinfo->columns[col]; assert(strlen(curcol->column_name) == curcol->column_namelen); hdrsize += curcol->column_namelen + 1; } tds_put_smallint(tds, hdrsize); for (col = 0; col < resinfo->num_cols; col++) { curcol = resinfo->columns[col]; tds_put_byte(tds, curcol->column_namelen); /* exclude the null */ tds_put_n(tds, curcol->column_name, curcol->column_namelen); } }
void tds_send_capabilities_token(TDSSOCKET * tds) { tds_put_byte(tds, TDS_CAPABILITY_TOKEN); tds_put_smallint(tds, 18); tds_put_byte(tds, 1); tds_put_byte(tds, 7); tds_put_byte(tds, 7); tds_put_byte(tds, 97); tds_put_byte(tds, 65); tds_put_byte(tds, 207); tds_put_byte(tds, 255); tds_put_byte(tds, 255); tds_put_byte(tds, 230); tds_put_byte(tds, 2); tds_put_byte(tds, 7); tds_put_byte(tds, 0); tds_put_byte(tds, 0); tds_put_byte(tds, 2); tds_put_byte(tds, 0); tds_put_byte(tds, 0); tds_put_byte(tds, 0); tds_put_byte(tds, 0); }
/** * Send one row of data to server * \tds * \param bcpinfo BCP information * \param get_col_data function to call to retrieve data to be sent * \param ignored function to call if we try to send NULL if not allowed (not used) * \param offset passed to get_col_data and null_error to specify the row to get * \return TDS_SUCCESS or TDS_FAIL. */ TDSRET tds_bcp_send_record(TDSSOCKET *tds, TDSBCPINFO *bcpinfo, tds_bcp_get_col_data get_col_data, tds_bcp_null_error null_error, int offset) { TDSCOLUMN *bindcol; int i, start_col = bcpinfo->next_col; TDSRET rc; tdsdump_log(TDS_DBG_FUNC, "tds_bcp_send_bcp_record(%p, %p, %p, %p, %d)\n", tds, bcpinfo, get_col_data, null_error, offset); if (tds->out_flag != TDS_BULK || tds_set_state(tds, TDS_WRITING) != TDS_WRITING) return TDS_FAIL; if (start_col > 0) { bindcol = bcpinfo->bindinfo->columns[start_col - 1]; *bindcol->column_lenbind = MIN((TDS_INT) bindcol->column_bindlen - bcpinfo->text_sent, *bindcol->column_lenbind); tds_put_n(tds, bindcol->column_varaddr, *bindcol->column_lenbind); bcpinfo->text_sent += *bindcol->column_lenbind; if ((TDS_UINT) bcpinfo->text_sent < bindcol->column_bindlen) { return TDS_SUCCESS; /* That's all for now. */ } else if (!IS_TDS7_PLUS(tds->conn)) { bcpinfo->blob_cols++; } bcpinfo->next_col = 0; bcpinfo->text_sent = 0; } if (IS_TDS7_PLUS(tds->conn)) { if (start_col == 0) { tds_put_byte(tds, TDS_ROW_TOKEN); /* 0xd1 */ } for (i = start_col; i < bcpinfo->bindinfo->num_cols; i++) { TDS_INT save_size; unsigned char *save_data; TDSBLOB blob; int /* bool */ has_text = 0; bindcol = bcpinfo->bindinfo->columns[i]; /* * Don't send the (meta)data for timestamp columns or * identity columns unless indentity_insert is enabled. */ if ((!bcpinfo->identity_insert_on && bindcol->column_identity) || bindcol->column_timestamp || !tds_bcp_is_bound(bcpinfo, bindcol)) { continue; } rc = get_col_data(bcpinfo, bindcol, offset); if (rc == TDS_FAIL) { tdsdump_log(TDS_DBG_INFO1, "get_col_data (column %d) failed\n", i + 1); goto cleanup; } else if (rc != TDS_SUCCESS) { /* CS_BLK_HAS_TEXT? */ has_text = 1; } tdsdump_log(TDS_DBG_INFO1, "gotten column %d length %d null %d\n", i + 1, bindcol->bcp_column_data->datalen, bindcol->bcp_column_data->is_null); save_size = bindcol->column_cur_size; save_data = bindcol->column_data; assert(bindcol->column_data == NULL); if (bindcol->bcp_column_data->is_null) { if ( !bindcol->column_nullable && !is_nullable_type(bindcol->on_server.column_type) ) { return TDS_FAIL; } bindcol->column_cur_size = -1; } else if (has_text) { bindcol->column_cur_size = bindcol->bcp_column_data->datalen; } else if (is_blob_col(bindcol)) { bindcol->column_cur_size = bindcol->bcp_column_data->datalen; memset(&blob, 0, sizeof(blob)); blob.textvalue = (TDS_CHAR *) bindcol->bcp_column_data->data; bindcol->column_data = (unsigned char *) &blob; } else { bindcol->column_cur_size = bindcol->bcp_column_data->datalen; bindcol->column_data = bindcol->bcp_column_data->data; } rc = bindcol->funcs->put_data(tds, bindcol, 1); bindcol->column_cur_size = save_size; bindcol->column_data = save_data; if (TDS_FAILED(rc)) goto cleanup; else if (has_text) { bcpinfo->next_col = i + 1; /* bcpinfo->text_sent = 0; */ break; } } } /* IS_TDS7_PLUS */ else { if (start_col == 0) { int row_pos; int row_sz_pos; int var_cols_written = 0; TDS_INT old_record_size = bcpinfo->bindinfo->row_size; unsigned char *record = bcpinfo->bindinfo->current_row; memset(record, '\0', old_record_size); /* zero the rowbuffer */ /* * offset 0 = number of var columns * offset 1 = row number. zeroed (datasever assigns) */ row_pos = 2; rc = TDS_FAIL; if ((row_pos = tds_bcp_add_fixed_columns(bcpinfo, get_col_data, null_error, offset, record, row_pos)) < 0) goto cleanup; row_sz_pos = row_pos; /* potential variable columns to write */ if ((row_pos = tds_bcp_add_variable_columns(bcpinfo, get_col_data, null_error, offset, record, row_pos, &var_cols_written)) < 0) goto cleanup; if (var_cols_written) { TDS_PUT_UA2(&record[row_sz_pos], row_pos); record[0] = var_cols_written; } tdsdump_log(TDS_DBG_INFO1, "old_record_size = %d new size = %d \n", old_record_size, row_pos); tds_put_smallint(tds, row_pos); tds_put_n(tds, record, row_pos); /* row is done, now handle any text/image data */ bcpinfo->blob_cols = 0; } for (i = start_col; i < bcpinfo->bindinfo->num_cols; i++) { bindcol = bcpinfo->bindinfo->columns[i]; if (is_blob_type(bindcol->column_type)) { /* Elide trailing NULLs */ if (bindcol->bcp_column_data->is_null) { int j; for (j = i + 1; j < bcpinfo->bindinfo->num_cols; ++j) { TDSCOLUMN *bindcol2 = bcpinfo->bindinfo->columns[j]; if (is_blob_type(bindcol2->column_type) && !bindcol2->bcp_column_data->is_null) { break; } } if (j == bcpinfo->bindinfo->num_cols) { i = j; break; } } rc = get_col_data(bcpinfo, bindcol, offset); if (rc == TDS_FAIL) goto cleanup; /* unknown but zero */ tds_put_smallint(tds, 0); tds_put_byte(tds, (unsigned char) bindcol->column_type); tds_put_byte(tds, 0xff - bcpinfo->blob_cols); /* * offset of txptr we stashed during variable * column processing */ tds_put_smallint(tds, bindcol->column_textpos); tds_put_int(tds, bindcol->bcp_column_data->datalen); if (rc != TDS_SUCCESS) { /* CS_BLK_HAS_TEXT? */ bcpinfo->next_col = i + 1; /* bcpinfo->text_sent = 0; */ break; } tds_put_n(tds, bindcol->bcp_column_data->data, bindcol->bcp_column_data->datalen); bcpinfo->blob_cols++; } } } if (i == bcpinfo->bindinfo->num_cols) { tds_set_state(tds, TDS_SENDING); bcpinfo->next_col = 0; } return TDS_SUCCESS; cleanup: tds_set_state(tds, TDS_SENDING); return rc; }
bool pool_user_send_login_ack(TDS_POOL * pool, TDS_POOL_USER * puser) { char msg[256]; char block[32]; TDSSOCKET *tds = puser->sock.tds, *mtds = puser->assigned_member->sock.tds; TDSLOGIN *login = puser->login; const char *database; const char *server = mtds->conn->server ? mtds->conn->server : "JDBC"; bool dbname_mismatch, odbc_mismatch; pool->user_logins++; /* copy a bit of information, resize socket with block */ tds->conn->tds_version = mtds->conn->tds_version; tds->conn->product_version = mtds->conn->product_version; memcpy(tds->conn->collation, mtds->conn->collation, sizeof(tds->conn->collation)); tds->conn->tds71rev1 = mtds->conn->tds71rev1; free(tds->conn->product_name); tds->conn->product_name = strdup(mtds->conn->product_name); tds_realloc_socket(tds, mtds->conn->env.block_size); tds->conn->env.block_size = mtds->conn->env.block_size; tds->conn->client_spid = mtds->conn->spid; /* if database is different use USE statement */ database = pool->database; dbname_mismatch = !tds_dstr_isempty(&login->database) && strcasecmp(tds_dstr_cstr(&login->database), database) != 0; odbc_mismatch = (login->option_flag2 & TDS_ODBC_ON) == 0; if (dbname_mismatch || odbc_mismatch) { char *str; int len = 128 + tds_quote_id(mtds, NULL, tds_dstr_cstr(&login->database),-1); TDSRET ret; if ((str = (char *) malloc(len)) == NULL) return false; str[0] = 0; /* swicth to dblib options */ if (odbc_mismatch) strcat(str, "SET ANSI_DEFAULTS OFF\nSET CONCAT_NULL_YIELDS_NULL OFF\n"); if (dbname_mismatch) { strcat(str, "USE "); tds_quote_id(mtds, strchr(str, 0), tds_dstr_cstr(&login->database), -1); } ret = tds_submit_query(mtds, str); free(str); if (TDS_FAILED(ret) || TDS_FAILED(tds_process_simple_query(mtds))) return false; if (dbname_mismatch) database = tds_dstr_cstr(&login->database); else database = mtds->conn->env.database; } // 7.0 // env database // database change message (with server name correct) // env language // language change message // env 0x3 charset ("iso_1") // env 0x5 lcid ("1033") // env 0x6 ("196609" ?? 0x30001) // loginack // env 0x4 packet size // done // // 7.1/7.2/7.3 // env database // database change message (with server name correct) // env 0x7 collation // env language // language change message // loginack // env 0x4 packet size // done tds->out_flag = TDS_REPLY; tds_env_change(tds, TDS_ENV_DATABASE, "master", database); sprintf(msg, "Changed database context to '%s'.", database); tds_send_msg(tds, 5701, 2, 0, msg, server, NULL, 1); if (!login->suppress_language) { tds_env_change(tds, TDS_ENV_LANG, NULL, "us_english"); tds_send_msg(tds, 5703, 1, 0, "Changed language setting to 'us_english'.", server, NULL, 1); } if (IS_TDS71_PLUS(tds->conn)) { tds_put_byte(tds, TDS_ENVCHANGE_TOKEN); tds_put_smallint(tds, 8); tds_put_byte(tds, TDS_ENV_SQLCOLLATION); tds_put_byte(tds, 5); tds_put_n(tds, tds->conn->collation, 5); tds_put_byte(tds, 0); } tds_send_login_ack(tds, mtds->conn->product_name); sprintf(block, "%d", tds->conn->env.block_size); tds_env_change(tds, TDS_ENV_PACKSIZE, block, block); /* tds_send_capabilities_token(tds); */ tds_send_done_token(tds, 0, 0); /* send it! */ tds_flush_packet(tds); tds_free_login(login); puser->login = NULL; return true; }