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