src/dbapi/driver/ftds64/freetds/tds/mem.c

Go to the documentation of this file.
00001 /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
00002  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  Brian Bruns
00003  * Copyright (C) 2005 Frediano Ziglio
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Library General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public
00016  * License along with this library; if not, write to the
00017  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018  * Boston, MA 02111-1307, USA.
00019  */
00020 
00021 #if HAVE_CONFIG_H
00022 #include <config.h>
00023 #endif /* HAVE_CONFIG_H */
00024 
00025 #if HAVE_STDLIB_H
00026 #include <stdlib.h>
00027 #endif /* HAVE_STDLIB_H */
00028 
00029 #if HAVE_STRING_H
00030 #include <string.h>
00031 #endif /* HAVE_STRING_H */
00032 
00033 #if HAVE_UNISTD_H
00034 #include <unistd.h>
00035 #endif /* HAVE_UNISTD_H */
00036 
00037 #include <assert.h>
00038 
00039 #include "tds.h"
00040 #include "tdsiconv.h"
00041 #include "tds_checks.h"
00042 #include "tdsstring.h"
00043 #include "replacements.h"
00044 #ifdef DMALLOC
00045 #include <dmalloc.h>
00046 #endif
00047 
00048 TDS_RCSID(var, "$Id: mem.c 174726 2009-10-30 13:43:52Z ivanovp $");
00049 
00050 static void tds_free_env(TDSSOCKET * tds);
00051 static void tds_free_compute_results(TDSSOCKET * tds);
00052 static void tds_free_compute_result(TDSCOMPUTEINFO * comp_info);
00053 
00054 #undef TEST_MALLOC
00055 #define TEST_MALLOC(dest,type) \
00056     {if (!(dest = (type*)malloc(sizeof(type)))) goto Cleanup;}
00057 
00058 #undef TEST_CALLOC
00059 #define TEST_CALLOC(dest,type,n) \
00060     {if (!(dest = (type*)calloc((n), sizeof(type)))) goto Cleanup;}
00061 
00062 #undef TEST_STRDUP
00063 #define TEST_STRDUP(dest,str) \
00064     {if (!(dest = strdup(str))) goto Cleanup;}
00065 
00066 /**
00067  * \ingroup libtds
00068  * \defgroup mem Memory allocation
00069  * Allocate or free resources. Allocation can fail only on out of memory.
00070  * In such case they return NULL and leave the state as before call.
00071  */
00072 
00073 /**
00074  * \addtogroup mem
00075  * \@{
00076  */
00077 
00078 /**
00079  * \fn TDSDYNAMIC *tds_alloc_dynamic(TDSSOCKET *tds, const char *id)
00080  * \brief Allocate a dynamic statement.
00081  * \param tds the connection within which to allocate the statement.
00082  * \param id a character label identifying the statement.
00083  * \return a pointer to the allocated structure (NULL on failure).
00084  *
00085  * tds_alloc_dynamic is used to implement placeholder code under TDS 5.0
00086  */
00087 TDSDYNAMIC *
00088 tds_alloc_dynamic(TDSSOCKET * tds, const char *id)
00089 {
00090     TDSDYNAMIC *dyn, *curr;
00091 
00092     /* check to see if id already exists (shouldn't) */
00093     for (curr = tds->dyns; curr != NULL; curr = curr->next)
00094         if (!strcmp(curr->id, id)) {
00095             /* id already exists! just return it */
00096             return curr;
00097         }
00098 
00099         dyn = (TDSDYNAMIC *) malloc(sizeof(TDSDYNAMIC));
00100         if (!dyn)
00101             return NULL;
00102         memset(dyn, 0, sizeof(TDSDYNAMIC));
00103 
00104     /* insert into list */
00105     dyn->next = tds->dyns;
00106     tds->dyns = dyn;
00107 
00108     tds_strlcpy(dyn->id, id, TDS_MAX_DYNID_LEN);
00109 
00110     return dyn;
00111 }
00112 
00113 /**
00114  * \fn void tds_free_input_params(TDSDYNAMIC *dyn)
00115  * \brief Frees all allocated input parameters of a dynamic statement.
00116  * \param dyn the dynamic statement whose input parameter are to be freed
00117  *
00118  * tds_free_input_params frees all parameters for the give dynamic statement
00119  */
00120 void
00121 tds_free_input_params(TDSDYNAMIC * dyn)
00122 {
00123     TDSPARAMINFO *info;
00124 
00125     info = dyn->params;
00126     if (info) {
00127         tds_free_param_results(info);
00128         dyn->params = NULL;
00129     }
00130 }
00131 
00132 /**
00133  * \fn void tds_free_dynamic(TDSSOCKET *tds, TDSDYNAMIC *dyn)
00134  * \brief Frees dynamic statement and remove from TDS
00135  * \param tds state information for the socket and the TDS protocol
00136  * \param dyn dynamic statement to be freed.
00137  */
00138 void
00139 tds_free_dynamic(TDSSOCKET * tds, TDSDYNAMIC * dyn)
00140 {
00141     TDSDYNAMIC **pcurr;
00142 
00143     /* avoid pointer to garbage */
00144     if (tds->cur_dyn == dyn)
00145         tds->cur_dyn = NULL;
00146 
00147     if (tds->current_results == dyn->res_info)
00148         tds->current_results = NULL;
00149 
00150     /* free from tds */
00151     for (pcurr = &tds->dyns; *pcurr != NULL; pcurr = &(*pcurr)->next)
00152         if (dyn == *pcurr) {
00153             *pcurr = dyn->next;
00154             break;
00155         }
00156 
00157     tds_free_results(dyn->res_info);
00158     tds_free_input_params(dyn);
00159     if (dyn->query)
00160         free(dyn->query);
00161     free(dyn);
00162 }
00163 
00164 /**
00165  * \fn TDSPARAMINFO *tds_alloc_param_result(TDSPARAMINFO *old_param)
00166  * \brief Adds a output parameter to TDSPARAMINFO.
00167  * \param old_param a pointer to the TDSPARAMINFO structure containing the
00168  * current set of output parameter, or NULL if none exists.
00169  * \return a pointer to the new TDSPARAMINFO structure.
00170  *
00171  * tds_alloc_param_result() works a bit differently than the other alloc result
00172  * functions.  Output parameters come in individually with no total number
00173  * given in advance, so we simply call this func every time with get a
00174  * TDS_PARAM_TOKEN and let it realloc the columns struct one bigger.
00175  * tds_free_all_results() usually cleans up after us.
00176  */
00177 TDSPARAMINFO *
00178 tds_alloc_param_result(TDSPARAMINFO * old_param)
00179 {
00180     TDSPARAMINFO *param_info;
00181     TDSCOLUMN *colinfo;
00182     TDSCOLUMN **cols;
00183 
00184     colinfo = (TDSCOLUMN *) malloc(sizeof(TDSCOLUMN));
00185     if (!colinfo)
00186         return NULL;
00187     memset(colinfo, 0, sizeof(TDSCOLUMN));
00188 
00189     if (!old_param || !old_param->num_cols) {
00190         cols = (TDSCOLUMN **) malloc(sizeof(TDSCOLUMN *));
00191     } else {
00192         cols = (TDSCOLUMN **) realloc(old_param->columns, sizeof(TDSCOLUMN *) * (old_param->num_cols + 1));
00193     }
00194     if (!cols)
00195         goto Cleanup;
00196 
00197     if (!old_param) {
00198         param_info = (TDSPARAMINFO *) malloc(sizeof(TDSPARAMINFO));
00199         if (!param_info) {
00200             free(cols);
00201             goto Cleanup;
00202         }
00203         memset(param_info, '\0', sizeof(TDSPARAMINFO));
00204         param_info->ref_count = 1;
00205     } else {
00206         param_info = old_param;
00207     }
00208     param_info->columns = cols;
00209     param_info->columns[param_info->num_cols++] = colinfo;
00210     return param_info;
00211       Cleanup:
00212     free(colinfo);
00213     return NULL;
00214 }
00215 
00216 /**
00217  * Delete latest parameter
00218  */
00219 void
00220 tds_free_param_result(TDSPARAMINFO * param_info)
00221 {
00222     TDSCOLUMN *col;
00223 
00224     if (!param_info || param_info->num_cols <= 0)
00225         return;
00226 
00227     col = param_info->columns[--param_info->num_cols];
00228     if (param_info->current_row && is_blob_type(col->column_type)) {
00229         TDSBLOB *blob = (TDSBLOB *) &(param_info->current_row[col->column_offset]);
00230         if (blob->textvalue)
00231             free(blob->textvalue);
00232     }
00233 
00234     param_info->row_size = col->column_offset;
00235     if (param_info->current_row) {
00236         if (param_info->row_size)
00237             param_info->current_row = realloc(param_info->current_row, param_info->row_size);
00238         else
00239             TDS_ZERO_FREE(param_info->current_row);
00240     }
00241 
00242     if (param_info->num_cols == 0 && param_info->columns)
00243         TDS_ZERO_FREE(param_info->columns);
00244 
00245     /*
00246      * NOTE some informations should be freed too but when this function
00247      * is called are not used. I hope to remove the need for this
00248      * function ASAP
00249      * A better way is to support different way to allocate and get
00250      * parameters
00251      * -- freddy77
00252      */
00253     free(col);
00254 }
00255 
00256 /**
00257  * Add another field to row. Is assumed that last TDSCOLUMN contain information about this.
00258  * Update also info structure.
00259  * @param info     parameters info where is contained row
00260  * @param curparam parameter to retrieve size information
00261  * @return NULL on failure or new row
00262  */
00263 unsigned char *
00264 tds_alloc_param_row(TDSPARAMINFO * info, TDSCOLUMN * curparam)
00265 {
00266     TDS_INT row_size;
00267     unsigned char *row;
00268 
00269     CHECK_COLUMN_EXTRA(curparam);
00270 #if ENABLE_EXTRA_CHECKS
00271     assert(info->row_size % TDS_ALIGN_SIZE == 0);
00272 #endif
00273 
00274     curparam->column_offset = info->row_size;
00275     if (is_numeric_type(curparam->column_type)) {
00276         row_size = sizeof(TDS_NUMERIC);
00277     } else if (is_blob_type(curparam->column_type)) {
00278         row_size = sizeof(TDSBLOB);
00279     } else {
00280         row_size = curparam->column_size;
00281     }
00282     row_size += info->row_size + (TDS_ALIGN_SIZE - 1);
00283     row_size -= row_size % TDS_ALIGN_SIZE;
00284 
00285 
00286 #if ENABLE_EXTRA_CHECKS
00287     assert((row_size % TDS_ALIGN_SIZE) == 0);
00288 #endif
00289 
00290     /* make sure the row buffer is big enough */
00291     if (info->current_row) {
00292         if (row_size > 0 && row_size > info->row_size) {
00293             row = (unsigned char *) realloc(info->current_row, row_size);
00294         } else {
00295             row = info->current_row;
00296         }
00297     } else {
00298         row = (unsigned char *) malloc(row_size);
00299     }
00300     if (!row)
00301         return NULL;
00302     /* if is a blob reset buffer */
00303     if (is_blob_type(curparam->column_type))
00304         memset(row + info->row_size, 0, sizeof(TDSBLOB));
00305     info->current_row = row;
00306     info->row_size = row_size;
00307 
00308     CHECK_PARAMINFO_EXTRA(info);
00309 
00310     return row;
00311 }
00312 
00313 /**
00314  * Allocate memory for storing compute info
00315  * return NULL on out of memory
00316  */
00317 
00318 static TDSCOMPUTEINFO *
00319 tds_alloc_compute_result(int num_cols, int by_cols)
00320 {
00321     int col;
00322     TDSCOMPUTEINFO *info;
00323 
00324     TEST_MALLOC(info, TDSCOMPUTEINFO);
00325     memset(info, '\0', sizeof(TDSCOMPUTEINFO));
00326     info->ref_count = 1;
00327 
00328     TEST_CALLOC(info->columns, TDSCOLUMN *, num_cols);
00329 
00330     tdsdump_log(TDS_DBG_INFO1, "alloc_compute_result. point 1\n");
00331     info->num_cols = num_cols;
00332     for (col = 0; col < num_cols; col++) {
00333         TEST_MALLOC(info->columns[col], TDSCOLUMN);
00334         memset(info->columns[col], '\0', sizeof(TDSCOLUMN));
00335     }
00336 
00337     tdsdump_log(TDS_DBG_INFO1, "alloc_compute_result. point 2\n");
00338 
00339     if (by_cols) {
00340         TEST_CALLOC(info->bycolumns, TDS_SMALLINT, by_cols);
00341         tdsdump_log(TDS_DBG_INFO1, "alloc_compute_result. point 3\n");
00342         info->by_cols = by_cols;
00343     }
00344 
00345     return info;
00346       Cleanup:
00347     tds_free_compute_result(info);
00348     return NULL;
00349 }
00350 
00351 TDSCOMPUTEINFO **
00352 tds_alloc_compute_results(TDSSOCKET * tds, int num_cols, int by_cols)
00353 {
00354     int n;
00355     TDSCOMPUTEINFO **comp_info;
00356     TDSCOMPUTEINFO *cur_comp_info;
00357 
00358     tdsdump_log(TDS_DBG_INFO1, "alloc_compute_result. num_cols = %d bycols = %d\n", num_cols, by_cols);
00359     tdsdump_log(TDS_DBG_INFO1, "alloc_compute_result. num_comp_info = %d\n", tds->num_comp_info);
00360 
00361     cur_comp_info = tds_alloc_compute_result(num_cols, by_cols);
00362     if (!cur_comp_info)
00363         return NULL;
00364 
00365     n = tds->num_comp_info;
00366     if (n == 0)
00367         comp_info = (TDSCOMPUTEINFO **) malloc(sizeof(TDSCOMPUTEINFO *));
00368     else
00369         comp_info = (TDSCOMPUTEINFO **) realloc(tds->comp_info, sizeof(TDSCOMPUTEINFO *) * (n + 1));
00370 
00371     if (!comp_info) {
00372         tds_free_compute_result(cur_comp_info);
00373         return NULL;
00374     }
00375 
00376     tds->comp_info = comp_info;
00377     comp_info[n] = cur_comp_info;
00378     tds->num_comp_info = n + 1;
00379 
00380     tdsdump_log(TDS_DBG_INFO1, "alloc_compute_result. num_comp_info = %d\n", tds->num_comp_info);
00381 
00382     return comp_info;
00383 }
00384 
00385 TDSRESULTINFO *
00386 tds_alloc_results(int num_cols)
00387 {
00388     TDSRESULTINFO *res_info;
00389     int col;
00390 
00391     TEST_MALLOC(res_info, TDSRESULTINFO);
00392     memset(res_info, '\0', sizeof(TDSRESULTINFO));
00393     res_info->ref_count = 1;
00394     TEST_CALLOC(res_info->columns, TDSCOLUMN *, num_cols);
00395     for (col = 0; col < num_cols; col++) {
00396         TEST_MALLOC(res_info->columns[col], TDSCOLUMN);
00397         memset(res_info->columns[col], '\0', sizeof(TDSCOLUMN));
00398     }
00399     res_info->num_cols = num_cols;
00400     res_info->row_size = 0;
00401     return res_info;
00402       Cleanup:
00403     tds_free_results(res_info);
00404     return NULL;
00405 }
00406 
00407 /**
00408  * Allocate space for row store
00409  * return NULL on out of memory
00410  */
00411 unsigned char *
00412 tds_alloc_row(TDSRESULTINFO * res_info)
00413 {
00414     unsigned char *ptr;
00415 
00416     ptr = (unsigned char *) malloc(res_info->row_size);
00417     if (ptr)
00418         memset(ptr, '\0', res_info->row_size);
00419     return ptr;
00420 }
00421 
00422 unsigned char *
00423 tds_alloc_compute_row(TDSCOMPUTEINFO * res_info)
00424 {
00425     unsigned char *ptr;
00426 
00427     ptr = (unsigned char *) malloc(res_info->row_size);
00428     if (ptr)
00429         memset(ptr, '\0', res_info->row_size);
00430     return ptr;
00431 }
00432 
00433 void
00434 tds_free_param_results(TDSPARAMINFO * param_info)
00435 {
00436     tds_free_results(param_info);
00437 }
00438 
00439 static void
00440 tds_free_compute_result(TDSCOMPUTEINFO * comp_info)
00441 {
00442     tds_free_results(comp_info);
00443 }
00444 
00445 static void
00446 tds_free_compute_results(TDSSOCKET * tds)
00447 {
00448     int i;
00449     TDSCOMPUTEINFO ** comp_info = tds->comp_info;
00450     TDS_INT num_comp = tds->num_comp_info;
00451 
00452     tds->comp_info = NULL;
00453     tds->num_comp_info = 0;
00454 
00455     for (i = 0; i < num_comp; i++) {
00456         if (comp_info && comp_info[i]) {
00457             if (tds->current_results == comp_info[i])
00458                 tds->current_results = NULL;
00459             tds_free_compute_result(comp_info[i]);
00460         }
00461     }
00462     if (num_comp)
00463         free(comp_info);
00464 }
00465 
00466 void
00467 tds_free_row(const TDSRESULTINFO * res_info, unsigned char *row)
00468 {
00469     int i;
00470     const TDSCOLUMN *curcol;
00471 
00472     assert(res_info);
00473     if (!row)
00474         return;
00475 
00476     for (i = 0; i < res_info->num_cols; ++i) {
00477         curcol = res_info->columns[i];
00478         if (is_blob_type(curcol->column_type))
00479             free(((TDSBLOB *) (row + curcol->column_offset))->textvalue);
00480     }
00481 
00482     free(row);
00483 }
00484 
00485 void
00486 tds_free_results(TDSRESULTINFO * res_info)
00487 {
00488     int i;
00489     TDSCOLUMN *curcol;
00490 
00491     if (!res_info)
00492         return;
00493 
00494     if (--res_info->ref_count != 0)
00495         return;
00496 
00497     if (res_info->num_cols && res_info->columns) {
00498         for (i = 0; i < res_info->num_cols; i++)
00499             if ((curcol = res_info->columns[i]) != NULL) {
00500                 if (curcol->bcp_terminator)
00501                     free(curcol->bcp_terminator);
00502                 tds_free_bcp_column_data(curcol->bcp_column_data);
00503                 if (res_info->current_row && is_blob_type(curcol->column_type)) {
00504                     /* ssikorsk */
00505                     TDSBLOB* blob = (TDSBLOB *) (res_info->current_row + curcol->column_offset);
00506                     if( blob->textvalue )
00507                     {
00508                         TDS_ZERO_FREE(blob->textvalue);
00509                     }
00510                     /* free(((TDSBLOB *) (res_info->current_row
00511                      * + curcol->column_offset))->textvalue);
00512                      * */
00513                 }
00514                 if (curcol->column_default)
00515                     free(curcol->column_default);
00516                 free(curcol);
00517             }
00518         free(res_info->columns);
00519     }
00520 
00521     if (res_info->current_row)
00522         free(res_info->current_row);
00523 
00524     if (res_info->bycolumns)
00525         free(res_info->bycolumns);
00526 
00527     free(res_info);
00528 }
00529 
00530 void
00531 tds_free_all_results(TDSSOCKET * tds)
00532 {
00533     tdsdump_log(TDS_DBG_FUNC, "tds_free_all_results()\n");
00534     if (tds->current_results == tds->res_info)
00535         tds->current_results = NULL;
00536     tds_free_results(tds->res_info);
00537     tds->res_info = NULL;
00538     if (tds->current_results == tds->param_info)
00539         tds->current_results = NULL;
00540     tds_free_param_results(tds->param_info);
00541     tds->param_info = NULL;
00542     tds_free_compute_results(tds);
00543     tds->has_status = 0;
00544     tds->ret_status = 0;
00545 }
00546 
00547 TDSCONTEXT *
00548 tds_alloc_context(void * parent)
00549 {
00550     TDSCONTEXT *context;
00551     TDSLOCALE *locale;
00552 
00553     locale = tds_get_locale();
00554     if (!locale)
00555         return NULL;
00556 
00557     context = (TDSCONTEXT *) malloc(sizeof(TDSCONTEXT));
00558     if (!context) {
00559         tds_free_locale(locale);
00560         return NULL;
00561     }
00562     memset(context, '\0', sizeof(TDSCONTEXT));
00563     context->locale = locale;
00564     context->parent = parent;
00565 
00566     return context;
00567 }
00568 
00569 void
00570 tds_free_context(TDSCONTEXT * context)
00571 {
00572     if (!context)
00573         return;
00574 
00575     tds_free_locale(context->locale);
00576     free(context);
00577 }
00578 
00579 TDSLOCALE *
00580 tds_alloc_locale(void)
00581 {
00582     TDSLOCALE *locale;
00583 
00584     locale = (TDSLOCALE *) malloc(sizeof(TDSLOCALE));
00585     if (!locale)
00586         return NULL;
00587     memset(locale, 0, sizeof(TDSLOCALE));
00588 
00589     return locale;
00590 }
00591 static const unsigned char defaultcaps[] = {
00592     0x01, 0x09, 0x00, 0x08, 0x06, 0x7D, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE,
00593     0x02, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x68, 0x00, 0x00, 0x00
00594 };
00595 
00596 /**
00597  * Allocate space for configure structure and initialize with default values
00598  * @param locale locale information (copied to configuration information)
00599  * @result allocated structure or NULL if out of memory
00600  */
00601 TDSCONNECTION *
00602 tds_alloc_connection(TDSLOCALE * locale)
00603 {
00604     TDSCONNECTION *connection;
00605     char hostname[128];
00606 
00607     TEST_MALLOC(connection, TDSCONNECTION);
00608     memset(connection, '\0', sizeof(TDSCONNECTION));
00609     tds_dstr_init(&connection->server_name);
00610     tds_dstr_init(&connection->language);
00611     tds_dstr_init(&connection->server_charset);
00612     tds_dstr_init(&connection->client_host_name);
00613     tds_dstr_init(&connection->app_name);
00614     tds_dstr_init(&connection->user_name);
00615     tds_dstr_init(&connection->password);
00616     tds_dstr_init(&connection->library);
00617     tds_dstr_init(&connection->ip_addr);
00618     tds_dstr_init(&connection->database);
00619     tds_dstr_init(&connection->dump_file);
00620     tds_dstr_init(&connection->client_charset);
00621     tds_dstr_init(&connection->instance_name);
00622 
00623     /* fill in all hardcoded defaults */
00624     if (!tds_dstr_copy(&connection->server_name, TDS_DEF_SERVER))
00625         goto Cleanup;
00626     connection->major_version = TDS_DEF_MAJOR;
00627     connection->minor_version = TDS_DEF_MINOR;
00628     connection->port = TDS_DEF_PORT;
00629     connection->block_size = 0;
00630     /* TODO use system default ?? */
00631     if (!tds_dstr_copy(&connection->client_charset, "ISO-8859-1"))
00632         goto Cleanup;
00633     if (locale) {
00634         if (locale->language)
00635             if (!tds_dstr_copy(&connection->language, locale->language))
00636                 goto Cleanup;
00637         if (locale->server_charset)
00638             if (!tds_dstr_copy(&connection->server_charset, locale->server_charset))
00639                 goto Cleanup;
00640     }
00641     if (tds_dstr_isempty(&connection->language)) {
00642         if (!tds_dstr_copy(&connection->language, TDS_DEF_LANG))
00643             goto Cleanup;
00644     }
00645     memset(hostname, '\0', sizeof(hostname));
00646     gethostname(hostname, sizeof(hostname));
00647     hostname[sizeof(hostname) - 1] = '\0';  /* make sure it's truncated */
00648     if (!tds_dstr_copy(&connection->client_host_name, hostname))
00649         goto Cleanup;
00650 
00651     memcpy(connection->capabilities, defaultcaps, TDS_MAX_CAPABILITY);
00652     return connection;
00653       Cleanup:
00654     tds_free_connection(connection);
00655     return NULL;
00656 }
00657 
00658 TDSCURSOR *
00659 tds_alloc_cursor(TDSSOCKET *tds, const char *name, TDS_INT namelen, const char *query, TDS_INT querylen)
00660 {
00661     TDSCURSOR *cursor;
00662     TDSCURSOR *pcursor;
00663 
00664     TEST_MALLOC(cursor, TDSCURSOR);
00665     memset(cursor, '\0', sizeof(TDSCURSOR));
00666     cursor->ref_count = 1;
00667 
00668     if ( tds->cursors == NULL ) {
00669         tds->cursors = cursor;
00670     } else {
00671         pcursor = tds->cursors;
00672         for (;;) {
00673             tdsdump_log(TDS_DBG_FUNC, "tds_alloc_cursor() : stepping thru existing cursors\n");
00674             if (pcursor->next == NULL)
00675                 break;
00676             pcursor = pcursor->next;
00677         }
00678         pcursor->next = cursor;
00679     }
00680     /* take into account reference in tds list */
00681     ++cursor->ref_count;
00682 
00683     TEST_CALLOC(cursor->cursor_name, char, namelen + 1);
00684 
00685     strcpy(cursor->cursor_name, name);
00686     cursor->cursor_name_len = namelen;
00687 
00688     TEST_CALLOC(cursor->query, char, querylen + 1);
00689 
00690     strcpy(cursor->query, query);
00691     cursor->query_len = querylen;
00692 
00693     return cursor;
00694 
00695       Cleanup:
00696     if (cursor)
00697         tds_free_cursor(tds, cursor);
00698         
00699    /* 0.95
00700     if (cursor)
00701         tds_cursor_deallocated(tds, cursor);
00702     tds_release_cursor(tds, cursor);
00703     */
00704     return NULL;
00705 }
00706 
00707 void
00708 tds_free_cursor(TDSSOCKET *tds, TDSCURSOR *cursor)
00709 {
00710     TDSCURSOR *victim = NULL;
00711     TDSCURSOR *prev = NULL;
00712     TDSCURSOR *next = NULL;
00713 
00714     tdsdump_log(TDS_DBG_FUNC, "tds_free_cursor() : freeing cursor_id %d\n", cursor->cursor_id);
00715     victim = tds->cursors;
00716 
00717     if (tds->cur_cursor == cursor)
00718         tds->cur_cursor = NULL;
00719 
00720     if (tds->current_results == cursor->res_info)
00721         tds->current_results = NULL;
00722 
00723     if (victim == NULL) {
00724         tdsdump_log(TDS_DBG_FUNC, "tds_free_cursor() : no allocated cursors %d\n", cursor->cursor_id);
00725         return;
00726     }
00727 
00728     for (;;) {
00729         if (victim == cursor)
00730             break;
00731         prev = victim;
00732         victim = victim->next;
00733         if (victim == NULL) {
00734             tdsdump_log(TDS_DBG_FUNC, "tds_free_cursor() : cannot find cursor_id %d\n", cursor->cursor_id);
00735             return;
00736         }
00737     }
00738 
00739     tdsdump_log(TDS_DBG_FUNC, "tds_free_cursor() : cursor_id %d found\n", cursor->cursor_id);
00740 
00741     next = victim->next;
00742 
00743     if (victim->cursor_name) {
00744         tdsdump_log(TDS_DBG_FUNC, "tds_free_cursor() : freeing cursor name\n");
00745         free(victim->cursor_name);
00746     }
00747 
00748     if (victim->query) {
00749         tdsdump_log(TDS_DBG_FUNC, "tds_free_cursor() : freeing cursor query\n");
00750         free(victim->query);
00751     }
00752 
00753     tdsdump_log(TDS_DBG_FUNC, "tds_free_cursor() : freeing cursor results\n");
00754     if (victim->res_info == tds->current_results)
00755         tds->current_results = NULL;
00756     tds_free_results(victim->res_info);
00757 
00758     tdsdump_log(TDS_DBG_FUNC, "tds_free_cursor() : relinking list\n");
00759 
00760     if (prev)
00761         prev->next = next;
00762     else
00763         tds->cursors = next;
00764 
00765     tdsdump_log(TDS_DBG_FUNC, "tds_free_cursor() : relinked list\n");
00766     tdsdump_log(TDS_DBG_FUNC, "tds_free_cursor() : cursor_id %d freed\n", cursor->cursor_id);
00767 
00768     free(victim);
00769 }
00770 
00771 void
00772 tds_cursor_deallocated(TDSSOCKET *tds, TDSCURSOR *cursor)
00773 {
00774     TDSCURSOR *victim = NULL;
00775     TDSCURSOR *prev = NULL;
00776     TDSCURSOR *next = NULL;
00777 
00778     tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : freeing cursor_id %d\n", cursor->cursor_id);
00779 
00780     if (tds->cur_cursor == cursor) {
00781         tds_release_cursor(tds, cursor);
00782         tds->cur_cursor = NULL;
00783     }
00784 
00785     victim = tds->cursors;
00786 
00787     if (victim == NULL) {
00788         tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : no allocated cursors %d\n", cursor->cursor_id);
00789         return;
00790     }
00791 
00792     for (;;) {
00793         if (victim == cursor)
00794             break;
00795         prev = victim;
00796         victim = victim->next;
00797         if (victim == NULL) {
00798             tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : cannot find cursor_id %d\n", cursor->cursor_id);
00799             return;
00800         }
00801     }
00802 
00803     tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : cursor_id %d found\n", cursor->cursor_id);
00804 
00805     next = victim->next;
00806 
00807     tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : relinking list\n");
00808 
00809     if (prev)
00810         prev->next = next;
00811     else
00812         tds->cursors = next;
00813 
00814     tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : relinked list\n");
00815 
00816     tds_release_cursor(tds, cursor);
00817 }
00818 
00819 
00820 void
00821 tds_release_cursor(TDSSOCKET *tds, TDSCURSOR *cursor)
00822 {
00823     if (!cursor || --cursor->ref_count > 0)
00824         return;
00825 
00826     tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor_id %d\n", cursor->cursor_id);
00827 
00828     tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor results\n");
00829     if (tds->current_results == cursor->res_info)
00830         tds->current_results = NULL;
00831     tds_free_results(cursor->res_info);
00832 
00833     if (cursor->cursor_name) {
00834         tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor name\n");
00835         free(cursor->cursor_name);
00836     }
00837 
00838     if (cursor->query) {
00839         tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor query\n");
00840         free(cursor->query);
00841     }
00842 
00843     tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : cursor_id %d freed\n", cursor->cursor_id);
00844     free(cursor);
00845 }
00846 
00847 TDSLOGIN *
00848 tds_alloc_login(void)
00849 {
00850     TDSLOGIN *tds_login;
00851 
00852     tds_login = (TDSLOGIN *) malloc(sizeof(TDSLOGIN));
00853     if (!tds_login)
00854         return NULL;
00855     memset(tds_login, '\0', sizeof(TDSLOGIN));
00856     tds_dstr_init(&tds_login->server_name);
00857     tds_dstr_init(&tds_login->server_addr);
00858     tds_dstr_init(&tds_login->language);
00859     tds_dstr_init(&tds_login->server_charset);
00860     tds_dstr_init(&tds_login->client_host_name);
00861     tds_dstr_init(&tds_login->app_name);
00862     tds_dstr_init(&tds_login->user_name);
00863     tds_dstr_init(&tds_login->password);
00864     tds_dstr_init(&tds_login->library);
00865     tds_dstr_init(&tds_login->client_charset);
00866     memcpy(tds_login->capabilities, defaultcaps, TDS_MAX_CAPABILITY);
00867     return tds_login;
00868 }
00869 
00870 void
00871 tds_free_login(TDSLOGIN * login)
00872 {
00873     if (login) {
00874         /* for security reason clear memory */
00875         tds_dstr_zero(&login->password);
00876         tds_dstr_free(&login->password);
00877         tds_dstr_free(&login->server_name);
00878         tds_dstr_free(&login->server_addr);
00879         tds_dstr_free(&login->language);
00880         tds_dstr_free(&login->server_charset);
00881         tds_dstr_free(&login->client_host_name);
00882         tds_dstr_free(&login->app_name);
00883         tds_dstr_free(&login->user_name);
00884         tds_dstr_free(&login->library);
00885         tds_dstr_free(&login->client_charset);
00886         free(login);
00887     }
00888 }
00889 TDSSOCKET *
00890 tds_alloc_socket(TDSCONTEXT * context, int bufsize)
00891 {
00892     TDSSOCKET *tds_socket;
00893 
00894     TEST_MALLOC(tds_socket, TDSSOCKET);
00895     memset(tds_socket, '\0', sizeof(TDSSOCKET));
00896     tds_socket->tds_ctx = context;
00897     tds_socket->in_buf_max = 0;
00898     TEST_CALLOC(tds_socket->out_buf, unsigned char, bufsize + TDS_ADDITIONAL_SPACE);
00899 
00900     tds_socket->parent = NULL;
00901     /*
00902      * TDS 7.0:
00903      * 0x02 indicates ODBC driver
00904      * 0x01 means change to initial language must succeed
00905      */
00906     tds_socket->option_flag2 = 0x03;
00907     tds_socket->env.block_size = bufsize;
00908 
00909     if (tds_iconv_alloc(tds_socket))
00910         goto Cleanup;
00911 
00912     /* Jeff's hack, init to no timeout */
00913     tds_socket->query_timeout = 0;
00914     tds_init_write_buf(tds_socket);
00915     tds_socket->s = INVALID_SOCKET;
00916     tds_socket->env_chg_func = NULL;
00917     return tds_socket;
00918       Cleanup:
00919     tds_free_socket(tds_socket);
00920     return NULL;
00921 }
00922 
00923 TDSSOCKET *
00924 tds_realloc_socket(TDSSOCKET * tds, int bufsize)
00925 {
00926     unsigned char *new_out_buf;
00927 
00928     assert(tds && tds->out_buf);
00929 
00930     if (tds->env.block_size == bufsize)
00931         return tds;
00932 
00933     if ((new_out_buf = (unsigned char *) realloc(tds->out_buf, bufsize + TDS_ADDITIONAL_SPACE)) != NULL) {
00934         tds->out_buf = new_out_buf;
00935         tds->env.block_size = bufsize;
00936         return tds;
00937     }
00938     return NULL;
00939 }
00940 
00941 void
00942 tds_free_socket(TDSSOCKET * tds)
00943 {
00944     if (tds) {
00945         tds_free_all_results(tds);
00946         tds_free_env(tds);
00947         while (tds->dyns)
00948             tds_free_dynamic(tds, tds->dyns);
00949         while (tds->cursors)
00950             tds_free_cursor(tds, tds->cursors);
00951             /* tds_cursor_deallocated(tds, tds->cursors); 0.95 */
00952         if (tds->in_buf)
00953             free(tds->in_buf);
00954         if (tds->out_buf)
00955             free(tds->out_buf);
00956 #ifdef NCBI_FTDS_ALLOW_TDS_80
00957 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
00958         tds_ssl_deinit(tds);
00959 #endif
00960 #endif
00961         tds_close_socket(tds);
00962         if (tds->date_fmt)
00963             free(tds->date_fmt);
00964         tds_iconv_free(tds);
00965         if (tds->product_name)
00966             free(tds->product_name);
00967         free(tds);
00968     }
00969 }
00970 void
00971 tds_free_locale(TDSLOCALE * locale)
00972 {
00973     if (!locale)
00974         return;
00975 
00976     if (locale->language)
00977         free(locale->language);
00978     if (locale->server_charset)
00979         free(locale->server_charset);
00980     if (locale->date_fmt)
00981         free(locale->date_fmt);
00982     free(locale);
00983 }
00984 
00985 void
00986 tds_free_connection(TDSCONNECTION * connection)
00987 {
00988     tds_dstr_free(&connection->server_name);
00989     tds_dstr_free(&connection->client_host_name);
00990     tds_dstr_free(&connection->language);
00991     tds_dstr_free(&connection->server_charset);
00992     tds_dstr_free(&connection->ip_addr);
00993     tds_dstr_free(&connection->database);
00994     tds_dstr_free(&connection->dump_file);
00995     tds_dstr_free(&connection->client_charset);
00996     tds_dstr_free(&connection->app_name);
00997     tds_dstr_free(&connection->user_name);
00998     /* cleared for security reason */
00999     tds_dstr_zero(&connection->password);
01000     tds_dstr_free(&connection->password);
01001     tds_dstr_free(&connection->library);
01002     tds_dstr_free(&connection->instance_name);
01003     free(connection);
01004 }
01005 
01006 static void
01007 tds_free_env(TDSSOCKET * tds)
01008 {
01009     if (tds->env.language)
01010         TDS_ZERO_FREE(tds->env.language);
01011     if (tds->env.charset)
01012         TDS_ZERO_FREE(tds->env.charset);
01013     if (tds->env.database)
01014         TDS_ZERO_FREE(tds->env.database);
01015 }
01016 
01017 void
01018 tds_free_msg(TDSMESSAGE * message)
01019 {
01020     if (message) {
01021         message->priv_msg_type = 0;
01022         message->msgno = 0;
01023         message->state = 0;
01024         message->severity = 0;
01025         message->line_number = 0;
01026         if (message->message)
01027             TDS_ZERO_FREE(message->message);
01028         if (message->server)
01029             TDS_ZERO_FREE(message->server);
01030         if (message->proc_name)
01031             TDS_ZERO_FREE(message->proc_name);
01032         if (message->sql_state)
01033             TDS_ZERO_FREE(message->sql_state);
01034     }
01035 }
01036 
01037 #define SQLS_ENTRY(number,state) case number: p = state; break
01038 
01039 char *
01040 tds_alloc_client_sqlstate(int msgno)
01041 {
01042     char *p = NULL;
01043 
01044     switch (msgno) {
01045         SQLS_ENTRY(17000, "S1T00"); /* timeouts ??? */
01046         SQLS_ENTRY(20004, "08S01"); /* Communication link failure */
01047         SQLS_ENTRY(20006, "08S01");
01048         SQLS_ENTRY(20009, "08S01");
01049         SQLS_ENTRY(20020, "08S01");
01050         SQLS_ENTRY(20019, "24000"); /* Invalid cursor state */
01051         SQLS_ENTRY(20014, "28000"); /* Invalid authorization specification */
01052         SQLS_ENTRY(2400, "42000");  /* Syntax error or access violation */
01053         SQLS_ENTRY(2401, "42000");
01054         SQLS_ENTRY(2403, "42000");
01055         SQLS_ENTRY(2404, "42000");
01056         SQLS_ENTRY(2402, "S1000");  /* General error */
01057     }
01058 
01059     if (p != NULL)
01060         return strdup(p);
01061     else
01062         return NULL;
01063 }
01064 
01065 char *
01066 tds_alloc_lookup_sqlstate(TDSSOCKET * tds, int msgno)
01067 {
01068     const char *p = NULL;
01069     char *q = NULL;
01070 
01071     if (TDS_IS_MSSQL(tds)) {
01072         switch (msgno) {    /* MSSQL Server */
01073 
01074             SQLS_ENTRY(3621,"01000");
01075             SQLS_ENTRY(8153,"01003");   /* Null in aggregate */
01076             SQLS_ENTRY(911, "08004");   /* Server rejected connection */
01077             SQLS_ENTRY(512, "21000");   /* Subquery returns more than one value */
01078             SQLS_ENTRY(213, "21S01");   /* Insert column list mismatch */
01079             SQLS_ENTRY(109, "21S01");
01080             SQLS_ENTRY(110, "21S01");
01081             SQLS_ENTRY(1774,"21S02");   /* Ref column mismatch */
01082             SQLS_ENTRY(8152,"22001");   /* String data would be truncated */
01083             SQLS_ENTRY(5146,"22003");   /* Numeric value out of range */
01084             SQLS_ENTRY(168, "22003");   /* Arithmetic overflow */
01085             SQLS_ENTRY(220, "22003");
01086             SQLS_ENTRY(232, "22003");
01087             SQLS_ENTRY(234, "22003");
01088             SQLS_ENTRY(236, "22003");
01089             SQLS_ENTRY(238, "22003");
01090             SQLS_ENTRY(244, "22003");
01091             SQLS_ENTRY(246, "22003");
01092             SQLS_ENTRY(248, "22003");
01093             SQLS_ENTRY(519, "22003");
01094             SQLS_ENTRY(520, "22003");
01095             SQLS_ENTRY(521, "22003");
01096             SQLS_ENTRY(522, "22003");
01097             SQLS_ENTRY(523, "22003");
01098             SQLS_ENTRY(524, "22003");
01099             SQLS_ENTRY(1007,"22003");
01100             SQLS_ENTRY(3606,"22003");
01101             SQLS_ENTRY(8115,"22003");
01102             SQLS_ENTRY(206, "22005");   /* Error in assignment */
01103             SQLS_ENTRY(235, "22005");
01104             SQLS_ENTRY(247, "22005");
01105             SQLS_ENTRY(249, "22005");
01106             SQLS_ENTRY(256, "22005");
01107             SQLS_ENTRY(257, "22005");
01108             SQLS_ENTRY(305, "22005");
01109             SQLS_ENTRY(409, "22005");
01110             SQLS_ENTRY(518, "22005");
01111             SQLS_ENTRY(529, "22005");
01112             SQLS_ENTRY(210, "22007");   /* Invalid datetime format */
01113             SQLS_ENTRY(241, "22007");
01114             SQLS_ENTRY(295, "22007");
01115             SQLS_ENTRY(242, "22008");   /* Datetime out of range */
01116             SQLS_ENTRY(296, "22008");
01117             SQLS_ENTRY(298, "22008");
01118             SQLS_ENTRY(535, "22008");
01119             SQLS_ENTRY(542, "22008");
01120             SQLS_ENTRY(517, "22008");
01121             SQLS_ENTRY(3607, "22012");  /* Div by zero */
01122             SQLS_ENTRY(8134, "22012");
01123             SQLS_ENTRY(245, "22018");   /* Syntax error? */
01124             SQLS_ENTRY(2627, "23000");  /* Constraint violation */
01125             SQLS_ENTRY(515, "23000");
01126             SQLS_ENTRY(233, "23000");
01127             SQLS_ENTRY(273, "23000");
01128             SQLS_ENTRY(530, "23000");
01129             SQLS_ENTRY(2601,"23000");
01130             SQLS_ENTRY(2615,"23000");
01131             SQLS_ENTRY(2626,"23000");
01132             SQLS_ENTRY(3604,"23000");
01133             SQLS_ENTRY(3605,"23000");
01134             SQLS_ENTRY(544, "23000");
01135             SQLS_ENTRY(547, "23000");
01136             SQLS_ENTRY(550, "23000");
01137             SQLS_ENTRY(4415, "23000");
01138             SQLS_ENTRY(1505, "23000");
01139             SQLS_ENTRY(1508, "23000");
01140             SQLS_ENTRY(3725, "23000");
01141             SQLS_ENTRY(3726, "23000");
01142             SQLS_ENTRY(4712, "23000");
01143             SQLS_ENTRY(10055, "23000");
01144             SQLS_ENTRY(10065, "23000");
01145             SQLS_ENTRY(11011, "23000");
01146             SQLS_ENTRY(11040, "23000");
01147             SQLS_ENTRY(16999, "24000"); /* Invalid cursor state */
01148             SQLS_ENTRY(16905, "24000");
01149             SQLS_ENTRY(16917, "24000");
01150             SQLS_ENTRY(16946, "24000");
01151             SQLS_ENTRY(16950, "24000");
01152             SQLS_ENTRY(266, "25000");   /* Invalid transaction state */
01153             SQLS_ENTRY(277,"25000");
01154             SQLS_ENTRY(611,"25000");
01155             SQLS_ENTRY(3906,"25000");
01156             SQLS_ENTRY(3908,"25000");
01157             SQLS_ENTRY(6401,"25000");
01158             SQLS_ENTRY(626, "25000");
01159             SQLS_ENTRY(627, "25000");
01160             SQLS_ENTRY(628, "25000");
01161             SQLS_ENTRY(3902, "25000");
01162             SQLS_ENTRY(3903, "25000");
01163             SQLS_ENTRY(3916, "25000");
01164             SQLS_ENTRY(3918, "25000");
01165             SQLS_ENTRY(3919, "25000");
01166             SQLS_ENTRY(3921, "25000");
01167             SQLS_ENTRY(3922, "25000");
01168             SQLS_ENTRY(3926, "25000");
01169             SQLS_ENTRY(7969, "25000");
01170             SQLS_ENTRY(8506, "25000");
01171             SQLS_ENTRY(15626, "25000");
01172             SQLS_ENTRY(18456, "28000"); /* Login failed? */
01173             SQLS_ENTRY(6104, "37000");  /* Syntax error or access violation */
01174             SQLS_ENTRY(8114, "37000");
01175             SQLS_ENTRY(131, "37000");
01176             SQLS_ENTRY(137, "37000");
01177             SQLS_ENTRY(170, "37000");
01178             SQLS_ENTRY(174, "37000");
01179             SQLS_ENTRY(201, "37000");
01180             SQLS_ENTRY(2812, "37000");
01181             SQLS_ENTRY(2526, "37000");
01182             SQLS_ENTRY(8144, "37000");
01183             SQLS_ENTRY(17308, "42000"); /* Syntax/Access violation */
01184             SQLS_ENTRY(17571, "42000");
01185             SQLS_ENTRY(18002, "42000");
01186             SQLS_ENTRY(229, "42000");
01187             SQLS_ENTRY(230, "42000");
01188             SQLS_ENTRY(262, "42000");
01189             SQLS_ENTRY(2557, "42000");
01190             SQLS_ENTRY(2571, "42000");
01191             SQLS_ENTRY(2760, "42000");
01192             SQLS_ENTRY(3110, "42000");
01193             SQLS_ENTRY(3704, "42000");
01194             SQLS_ENTRY(4613, "42000");
01195             SQLS_ENTRY(4618, "42000");
01196             SQLS_ENTRY(4834, "42000");
01197             SQLS_ENTRY(5011, "42000");
01198             SQLS_ENTRY(5116, "42000");
01199             SQLS_ENTRY(5812, "42000");
01200             SQLS_ENTRY(6004, "42000");
01201             SQLS_ENTRY(6102, "42000");
01202             SQLS_ENTRY(7956, "42000");
01203             SQLS_ENTRY(11010, "42000");
01204             SQLS_ENTRY(11045, "42000");
01205             SQLS_ENTRY(14126, "42000");
01206             SQLS_ENTRY(15247, "42000");
01207             SQLS_ENTRY(15622, "42000");
01208             SQLS_ENTRY(20604, "42000");
01209             SQLS_ENTRY(21049, "42000");
01210             SQLS_ENTRY(113, "42000");
01211             SQLS_ENTRY(2714, "42S01");  /* Table or view already exists */
01212             SQLS_ENTRY(208, "42S02");   /* Table or view not found */
01213             SQLS_ENTRY(3701, "42S02");
01214             SQLS_ENTRY(1913, "42S11");  /* Index already exists */
01215             SQLS_ENTRY(15605, "42S11");
01216             SQLS_ENTRY(307, "42S12");   /* Index not found */
01217             SQLS_ENTRY(308, "42S12");
01218             SQLS_ENTRY(10033, "42S12");
01219             SQLS_ENTRY(15323, "42S12");
01220             SQLS_ENTRY(18833, "42S12");
01221             SQLS_ENTRY(4925, "42S21");  /* Column already exists */
01222             SQLS_ENTRY(21255, "42S21");
01223             SQLS_ENTRY(1911, "42S22");  /* Column not found */
01224             SQLS_ENTRY(207, "42S22");
01225             SQLS_ENTRY(4924, "42S22");
01226             SQLS_ENTRY(4926, "42S22");
01227             SQLS_ENTRY(15645, "42S22");
01228             SQLS_ENTRY(21166, "42S22");
01229         }
01230     } else {
01231         switch (msgno) {    /* Sybase */
01232             SQLS_ENTRY(3621, "01000");
01233             SQLS_ENTRY(9501, "01003");  /* Null in aggregate */
01234             SQLS_ENTRY(911, "08004");   /* Server rejected connection */
01235             SQLS_ENTRY(512, "21000");   /* Subquery returns more than one value */
01236             SQLS_ENTRY(213, "21S01");   /* Insert column list mismatch */
01237             SQLS_ENTRY(109, "21S01");
01238             SQLS_ENTRY(110, "21S01");
01239             SQLS_ENTRY(1715, "21S02");  /* Ref column mismatch */
01240             SQLS_ENTRY(9502, "22001");  /* String data would be truncated */
01241             SQLS_ENTRY(220, "22003");   /* Arithmetic overflow */
01242             SQLS_ENTRY(168, "22003");
01243             SQLS_ENTRY(227, "22003");
01244             SQLS_ENTRY(232, "22003");
01245             SQLS_ENTRY(234, "22003");
01246             SQLS_ENTRY(236, "22003");
01247             SQLS_ENTRY(238, "22003");
01248             SQLS_ENTRY(244, "22003");
01249             SQLS_ENTRY(246, "22003");
01250             SQLS_ENTRY(247, "22003");
01251             SQLS_ENTRY(248, "22003");
01252             SQLS_ENTRY(519, "22003");
01253             SQLS_ENTRY(520, "22003");
01254             SQLS_ENTRY(521, "22003");
01255             SQLS_ENTRY(522, "22003");
01256             SQLS_ENTRY(523, "22003");
01257             SQLS_ENTRY(524, "22003");
01258             SQLS_ENTRY(3606, "22003");
01259             SQLS_ENTRY(206, "22005");   /* Error in assignment */
01260             SQLS_ENTRY(235, "22005");
01261             SQLS_ENTRY(249, "22005");
01262             SQLS_ENTRY(256, "22005");
01263             SQLS_ENTRY(305, "22005");
01264             SQLS_ENTRY(409, "22005");
01265             SQLS_ENTRY(518, "22005");
01266             SQLS_ENTRY(529, "22005");
01267             SQLS_ENTRY(535, "22008");   /* Datetime out of range */
01268             SQLS_ENTRY(542, "22008");
01269             SQLS_ENTRY(517, "22008");
01270             SQLS_ENTRY(3607, "22012");  /* Div by zero */
01271             SQLS_ENTRY(245, "22018");   /* Syntax error? */
01272             SQLS_ENTRY(544, "23000");   /* Constraint violation */
01273             SQLS_ENTRY(233, "23000");
01274             SQLS_ENTRY(273, "23000");
01275             SQLS_ENTRY(530, "23000");
01276             SQLS_ENTRY(2601,"23000");
01277             SQLS_ENTRY(2615,"23000");
01278             SQLS_ENTRY(2626,"23000");
01279             SQLS_ENTRY(3604,"23000");
01280             SQLS_ENTRY(3605,"23000");
01281             SQLS_ENTRY(545, "23000");
01282             SQLS_ENTRY(546, "23000");
01283             SQLS_ENTRY(547, "23000");
01284             SQLS_ENTRY(548, "23000");
01285             SQLS_ENTRY(549, "23000");
01286             SQLS_ENTRY(550, "23000");
01287             SQLS_ENTRY(1505, "23000");
01288             SQLS_ENTRY(1508, "23000");
01289             SQLS_ENTRY(565, "24000");   /* Invalid cursor state */
01290             SQLS_ENTRY(558, "24000");
01291             SQLS_ENTRY(559, "24000");
01292             SQLS_ENTRY(6235, "24000");
01293             SQLS_ENTRY(583, "24000");
01294             SQLS_ENTRY(6259, "24000");
01295             SQLS_ENTRY(6260, "24000");
01296             SQLS_ENTRY(562, "24000");
01297             SQLS_ENTRY(277, "25000");   /* Invalid transaction state */
01298             SQLS_ENTRY(611,"25000");
01299             SQLS_ENTRY(3906,"25000");
01300             SQLS_ENTRY(3908,"25000");
01301             SQLS_ENTRY(6401,"25000");
01302             SQLS_ENTRY(627, "25000");
01303             SQLS_ENTRY(628, "25000");
01304             SQLS_ENTRY(641, "25000");
01305             SQLS_ENTRY(642, "25000");
01306             SQLS_ENTRY(1276, "25000");
01307             SQLS_ENTRY(3902, "25000");
01308             SQLS_ENTRY(3903, "25000");
01309             SQLS_ENTRY(6104, "37000");  /* Syntax error or access violation */
01310             SQLS_ENTRY(102, "37000");
01311             SQLS_ENTRY(137, "37000");
01312             SQLS_ENTRY(7327, "37000");
01313             SQLS_ENTRY(201, "37000");
01314             SQLS_ENTRY(257, "37000");
01315             SQLS_ENTRY(2812, "37000");
01316             SQLS_ENTRY(2526, "37000");
01317             SQLS_ENTRY(11021, "37000");
01318             SQLS_ENTRY(229, "42000");   /* Syntax/Access violation */
01319             SQLS_ENTRY(230, "42000");
01320             SQLS_ENTRY(262, "42000");
01321             SQLS_ENTRY(4602, "42000");
01322             SQLS_ENTRY(4603, "42000");
01323             SQLS_ENTRY(4608, "42000");
01324             SQLS_ENTRY(10306, "42000");
01325             SQLS_ENTRY(10323, "42000");
01326             SQLS_ENTRY(10330, "42000");
01327             SQLS_ENTRY(10331, "42000");
01328             SQLS_ENTRY(10332, "42000");
01329             SQLS_ENTRY(11110, "42000");
01330             SQLS_ENTRY(11113, "42000");
01331             SQLS_ENTRY(11118, "42000");
01332             SQLS_ENTRY(11121, "42000");
01333             SQLS_ENTRY(17222, "42000");
01334             SQLS_ENTRY(17223, "42000");
01335             SQLS_ENTRY(18350, "42000");
01336             SQLS_ENTRY(18351, "42000");
01337             SQLS_ENTRY(113, "42000");
01338             SQLS_ENTRY(2714, "42S01");  /* Table or view already exists */
01339             SQLS_ENTRY(208, "42S02");   /* Table or view not found */
01340             SQLS_ENTRY(3701, "42S02");
01341             SQLS_ENTRY(1913, "42S11");  /* Index already exists */
01342             SQLS_ENTRY(307, "42S12");   /* Index not found */
01343             SQLS_ENTRY(7010, "42S12");
01344             SQLS_ENTRY(18091, "42S12");
01345             SQLS_ENTRY(1921, "42S21");  /* Column already exists */
01346             SQLS_ENTRY(1720, "42S22");  /* Column not found */
01347             SQLS_ENTRY(207, "42S22");
01348             SQLS_ENTRY(4934, "42S22");
01349             SQLS_ENTRY(18117, "42S22");
01350         }
01351     }
01352 
01353     if (p != NULL && (q = strdup(p)) != NULL) {
01354         /* FIXME correct here ?? */
01355         /* Convert known ODBC 3.x states listed above to 2.x */
01356         if (memcmp(q, "42S", 3) == 0)
01357             memcpy(q, "S00", 3);
01358 
01359         return q;
01360     }
01361     return NULL;
01362 }
01363 
01364 BCPCOLDATA *
01365 tds_alloc_bcp_column_data(int column_size)
01366 {
01367     BCPCOLDATA *coldata;
01368 
01369     TEST_MALLOC(coldata, BCPCOLDATA);
01370     memset(coldata, '\0', sizeof(BCPCOLDATA));
01371 
01372     TEST_CALLOC(coldata->data, unsigned char, column_size);
01373 
01374     return coldata;
01375 Cleanup:
01376     tds_free_bcp_column_data(coldata);
01377     return NULL;
01378 }
01379 
01380 void
01381 tds_free_bcp_column_data(BCPCOLDATA * coldata)
01382 {
01383     if (!coldata)
01384         return;
01385 
01386     if (coldata->data)
01387         free(coldata->data);
01388     free(coldata);
01389 }
01390 
01391 /** \@} */
01392 
01393 

Generated on Wed Dec 9 04:16:02 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Wed Dec 09 08:17:57 2009 by modify_doxy.py rev. 173732