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 78992 : desc_alloc(SQLHANDLE parent, int desc_type, SQLSMALLINT alloc_type)
42 : {
43 : TDS_DESC *desc;
44 :
45 78992 : desc = tds_new0(TDS_DESC, 1);
46 157984 : if (!desc || tds_mutex_init(&desc->mtx)) {
47 0 : free(desc);
48 0 : return NULL;
49 : }
50 :
51 : /* set default header values */
52 78992 : desc->htype = SQL_HANDLE_DESC;
53 78992 : desc->type = desc_type;
54 78992 : desc->parent = parent;
55 78992 : desc->header.sql_desc_alloc_type = alloc_type;
56 78992 : desc->header.sql_desc_count = 0;
57 78992 : desc->records = NULL;
58 :
59 78992 : switch (desc_type) {
60 : case DESC_IRD:
61 : case DESC_IPD:
62 : break;
63 39506 : case DESC_ARD:
64 : case DESC_APD:
65 39506 : desc->header.sql_desc_bind_type = SQL_BIND_BY_COLUMN;
66 39506 : desc->header.sql_desc_array_size = 1;
67 39506 : break;
68 0 : default:
69 0 : free(desc);
70 0 : return NULL;
71 : }
72 78992 : CHECK_DESC_EXTRA(desc);
73 78992 : 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 33309 : desc_alloc_records(TDS_DESC * desc, unsigned count)
88 : {
89 : struct _drecord *drec;
90 : int i;
91 :
92 : /* shrink records */
93 33309 : if (desc->header.sql_desc_count >= count) {
94 4456 : for (i = count; i < desc->header.sql_desc_count; ++i)
95 10 : desc_free_record(&desc->records[i]);
96 4446 : desc->header.sql_desc_count = count;
97 4446 : return SQL_SUCCESS;
98 : }
99 :
100 28863 : if (!TDS_RESIZE(desc->records, count))
101 : return SQL_ERROR;
102 28863 : memset(desc->records + desc->header.sql_desc_count, 0, sizeof(struct _drecord) * (count - desc->header.sql_desc_count));
103 :
104 65268 : for (i = desc->header.sql_desc_count; i < count; ++i) {
105 36405 : drec = &desc->records[i];
106 :
107 : #define STR_OP(name) tds_dstr_init(&drec->name)
108 327645 : SQL_DESC_STRINGS;
109 : #undef STR_OP
110 :
111 36405 : switch (desc->type) {
112 24297 : case DESC_IRD:
113 : case DESC_IPD:
114 24297 : drec->sql_desc_parameter_type = SQL_PARAM_INPUT;
115 24297 : break;
116 12108 : case DESC_ARD:
117 : case DESC_APD:
118 12108 : drec->sql_desc_concise_type = SQL_C_DEFAULT;
119 12108 : drec->sql_desc_type = SQL_C_DEFAULT;
120 12108 : break;
121 : }
122 : }
123 28863 : desc->header.sql_desc_count = count;
124 28863 : return SQL_SUCCESS;
125 : }
126 :
127 : static void
128 36405 : desc_free_record(struct _drecord *drec)
129 : {
130 : #define STR_OP(name) tds_dstr_free(&drec->name)
131 36405 : SQL_DESC_STRINGS;
132 : #undef STR_OP
133 36405 : if (drec->sql_desc_concise_type == SQL_SS_TABLE)
134 32 : tvp_free((SQLTVP *) drec->sql_desc_data_ptr);
135 36405 : }
136 :
137 : SQLRETURN
138 178063 : desc_free_records(TDS_DESC * desc)
139 : {
140 : int i;
141 :
142 178063 : if (desc->records) {
143 36395 : for (i = 0; i < desc->header.sql_desc_count; i++)
144 36395 : desc_free_record(&desc->records[i]);
145 26875 : TDS_ZERO_FREE(desc->records);
146 : }
147 :
148 178063 : desc->header.sql_desc_count = 0;
149 178063 : return SQL_SUCCESS;
150 : }
151 :
152 : SQLRETURN
153 10 : desc_copy(TDS_DESC * dest, TDS_DESC * src)
154 : {
155 : int i;
156 10 : TDS_DESC tmp = *dest;
157 :
158 : /* copy header */
159 10 : tmp.header = src->header;
160 :
161 : /* sql_desc_alloc_type should remain unchanged */
162 10 : tmp.header.sql_desc_alloc_type = dest->header.sql_desc_alloc_type;
163 :
164 : /* set no records */
165 10 : tmp.header.sql_desc_count = 0;
166 10 : tmp.records = NULL;
167 :
168 10 : tmp.errs.num_errors = 0;
169 10 : tmp.errs.errs = NULL;
170 :
171 10 : if (desc_alloc_records(&tmp, src->header.sql_desc_count) != SQL_SUCCESS)
172 : return SQL_ERROR;
173 :
174 20 : for (i = 0; i < src->header.sql_desc_count; ++i) {
175 20 : struct _drecord *src_rec = &src->records[i];
176 20 : struct _drecord *dest_rec = &tmp.records[i];
177 :
178 : /* copy all integers at once ! */
179 20 : 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 180 : 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 140 : SQL_DESC_STRINGS;
189 : #undef STR_OP
190 : }
191 :
192 : /* success, copy back to our descriptor */
193 10 : desc_free_records(dest);
194 10 : odbc_errs_reset(&dest->errs);
195 10 : *dest = tmp;
196 10 : 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 78992 : desc_free(TDS_DESC * desc)
206 : {
207 78992 : if (desc) {
208 78992 : desc_free_records(desc);
209 78992 : odbc_errs_reset(&desc->errs);
210 78992 : tds_mutex_free(&desc->mtx);
211 78992 : free(desc);
212 : }
213 78992 : return SQL_SUCCESS;
214 : }
215 :
216 : TDS_DBC *
217 10 : desc_get_dbc(TDS_DESC *desc)
218 : {
219 10 : if (IS_HSTMT(desc->parent))
220 10 : return ((TDS_STMT *) desc->parent)->dbc;
221 :
222 : return (TDS_DBC *) desc->parent;
223 : }
224 :
225 : SQLTVP *
226 4128 : tvp_alloc(TDS_STMT *stmt)
227 : {
228 4128 : SQLTVP *tvp = tds_new0(SQLTVP, 1);
229 8256 : tds_dstr_init(&tvp->type_name);
230 4128 : tvp->ipd = desc_alloc(stmt, DESC_IPD, SQL_DESC_ALLOC_AUTO);
231 4128 : tvp->apd = desc_alloc(stmt, DESC_APD, SQL_DESC_ALLOC_AUTO);
232 4128 : if (!tvp->ipd || !tvp->apd) {
233 0 : tvp_free(tvp);
234 0 : return NULL;
235 : }
236 4128 : tvp->ipd->focus = -1;
237 4128 : tvp->apd->focus = -1;
238 4128 : return tvp;
239 : }
240 :
241 : void
242 4128 : tvp_free(SQLTVP *tvp)
243 : {
244 4128 : if (!tvp)
245 : return;
246 :
247 4128 : desc_free(tvp->ipd);
248 4128 : desc_free(tvp->apd);
249 4128 : tds_dstr_free(&tvp->type_name);
250 4128 : free(tvp);
251 : }
|