~ubuntu-branches/debian/lenny/freetds/lenny

« back to all changes in this revision

Viewing changes to src/tds/tds_checks.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2008-08-02 11:49:53 UTC
  • mfrom: (2.1.10 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080802114953-0qdeowgl63k42n2c
Tags: 0.82-4
* Fix a typo in the freetds-common description, ugh
* Versioned replaces of libct4 by freetds-common, since the current one
  obviously doesn't have overlapping files.
* tdsodbc: check for /var/lib/odbc existence before removing it in the
  postinst, since there are cases where it won't exist on upgrade (i.e.,
  if the driver was never enabled in the first place).  Closes: #493303.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* FreeTDS - Library of routines accessing Sybase and Microsoft databases
 
2
 * Copyright (C) 2004, 2005 Frediano Ziglio
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Library General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Library General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Library General Public
 
15
 * License along with this library; if not, write to the
 
16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
 * Boston, MA 02111-1307, USA.
 
18
 */
 
19
#if HAVE_CONFIG_H
 
20
#include <config.h>
 
21
#endif /* HAVE_CONFIG_H */
 
22
 
 
23
#undef NDEBUG
 
24
 
 
25
#include <stdarg.h>
 
26
#include <stdio.h>
 
27
 
 
28
#if HAVE_STDLIB_H
 
29
#include <stdlib.h>
 
30
#endif /* HAVE_STDLIB_H */
 
31
 
 
32
#if HAVE_STRING_H
 
33
#include <string.h>
 
34
#endif /* HAVE_STRING_H */
 
35
 
 
36
#include <assert.h>
 
37
 
 
38
#include "tds.h"
 
39
#include "tdsconvert.h"
 
40
#include "tdsstring.h"
 
41
#include "tds_checks.h"
 
42
 
 
43
#ifdef DMALLOC
 
44
#include <dmalloc.h>
 
45
#endif
 
46
 
 
47
TDS_RCSID(var, "$Id: tds_checks.c,v 1.20 2007/06/21 07:21:21 freddy77 Exp $");
 
48
 
 
49
#if ENABLE_EXTRA_CHECKS
 
50
 
 
51
void
 
52
tds_check_tds_extra(const TDSSOCKET * tds)
 
53
{
 
54
        const int invalid_state = 0;
 
55
        int found, i;
 
56
        int result_found = 0;
 
57
        TDSDYNAMIC *cur_dyn = NULL;
 
58
        TDSCURSOR *cur_cursor = NULL;
 
59
 
 
60
        assert(tds);
 
61
 
 
62
        /* teset state and connection */
 
63
        switch (tds->state) {
 
64
        case TDS_DEAD:
 
65
        case TDS_QUERYING:
 
66
        case TDS_PENDING:
 
67
        case TDS_IDLE:
 
68
        case TDS_READING:
 
69
                break;
 
70
        default:
 
71
                assert(invalid_state);
 
72
        }
 
73
 
 
74
        assert(tds->state == TDS_DEAD || !TDS_IS_SOCKET_INVALID(tds->s));
 
75
        assert(tds->state != TDS_DEAD || TDS_IS_SOCKET_INVALID(tds->s));
 
76
 
 
77
        /* test env */
 
78
        tds_check_env_extra(&tds->env);
 
79
 
 
80
        /* test buffers and positions */
 
81
        assert(tds->in_pos <= tds->in_len && tds->in_len <= tds->in_buf_max);
 
82
        /* TODO remove blocksize from env and use out_len ?? */
 
83
/*      assert(tds->out_pos <= tds->out_len); */
 
84
/*      assert(tds->out_len == 0 || tds->out_buf != NULL); */
 
85
        assert(tds->out_pos <= tds->env.block_size);
 
86
        assert(tds->env.block_size == 0 || tds->out_buf != NULL);
 
87
        assert(tds->in_buf_max == 0 || tds->in_buf != NULL);
 
88
 
 
89
        /* test res_info */
 
90
        if (tds->res_info) {
 
91
                tds_check_resultinfo_extra(tds->res_info);
 
92
                if (tds->current_results == tds->res_info)
 
93
                        result_found = 1;
 
94
        }
 
95
 
 
96
        /* test num_comp_info, comp_info */
 
97
        assert(tds->num_comp_info >= 0);
 
98
        for (i = 0; i < tds->num_comp_info; ++i) {
 
99
                assert(tds->comp_info);
 
100
                tds_check_resultinfo_extra(tds->comp_info[i]);
 
101
                if (tds->current_results == tds->comp_info[i])
 
102
                        result_found = 1;
 
103
        }
 
104
 
 
105
        /* param_info */
 
106
        if (tds->param_info) {
 
107
                tds_check_resultinfo_extra(tds->param_info);
 
108
                if (tds->current_results == tds->param_info)
 
109
                        result_found = 1;
 
110
        }
 
111
 
 
112
        /* test cursors */
 
113
        found = 0;
 
114
        for (cur_cursor = tds->cursors; cur_cursor != NULL; cur_cursor = cur_cursor->next) {
 
115
                tds_check_cursor_extra(cur_cursor);
 
116
                if (tds->current_results == cur_cursor->res_info)
 
117
                        result_found = 1;
 
118
                if (cur_cursor == tds->cur_cursor)
 
119
                        found = 1;
 
120
        }
 
121
        assert(found || tds->cur_cursor == NULL);
 
122
 
 
123
        /* test num_dyms, cur_dyn, dyns */
 
124
        found = 0;
 
125
        for (cur_dyn = tds->dyns; cur_dyn != NULL; cur_dyn = cur_dyn->next) {
 
126
                if (cur_dyn == tds->cur_dyn)
 
127
                        found = 1;
 
128
                tds_check_dynamic_extra(cur_dyn);
 
129
                if (tds->current_results == cur_dyn->res_info)
 
130
                        result_found = 1;
 
131
        }
 
132
        assert(found || tds->cur_dyn == NULL);
 
133
 
 
134
        /* test tds_ctx */
 
135
        tds_check_context_extra(tds->tds_ctx);
 
136
 
 
137
        /* TODO test char_conv_count, char_convs */
 
138
 
 
139
        /* current_results should be one of res_info, comp_info, param_info or dynamic */
 
140
        /*
 
141
         * TODO this test was here to check that current_results was an alias
 
142
         * but with cursor and reference counting current_results can point
 
143
         * to a cursor result available on upper layer
 
144
         * Perhaps we should free results on deallocate and enable
 
145
         * assert again?
 
146
         */
 
147
        /* assert(result_found || tds->current_results == NULL); */
 
148
 
 
149
        /* we can't have compute and no results */
 
150
        assert(tds->num_comp_info == 0 || tds->res_info != NULL);
 
151
 
 
152
        /* we can't have normal and parameters results */
 
153
        /* TODO too strict ?? */
 
154
/*      assert(tds->param_info == NULL || tds->res_info == NULL); */
 
155
}
 
156
 
 
157
void
 
158
tds_check_context_extra(const TDSCONTEXT * ctx)
 
159
{
 
160
        assert(ctx);
 
161
}
 
162
 
 
163
void
 
164
tds_check_env_extra(const TDSENV * env)
 
165
{
 
166
        assert(env);
 
167
 
 
168
        assert(env->block_size >= 0 && env->block_size <= 65536);
 
169
}
 
170
 
 
171
void
 
172
tds_check_column_extra(const TDSCOLUMN * column)
 
173
{
 
174
        int size;
 
175
        TDSSOCKET tds;
 
176
        int varint_ok;
 
177
 
 
178
        assert(column);
 
179
 
 
180
        assert(column->column_varint_size <= 5 && column->column_varint_size != 3);
 
181
 
 
182
        assert(column->column_scale <= column->column_prec);
 
183
        assert(column->column_prec <= 77);
 
184
 
 
185
        /* I don't like this that much... freddy77 */
 
186
        if (column->column_type == 0)
 
187
                return;
 
188
 
 
189
        assert(strlen(column->table_name) < sizeof(column->table_name));
 
190
        assert(strlen(column->column_name) < sizeof(column->column_name));
 
191
 
 
192
        /* check type and server type same or SQLNCHAR -> SQLCHAR */
 
193
        assert(tds_get_cardinal_type(column->on_server.column_type) == column->column_type
 
194
                || (tds_get_null_type(column->column_type) == column->on_server.column_type 
 
195
                && column->column_varint_size == 1 && is_fixed_type(column->column_type)));
 
196
        tds.minor_version = 0;
 
197
        tds.major_version = 5;
 
198
        varint_ok = tds_get_varint_size(&tds, column->on_server.column_type) == column->column_varint_size;
 
199
        tds.major_version = 7;
 
200
        varint_ok = varint_ok || tds_get_varint_size(&tds, column->on_server.column_type) == column->column_varint_size;
 
201
        assert(varint_ok);
 
202
 
 
203
        /* check current size <= size */
 
204
        if (is_numeric_type(column->column_type)) {
 
205
                /* I don't like that much this difference between numeric and not numeric - freddy77 */
 
206
                /* TODO what should be the size ?? */
 
207
                assert(column->column_prec >= 1 && column->column_prec <= 77);
 
208
                assert(column->column_scale <= column->column_prec);
 
209
/*              assert(column->column_cur_size == tds_numeric_bytes_per_prec[column->column_prec] + 2 || column->column_cur_size == -1); */
 
210
        } else {
 
211
                assert(column->column_cur_size <= column->column_size);
 
212
        }
 
213
 
 
214
        /* check size of fixed type correct */
 
215
        size = tds_get_size_by_type(column->column_type);
 
216
        assert(size != 0 || column->column_type == SYBVOID);
 
217
        if (size >= 0 && column->column_type != SYBBITN) {
 
218
                /* check macro */
 
219
                assert(is_fixed_type(column->column_type));
 
220
                /* check current size */
 
221
                assert(size == column->column_size);
 
222
                /* check cases where server need nullable types */
 
223
                if (column->column_type != column->on_server.column_type && (column->column_type != SYBINT8 || column->on_server.column_type != SYB5INT8)) {
 
224
                        assert(!is_fixed_type(column->on_server.column_type));
 
225
                        assert(column->column_varint_size == 1);
 
226
                        assert(column->column_size == column->column_cur_size || column->column_cur_size == -1);
 
227
                } else {
 
228
                        assert(column->column_varint_size == 0 || (column->column_type == SYBUNIQUE && column->column_varint_size == 1));
 
229
                        assert(column->column_size == column->column_cur_size || 
 
230
                                (column->column_type == SYBUNIQUE && column->column_cur_size == -1));
 
231
                }
 
232
                assert(column->column_size == column->on_server.column_size);
 
233
        } else {
 
234
                assert(!is_fixed_type(column->column_type));
 
235
                assert(column->char_conv || (column->on_server.column_size == column->column_size || column->on_server.column_size == 0));
 
236
                assert(column->column_varint_size != 0);
 
237
        }
 
238
 
 
239
        /* check size of nullable types (ie intN) it's supported */
 
240
        if (tds_get_conversion_type(column->column_type, 4) != column->column_type) {
 
241
                /* check macro */
 
242
                assert(is_nullable_type(column->column_type));
 
243
                /* check that size it's correct for this type of nullable */
 
244
                assert(tds_get_conversion_type(column->column_type, column->column_size) != column->column_type);
 
245
                /* check current size */
 
246
                assert(column->column_size >= column->column_cur_size || column->column_cur_size == -1);
 
247
                /* check same type and size on server */
 
248
                assert(column->column_type == column->on_server.column_type);
 
249
                assert(column->column_size == column->on_server.column_size);
 
250
        }
 
251
}
 
252
 
 
253
void
 
254
tds_check_resultinfo_extra(const TDSRESULTINFO * res_info)
 
255
{
 
256
        int i;
 
257
 
 
258
        assert(res_info);
 
259
        assert(res_info->num_cols >= 0);
 
260
        assert(res_info->ref_count > 0);
 
261
        for (i = 0; i < res_info->num_cols; ++i) {
 
262
                assert(res_info->columns);
 
263
                tds_check_column_extra(res_info->columns[i]);
 
264
                assert(res_info->columns[i]->column_data != NULL || res_info->row_size == 0);
 
265
        }
 
266
 
 
267
        assert(res_info->row_size >= 0);
 
268
 
 
269
        assert(res_info->computeid >= 0);
 
270
 
 
271
        assert(res_info->by_cols >= 0);
 
272
        assert(res_info->by_cols == 0 || res_info->bycolumns);
 
273
}
 
274
 
 
275
void
 
276
tds_check_cursor_extra(const TDSCURSOR * cursor)
 
277
{
 
278
}
 
279
 
 
280
void
 
281
tds_check_dynamic_extra(const TDSDYNAMIC * dyn)
 
282
{
 
283
        assert(dyn);
 
284
 
 
285
        if (dyn->res_info)
 
286
                tds_check_resultinfo_extra(dyn->res_info);
 
287
        if (dyn->params)
 
288
                tds_check_resultinfo_extra(dyn->params);
 
289
 
 
290
        assert(!dyn->emulated || dyn->query);
 
291
}
 
292
 
 
293
#endif /* ENABLE_EXTRA_CHECKS */