Line data Source code
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 : #include <config.h>
22 :
23 : #include <stdarg.h>
24 : #include <stdio.h>
25 :
26 : #if HAVE_STDLIB_H
27 : #include <stdlib.h>
28 : #endif /* HAVE_STDLIB_H */
29 :
30 : #if HAVE_STRING_H
31 : #include <string.h>
32 : #endif /* HAVE_STRING_H */
33 :
34 : #include <freetds/odbc.h>
35 : #include <freetds/utils/string.h>
36 : #include <odbcss.h>
37 :
38 : static void desc_free_record(struct _drecord *drec);
39 :
40 : TDS_DESC *
41 57524 : desc_alloc(SQLHANDLE parent, int desc_type, SQLSMALLINT alloc_type)
42 : {
43 : TDS_DESC *desc;
44 :
45 57524 : desc = tds_new0(TDS_DESC, 1);
46 115048 : if (!desc || tds_mutex_init(&desc->mtx)) {
47 0 : free(desc);
48 0 : return NULL;
49 : }
50 :
51 : /* set default header values */
52 57524 : desc->htype = SQL_HANDLE_DESC;
53 57524 : desc->type = desc_type;
54 57524 : desc->parent = parent;
55 57524 : desc->header.sql_desc_alloc_type = alloc_type;
56 57524 : desc->header.sql_desc_count = 0;
57 57524 : desc->records = NULL;
58 :
59 57524 : switch (desc_type) {
60 : case DESC_IRD:
61 : case DESC_IPD:
62 : break;
63 28770 : case DESC_ARD:
64 : case DESC_APD:
65 28770 : desc->header.sql_desc_bind_type = SQL_BIND_BY_COLUMN;
66 28770 : desc->header.sql_desc_array_size = 1;
67 28770 : break;
68 0 : default:
69 0 : free(desc);
70 0 : return NULL;
71 : }
72 57524 : CHECK_DESC_EXTRA(desc);
73 57524 : return desc;
74 : }
75 :
76 : #define SQL_DESC_STRINGS \
77 : STR_OP(sql_desc_base_column_name); \
78 : STR_OP(sql_desc_base_table_name); \
79 : STR_OP(sql_desc_catalog_name); \
80 : STR_OP(sql_desc_label); \
81 : STR_OP(sql_desc_local_type_name); \
82 : STR_OP(sql_desc_name); \
83 : STR_OP(sql_desc_schema_name); \
84 : STR_OP(sql_desc_table_name)
85 :
86 : SQLRETURN
87 21934 : desc_alloc_records(TDS_DESC * desc, unsigned count)
88 : {
89 : struct _drecord *drec;
90 : int i;
91 :
92 : /* shrink records */
93 21934 : if (desc->header.sql_desc_count >= count) {
94 56 : for (i = count; i < desc->header.sql_desc_count; ++i)
95 0 : desc_free_record(&desc->records[i]);
96 56 : desc->header.sql_desc_count = count;
97 56 : return SQL_SUCCESS;
98 : }
99 :
100 21878 : if (!TDS_RESIZE(desc->records, count))
101 : return SQL_ERROR;
102 21878 : memset(desc->records + desc->header.sql_desc_count, 0, sizeof(struct _drecord) * (count - desc->header.sql_desc_count));
103 :
104 49708 : for (i = desc->header.sql_desc_count; i < count; ++i) {
105 27830 : drec = &desc->records[i];
106 :
107 : #define STR_OP(name) tds_dstr_init(&drec->name)
108 250470 : SQL_DESC_STRINGS;
109 : #undef STR_OP
110 :
111 27830 : switch (desc->type) {
112 18660 : case DESC_IRD:
113 : case DESC_IPD:
114 18660 : drec->sql_desc_parameter_type = SQL_PARAM_INPUT;
115 18660 : break;
116 9170 : case DESC_ARD:
117 : case DESC_APD:
118 9170 : drec->sql_desc_concise_type = SQL_C_DEFAULT;
119 9170 : drec->sql_desc_type = SQL_C_DEFAULT;
120 9170 : break;
121 : }
122 : }
123 21878 : desc->header.sql_desc_count = count;
124 21878 : return SQL_SUCCESS;
125 : }
126 :
127 : static void
128 27830 : desc_free_record(struct _drecord *drec)
129 : {
130 : #define STR_OP(name) tds_dstr_free(&drec->name)
131 27830 : SQL_DESC_STRINGS;
132 : #undef STR_OP
133 27830 : if (drec->sql_desc_concise_type == SQL_SS_TABLE)
134 16 : tvp_free((SQLTVP *) drec->sql_desc_data_ptr);
135 27830 : }
136 :
137 : SQLRETURN
138 132661 : desc_free_records(TDS_DESC * desc)
139 : {
140 : int i;
141 :
142 132661 : if (desc->records) {
143 27830 : for (i = 0; i < desc->header.sql_desc_count; i++)
144 27830 : desc_free_record(&desc->records[i]);
145 20390 : TDS_ZERO_FREE(desc->records);
146 : }
147 :
148 132661 : desc->header.sql_desc_count = 0;
149 132661 : return SQL_SUCCESS;
150 : }
151 :
152 : SQLRETURN
153 8 : desc_copy(TDS_DESC * dest, TDS_DESC * src)
154 : {
155 : int i;
156 8 : TDS_DESC tmp = *dest;
157 :
158 : /* copy header */
159 8 : tmp.header = src->header;
160 :
161 : /* sql_desc_alloc_type should remain unchanged */
162 8 : tmp.header.sql_desc_alloc_type = dest->header.sql_desc_alloc_type;
163 :
164 : /* set no records */
165 8 : tmp.header.sql_desc_count = 0;
166 8 : tmp.records = NULL;
167 :
168 8 : tmp.errs.num_errors = 0;
169 8 : tmp.errs.errs = NULL;
170 :
171 8 : if (desc_alloc_records(&tmp, src->header.sql_desc_count) != SQL_SUCCESS)
172 : return SQL_ERROR;
173 :
174 16 : for (i = 0; i < src->header.sql_desc_count; ++i) {
175 16 : struct _drecord *src_rec = &src->records[i];
176 16 : struct _drecord *dest_rec = &tmp.records[i];
177 :
178 : /* copy all integers at once ! */
179 16 : memcpy(dest_rec, src_rec, sizeof(struct _drecord));
180 :
181 : /* reinitialize string, avoid doubling pointers */
182 : #define STR_OP(name) tds_dstr_init(&dest_rec->name)
183 144 : SQL_DESC_STRINGS;
184 : #undef STR_OP
185 :
186 : /* copy strings */
187 : #define STR_OP(name) if (!tds_dstr_dup(&dest_rec->name, &src_rec->name)) goto Cleanup
188 112 : SQL_DESC_STRINGS;
189 : #undef STR_OP
190 : }
191 :
192 : /* success, copy back to our descriptor */
193 8 : desc_free_records(dest);
194 8 : odbc_errs_reset(&dest->errs);
195 8 : *dest = tmp;
196 8 : return SQL_SUCCESS;
197 :
198 0 : Cleanup:
199 0 : desc_free_records(&tmp);
200 0 : odbc_errs_reset(&tmp.errs);
201 0 : return SQL_ERROR;
202 : }
203 :
204 : SQLRETURN
205 57524 : desc_free(TDS_DESC * desc)
206 : {
207 57524 : if (desc) {
208 57524 : desc_free_records(desc);
209 57524 : odbc_errs_reset(&desc->errs);
210 57524 : tds_mutex_free(&desc->mtx);
211 57524 : free(desc);
212 : }
213 57524 : return SQL_SUCCESS;
214 : }
215 :
216 : TDS_DBC *
217 8 : desc_get_dbc(TDS_DESC *desc)
218 : {
219 8 : if (IS_HSTMT(desc->parent))
220 8 : return ((TDS_STMT *) desc->parent)->dbc;
221 :
222 : return (TDS_DBC *) desc->parent;
223 : }
224 :
225 : SQLTVP *
226 2064 : tvp_alloc(TDS_STMT *stmt)
227 : {
228 2064 : SQLTVP *tvp = tds_new0(SQLTVP, 1);
229 4128 : tds_dstr_init(&tvp->type_name);
230 2064 : tvp->ipd = desc_alloc(stmt, DESC_IPD, SQL_DESC_ALLOC_AUTO);
231 2064 : tvp->apd = desc_alloc(stmt, DESC_APD, SQL_DESC_ALLOC_AUTO);
232 2064 : if (!tvp->ipd || !tvp->apd) {
233 0 : tvp_free(tvp);
234 0 : return NULL;
235 : }
236 2064 : tvp->ipd->focus = -1;
237 2064 : tvp->apd->focus = -1;
238 2064 : return tvp;
239 : }
240 :
241 : void
242 2064 : tvp_free(SQLTVP *tvp)
243 : {
244 2064 : if (!tvp)
245 : return;
246 :
247 2064 : desc_free(tvp->ipd);
248 2064 : desc_free(tvp->apd);
249 2064 : tds_dstr_free(&tvp->type_name);
250 2064 : free(tvp);
251 : }
|