Line data Source code
1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Brian Bruns
3 : * Copyright (C) 2005-2015 Frediano Ziglio
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Library General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2 of the License, or (at your option) any later version.
9 : *
10 : * This library is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Library General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU Library General Public
16 : * License along with this library; if not, write to the
17 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 : * Boston, MA 02111-1307, USA.
19 : */
20 :
21 : #include <config.h>
22 :
23 : #include <stdlib.h>
24 :
25 : #if HAVE_UNISTD_H
26 : #include <unistd.h>
27 : #endif /* HAVE_UNISTD_H */
28 :
29 : #include <assert.h>
30 :
31 : #include <freetds/tds.h>
32 : #include <freetds/iconv.h>
33 : #include <freetds/tls.h>
34 : #include <freetds/checks.h>
35 : #include <freetds/utils/string.h>
36 : #include <freetds/replacements.h>
37 : #include <freetds/enum_cap.h>
38 : #include <freetds/utils.h>
39 :
40 : #if HAVE_SYS_SOCKET_H
41 : #include <sys/socket.h>
42 : #endif
43 :
44 : #ifdef HAVE_STRING_H
45 : #include <string.h>
46 : #endif
47 :
48 : #ifdef HAVE_LOCALE_H
49 : #include <locale.h>
50 : #endif /* HAVE_LOCALE_H */
51 :
52 : #ifdef HAVE_LANGINFO_H
53 : #include <langinfo.h>
54 : #endif /* HAVE_LANGINFO_H */
55 :
56 : static void tds_free_env(TDSCONNECTION * conn);
57 : static void tds_free_compute_results(TDSSOCKET * tds);
58 : static void tds_free_compute_result(TDSCOMPUTEINFO * comp_info);
59 :
60 : #undef TEST_MALLOC
61 : #define TEST_MALLOC(dest,type) \
62 : {if (!(dest = (type*)calloc(1, sizeof(type)))) goto Cleanup;}
63 :
64 : #undef TEST_CALLOC
65 : #define TEST_CALLOC(dest,type,n) \
66 : {if (!(dest = (type*)calloc((n), sizeof(type)))) goto Cleanup;}
67 :
68 : /**
69 : * \ingroup libtds
70 : * \defgroup mem Memory allocation
71 : * Allocate or free resources. Allocation can fail only on out of memory.
72 : * In such case they return NULL and leave the state as before call.
73 : * Mainly function names are in the form tds_alloc_XX or tds_free_XXX.
74 : * tds_alloc_XXX functions allocate structures and return pointer to allocated
75 : * data while tds_free_XXX take structure pointers and free them. Some functions
76 : * require additional parameters to initialize structure correctly.
77 : * The main exception are structures that use reference counting. These structures
78 : * have tds_alloc_XXX functions but instead of tds_free_XXX use tds_release_XXX.
79 : */
80 :
81 : /**
82 : * \addtogroup mem
83 : * @{
84 : */
85 :
86 : static volatile unsigned int inc_num = 1;
87 :
88 : /**
89 : * Get an id for dynamic query based on TDS information
90 : * \param conn state information for the connection and the TDS protocol
91 : * \return TDS_FAIL or TDS_SUCCESS
92 : */
93 : static char *
94 657816 : tds_get_dynid(TDSCONNECTION * conn, char *id)
95 : {
96 : unsigned long n;
97 : int i;
98 : char *p;
99 : char c;
100 :
101 : CHECK_CONN_EXTRA(conn);
102 :
103 657816 : inc_num = (inc_num + 1) & 0xffff;
104 : /* some version of Sybase require length <= 10, so we code id */
105 657816 : n = (unsigned long) (TDS_INTPTR) conn;
106 657816 : p = id;
107 657816 : *p++ = (char) ('a' + (n % 26u));
108 657816 : n /= 26u;
109 6578160 : for (i = 0; i < 9; ++i) {
110 5920344 : c = (char) ('0' + (n % 36u));
111 5920344 : *p++ = (c < ('0' + 10)) ? c : c + ('a' - '0' - 10);
112 : /* tdsdump_log(TDS_DBG_INFO1, "%d -> %d(%c)\n", (int) (n%36u),p[-1],p[-1]); */
113 5920344 : n /= 36u;
114 5920344 : if (i == 4)
115 657816 : n += 3u * inc_num;
116 : }
117 657816 : *p = 0;
118 657816 : return id;
119 : }
120 :
121 : #include <freetds/pushvis.h>
122 : extern const TDSCOLUMNFUNCS tds_invalid_funcs;
123 : #include <freetds/popvis.h>
124 :
125 : static TDSCOLUMN *
126 104943 : tds_alloc_column(void)
127 : {
128 : TDSCOLUMN *col;
129 :
130 104943 : TEST_MALLOC(col, TDSCOLUMN);
131 209886 : tds_dstr_init(&col->table_name);
132 209886 : tds_dstr_init(&col->column_name);
133 209886 : tds_dstr_init(&col->table_column_name);
134 104943 : col->funcs = &tds_invalid_funcs;
135 104943 : col->use_iconv_out = 1;
136 :
137 104943 : Cleanup:
138 104943 : return col;
139 : }
140 :
141 : static void
142 104869 : tds_free_column(TDSCOLUMN *col)
143 : {
144 104869 : tds_dstr_free(&col->table_name);
145 104869 : tds_dstr_free(&col->column_name);
146 104869 : tds_dstr_free(&col->table_column_name);
147 104869 : free(col);
148 104869 : }
149 :
150 :
151 : /**
152 : * \fn TDSDYNAMIC *tds_alloc_dynamic(TDSCONNECTION *conn, const char *id)
153 : * \brief Allocate a dynamic statement.
154 : * \param conn the connection within which to allocate the statement.
155 : * \param id a character label identifying the statement.
156 : * \return a pointer to the allocated structure (NULL on failure).
157 : *
158 : * tds_alloc_dynamic is used to implement placeholder code under TDS 5.0
159 : */
160 : TDSDYNAMIC *
161 657826 : tds_alloc_dynamic(TDSCONNECTION * conn, const char *id)
162 : {
163 : TDSDYNAMIC *dyn;
164 : char tmp_id[30];
165 :
166 657826 : if (id) {
167 : /* check to see if id already exists (shouldn't) */
168 20 : if (tds_lookup_dynamic(conn, id))
169 : return NULL;
170 : } else {
171 : unsigned int n;
172 : id = tmp_id;
173 :
174 : for (n = 0;;) {
175 657816 : if (!tds_lookup_dynamic(conn, tds_get_dynid(conn, tmp_id)))
176 : break;
177 10 : if (++n == 256)
178 : return NULL;
179 : }
180 : }
181 :
182 657826 : TEST_MALLOC(dyn, TDSDYNAMIC);
183 :
184 : /* take into account pointer in list */
185 657826 : dyn->ref_count = 2;
186 :
187 : /* insert into list */
188 657826 : dyn->next = conn->dyns;
189 657826 : conn->dyns = dyn;
190 :
191 657826 : strlcpy(dyn->id, id, TDS_MAX_DYNID_LEN);
192 :
193 657826 : return dyn;
194 :
195 657826 : Cleanup:
196 : return NULL;
197 : }
198 :
199 : /**
200 : * \fn void tds_free_input_params(TDSDYNAMIC *dyn)
201 : * \brief Frees all allocated input parameters of a dynamic statement.
202 : * \param dyn the dynamic statement whose input parameter are to be freed
203 : *
204 : * tds_free_input_params frees all parameters for the give dynamic statement
205 : */
206 : void
207 1502 : tds_free_input_params(TDSDYNAMIC * dyn)
208 : {
209 : TDSPARAMINFO *info;
210 :
211 659328 : info = dyn->params;
212 659328 : if (info) {
213 1482 : tds_free_param_results(info);
214 1084 : dyn->params = NULL;
215 : }
216 1502 : }
217 :
218 : /*
219 : * Called when dynamic got deallocated from server
220 : */
221 : void
222 658026 : tds_dynamic_deallocated(TDSCONNECTION *conn, TDSDYNAMIC *dyn)
223 : {
224 : TDSDYNAMIC **victim;
225 :
226 658026 : tdsdump_log(TDS_DBG_FUNC, "tds_dynamic_deallocated() : freeing dynamic_id %s\n", dyn->id);
227 :
228 658026 : victim = &conn->dyns;
229 1316252 : while (*victim != dyn) {
230 400 : if (*victim == NULL) {
231 200 : tdsdump_log(TDS_DBG_FUNC, "tds_dynamic_deallocated() : cannot find id %s\n", dyn->id);
232 : return;
233 : }
234 200 : victim = &(*victim)->next;
235 : }
236 :
237 : /* remove from list */
238 657826 : *victim = dyn->next;
239 657826 : dyn->next = NULL;
240 :
241 : /* assure there is no id left */
242 657826 : dyn->num_id = 0;
243 :
244 657826 : tds_release_dynamic(&dyn);
245 : }
246 :
247 :
248 : /**
249 : * \fn void tds_release_dynamic(TDSDYNAMIC **pdyn)
250 : * \brief Frees dynamic statement
251 : * \param pdyn pointer to dynamic statement to be freed.
252 : */
253 : void
254 1411745 : tds_release_dynamic(TDSDYNAMIC ** pdyn)
255 : {
256 : TDSDYNAMIC *dyn;
257 :
258 1411745 : dyn = *pdyn;
259 1411745 : *pdyn = NULL;
260 1411745 : if (!dyn || --dyn->ref_count > 0)
261 : return;
262 :
263 1315652 : tds_detach_results(dyn->res_info);
264 :
265 657826 : tds_free_results(dyn->res_info);
266 657826 : tds_free_input_params(dyn);
267 657826 : free(dyn->query);
268 657826 : free(dyn);
269 : }
270 :
271 : /**
272 : * \fn TDSPARAMINFO *tds_alloc_param_result(TDSPARAMINFO *old_param)
273 : * \brief Adds a output parameter to TDSPARAMINFO.
274 : * \param old_param a pointer to the TDSPARAMINFO structure containing the
275 : * current set of output parameter, or NULL if none exists.
276 : * \return a pointer to the new TDSPARAMINFO structure.
277 : *
278 : * tds_alloc_param_result() works a bit differently than the other alloc result
279 : * functions. Output parameters come in individually with no total number
280 : * given in advance, so we simply call this func every time with get a
281 : * TDS_PARAM_TOKEN and let it realloc the columns struct one bigger.
282 : * tds_free_all_results() usually cleans up after us.
283 : */
284 : TDSPARAMINFO *
285 42234 : tds_alloc_param_result(TDSPARAMINFO * old_param)
286 : {
287 : TDSPARAMINFO *param_info;
288 : TDSCOLUMN *colinfo;
289 :
290 : /* parameters cannot have row associated */
291 42234 : if (old_param && (old_param->current_row || old_param->row_free))
292 : return NULL;
293 :
294 42234 : colinfo = tds_alloc_column();
295 42234 : if (!colinfo)
296 : return NULL;
297 :
298 42234 : param_info = old_param;
299 42234 : if (!param_info) {
300 29986 : TEST_MALLOC(param_info, TDSPARAMINFO);
301 29986 : param_info->ref_count = 1;
302 : }
303 :
304 42234 : if (!TDS_RESIZE(param_info->columns, param_info->num_cols + 1u))
305 : goto Cleanup;
306 :
307 42234 : param_info->columns[param_info->num_cols++] = colinfo;
308 42234 : return param_info;
309 :
310 0 : Cleanup:
311 0 : if (!old_param)
312 0 : free(param_info);
313 0 : free(colinfo);
314 0 : return NULL;
315 : }
316 :
317 : /**
318 : * Delete latest parameter
319 : */
320 : void
321 14 : tds_free_param_result(TDSPARAMINFO * param_info)
322 : {
323 : TDSCOLUMN *col;
324 :
325 14 : if (!param_info || param_info->num_cols <= 0)
326 : return;
327 :
328 14 : col = param_info->columns[--param_info->num_cols];
329 14 : if (col->column_data && col->column_data_free)
330 14 : col->column_data_free(col);
331 :
332 14 : if (param_info->num_cols == 0)
333 14 : TDS_ZERO_FREE(param_info->columns);
334 :
335 : /*
336 : * NOTE some information should be freed too but when this function
337 : * is called are not used. I hope to remove the need for this
338 : * function ASAP
339 : * A better way is to support different way to allocate and get
340 : * parameters
341 : * -- freddy77
342 : */
343 14 : tds_free_column(col);
344 : }
345 :
346 : static void
347 : tds_free_tvp_row(TDS_TVP_ROW *row)
348 : {
349 72 : tds_free_param_results(row->params);
350 : }
351 :
352 : static void
353 26140 : tds_param_free(TDSCOLUMN *col)
354 : {
355 26140 : if (!col->column_data)
356 : return;
357 :
358 26140 : if (col->column_type == SYBMSTABLE) {
359 8 : tds_deinit_tvp((TDS_TVP *) col->column_data);
360 26132 : } else if (is_blob_col(col)) {
361 2166 : TDSBLOB *blob = (TDSBLOB *) col->column_data;
362 2166 : free(blob->textvalue);
363 : }
364 :
365 26140 : TDS_ZERO_FREE(col->column_data);
366 : }
367 :
368 : /**
369 : * Allocate data for a parameter.
370 : * @param curparam parameter to retrieve size information
371 : * @return NULL on failure or new data
372 : */
373 : void *
374 26140 : tds_alloc_param_data(TDSCOLUMN * curparam)
375 : {
376 : TDS_INT data_size;
377 : void *data;
378 :
379 26140 : CHECK_COLUMN_EXTRA(curparam);
380 :
381 26140 : data_size = curparam->funcs->row_len(curparam);
382 :
383 : /* allocate data */
384 26140 : if (curparam->column_data && curparam->column_data_free)
385 0 : curparam->column_data_free(curparam);
386 26140 : curparam->column_data_free = tds_param_free;
387 :
388 26140 : data = malloc(data_size);
389 26140 : curparam->column_data = (unsigned char*) data;
390 26140 : if (!data)
391 : return NULL;
392 : /* if is a blob reset buffer */
393 26140 : if (is_blob_col(curparam) || curparam->column_type == SYBMSTABLE)
394 2174 : memset(data, 0, data_size);
395 :
396 : return data;
397 : }
398 :
399 : /**
400 : * Allocate memory for storing compute info
401 : * return NULL on out of memory
402 : */
403 :
404 : static TDSCOMPUTEINFO *
405 72 : tds_alloc_compute_result(TDS_USMALLINT num_cols, TDS_USMALLINT by_cols)
406 : {
407 : TDS_USMALLINT col;
408 : TDSCOMPUTEINFO *info;
409 :
410 72 : TEST_MALLOC(info, TDSCOMPUTEINFO);
411 72 : info->ref_count = 1;
412 :
413 72 : TEST_CALLOC(info->columns, TDSCOLUMN *, num_cols);
414 :
415 72 : info->num_cols = num_cols;
416 144 : for (col = 0; col < num_cols; col++)
417 72 : if (!(info->columns[col] = tds_alloc_column()))
418 : goto Cleanup;
419 :
420 72 : if (by_cols) {
421 24 : TEST_CALLOC(info->bycolumns, TDS_SMALLINT, by_cols);
422 24 : info->by_cols = by_cols;
423 : }
424 :
425 : return info;
426 0 : Cleanup:
427 0 : tds_free_compute_result(info);
428 0 : return NULL;
429 : }
430 :
431 : TDSCOMPUTEINFO **
432 72 : tds_alloc_compute_results(TDSSOCKET * tds, TDS_USMALLINT num_cols, TDS_USMALLINT by_cols)
433 : {
434 : TDS_UINT n;
435 : TDSCOMPUTEINFO **comp_info;
436 : TDSCOMPUTEINFO *cur_comp_info;
437 :
438 72 : tdsdump_log(TDS_DBG_FUNC, "alloc_compute_result. num_cols = %d bycols = %d\n", num_cols, by_cols);
439 72 : tdsdump_log(TDS_DBG_FUNC, "alloc_compute_result. num_comp_info = %d\n", tds->num_comp_info);
440 :
441 72 : cur_comp_info = tds_alloc_compute_result(num_cols, by_cols);
442 72 : if (!cur_comp_info)
443 : return NULL;
444 :
445 72 : n = tds->num_comp_info;
446 72 : comp_info = (TDSCOMPUTEINFO **) TDS_RESIZE(tds->comp_info, n + 1u);
447 72 : if (!comp_info) {
448 0 : tds_free_compute_result(cur_comp_info);
449 0 : return NULL;
450 : }
451 :
452 72 : tds->comp_info = comp_info;
453 72 : comp_info[n] = cur_comp_info;
454 72 : tds->num_comp_info = n + 1u;
455 :
456 72 : tdsdump_log(TDS_DBG_FUNC, "alloc_compute_result. num_comp_info = %d\n", tds->num_comp_info);
457 :
458 : return comp_info;
459 : }
460 :
461 : TDSRESULTINFO *
462 35137 : tds_alloc_results(TDS_USMALLINT num_cols)
463 : {
464 : TDSRESULTINFO *res_info;
465 : TDS_USMALLINT col;
466 :
467 35137 : TEST_MALLOC(res_info, TDSRESULTINFO);
468 35137 : res_info->ref_count = 1;
469 35137 : if (num_cols)
470 34949 : TEST_CALLOC(res_info->columns, TDSCOLUMN *, num_cols);
471 62637 : for (col = 0; col < num_cols; col++)
472 62637 : if (!(res_info->columns[col] = tds_alloc_column()))
473 : goto Cleanup;
474 35137 : res_info->num_cols = num_cols;
475 35137 : res_info->row_size = 0;
476 35137 : return res_info;
477 0 : Cleanup:
478 0 : tds_free_results(res_info);
479 0 : return NULL;
480 : }
481 :
482 : void
483 467585 : tds_set_current_results(TDSSOCKET *tds, TDSRESULTINFO *info)
484 : {
485 467585 : tds_detach_results(info);
486 467585 : if (tds->current_results)
487 530 : tds->current_results->attached_to = NULL;
488 467585 : if (info)
489 467577 : info->attached_to = tds;
490 467585 : tds->in_row = (info != NULL);
491 467585 : tds->current_results = info;
492 467585 : }
493 :
494 : /**
495 : * Detach result info from it current socket
496 : */
497 : void
498 0 : tds_detach_results(TDSRESULTINFO *info)
499 : {
500 1480305 : if (info && info->attached_to) {
501 467041 : info->attached_to->current_results = NULL;
502 467041 : info->attached_to->in_row = false;
503 467041 : info->attached_to = NULL;
504 : }
505 0 : }
506 :
507 : static void
508 34597 : tds_row_free(TDSRESULTINFO *res_info, unsigned char *row)
509 : {
510 : int i;
511 : const TDSCOLUMN *col;
512 :
513 34597 : if (!res_info || !row)
514 : return;
515 :
516 62249 : for (i = 0; i < res_info->num_cols; ++i) {
517 62249 : col = res_info->columns[i];
518 :
519 62249 : if (is_blob_col(col)) {
520 3614 : TDSBLOB *blob = (TDSBLOB *) &row[col->column_data - res_info->current_row];
521 3614 : if (blob->textvalue)
522 2872 : TDS_ZERO_FREE(blob->textvalue);
523 : }
524 : }
525 :
526 34597 : free(row);
527 : }
528 :
529 : /**
530 : * Allocate space for row store
531 : * return NULL on out of memory
532 : */
533 : TDSRET
534 34627 : tds_alloc_row(TDSRESULTINFO * res_info)
535 : {
536 34627 : int i, num_cols = res_info->num_cols;
537 : unsigned char *ptr;
538 : TDSCOLUMN *col;
539 : TDS_UINT row_size;
540 :
541 : /* compute row size */
542 34627 : row_size = 0;
543 96950 : for (i = 0; i < num_cols; ++i) {
544 62323 : col = res_info->columns[i];
545 :
546 62323 : col->column_data_free = NULL;
547 :
548 62323 : row_size += col->funcs->row_len(col);
549 62323 : row_size += (TDS_ALIGN_SIZE - 1);
550 62323 : row_size -= row_size % TDS_ALIGN_SIZE;
551 : }
552 34627 : res_info->row_size = row_size;
553 :
554 34627 : ptr = tds_new0(unsigned char, row_size ? row_size : 1);
555 34627 : res_info->current_row = ptr;
556 34627 : if (!ptr)
557 : return TDS_FAIL;
558 34627 : res_info->row_free = tds_row_free;
559 :
560 : /* fill column_data */
561 34627 : row_size = 0;
562 96950 : for (i = 0; i < num_cols; ++i) {
563 62323 : col = res_info->columns[i];
564 :
565 62323 : col->column_data = ptr + row_size;
566 :
567 62323 : row_size += col->funcs->row_len(col);
568 62323 : row_size += (TDS_ALIGN_SIZE - 1);
569 62323 : row_size -= row_size % TDS_ALIGN_SIZE;
570 : }
571 :
572 : return TDS_SUCCESS;
573 : }
574 :
575 : TDSRET
576 72 : tds_alloc_compute_row(TDSCOMPUTEINFO * res_info)
577 : {
578 72 : return tds_alloc_row(res_info);
579 : }
580 :
581 : void
582 106265 : tds_free_param_results(TDSPARAMINFO * param_info)
583 : {
584 246053 : tds_free_results(param_info);
585 106265 : }
586 :
587 : static void
588 : tds_free_compute_result(TDSCOMPUTEINFO * comp_info)
589 : {
590 72 : tds_free_results(comp_info);
591 : }
592 :
593 : static void
594 138254 : tds_free_compute_results(TDSSOCKET * tds)
595 : {
596 138254 : TDSCOMPUTEINFO ** comp_info = tds->comp_info;
597 138254 : TDS_UINT i, num_comp = tds->num_comp_info;
598 :
599 138254 : tds->comp_info = NULL;
600 138254 : tds->num_comp_info = 0;
601 :
602 138326 : for (i = 0; i < num_comp; i++) {
603 72 : if (comp_info && comp_info[i]) {
604 144 : tds_detach_results(comp_info[i]);
605 72 : tds_free_compute_result(comp_info[i]);
606 : }
607 : }
608 138254 : if (num_comp)
609 48 : free(comp_info);
610 138254 : }
611 :
612 : void
613 195717 : tds_free_row(TDSRESULTINFO * res_info, unsigned char *row)
614 : {
615 195717 : assert(res_info);
616 195717 : if (!row || !res_info->row_free)
617 : return;
618 :
619 2720 : res_info->row_free(res_info, row);
620 : }
621 :
622 : void
623 1360298 : tds_free_results(TDSRESULTINFO * res_info)
624 : {
625 : int i;
626 : TDSCOLUMN *curcol;
627 :
628 1360298 : if (!res_info)
629 : return;
630 :
631 272848 : if (--res_info->ref_count != 0)
632 : return;
633 :
634 65165 : tds_detach_results(res_info);
635 :
636 65165 : if (res_info->num_cols && res_info->columns) {
637 104855 : for (i = 0; i < res_info->num_cols; i++)
638 104855 : if ((curcol = res_info->columns[i]) != NULL) {
639 104855 : if (curcol->bcp_terminator)
640 54 : TDS_ZERO_FREE(curcol->bcp_terminator);
641 104855 : tds_free_bcp_column_data(curcol->bcp_column_data);
642 104855 : curcol->bcp_column_data = NULL;
643 104855 : if (curcol->column_data && curcol->column_data_free)
644 26688 : curcol->column_data_free(curcol);
645 : }
646 : }
647 :
648 65165 : if (res_info->current_row && res_info->row_free)
649 31955 : res_info->row_free(res_info, res_info->current_row);
650 :
651 65165 : if (res_info->num_cols && res_info->columns) {
652 104855 : for (i = 0; i < res_info->num_cols; i++)
653 104855 : if ((curcol = res_info->columns[i]) != NULL)
654 104855 : tds_free_column(curcol);
655 65151 : free(res_info->columns);
656 : }
657 :
658 65165 : free(res_info->bycolumns);
659 :
660 65165 : free(res_info);
661 : }
662 :
663 : void
664 138254 : tds_free_all_results(TDSSOCKET * tds)
665 : {
666 138254 : tdsdump_log(TDS_DBG_FUNC, "tds_free_all_results()\n");
667 276508 : tds_detach_results(tds->res_info);
668 138254 : tds_free_results(tds->res_info);
669 138254 : tds->res_info = NULL;
670 276508 : tds_detach_results(tds->param_info);
671 276508 : tds_free_param_results(tds->param_info);
672 138254 : tds->param_info = NULL;
673 138254 : tds_free_compute_results(tds);
674 138254 : tds->has_status = false;
675 138254 : tds->in_row = false;
676 138254 : tds->ret_status = 0;
677 138254 : if (tds->cur_dyn)
678 6168 : tds_detach_results(tds->cur_dyn->res_info);
679 138254 : }
680 :
681 : /*
682 : * Return true if winsock is initialized, else false.
683 : */
684 : static bool
685 : winsock_initialized(void)
686 : {
687 : #ifdef _WIN32
688 : static bool initialized = false;
689 : static tds_mutex mtx = TDS_MUTEX_INITIALIZER;
690 :
691 : int erc;
692 :
693 : if (initialized)
694 : return true;
695 :
696 : tds_mutex_lock(&mtx);
697 : /* same check inside the mutex */
698 : if (initialized) {
699 : tds_mutex_unlock(&mtx);
700 : return true;
701 : }
702 :
703 : /* initialize the socket layer */
704 : erc = tds_socket_init();
705 : initialized = (erc == 0);
706 : tds_mutex_unlock(&mtx);
707 :
708 : if (erc != 0) {
709 : char *errstr = sock_strerror(erc);
710 : tdsdump_log(TDS_DBG_ERROR, "tds_init_winsock: WSAStartup failed with %d (%s)\n", erc, errstr);
711 : sock_strerror_free(errstr);
712 : return false;
713 : }
714 : #endif
715 : return true;
716 : }
717 :
718 : TDSCONTEXT *
719 3651 : tds_alloc_context(void * parent)
720 : {
721 : TDSCONTEXT *context;
722 : TDSLOCALE *locale;
723 :
724 : if (!winsock_initialized())
725 : return NULL;
726 :
727 3651 : if ((locale = tds_get_locale()) == NULL)
728 : return NULL;
729 :
730 3651 : if ((context = tds_new0(TDSCONTEXT, 1)) == NULL) {
731 0 : tds_free_locale(locale);
732 0 : return NULL;
733 : }
734 3651 : context->locale = locale;
735 3651 : context->parent = parent;
736 3651 : context->money_use_2_digits = false;
737 :
738 3651 : return context;
739 : }
740 :
741 : void
742 3621 : tds_free_context(TDSCONTEXT * context)
743 : {
744 3621 : if (!context)
745 : return;
746 :
747 3621 : tds_free_locale(context->locale);
748 3621 : free(context);
749 : }
750 :
751 : TDSLOCALE *
752 3731 : tds_alloc_locale(void)
753 : {
754 : TDSLOCALE *locale;
755 :
756 3731 : TEST_MALLOC(locale, TDSLOCALE);
757 :
758 : return locale;
759 :
760 0 : Cleanup:
761 0 : tds_free_locale(locale);
762 0 : return NULL;
763 : }
764 :
765 : /*
766 : * Default capabilities.
767 : */
768 : #undef REQ
769 : #define SUPPORTED_REQ_CAP(i) \
770 : REQ(i,LANG) REQ(i,RPC) REQ(i,EVT) REQ(i,MSTMT) REQ(i,BCP) REQ(i,CURSOR) REQ(i,DYNF) \
771 : REQ(i,MSG) REQ(i,PARAM) REQ(i,DATA_INT1) REQ(i,DATA_INT2) REQ(i,DATA_INT4) REQ(i,DATA_BIT) \
772 : REQ(i,DATA_CHAR) REQ(i,DATA_VCHAR) REQ(i,DATA_BIN) REQ(i,DATA_VBIN) REQ(i,DATA_MNY8) \
773 : REQ(i,DATA_MNY4) REQ(i,DATA_DATE8) REQ(i,DATA_DATE4) REQ(i,DATA_FLT4) REQ(i,DATA_FLT8) \
774 : REQ(i,DATA_NUM) REQ(i,DATA_TEXT) REQ(i,DATA_IMAGE) REQ(i,DATA_DEC) REQ(i,DATA_LCHAR) \
775 : REQ(i,DATA_LBIN) REQ(i,DATA_INTN) REQ(i,DATA_DATETIMEN) REQ(i,DATA_MONEYN) \
776 : REQ(i,CSR_PREV) REQ(i,CSR_FIRST) REQ(i,CSR_LAST) REQ(i,CSR_ABS) REQ(i,CSR_REL) \
777 : REQ(i,CSR_MULTI) REQ(i,CON_INBAND) REQ(i,PROTO_TEXT) REQ(i,PROTO_BULK) \
778 : REQ(i,DATA_SENSITIVITY) REQ(i,DATA_BOUNDARY) REQ(i,PROTO_DYNPROC) REQ(i,DATA_FLTN) \
779 : REQ(i,DATA_BITN) REQ(i,DATA_INT8) REQ(i,DOL_BULK) REQ(i,WIDETABLE) \
780 : REQ(i,DATA_UINT2) REQ(i,DATA_UINT4) REQ(i,DATA_UINT8) REQ(i,DATA_UINTN) REQ(i,LARGEIDENT) \
781 : REQ(i,SRVPKTSIZE) REQ(i,DATA_DATE) REQ(i,DATA_TIME) REQ(i,DATA_BIGTIME) REQ(i,DATA_BIGDATETIME)
782 : #define REQ(i,n) |(((TDS_REQ_ ## n / 8) == i)?(1<<(TDS_REQ_ ## n & 7)):0)
783 : #define REQB(i) 0 SUPPORTED_REQ_CAP(i)
784 :
785 : #undef RES
786 : #define SUPPORTED_RES_CAP(i) \
787 : RES(i,CON_NOOOB) RES(i,PROTO_NOTEXT) RES(i,PROTO_NOBULK) RES(i,NOTDSDEBUG)
788 : #define RES(i,n) |(((TDS_RES_ ## n / 8) == i)?(1<<(TDS_RES_ ## n & 7)):0)
789 : #define RESB(i) 0 SUPPORTED_RES_CAP(i)
790 :
791 : static const TDS_CAPABILITIES defaultcaps = { {
792 : /* type, len, data, data, data, data, data, data, data, data, data, data, data, data, data, data (14 bytes) */
793 : { 1, 14, { REQB(13), REQB(12), REQB(11), REQB(10), REQB(9), REQB(8), REQB(7),
794 : REQB(6), REQB(5), REQB(4), REQB(3), REQB(2), REQB(1), REQB(0) } },
795 : { 2, 14, { RESB(13), RESB(12), RESB(11), RESB(10), RESB(9), RESB(8), RESB(7),
796 : RESB(6), RESB(5), RESB(4), RESB(3), RESB(2), RESB(1), RESB(0) } }
797 : } };
798 : /* check we match the values size */
799 : TDS_COMPILE_CHECK(tds_values_len, sizeof(defaultcaps.types[0].values) == 14);
800 : /* check we match the default size */
801 : TDS_COMPILE_CHECK(tds_cap_len, sizeof(defaultcaps) == TDS_MAX_CAPABILITY);
802 :
803 : /**
804 : * Initialize login structure with locale information and other stuff for connection
805 : * @param locale locale information (copied to configuration information)
806 : * @result login structure or NULL if initialization error
807 : */
808 : TDSLOGIN*
809 3826 : tds_init_login(TDSLOGIN *login, TDSLOCALE * locale)
810 : {
811 : char hostname[128];
812 : #if HAVE_NL_LANGINFO && defined(CODESET)
813 : const char *charset;
814 : #elif !defined(_WIN32)
815 : char *lc_all, *tok = NULL;
816 : #endif
817 : #ifdef _WIN32
818 : char cp[128];
819 : #endif
820 :
821 : /*
822 : * TDS 7.0:
823 : * ODBC driver settings.
824 : * Change to initial language must succeed.
825 : */
826 3826 : login->option_flag2 = TDS_INIT_LANG_REQUIRED|TDS_ODBC_ON;
827 3826 : login->tds_version = TDS_DEFAULT_VERSION;
828 3826 : login->block_size = 0;
829 :
830 : #if HAVE_NL_LANGINFO && defined(CODESET)
831 3826 : charset = nl_langinfo(CODESET);
832 3826 : if (strcmp(tds_canonical_charset_name(charset), "US-ASCII") == 0)
833 3814 : charset = "ISO-8859-1";
834 3826 : if (!tds_dstr_copy(&login->client_charset, charset))
835 : return NULL;
836 : #else
837 : if (!tds_dstr_copy(&login->client_charset, "ISO-8859-1"))
838 : return NULL;
839 :
840 : #ifdef _WIN32
841 : /* for Windows uses GetLocaleInfoA */
842 : strcpy(cp, "CP");
843 : if (GetLocaleInfoA(GetThreadLocale(), LOCALE_IDEFAULTANSICODEPAGE, cp + 2, sizeof(cp) - 2) > 0)
844 : if (!tds_dstr_copy(&login->client_charset, cp))
845 : return NULL;
846 : #else
847 : if ((lc_all = strdup(setlocale(LC_ALL, NULL))) == NULL)
848 : return NULL;
849 :
850 : if (strtok_r(lc_all, ".", &tok)) {
851 : char *encoding = strtok_r(NULL, "@", &tok);
852 : if (encoding) {
853 : if (!tds_dstr_copy(&login->client_charset, encoding)) {
854 : free(lc_all);
855 : return NULL;
856 : }
857 : }
858 : }
859 : free(lc_all);
860 : #endif
861 : #endif
862 :
863 3826 : if (locale) {
864 3826 : if (locale->language)
865 0 : if (!tds_dstr_copy(&login->language, locale->language))
866 : return NULL;
867 3826 : if (locale->server_charset)
868 0 : if (!tds_dstr_copy(&login->server_charset, locale->server_charset))
869 : return NULL;
870 : }
871 7652 : if (tds_dstr_isempty(&login->language)) {
872 3756 : if (!tds_dstr_copy(&login->language, TDS_DEF_LANG))
873 : return NULL;
874 : }
875 3826 : memset(hostname, '\0', sizeof(hostname));
876 3826 : gethostname(hostname, sizeof(hostname));
877 3826 : hostname[sizeof(hostname) - 1] = '\0'; /* make sure it's terminated */
878 3826 : if (!tds_dstr_copy(&login->client_host_name, hostname))
879 : return NULL;
880 :
881 3826 : login->valid_configuration = 1;
882 3826 : login->check_ssl_hostname = 1;
883 :
884 3826 : return login;
885 : }
886 :
887 : TDSCURSOR *
888 2364 : tds_alloc_cursor(TDSSOCKET *tds, const char *name, size_t namelen, const char *query, size_t querylen)
889 : {
890 : TDSCURSOR *cursor;
891 : TDSCURSOR *pcursor;
892 :
893 2364 : TEST_MALLOC(cursor, TDSCURSOR);
894 2364 : cursor->ref_count = 1;
895 :
896 2364 : cursor->type = TDS_CUR_TYPE_KEYSET;
897 2364 : cursor->concurrency = TDS_CUR_CONCUR_OPTIMISTIC;
898 :
899 2364 : TEST_CALLOC(cursor->cursor_name, char, namelen + 1);
900 2364 : memcpy(cursor->cursor_name, name, namelen);
901 :
902 2364 : TEST_CALLOC(cursor->query, char, querylen + 1);
903 2364 : memcpy(cursor->query, query, querylen);
904 :
905 2364 : if (tds->conn->cursors == NULL) {
906 2330 : tds->conn->cursors = cursor;
907 : } else {
908 0 : for (pcursor = tds->conn->cursors; pcursor->next; pcursor = pcursor->next)
909 0 : continue;
910 34 : pcursor->next = cursor;
911 : }
912 : /* take into account reference in connection list */
913 2364 : ++cursor->ref_count;
914 :
915 2364 : return cursor;
916 :
917 0 : Cleanup:
918 0 : tds_release_cursor(&cursor);
919 0 : return NULL;
920 : }
921 :
922 : /*
923 : * Called when cursor got deallocated from server
924 : */
925 : void
926 2364 : tds_cursor_deallocated(TDSCONNECTION *conn, TDSCURSOR *cursor)
927 : {
928 : TDSCURSOR **victim;
929 :
930 2364 : tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : freeing cursor_id %d\n", cursor->cursor_id);
931 :
932 2364 : victim = &conn->cursors;
933 4744 : while (*victim != cursor) {
934 16 : if (*victim == NULL) {
935 0 : tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : cannot find cursor_id %d\n", cursor->cursor_id);
936 : return;
937 : }
938 16 : victim = &(*victim)->next;
939 : }
940 :
941 : /* remove from list */
942 2364 : *victim = cursor->next;
943 2364 : cursor->next = NULL;
944 :
945 2364 : tds_release_cursor(&cursor);
946 : }
947 :
948 : /*
949 : * Decrement reference counter and free if necessary.
950 : * Called internally by libTDS and by upper library when you don't need
951 : * cursor reference anymore
952 : */
953 : void
954 89160 : tds_release_cursor(TDSCURSOR **pcursor)
955 : {
956 89160 : TDSCURSOR *cursor = *pcursor;
957 89160 : *pcursor = NULL;
958 89160 : if (!cursor || --cursor->ref_count > 0)
959 : return;
960 :
961 2364 : tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor_id %d\n", cursor->cursor_id);
962 :
963 2364 : tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor results\n");
964 4728 : tds_detach_results(cursor->res_info);
965 2364 : tds_free_results(cursor->res_info);
966 :
967 2364 : if (cursor->cursor_name) {
968 2364 : tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor name\n");
969 2364 : free(cursor->cursor_name);
970 : }
971 :
972 2364 : if (cursor->query) {
973 2364 : tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor query\n");
974 2364 : free(cursor->query);
975 : }
976 :
977 2364 : tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : cursor_id %d freed\n", cursor->cursor_id);
978 2364 : free(cursor);
979 : }
980 :
981 : TDSLOGIN *
982 7160 : tds_alloc_login(bool use_environment)
983 : {
984 7160 : TDSLOGIN *login = NULL;
985 7160 : const char *server_name = TDS_DEF_SERVER;
986 :
987 7160 : TEST_MALLOC(login, TDSLOGIN);
988 7160 : login->check_ssl_hostname = 1;
989 7160 : login->use_utf16 = 1;
990 7160 : login->bulk_copy = 1;
991 14320 : tds_dstr_init(&login->server_name);
992 14320 : tds_dstr_init(&login->language);
993 14320 : tds_dstr_init(&login->server_charset);
994 14320 : tds_dstr_init(&login->client_host_name);
995 14320 : tds_dstr_init(&login->server_host_name);
996 14320 : tds_dstr_init(&login->app_name);
997 14320 : tds_dstr_init(&login->user_name);
998 14320 : tds_dstr_init(&login->password);
999 14320 : tds_dstr_init(&login->library);
1000 14320 : tds_dstr_init(&login->new_password);
1001 :
1002 7160 : login->ip_addrs = NULL;
1003 :
1004 14320 : tds_dstr_init(&login->database);
1005 7160 : login->dump_file = NULL;
1006 14320 : tds_dstr_init(&login->client_charset);
1007 14320 : tds_dstr_init(&login->instance_name);
1008 14320 : tds_dstr_init(&login->server_realm_name);
1009 14320 : tds_dstr_init(&login->server_spn);
1010 14320 : tds_dstr_init(&login->cafile);
1011 14320 : tds_dstr_init(&login->crlfile);
1012 14320 : tds_dstr_init(&login->certificate_host_name);
1013 14320 : tds_dstr_init(&login->db_filename);
1014 14320 : tds_dstr_init(&login->openssl_ciphers);
1015 14320 : tds_dstr_init(&login->gnutls_ciphers);
1016 14320 : tds_dstr_init(&login->routing_address);
1017 :
1018 7160 : if (use_environment) {
1019 : const char *s;
1020 3334 : if ((s=getenv("DSQUERY")) != NULL)
1021 0 : server_name = s;
1022 :
1023 3334 : if ((s=getenv("TDSQUERY")) != NULL)
1024 0 : server_name = s;
1025 : }
1026 :
1027 7160 : if (!tds_dstr_copy(&login->server_name, server_name)) {
1028 0 : free(login);
1029 0 : return NULL;
1030 : }
1031 :
1032 7160 : login->capabilities = defaultcaps;
1033 7160 : login->use_ntlmv2_specified = 0;
1034 7160 : login->use_ntlmv2 = 1;
1035 :
1036 0 : Cleanup:
1037 : return login;
1038 : }
1039 :
1040 : void
1041 7852 : tds_free_login(TDSLOGIN * login)
1042 : {
1043 7852 : if (!login)
1044 : return;
1045 :
1046 : /* for security reason clear memory */
1047 7128 : tds_dstr_zero(&login->password);
1048 7128 : tds_dstr_free(&login->password);
1049 7128 : tds_dstr_zero(&login->new_password);
1050 7128 : tds_dstr_free(&login->new_password);
1051 7128 : tds_dstr_free(&login->server_name);
1052 7128 : tds_dstr_free(&login->language);
1053 7128 : tds_dstr_free(&login->server_charset);
1054 7128 : tds_dstr_free(&login->client_host_name);
1055 7128 : tds_dstr_free(&login->app_name);
1056 7128 : tds_dstr_free(&login->user_name);
1057 7128 : tds_dstr_free(&login->library);
1058 7128 : tds_dstr_free(&login->client_charset);
1059 7128 : tds_dstr_free(&login->server_host_name);
1060 :
1061 7128 : if (login->ip_addrs != NULL)
1062 3824 : freeaddrinfo(login->ip_addrs);
1063 :
1064 7128 : tds_dstr_free(&login->database);
1065 7128 : free(login->dump_file);
1066 7128 : tds_dstr_free(&login->instance_name);
1067 7128 : tds_dstr_free(&login->server_realm_name);
1068 7128 : tds_dstr_free(&login->server_spn);
1069 7128 : tds_dstr_free(&login->cafile);
1070 7128 : tds_dstr_free(&login->crlfile);
1071 7128 : tds_dstr_free(&login->certificate_host_name);
1072 7128 : tds_dstr_free(&login->db_filename);
1073 7128 : tds_dstr_free(&login->openssl_ciphers);
1074 7128 : tds_dstr_free(&login->gnutls_ciphers);
1075 7128 : tds_dstr_free(&login->routing_address);
1076 7128 : free(login);
1077 : }
1078 :
1079 : TDSPACKET *
1080 15480 : tds_alloc_packet(void *buf, unsigned len)
1081 : {
1082 15480 : TDSPACKET *packet = (TDSPACKET *) malloc(len + TDS_OFFSET(TDSPACKET, buf));
1083 15480 : if (TDS_LIKELY(packet)) {
1084 10781 : tds_packet_zero_data_start(packet);
1085 15480 : packet->data_len = 0;
1086 15480 : packet->capacity = len;
1087 15480 : packet->sid = 0;
1088 15480 : packet->next = NULL;
1089 15480 : if (buf) {
1090 235 : memcpy(packet->buf, buf, len);
1091 235 : packet->data_len = len;
1092 : }
1093 : }
1094 15480 : return packet;
1095 : }
1096 :
1097 : TDSPACKET *
1098 50495 : tds_realloc_packet(TDSPACKET *packet, unsigned len)
1099 : {
1100 58109 : if (packet->capacity < len) {
1101 6276 : packet = (TDSPACKET *) realloc(packet, len + TDS_OFFSET(TDSPACKET, buf));
1102 6276 : if (TDS_LIKELY(packet))
1103 6276 : packet->capacity = len;
1104 : }
1105 50495 : return packet;
1106 : }
1107 :
1108 : void
1109 52463 : tds_free_packets(TDSPACKET *packet)
1110 : {
1111 : TDSPACKET *next;
1112 67868 : for (; packet; packet = next) {
1113 15405 : next = packet->next;
1114 15405 : free(packet);
1115 : }
1116 52463 : }
1117 :
1118 : static void
1119 4607 : tds_deinit_connection(TDSCONNECTION *conn)
1120 : {
1121 4607 : if (conn->authentication)
1122 0 : conn->authentication->free(conn, conn->authentication);
1123 4607 : conn->authentication = NULL;
1124 9278 : while (conn->dyns)
1125 64 : tds_dynamic_deallocated(conn, conn->dyns);
1126 4633 : while (conn->cursors)
1127 26 : tds_cursor_deallocated(conn, conn->cursors);
1128 4607 : tds_ssl_deinit(conn);
1129 : /* close connection and free inactive sockets */
1130 4607 : tds_connection_close(conn);
1131 4607 : tds_wakeup_close(&conn->wakeup);
1132 4607 : tds_iconv_free(conn);
1133 4607 : free(conn->product_name);
1134 4607 : free(conn->server);
1135 4607 : tds_free_env(conn);
1136 9214 : tds_free_packets(conn->packet_cache);
1137 4607 : tds_mutex_free(&conn->list_mtx);
1138 : #if ENABLE_ODBC_MARS
1139 4652 : tds_free_packets(conn->packets);
1140 4652 : tds_free_packets(conn->recv_packet);
1141 4652 : tds_free_packets(conn->send_packets);
1142 2326 : free(conn->sessions);
1143 : #endif
1144 4607 : }
1145 :
1146 : static TDSCONNECTION *
1147 4637 : tds_init_connection(TDSCONNECTION *conn, TDSCONTEXT *context, unsigned int bufsize)
1148 : {
1149 4637 : conn->env.block_size = bufsize;
1150 4637 : conn->s = INVALID_SOCKET;
1151 4637 : conn->use_iconv_in = 1;
1152 4637 : conn->tds_ctx = context;
1153 4637 : conn->ncharsize = 1;
1154 4637 : conn->unicharsize = 1;
1155 :
1156 4637 : if (tds_wakeup_init(&conn->wakeup))
1157 : goto Cleanup;
1158 :
1159 4637 : if (tds_iconv_alloc(conn))
1160 : goto Cleanup;
1161 :
1162 9274 : if (tds_mutex_init(&conn->list_mtx))
1163 : goto Cleanup;
1164 :
1165 : #if ENABLE_ODBC_MARS
1166 2341 : TEST_CALLOC(conn->sessions, TDSSOCKET*, 64);
1167 2341 : conn->num_sessions = 64;
1168 : #endif
1169 2341 : return conn;
1170 :
1171 0 : Cleanup:
1172 0 : tds_wakeup_close(&conn->wakeup);
1173 0 : tds_iconv_free(conn);
1174 0 : return NULL;
1175 : }
1176 :
1177 : static TDSSOCKET *
1178 4647 : tds_init_socket(TDSSOCKET * tds_socket, unsigned int bufsize)
1179 : {
1180 : TDSPACKET *pkt;
1181 :
1182 4647 : tds_socket->parent = NULL;
1183 :
1184 4647 : tds_socket->recv_packet = tds_alloc_packet(NULL, bufsize);
1185 4647 : if (!tds_socket->recv_packet)
1186 : goto Cleanup;
1187 4647 : tds_socket->in_buf = tds_socket->recv_packet->buf;
1188 :
1189 4647 : pkt = tds_alloc_packet(NULL, bufsize + TDS_ADDITIONAL_SPACE);
1190 4647 : if (!pkt)
1191 : goto Cleanup;
1192 4647 : tds_set_current_send_packet(tds_socket, pkt);
1193 :
1194 4647 : tds_socket->out_buf_max = bufsize;
1195 :
1196 : /* Jeff's hack, init to no timeout */
1197 4647 : tds_socket->query_timeout = 0;
1198 4647 : tds_init_write_buf(tds_socket);
1199 4647 : tds_socket->state = TDS_DEAD;
1200 4647 : tds_socket->env_chg_func = NULL;
1201 9294 : if (tds_mutex_init(&tds_socket->wire_mtx))
1202 : goto Cleanup;
1203 :
1204 : #ifdef ENABLE_ODBC_MARS
1205 2351 : tds_socket->sid = 0;
1206 2351 : if (tds_cond_init(&tds_socket->packet_cond))
1207 : goto Cleanup;
1208 :
1209 2351 : tds_socket->recv_seq = 0;
1210 2351 : tds_socket->send_seq = 0;
1211 2351 : tds_socket->recv_wnd = 4;
1212 2351 : tds_socket->send_wnd = 4;
1213 : #endif
1214 2351 : return tds_socket;
1215 :
1216 0 : Cleanup:
1217 : return NULL;
1218 : }
1219 :
1220 :
1221 : #if ENABLE_ODBC_MARS
1222 : static void
1223 2326 : tds_free_connection(TDSCONNECTION *conn)
1224 : {
1225 2326 : if (!conn) return;
1226 2326 : assert(conn->in_net_tds == NULL);
1227 2326 : tds_deinit_connection(conn);
1228 2326 : free(conn);
1229 : }
1230 :
1231 : static TDSCONNECTION *
1232 2341 : tds_alloc_connection(TDSCONTEXT *context, unsigned int bufsize)
1233 : {
1234 : TDSCONNECTION *conn;
1235 :
1236 2341 : TEST_MALLOC(conn, TDSCONNECTION);
1237 2341 : if (!tds_init_connection(conn, context, bufsize))
1238 : goto Cleanup;
1239 : return conn;
1240 :
1241 0 : Cleanup:
1242 0 : tds_free_connection(conn);
1243 0 : return NULL;
1244 : }
1245 :
1246 : static TDSSOCKET *
1247 2351 : tds_alloc_socket_base(unsigned int bufsize)
1248 : {
1249 : TDSSOCKET *tds_socket;
1250 :
1251 2351 : TEST_MALLOC(tds_socket, TDSSOCKET);
1252 2351 : if (!tds_init_socket(tds_socket, bufsize))
1253 : goto Cleanup;
1254 : return tds_socket;
1255 :
1256 0 : Cleanup:
1257 0 : tds_free_socket(tds_socket);
1258 0 : return NULL;
1259 : }
1260 :
1261 : TDSSOCKET *
1262 2341 : tds_alloc_socket(TDSCONTEXT * context, unsigned int bufsize)
1263 : {
1264 2341 : TDSCONNECTION *conn = tds_alloc_connection(context, bufsize);
1265 : TDSSOCKET *tds;
1266 :
1267 2341 : if (!conn)
1268 : return NULL;
1269 :
1270 2341 : tds = tds_alloc_socket_base(bufsize);
1271 2341 : if (tds) {
1272 2341 : conn->sessions[0] = tds;
1273 2341 : tds->conn = conn;
1274 2341 : return tds;
1275 : }
1276 0 : tds_free_connection(conn);
1277 0 : return NULL;
1278 : }
1279 :
1280 : static bool
1281 10 : tds_alloc_new_sid(TDSSOCKET *tds)
1282 : {
1283 : uint16_t sid;
1284 10 : TDSCONNECTION *conn = tds->conn;
1285 :
1286 10 : tds_mutex_lock(&conn->list_mtx);
1287 13 : for (sid = 1; sid < conn->num_sessions; ++sid)
1288 13 : if (!conn->sessions[sid])
1289 : break;
1290 10 : if (sid == conn->num_sessions) {
1291 : /* extend array */
1292 0 : TDSSOCKET **s = (TDSSOCKET **) TDS_RESIZE(conn->sessions, sid+64);
1293 0 : if (!s)
1294 : goto error;
1295 0 : memset(s + conn->num_sessions, 0, sizeof(*s) * 64);
1296 0 : conn->num_sessions += 64;
1297 : }
1298 10 : conn->sessions[sid] = tds;
1299 10 : tds->sid = sid;
1300 10 : error:
1301 10 : tds_mutex_unlock(&conn->list_mtx);
1302 10 : return tds->sid != 0;
1303 : }
1304 :
1305 : TDSSOCKET *
1306 16 : tds_alloc_additional_socket(TDSCONNECTION *conn)
1307 : {
1308 : TDSSOCKET *tds;
1309 16 : if (!IS_TDS72_PLUS(conn) || !conn->mars)
1310 : return NULL;
1311 :
1312 10 : tds = tds_alloc_socket_base(sizeof(TDS72_SMP_HEADER) + conn->env.block_size);
1313 10 : if (!tds)
1314 : return NULL;
1315 10 : tds->send_packet->data_start = sizeof(TDS72_SMP_HEADER);
1316 10 : tds->out_buf = tds->send_packet->buf + sizeof(TDS72_SMP_HEADER);
1317 10 : tds->out_buf_max -= sizeof(TDS72_SMP_HEADER);
1318 :
1319 10 : tds->conn = conn;
1320 10 : if (!tds_alloc_new_sid(tds))
1321 : goto Cleanup;
1322 :
1323 10 : tds->state = TDS_IDLE;
1324 10 : if (TDS_FAILED(tds_append_syn(tds)))
1325 : goto Cleanup;
1326 :
1327 : return tds;
1328 :
1329 0 : Cleanup:
1330 0 : tds_free_socket(tds);
1331 0 : return NULL;
1332 : }
1333 : #else /* !ENABLE_ODBC_MARS */
1334 : TDSSOCKET *
1335 2296 : tds_alloc_socket(TDSCONTEXT * context, unsigned int bufsize)
1336 : {
1337 : TDSSOCKET *tds_socket;
1338 :
1339 2296 : TEST_MALLOC(tds_socket, TDSSOCKET);
1340 2296 : if (!tds_init_connection(tds_socket->conn, context, bufsize))
1341 : goto Cleanup;
1342 2296 : if (!tds_init_socket(tds_socket, bufsize))
1343 : goto Cleanup;
1344 : return tds_socket;
1345 :
1346 0 : Cleanup:
1347 0 : tds_free_socket(tds_socket);
1348 0 : return NULL;
1349 : }
1350 : #endif /* !ENABLE_ODBC_MARS */
1351 :
1352 : TDSSOCKET *
1353 7614 : tds_realloc_socket(TDSSOCKET * tds, unsigned int bufsize)
1354 : {
1355 : TDSPACKET *packet;
1356 : #if ENABLE_ODBC_MARS
1357 3937 : size_t smp_hdr_len = tds->conn->mars ? sizeof(TDS72_SMP_HEADER) : 0;
1358 : #else
1359 : enum { smp_hdr_len = 0 };
1360 : #endif
1361 :
1362 7614 : assert(tds && tds->out_buf && tds->send_packet);
1363 :
1364 7614 : if (bufsize < 512)
1365 0 : bufsize = 512;
1366 :
1367 : /* prevent nasty memory conditions, server should send the request at
1368 : * the beginning only */
1369 7614 : if (tds->out_pos > bufsize || tds->frozen)
1370 : return NULL;
1371 :
1372 7614 : tds->conn->env.block_size = bufsize;
1373 :
1374 15228 : packet = tds_realloc_packet(tds->send_packet, smp_hdr_len + bufsize + TDS_ADDITIONAL_SPACE);
1375 7614 : if (packet == NULL)
1376 : return NULL;
1377 :
1378 : #if ENABLE_ODBC_MARS
1379 3937 : packet->data_start = smp_hdr_len;
1380 : #endif
1381 7614 : tds->out_buf_max = bufsize;
1382 7614 : tds_set_current_send_packet(tds, packet);
1383 7614 : return tds;
1384 : }
1385 :
1386 : #if ENABLE_ODBC_MARS
1387 : static void
1388 2336 : tds_connection_remove_socket(TDSCONNECTION *conn, TDSSOCKET *tds)
1389 : {
1390 : unsigned n;
1391 2336 : bool must_free_connection = true;
1392 2336 : tds_mutex_lock(&conn->list_mtx);
1393 2336 : if (tds->sid < conn->num_sessions)
1394 2336 : conn->sessions[tds->sid] = NULL;
1395 151200 : for (n = 0; n < conn->num_sessions; ++n)
1396 148874 : if (TDSSOCKET_VALID(conn->sessions[n])) {
1397 : must_free_connection = false;
1398 : break;
1399 : }
1400 2336 : if (!must_free_connection) {
1401 : /* tds use connection member so must be valid */
1402 10 : tds_append_fin(tds);
1403 : }
1404 2336 : tds_mutex_unlock(&conn->list_mtx);
1405 :
1406 : /* detach entirely */
1407 2336 : tds->conn = NULL;
1408 :
1409 2336 : if (must_free_connection)
1410 2326 : tds_free_connection(conn);
1411 2336 : }
1412 : #else
1413 : static void inline
1414 : tds_connection_remove_socket(TDSCONNECTION *conn, TDSSOCKET *tds TDS_UNUSED)
1415 : {
1416 2281 : tds_deinit_connection(conn);
1417 : }
1418 : #endif
1419 :
1420 : void
1421 7195 : tds_free_socket(TDSSOCKET * tds)
1422 : {
1423 : #if ENABLE_EXTRA_CHECKS
1424 : TDSDYNAMIC *dyn;
1425 : TDSCURSOR *cur;
1426 : #endif
1427 :
1428 7195 : if (!tds)
1429 : return;
1430 :
1431 : /* detach this socket */
1432 4617 : tds_release_cur_dyn(tds);
1433 4617 : tds_release_cursor(&tds->cur_cursor);
1434 9234 : tds_detach_results(tds->current_results);
1435 : #if ENABLE_EXTRA_CHECKS
1436 4685 : for (dyn = tds->conn->dyns; dyn; dyn = dyn->next) {
1437 68 : if (dyn->res_info && dyn->res_info->attached_to == tds) {
1438 0 : assert(0);
1439 : }
1440 : }
1441 4643 : for (cur = tds->conn->cursors; cur; cur = cur->next) {
1442 26 : if (cur->res_info && cur->res_info->attached_to == tds) {
1443 0 : assert(0);
1444 : }
1445 : }
1446 : #endif
1447 4617 : tds_free_all_results(tds);
1448 : #if ENABLE_ODBC_MARS
1449 4672 : tds_cond_destroy(&tds->packet_cond);
1450 : #endif
1451 :
1452 6898 : tds_connection_remove_socket(tds->conn, tds);
1453 9234 : tds_free_packets(tds->recv_packet);
1454 4617 : if (tds->frozen_packets)
1455 : tds_free_packets(tds->frozen_packets);
1456 : else
1457 4617 : tds_free_packets(tds->send_packet);
1458 4617 : free(tds);
1459 : }
1460 :
1461 : void
1462 3701 : tds_free_locale(TDSLOCALE * locale)
1463 : {
1464 3701 : if (!locale)
1465 : return;
1466 :
1467 3701 : free(locale->language);
1468 3701 : free(locale->server_charset);
1469 3701 : free(locale->datetime_fmt);
1470 3701 : free(locale->date_fmt);
1471 3701 : free(locale->time_fmt);
1472 3701 : free(locale);
1473 : }
1474 :
1475 : static void
1476 4607 : tds_free_env(TDSCONNECTION* conn)
1477 : {
1478 4607 : if (conn->env.language)
1479 2918 : TDS_ZERO_FREE(conn->env.language);
1480 4607 : if (conn->env.charset)
1481 546 : TDS_ZERO_FREE(conn->env.charset);
1482 4607 : if (conn->env.database)
1483 3632 : TDS_ZERO_FREE(conn->env.database);
1484 4607 : }
1485 :
1486 : void
1487 15803 : tds_free_msg(TDSMESSAGE * message)
1488 : {
1489 15803 : if (message) {
1490 15803 : message->priv_msg_type = 0;
1491 15803 : message->msgno = 0;
1492 15803 : message->state = 0;
1493 15803 : message->severity = 0;
1494 15803 : message->line_number = 0;
1495 15803 : TDS_ZERO_FREE(message->message);
1496 15803 : TDS_ZERO_FREE(message->server);
1497 15803 : TDS_ZERO_FREE(message->proc_name);
1498 15803 : TDS_ZERO_FREE(message->sql_state);
1499 : }
1500 15803 : }
1501 :
1502 : #define SQLS_ENTRY(number,state) case number: p = state; break
1503 :
1504 : char *
1505 41316 : tds_alloc_client_sqlstate(int msgno)
1506 : {
1507 41316 : const char *p = NULL;
1508 :
1509 41316 : switch (msgno) {
1510 : SQLS_ENTRY(17000, "S1T00"); /* timeouts ??? */
1511 1 : SQLS_ENTRY(20004, "08S01"); /* Communication link failure */
1512 72 : SQLS_ENTRY(20006, "08S01");
1513 0 : SQLS_ENTRY(20009, "08S01");
1514 0 : SQLS_ENTRY(20020, "08S01");
1515 0 : SQLS_ENTRY(20019, "24000"); /* Invalid cursor state */
1516 0 : SQLS_ENTRY(20014, "28000"); /* Invalid authorization specification */
1517 36030 : SQLS_ENTRY(2400, "42000"); /* Syntax error or access violation */
1518 740 : SQLS_ENTRY(2401, "42000");
1519 1930 : SQLS_ENTRY(2403, "42000");
1520 0 : SQLS_ENTRY(2404, "42000");
1521 2211 : SQLS_ENTRY(2402, "S1000"); /* General error */
1522 : }
1523 :
1524 : if (p != NULL)
1525 40984 : return strdup(p);
1526 : else
1527 : return NULL;
1528 : }
1529 :
1530 : char *
1531 15694 : tds_alloc_lookup_sqlstate(TDSSOCKET * tds, int msgno)
1532 : {
1533 15694 : const char *p = NULL;
1534 15694 : char *q = NULL;
1535 :
1536 15694 : if (TDS_IS_MSSQL(tds)) {
1537 7420 : switch (msgno) { /* MSSQL Server */
1538 :
1539 752 : SQLS_ENTRY(3621,"01000");
1540 26 : SQLS_ENTRY(8153,"01003"); /* Null in aggregate */
1541 8 : SQLS_ENTRY(911, "08004"); /* Server rejected connection */
1542 0 : SQLS_ENTRY(512, "21000"); /* Subquery returns more than one value */
1543 0 : SQLS_ENTRY(213, "21S01"); /* Insert column list mismatch */
1544 0 : SQLS_ENTRY(109, "21S01");
1545 0 : SQLS_ENTRY(110, "21S01");
1546 0 : SQLS_ENTRY(1774,"21S02"); /* Ref column mismatch */
1547 0 : SQLS_ENTRY(8152,"22001"); /* String data would be truncated */
1548 0 : SQLS_ENTRY(5146,"22003"); /* Numeric value out of range */
1549 0 : SQLS_ENTRY(168, "22003"); /* Arithmetic overflow */
1550 656 : SQLS_ENTRY(220, "22003");
1551 0 : SQLS_ENTRY(232, "22003");
1552 0 : SQLS_ENTRY(234, "22003");
1553 0 : SQLS_ENTRY(236, "22003");
1554 0 : SQLS_ENTRY(238, "22003");
1555 0 : SQLS_ENTRY(244, "22003");
1556 0 : SQLS_ENTRY(246, "22003");
1557 0 : SQLS_ENTRY(248, "22003");
1558 0 : SQLS_ENTRY(519, "22003");
1559 0 : SQLS_ENTRY(520, "22003");
1560 0 : SQLS_ENTRY(521, "22003");
1561 0 : SQLS_ENTRY(522, "22003");
1562 0 : SQLS_ENTRY(523, "22003");
1563 0 : SQLS_ENTRY(524, "22003");
1564 0 : SQLS_ENTRY(1007,"22003");
1565 0 : SQLS_ENTRY(3606,"22003");
1566 0 : SQLS_ENTRY(8115,"22003");
1567 0 : SQLS_ENTRY(206, "22005"); /* Error in assignment */
1568 0 : SQLS_ENTRY(235, "22005");
1569 0 : SQLS_ENTRY(247, "22005");
1570 0 : SQLS_ENTRY(249, "22005");
1571 0 : SQLS_ENTRY(256, "22005");
1572 0 : SQLS_ENTRY(257, "22005");
1573 0 : SQLS_ENTRY(305, "22005");
1574 0 : SQLS_ENTRY(409, "22005");
1575 0 : SQLS_ENTRY(518, "22005");
1576 0 : SQLS_ENTRY(529, "22005");
1577 0 : SQLS_ENTRY(210, "22007"); /* Invalid datetime format */
1578 0 : SQLS_ENTRY(241, "22007");
1579 0 : SQLS_ENTRY(295, "22007");
1580 16 : SQLS_ENTRY(242, "22008"); /* Datetime out of range */
1581 0 : SQLS_ENTRY(296, "22008");
1582 0 : SQLS_ENTRY(298, "22008");
1583 0 : SQLS_ENTRY(535, "22008");
1584 0 : SQLS_ENTRY(542, "22008");
1585 8 : SQLS_ENTRY(517, "22008");
1586 0 : SQLS_ENTRY(3607, "22012"); /* Div by zero */
1587 164 : SQLS_ENTRY(8134, "22012");
1588 0 : SQLS_ENTRY(245, "22018"); /* Syntax error? */
1589 8 : SQLS_ENTRY(2627, "23000"); /* Constraint violation */
1590 8 : SQLS_ENTRY(515, "23000");
1591 0 : SQLS_ENTRY(233, "23000");
1592 0 : SQLS_ENTRY(273, "23000");
1593 0 : SQLS_ENTRY(530, "23000");
1594 0 : SQLS_ENTRY(2601,"23000");
1595 0 : SQLS_ENTRY(2615,"23000");
1596 0 : SQLS_ENTRY(2626,"23000");
1597 0 : SQLS_ENTRY(3604,"23000");
1598 0 : SQLS_ENTRY(3605,"23000");
1599 0 : SQLS_ENTRY(544, "23000");
1600 0 : SQLS_ENTRY(547, "23000");
1601 0 : SQLS_ENTRY(550, "23000");
1602 0 : SQLS_ENTRY(4415, "23000");
1603 0 : SQLS_ENTRY(1505, "23000");
1604 0 : SQLS_ENTRY(1508, "23000");
1605 0 : SQLS_ENTRY(3725, "23000");
1606 0 : SQLS_ENTRY(3726, "23000");
1607 0 : SQLS_ENTRY(4712, "23000");
1608 0 : SQLS_ENTRY(10055, "23000");
1609 0 : SQLS_ENTRY(10065, "23000");
1610 0 : SQLS_ENTRY(11011, "23000");
1611 0 : SQLS_ENTRY(11040, "23000");
1612 0 : SQLS_ENTRY(16999, "24000"); /* Invalid cursor state */
1613 0 : SQLS_ENTRY(16905, "24000");
1614 0 : SQLS_ENTRY(16917, "24000");
1615 0 : SQLS_ENTRY(16946, "24000");
1616 0 : SQLS_ENTRY(16950, "24000");
1617 0 : SQLS_ENTRY(266, "25000"); /* Invalid transaction state */
1618 0 : SQLS_ENTRY(277,"25000");
1619 0 : SQLS_ENTRY(611,"25000");
1620 0 : SQLS_ENTRY(3906,"25000");
1621 0 : SQLS_ENTRY(3908,"25000");
1622 0 : SQLS_ENTRY(6401,"25000");
1623 0 : SQLS_ENTRY(626, "25000");
1624 0 : SQLS_ENTRY(627, "25000");
1625 0 : SQLS_ENTRY(628, "25000");
1626 0 : SQLS_ENTRY(3902, "25000");
1627 0 : SQLS_ENTRY(3903, "25000");
1628 0 : SQLS_ENTRY(3916, "25000");
1629 0 : SQLS_ENTRY(3918, "25000");
1630 0 : SQLS_ENTRY(3919, "25000");
1631 0 : SQLS_ENTRY(3921, "25000");
1632 0 : SQLS_ENTRY(3922, "25000");
1633 16 : SQLS_ENTRY(3926, "25000");
1634 0 : SQLS_ENTRY(7969, "25000");
1635 0 : SQLS_ENTRY(8506, "25000");
1636 0 : SQLS_ENTRY(15626, "25000");
1637 0 : SQLS_ENTRY(18456, "28000"); /* Login failed? */
1638 0 : SQLS_ENTRY(6104, "37000"); /* Syntax error or access violation */
1639 0 : SQLS_ENTRY(8114, "37000");
1640 0 : SQLS_ENTRY(131, "37000");
1641 2 : SQLS_ENTRY(137, "37000");
1642 24 : SQLS_ENTRY(170, "37000");
1643 0 : SQLS_ENTRY(174, "37000");
1644 0 : SQLS_ENTRY(201, "37000");
1645 8 : SQLS_ENTRY(2812, "37000");
1646 0 : SQLS_ENTRY(2526, "37000");
1647 0 : SQLS_ENTRY(8144, "37000");
1648 0 : SQLS_ENTRY(17308, "42000"); /* Syntax/Access violation */
1649 0 : SQLS_ENTRY(17571, "42000");
1650 0 : SQLS_ENTRY(18002, "42000");
1651 0 : SQLS_ENTRY(229, "42000");
1652 0 : SQLS_ENTRY(230, "42000");
1653 0 : SQLS_ENTRY(262, "42000");
1654 0 : SQLS_ENTRY(2557, "42000");
1655 0 : SQLS_ENTRY(2571, "42000");
1656 0 : SQLS_ENTRY(2760, "42000");
1657 0 : SQLS_ENTRY(3110, "42000");
1658 0 : SQLS_ENTRY(3704, "42000");
1659 0 : SQLS_ENTRY(4613, "42000");
1660 0 : SQLS_ENTRY(4618, "42000");
1661 0 : SQLS_ENTRY(4834, "42000");
1662 0 : SQLS_ENTRY(5011, "42000");
1663 0 : SQLS_ENTRY(5116, "42000");
1664 0 : SQLS_ENTRY(5812, "42000");
1665 0 : SQLS_ENTRY(6004, "42000");
1666 0 : SQLS_ENTRY(6102, "42000");
1667 0 : SQLS_ENTRY(7956, "42000");
1668 0 : SQLS_ENTRY(11010, "42000");
1669 0 : SQLS_ENTRY(11045, "42000");
1670 0 : SQLS_ENTRY(14126, "42000");
1671 0 : SQLS_ENTRY(15247, "42000");
1672 0 : SQLS_ENTRY(15622, "42000");
1673 0 : SQLS_ENTRY(20604, "42000");
1674 0 : SQLS_ENTRY(21049, "42000");
1675 0 : SQLS_ENTRY(113, "42000");
1676 0 : SQLS_ENTRY(2714, "42S01"); /* Table or view already exists */
1677 24 : SQLS_ENTRY(208, "42S02"); /* Table or view not found */
1678 196 : SQLS_ENTRY(3701, "42S02");
1679 0 : SQLS_ENTRY(1913, "42S11"); /* Index already exists */
1680 0 : SQLS_ENTRY(15605, "42S11");
1681 0 : SQLS_ENTRY(307, "42S12"); /* Index not found */
1682 0 : SQLS_ENTRY(308, "42S12");
1683 0 : SQLS_ENTRY(10033, "42S12");
1684 0 : SQLS_ENTRY(15323, "42S12");
1685 0 : SQLS_ENTRY(18833, "42S12");
1686 0 : SQLS_ENTRY(4925, "42S21"); /* Column already exists */
1687 0 : SQLS_ENTRY(21255, "42S21");
1688 0 : SQLS_ENTRY(1911, "42S22"); /* Column not found */
1689 48 : SQLS_ENTRY(207, "42S22");
1690 0 : SQLS_ENTRY(4924, "42S22");
1691 0 : SQLS_ENTRY(4926, "42S22");
1692 0 : SQLS_ENTRY(15645, "42S22");
1693 0 : SQLS_ENTRY(21166, "42S22");
1694 : }
1695 : } else {
1696 8274 : switch (msgno) { /* Sybase */
1697 4 : SQLS_ENTRY(3621, "01000");
1698 0 : SQLS_ENTRY(9501, "01003"); /* Null in aggregate */
1699 1 : SQLS_ENTRY(911, "08004"); /* Server rejected connection */
1700 0 : SQLS_ENTRY(512, "21000"); /* Subquery returns more than one value */
1701 0 : SQLS_ENTRY(213, "21S01"); /* Insert column list mismatch */
1702 0 : SQLS_ENTRY(109, "21S01");
1703 0 : SQLS_ENTRY(110, "21S01");
1704 0 : SQLS_ENTRY(1715, "21S02"); /* Ref column mismatch */
1705 0 : SQLS_ENTRY(9502, "22001"); /* String data would be truncated */
1706 0 : SQLS_ENTRY(220, "22003"); /* Arithmetic overflow */
1707 0 : SQLS_ENTRY(168, "22003");
1708 0 : SQLS_ENTRY(227, "22003");
1709 0 : SQLS_ENTRY(232, "22003");
1710 0 : SQLS_ENTRY(234, "22003");
1711 0 : SQLS_ENTRY(236, "22003");
1712 0 : SQLS_ENTRY(238, "22003");
1713 0 : SQLS_ENTRY(244, "22003");
1714 0 : SQLS_ENTRY(246, "22003");
1715 0 : SQLS_ENTRY(247, "22003");
1716 0 : SQLS_ENTRY(248, "22003");
1717 0 : SQLS_ENTRY(519, "22003");
1718 0 : SQLS_ENTRY(520, "22003");
1719 0 : SQLS_ENTRY(521, "22003");
1720 0 : SQLS_ENTRY(522, "22003");
1721 0 : SQLS_ENTRY(523, "22003");
1722 0 : SQLS_ENTRY(524, "22003");
1723 0 : SQLS_ENTRY(3606, "22003");
1724 0 : SQLS_ENTRY(206, "22005"); /* Error in assignment */
1725 0 : SQLS_ENTRY(235, "22005");
1726 4 : SQLS_ENTRY(249, "22005");
1727 0 : SQLS_ENTRY(256, "22005");
1728 0 : SQLS_ENTRY(305, "22005");
1729 0 : SQLS_ENTRY(409, "22005");
1730 0 : SQLS_ENTRY(518, "22005");
1731 0 : SQLS_ENTRY(529, "22005");
1732 0 : SQLS_ENTRY(535, "22008"); /* Datetime out of range */
1733 0 : SQLS_ENTRY(542, "22008");
1734 2 : SQLS_ENTRY(517, "22008");
1735 0 : SQLS_ENTRY(3607, "22012"); /* Div by zero */
1736 0 : SQLS_ENTRY(245, "22018"); /* Syntax error? */
1737 0 : SQLS_ENTRY(544, "23000"); /* Constraint violation */
1738 0 : SQLS_ENTRY(233, "23000");
1739 0 : SQLS_ENTRY(273, "23000");
1740 0 : SQLS_ENTRY(530, "23000");
1741 0 : SQLS_ENTRY(2601,"23000");
1742 0 : SQLS_ENTRY(2615,"23000");
1743 0 : SQLS_ENTRY(2626,"23000");
1744 0 : SQLS_ENTRY(3604,"23000");
1745 0 : SQLS_ENTRY(3605,"23000");
1746 0 : SQLS_ENTRY(545, "23000");
1747 0 : SQLS_ENTRY(546, "23000");
1748 0 : SQLS_ENTRY(547, "23000");
1749 0 : SQLS_ENTRY(548, "23000");
1750 0 : SQLS_ENTRY(549, "23000");
1751 0 : SQLS_ENTRY(550, "23000");
1752 0 : SQLS_ENTRY(1505, "23000");
1753 0 : SQLS_ENTRY(1508, "23000");
1754 0 : SQLS_ENTRY(565, "24000"); /* Invalid cursor state */
1755 0 : SQLS_ENTRY(558, "24000");
1756 0 : SQLS_ENTRY(559, "24000");
1757 0 : SQLS_ENTRY(6235, "24000");
1758 0 : SQLS_ENTRY(583, "24000");
1759 0 : SQLS_ENTRY(6259, "24000");
1760 0 : SQLS_ENTRY(6260, "24000");
1761 0 : SQLS_ENTRY(562, "24000");
1762 0 : SQLS_ENTRY(277, "25000"); /* Invalid transaction state */
1763 0 : SQLS_ENTRY(611,"25000");
1764 0 : SQLS_ENTRY(3906,"25000");
1765 0 : SQLS_ENTRY(3908,"25000");
1766 0 : SQLS_ENTRY(6401,"25000");
1767 0 : SQLS_ENTRY(627, "25000");
1768 0 : SQLS_ENTRY(628, "25000");
1769 0 : SQLS_ENTRY(641, "25000");
1770 0 : SQLS_ENTRY(642, "25000");
1771 0 : SQLS_ENTRY(1276, "25000");
1772 0 : SQLS_ENTRY(3902, "25000");
1773 0 : SQLS_ENTRY(3903, "25000");
1774 0 : SQLS_ENTRY(6104, "37000"); /* Syntax error or access violation */
1775 0 : SQLS_ENTRY(102, "37000");
1776 24 : SQLS_ENTRY(137, "37000");
1777 0 : SQLS_ENTRY(7327, "37000");
1778 0 : SQLS_ENTRY(201, "37000");
1779 0 : SQLS_ENTRY(257, "37000");
1780 2 : SQLS_ENTRY(2812, "37000");
1781 0 : SQLS_ENTRY(2526, "37000");
1782 0 : SQLS_ENTRY(11021, "37000");
1783 0 : SQLS_ENTRY(229, "42000"); /* Syntax/Access violation */
1784 0 : SQLS_ENTRY(230, "42000");
1785 0 : SQLS_ENTRY(262, "42000");
1786 0 : SQLS_ENTRY(4602, "42000");
1787 0 : SQLS_ENTRY(4603, "42000");
1788 0 : SQLS_ENTRY(4608, "42000");
1789 0 : SQLS_ENTRY(10306, "42000");
1790 0 : SQLS_ENTRY(10323, "42000");
1791 0 : SQLS_ENTRY(10330, "42000");
1792 0 : SQLS_ENTRY(10331, "42000");
1793 0 : SQLS_ENTRY(10332, "42000");
1794 0 : SQLS_ENTRY(11110, "42000");
1795 0 : SQLS_ENTRY(11113, "42000");
1796 0 : SQLS_ENTRY(11118, "42000");
1797 0 : SQLS_ENTRY(11121, "42000");
1798 0 : SQLS_ENTRY(17222, "42000");
1799 0 : SQLS_ENTRY(17223, "42000");
1800 0 : SQLS_ENTRY(18350, "42000");
1801 0 : SQLS_ENTRY(18351, "42000");
1802 0 : SQLS_ENTRY(113, "42000");
1803 0 : SQLS_ENTRY(2714, "42S01"); /* Table or view already exists */
1804 0 : SQLS_ENTRY(208, "42S02"); /* Table or view not found */
1805 44 : SQLS_ENTRY(3701, "42S02");
1806 0 : SQLS_ENTRY(1913, "42S11"); /* Index already exists */
1807 0 : SQLS_ENTRY(307, "42S12"); /* Index not found */
1808 0 : SQLS_ENTRY(7010, "42S12");
1809 0 : SQLS_ENTRY(18091, "42S12");
1810 0 : SQLS_ENTRY(1921, "42S21"); /* Column already exists */
1811 0 : SQLS_ENTRY(1720, "42S22"); /* Column not found */
1812 6 : SQLS_ENTRY(207, "42S22");
1813 0 : SQLS_ENTRY(4934, "42S22");
1814 0 : SQLS_ENTRY(18117, "42S22");
1815 : }
1816 : }
1817 :
1818 15694 : if (p != NULL && (q = strdup(p)) != NULL) {
1819 : /* FIXME correct here ?? */
1820 : /* Convert known ODBC 3.x states listed above to 2.x */
1821 2051 : if (memcmp(q, "42S", 3) == 0)
1822 318 : memcpy(q, "S00", 3);
1823 :
1824 : return q;
1825 : }
1826 : return NULL;
1827 : }
1828 :
1829 : BCPCOLDATA *
1830 3186 : tds_alloc_bcp_column_data(unsigned int column_size)
1831 : {
1832 : BCPCOLDATA *coldata;
1833 :
1834 3186 : TEST_MALLOC(coldata, BCPCOLDATA);
1835 :
1836 3186 : if (column_size > 4 * 1024)
1837 116 : column_size = 4 * 1024;
1838 3186 : TEST_CALLOC(coldata->data, unsigned char, column_size);
1839 :
1840 : return coldata;
1841 0 : Cleanup:
1842 0 : tds_free_bcp_column_data(coldata);
1843 0 : return NULL;
1844 : }
1845 :
1846 : void
1847 104855 : tds_free_bcp_column_data(BCPCOLDATA * coldata)
1848 : {
1849 104855 : if (!coldata)
1850 : return;
1851 :
1852 3186 : free(coldata->data);
1853 3186 : free(coldata);
1854 : }
1855 :
1856 : TDSBCPINFO *
1857 394 : tds_alloc_bcpinfo(void)
1858 : {
1859 : TDSBCPINFO *bcpinfo;
1860 :
1861 394 : TEST_MALLOC(bcpinfo, TDSBCPINFO);
1862 :
1863 788 : tds_dstr_init(&bcpinfo->hint);
1864 788 : tds_dstr_init(&bcpinfo->tablename);
1865 :
1866 394 : return bcpinfo;
1867 394 : Cleanup:
1868 : return NULL;
1869 : }
1870 :
1871 : void
1872 648 : tds_deinit_bcpinfo(TDSBCPINFO *bcpinfo)
1873 : {
1874 648 : tds_dstr_free(&bcpinfo->hint);
1875 648 : tds_dstr_free(&bcpinfo->tablename);
1876 648 : TDS_ZERO_FREE(bcpinfo->insert_stmt);
1877 648 : tds_free_results(bcpinfo->bindinfo);
1878 648 : bcpinfo->bindinfo = NULL;
1879 648 : TDS_ZERO_FREE(bcpinfo->sybase_colinfo);
1880 648 : bcpinfo->sybase_count = 0;
1881 648 : }
1882 :
1883 : void
1884 2738 : tds_free_bcpinfo(TDSBCPINFO *bcpinfo)
1885 : {
1886 2738 : if (bcpinfo) {
1887 394 : tds_deinit_bcpinfo(bcpinfo);
1888 394 : free(bcpinfo);
1889 : }
1890 2738 : }
1891 :
1892 : /**
1893 : * Reallocate a pointer and update it if success
1894 : * \param pp pointer to pointer to be reallocated
1895 : * \param new_size new size to be allocated
1896 : * \return new pointer allocated, NULL on failure
1897 : */
1898 : void *
1899 140271 : tds_realloc(void **pp, size_t new_size)
1900 : {
1901 : void *p;
1902 :
1903 : /* some implementation of malloc/realloc does not like size==0 */
1904 140271 : if (!new_size)
1905 0 : new_size = 1;
1906 :
1907 : /* use malloc if not allocated before, some implementations require it */
1908 140271 : if (*pp)
1909 55336 : p = realloc(*pp, new_size);
1910 : else
1911 84935 : p = malloc(new_size);
1912 :
1913 : /* update pointer only on success */
1914 140271 : if (p)
1915 140271 : *pp = p;
1916 :
1917 140271 : return p;
1918 : }
1919 :
1920 : void
1921 16 : tds_deinit_tvp(TDS_TVP *table)
1922 : {
1923 : TDS_TVP_ROW *tvp_row, *next_row;
1924 :
1925 16 : free(table->schema);
1926 16 : table->schema = NULL;
1927 16 : free(table->name);
1928 16 : table->name = NULL;
1929 32 : tds_free_param_results(table->metadata);
1930 16 : table->metadata = NULL;
1931 52 : for (tvp_row = table->row; tvp_row != NULL; tvp_row = next_row) {
1932 36 : next_row = tvp_row->next;
1933 36 : tds_free_tvp_row(tvp_row);
1934 36 : free(tvp_row);
1935 : }
1936 16 : table->row = NULL;
1937 16 : }
1938 :
1939 : /** @} */
|