113
117
#include "odbcserver.h"
115
119
/* ---------------- Main functions ---------------------------------------*/
117
static void spawn_odbc_connection(int port);
120
static void spawn_sup(const char *port);
119
DWORD WINAPI database_handler(int port);
122
DWORD WINAPI database_handler(const char *port);
121
void database_handler(int port);
124
void database_handler(const char *port);
123
126
static db_result_msg handle_db_request(byte *reqstring, db_state *state);
127
static void supervise(const char *port);
125
128
/* ----------------- ODBC functions --------------------------------------*/
127
130
static db_result_msg db_connect(byte *connStrIn, db_state *state);
168
171
/* ------------- Socket communication functions --------------------------*/
171
static void connect_to_erlang(SOCKET socket, int port);
172
static SOCKET create_socket(void);
174
static SOCKET connect_to_erlang(const char *port);
173
175
static void send_msg(db_result_msg *msg, SOCKET socket);
174
static byte * receive_msg(SOCKET socket);
175
static Boolean receive_msg_part(SOCKET socket, byte * buffer, size_t msg_len);
176
static byte *receive_msg(SOCKET socket);
177
static Boolean receive_msg_part(SOCKET socket,
178
byte * buffer, size_t msg_len);
176
179
static Boolean send_msg_part(SOCKET socket, byte * buffer, size_t msg_len);
177
180
static void close_socket(SOCKET socket);
178
181
static void init_winsock(void);
180
static void connect_to_erlang(int socket, int port);
181
static int create_socket(void);
183
static int connect_to_erlang(const char *port);
182
184
static void send_msg(db_result_msg *msg, int socket);
183
static byte * receive_msg(int socket);
185
static byte *receive_msg(int socket);
184
186
static Boolean receive_msg_part(int socket, byte * buffer, size_t msg_len);
185
187
static Boolean send_msg_part(int socket, byte * buffer, size_t msg_len);
186
188
static void close_socket(int socket);
247
250
byte *msg = NULL;
248
int reason, msg_len, supervisor_port, odbc_port;
251
char *temp = NULL, *supervisor_port = NULL, *odbc_port = NULL;
252
254
_setmode(_fileno( stdin), _O_BINARY);
257
257
msg = receive_erlang_port_msg();
259
supervisor_port = atoi(strtok(msg, ";"));
260
odbc_port = atoi(strtok(NULL, ";"));
264
socket = create_socket();
266
connect_to_erlang(socket, supervisor_port);
268
spawn_odbc_connection(odbc_port);
270
msg = receive_msg(socket);
272
if(msg[0] == SHUTDOWN) {
273
reason = EXIT_SUCCESS;
275
reason = EXIT_FAILURE; /* Should not happen */
278
close_socket(socket);
259
temp = strtok(msg, ";");
260
length = strlen(temp);
261
supervisor_port = safe_malloc(length + 1);
262
strcpy(supervisor_port, temp);
264
temp = strtok(NULL, ";");
265
length = strlen(temp);
266
odbc_port = safe_malloc(length + 1);
267
strcpy(odbc_port, temp);
271
spawn_sup(supervisor_port);
272
database_handler(odbc_port);
285
static void spawn_odbc_connection(int port)
276
static void spawn_sup(const char *port)
288
(HANDLE)_beginthreadex(NULL, 0, database_handler, port, 0, &threadId);
279
(HANDLE)_beginthreadex(NULL, 0, supervise, port, 0, &threadId);
291
static void spawn_odbc_connection(int port)
282
static void spawn_sup(const char *port)
293
284
pthread_t thread;
296
287
result = pthread_create(&thread, NULL,
297
(void *(*)(void *))database_handler,
288
(void *(*)(void *))supervise,
300
291
DO_EXIT(EXIT_THREAD);
306
DWORD WINAPI database_handler(int port)
295
void supervise(const char *port) {
305
socket = connect_to_erlang(port);
306
msg = receive_msg(socket);
308
if(msg[0] == SHUTDOWN) {
309
reason = EXIT_SUCCESS;
311
reason = EXIT_FAILURE; /* Should not happen */
315
close_socket(socket);
321
DWORD WINAPI database_handler(const char *port)
308
void database_handler(int port)
323
void database_handler(const char *port)
311
326
db_result_msg msg;
312
327
byte *request_buffer = NULL;
314
{NULL, NULL, NULL, NULL, 0, {NULL, 0, 0}, FALSE, FALSE, FALSE, FALSE};
329
{NULL, NULL, NULL, NULL, 0, {NULL, 0, 0},
330
FALSE, FALSE, FALSE, FALSE, FALSE};
322
socket = create_socket();
323
connect_to_erlang(socket, port);
339
socket = connect_to_erlang(port);
326
342
request_buffer = receive_msg(socket);
535
551
ei_x_new_with_version(&dynamic_buffer(state));
537
if (result == SQL_NO_DATA_FOUND) { /* OTP-5759, fails when 0 rows deleted */
538
ei_x_encode_tuple_header(&dynamic_buffer(state), 2);
539
ei_x_encode_atom(&dynamic_buffer(state), "updated");
540
ei_x_encode_long(&dynamic_buffer(state), 0);
553
/* OTP-5759, fails when 0 rows deleted */
554
if (result == SQL_NO_DATA_FOUND) {
555
msg = encode_result(state);
542
557
/* Handle multiple result sets */
702
717
db_result_msg msg;
703
int i,j, ver, num_param_values,
718
int i, num_param_values, ver = 0,
704
719
erl_type = 0, index = 0, size = 0, cols = 0;
705
720
long long_num_param_values;
706
721
param_status param_status;
708
723
param_array *params;
710
725
if (associated_result_set(state)) {
711
726
clean_state(state);
713
728
associated_result_set(state) = FALSE;
729
param_query(state) = TRUE;
715
731
msg = encode_empty_message();
717
733
ei_decode_version(buffer, &index, &ver);
718
735
ei_decode_tuple_header(buffer, &index, &size);
720
ei_get_type(buffer, &index, &erl_type, &size);
737
ei_get_type(buffer, &index, &erl_type, &size);
721
739
sql = (byte*)safe_malloc((sizeof(byte) * (size + 1)));
722
740
ei_decode_string(buffer, &index, sql);
724
742
ei_decode_long(buffer, &index, &long_num_param_values);
725
744
num_param_values = (int)long_num_param_values;
726
745
ei_decode_list_header(buffer, &index, &cols);
730
init_param_statement(cols, num_param_values, state);
748
init_param_statement(cols, num_param_values, state, ¶m_status);
732
750
params = bind_parameter_arrays(buffer, &index, cols,
733
751
num_param_values, state);
735
753
if(params != NULL) {
736
754
if(!sql_success(SQLExecDirect(statement_handle(state),
737
755
sql, SQL_NTS))) {
918
937
term to be returned to the erlang client. */
919
938
static db_result_msg encode_result(db_state *state)
921
SQLSMALLINT num_of_columns;
922
SQLINTEGER RowCountPtr;
940
SQLSMALLINT num_of_columns = 0;
941
SQLINTEGER RowCountPtr = 0, paramBatch = 0;
923
942
db_result_msg msg;
924
int elements, update, num_of_rows;
943
int elements, update, num_of_rows = 0;
927
946
msg = encode_empty_message();
945
964
DO_EXIT(EXIT_ROWS);
948
num_of_rows = (int)RowCountPtr;
967
if(param_query(state) && update) {
968
if(!sql_success(SQLGetInfo(connection_handle(state),
969
SQL_PARAM_ARRAY_ROW_COUNTS,
970
(SQLPOINTER)¶mBatch,
973
DO_EXIT(EXIT_DRIVER_INFO);
976
if(paramBatch == SQL_PARC_BATCH ) {
977
/* Individual row counts (one for each parameter set)
978
are available, sum them up */
980
num_of_rows = num_of_rows + (int)RowCountPtr;
981
msg = more_result_sets(state);
982
/* We don't want to continue if an error occured */
983
if (msg.length != 0) {
986
if(exists_more_result_sets(state)) {
987
if(!sql_success(SQLRowCount(statement_handle(state),
992
} while (exists_more_result_sets(state));
994
/* Row counts are rolled up into one (SQL_PARC_NO_BATCH) */
995
num_of_rows = (int)RowCountPtr;
998
num_of_rows = (int)RowCountPtr;
950
1000
ei_x_encode_tuple_header(&dynamic_buffer(state), elements);
951
1001
ei_x_encode_atom(&dynamic_buffer(state), atom);
1468
1516
/* ------------- Socket communication functions --------------------------*/
1471
static SOCKET create_socket(void)
1473
return socket(AF_INET, SOCK_STREAM, 0);
1477
static int create_socket(void)
1479
struct protoent *protocol;
1481
protocol = getprotobyname("tcp");
1482
return socket(AF_INET, SOCK_STREAM, protocol->p_proto);
1488
static void connect_to_erlang(SOCKET socket, int port)
1490
static void connect_to_erlang(int socket, int port)
1518
/* Currently only an old windows compiler is supported so we do not have ipv6
1520
static SOCKET connect_to_erlang(const char *port)
1493
1523
struct sockaddr_in sin;
1525
sock = socket(AF_INET, SOCK_STREAM, 0);
1495
1527
memset(&sin, 0, sizeof(sin));
1496
sin.sin_port = htons ((unsigned short)port);
1528
sin.sin_port = htons ((unsigned short)atoi(port));
1497
1529
sin.sin_family = AF_INET;
1498
1530
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
1500
if (connect(socket, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
1501
close_socket(socket);
1502
DO_EXIT(EXIT_SOCKET_CONNECT);
1532
if (connect(sock, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
1534
DO_EXIT(EXIT_SOCKET_CONNECT);
1539
static int connect_to_erlang(const char *port)
1543
struct addrinfo hints;
1544
struct addrinfo *erlang_ai, *first;
1546
memset(&hints, 0, sizeof(hints));
1547
hints.ai_family = PF_UNSPEC; /* PF_INET or PF_INET6 */
1548
hints.ai_socktype = SOCK_STREAM;
1549
hints.ai_protocol = IPPROTO_TCP;
1551
if (getaddrinfo("localhost", port, &hints, &first) != 0) {
1552
DO_EXIT(EXIT_FAILURE);
1555
for (erlang_ai = first; erlang_ai; erlang_ai = erlang_ai->ai_next) {
1557
sock = socket(erlang_ai->ai_family, erlang_ai->ai_socktype,
1558
erlang_ai->ai_protocol);
1561
if (connect(sock, (struct sockaddr*)erlang_ai->ai_addr,
1562
erlang_ai->ai_addrlen) < 0) {
1570
freeaddrinfo(first);
1574
DO_EXIT(EXIT_SOCKET_CONNECT);
1507
1582
static void close_socket(SOCKET socket)
1900
1974
params->offset = 0;
1903
static param_status init_param_statement(int cols, int num_param_values,
1977
static void init_param_statement(int cols, int num_param_values,
1978
db_state *state, param_status *status)
1906
param_status status;
1908
status.param_status_array =
1909
(SQLUSMALLINT *)malloc(num_param_values * sizeof(SQLUSMALLINT));
1910
status.params_processed = 0;
1980
status -> param_status_array =
1981
(SQLUSMALLINT *)safe_malloc(num_param_values * sizeof(SQLUSMALLINT));
1982
status -> params_processed = 0;
1912
1984
if(!sql_success(SQLAllocHandle(SQL_HANDLE_STMT,
1913
1985
connection_handle(state),
1932
2006
if(!sql_success(SQLSetStmtAttr(statement_handle(state),
1933
2007
SQL_ATTR_PARAM_STATUS_PTR,
1934
status.param_status_array, 0))) {
2008
(status -> param_status_array), 0))) {
1935
2009
DO_EXIT(EXIT_PARAM_ARRAY);
1938
2012
if(!sql_success(SQLSetStmtAttr(statement_handle(state),
1939
2013
SQL_ATTR_PARAMS_PROCESSED_PTR,
1940
&status.params_processed, 0))) {
2014
&(status -> params_processed), 0))) {
1941
2015
DO_EXIT(EXIT_PARAM_ARRAY);
1947
2019
static void map_dec_num_2_c_column(col_type *type, int precision, int scale)