1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 2003 Steve Murphree
3 : * Copyright (C) 2004, 2005 Ziglio Frediano
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 : #if HAVE_CONFIG_H
22 : #include <config.h>
23 : #endif /* HAVE_CONFIG_H */
24 :
25 : #include <stdio.h>
26 :
27 : #if HAVE_STDLIB_H
28 : #include <stdlib.h>
29 : #endif /* HAVE_STDLIB_H */
30 :
31 : #if HAVE_STRING_H
32 : #include <string.h>
33 : #endif /* HAVE_STRING_H */
34 :
35 : #include "tdsodbc.h"
36 : #include "tdsstring.h"
37 :
38 : #ifdef DMALLOC
39 : #include <dmalloc.h>
40 : #endif
41 :
42 : static void desc_free_record(struct _drecord *drec);
43 :
44 : TDS_DESC *
45 : desc_alloc(SQLHANDLE parent, int desc_type, int alloc_type)
46 516 : {
47 : TDS_DESC *desc;
48 :
49 516 : desc = (TDS_DESC *) malloc(sizeof(TDS_DESC));
50 516 : if (!desc)
51 0 : return NULL;
52 516 : memset(desc, 0, sizeof(TDS_DESC));
53 :
54 : /* set defualt header values */
55 516 : desc->htype = SQL_HANDLE_DESC;
56 516 : desc->type = desc_type;
57 516 : desc->parent = parent;
58 516 : desc->header.sql_desc_alloc_type = alloc_type;
59 516 : desc->header.sql_desc_count = 0;
60 516 : desc->records = NULL;
61 :
62 516 : switch (desc_type) {
63 : case DESC_IRD:
64 : case DESC_IPD:
65 258 : break;
66 : case DESC_ARD:
67 : case DESC_APD:
68 258 : desc->header.sql_desc_bind_type = SQL_BIND_BY_COLUMN;
69 258 : desc->header.sql_desc_array_size = 1;
70 258 : break;
71 : default:
72 0 : free(desc);
73 0 : return NULL;
74 : }
75 516 : return desc;
76 : }
77 :
78 : SQLRETURN
79 : desc_alloc_records(TDS_DESC * desc, unsigned count)
80 853 : {
81 : struct _drecord *drec, *drecs;
82 : int i;
83 :
84 : /* shrink records */
85 853 : if (desc->header.sql_desc_count >= count) {
86 14 : for (i = count; i < desc->header.sql_desc_count; ++i)
87 0 : desc_free_record(&desc->records[i]);
88 14 : desc->header.sql_desc_count = count;
89 14 : return SQL_SUCCESS;
90 : }
91 :
92 839 : if (desc->records)
93 114 : drecs = (struct _drecord *) realloc(desc->records, sizeof(struct _drecord) * (count + 0));
94 : else
95 725 : drecs = (struct _drecord *) malloc(sizeof(struct _drecord) * (count + 0));
96 839 : if (!drecs)
97 0 : return SQL_ERROR;
98 839 : desc->records = drecs;
99 839 : memset(desc->records + desc->header.sql_desc_count, 0, sizeof(struct _drecord) * (count - desc->header.sql_desc_count));
100 :
101 2719 : for (i = desc->header.sql_desc_count; i < count; ++i) {
102 1880 : drec = &desc->records[i];
103 :
104 1880 : tds_dstr_init(&drec->sql_desc_label);
105 1880 : tds_dstr_init(&drec->sql_desc_name);
106 1880 : tds_dstr_init(&drec->sql_desc_base_column_name);
107 1880 : tds_dstr_init(&drec->sql_desc_base_table_name);
108 1880 : tds_dstr_init(&drec->sql_desc_catalog_name);
109 1880 : tds_dstr_init(&drec->sql_desc_local_type_name);
110 1880 : tds_dstr_init(&drec->sql_desc_schema_name);
111 1880 : tds_dstr_init(&drec->sql_desc_table_name);
112 :
113 1880 : switch (desc->type) {
114 : case DESC_IRD:
115 : case DESC_IPD:
116 1526 : drec->sql_desc_parameter_type = SQL_PARAM_INPUT;
117 1526 : break;
118 : case DESC_ARD:
119 : case DESC_APD:
120 354 : drec->sql_desc_concise_type = SQL_C_DEFAULT;
121 354 : drec->sql_desc_type = SQL_C_DEFAULT;
122 : break;
123 : }
124 : }
125 839 : desc->header.sql_desc_count = count;
126 839 : return SQL_SUCCESS;
127 : }
128 :
129 : #define IF_FREE(x) if (x) {free(x); x = NULL;}
130 :
131 : static void
132 : desc_free_record(struct _drecord *drec)
133 1880 : {
134 1880 : tds_dstr_free(&drec->sql_desc_base_column_name);
135 1880 : tds_dstr_free(&drec->sql_desc_base_table_name);
136 1880 : tds_dstr_free(&drec->sql_desc_catalog_name);
137 1880 : tds_dstr_free(&drec->sql_desc_label);
138 1880 : tds_dstr_free(&drec->sql_desc_local_type_name);
139 1880 : tds_dstr_free(&drec->sql_desc_name);
140 1880 : tds_dstr_free(&drec->sql_desc_schema_name);
141 1880 : tds_dstr_free(&drec->sql_desc_table_name);
142 1880 : }
143 :
144 : SQLRETURN
145 : desc_free_records(TDS_DESC * desc)
146 2687 : {
147 : int i;
148 :
149 2687 : if (desc->records) {
150 2605 : for (i = 0; i < desc->header.sql_desc_count; i++)
151 1880 : desc_free_record(&desc->records[i]);
152 725 : TDS_ZERO_FREE(desc->records);
153 : }
154 :
155 2687 : desc->header.sql_desc_count = 0;
156 2687 : return SQL_SUCCESS;
157 : }
158 :
159 : SQLRETURN
160 : desc_copy(TDS_DESC * dest, TDS_DESC * src)
161 0 : {
162 : int i;
163 :
164 : /* first clear all records to free all strings */
165 0 : desc_free_records(dest);
166 0 : if (desc_alloc_records(dest, src->header.sql_desc_count) != SQL_SUCCESS)
167 0 : return SQL_ERROR;
168 0 : dest->header.sql_desc_bind_type = src->header.sql_desc_bind_type;
169 0 : dest->header.sql_desc_array_size = src->header.sql_desc_array_size;
170 0 : dest->header.sql_desc_array_status_ptr = src->header.sql_desc_array_status_ptr;
171 0 : dest->header.sql_desc_rows_processed_ptr = src->header.sql_desc_rows_processed_ptr;
172 0 : dest->header.sql_desc_bind_offset_ptr = src->header.sql_desc_bind_offset_ptr;
173 0 : if (!src->header.sql_desc_count)
174 0 : return SQL_SUCCESS;
175 :
176 0 : for (i = 0; i < src->header.sql_desc_count; ++i) {
177 0 : struct _drecord *src_rec = &src->records[i];
178 0 : struct _drecord *dest_rec = &dest->records[i];
179 :
180 : /* copy all integer in one time ! */
181 0 : desc_free_record(dest_rec);
182 0 : memcpy(dest_rec, src_rec, sizeof(struct _drecord));
183 :
184 : /* reinitialize string, avoid doubling pointers */
185 : #define CINIT(name) tds_dstr_init(&dest_rec->name);
186 0 : CINIT(sql_desc_base_column_name);
187 0 : CINIT(sql_desc_base_table_name);
188 0 : CINIT(sql_desc_catalog_name);
189 0 : CINIT(sql_desc_label);
190 0 : CINIT(sql_desc_local_type_name);
191 0 : CINIT(sql_desc_name);
192 0 : CINIT(sql_desc_schema_name);
193 0 : CINIT(sql_desc_table_name);
194 : #undef CINIT
195 :
196 : /* copy strings */
197 : #define CCOPY(name) if (!tds_dstr_copy(&dest_rec->name, tds_dstr_cstr(&src_rec->name))) return SQL_ERROR;
198 0 : CCOPY(sql_desc_base_column_name);
199 0 : CCOPY(sql_desc_base_table_name);
200 0 : CCOPY(sql_desc_catalog_name);
201 0 : CCOPY(sql_desc_label);
202 0 : CCOPY(sql_desc_local_type_name);
203 0 : CCOPY(sql_desc_name);
204 0 : CCOPY(sql_desc_schema_name);
205 0 : CCOPY(sql_desc_table_name);
206 : #undef CCOPY
207 : }
208 0 : return SQL_SUCCESS;
209 : }
210 :
211 : SQLRETURN
212 : desc_free(TDS_DESC * desc)
213 516 : {
214 516 : if (desc) {
215 516 : desc_free_records(desc);
216 516 : odbc_errs_reset(&desc->errs);
217 516 : free(desc);
218 : }
219 516 : return SQL_SUCCESS;
220 : }
|