NCBI C++ ToolKit
tds_checks.c
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2  * Copyright (C) 2004-2011 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 #include <config.h>
20 
21 #undef NDEBUG
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 <assert.h>
35 
36 #include <freetds/tds.h>
37 #include <freetds/convert.h>
38 #include <freetds/string.h>
39 #include <freetds/checks.h>
40 
41 #if ENABLE_EXTRA_CHECKS
42 static void
43 tds_check_packet_extra(const TDSPACKET * packet)
44 {
45  assert(packet);
46  for (; packet; packet = packet->next) {
47  assert(packet->len <= packet->capacity);
48  assert(packet->sid >= -1);
49  }
50 }
51 
52 void
54 {
55  const int invalid_state = 0;
56  TDS_UINT i;
57  TDSDYNAMIC *cur_dyn = NULL;
58  TDSCURSOR *cur_cursor = NULL;
59 
60  assert(tds);
61 
62  /* test state and connection */
63  switch (tds->state) {
64  case TDS_DEAD:
65  case TDS_WRITING:
66  case TDS_SENDING:
67  case TDS_PENDING:
68  case TDS_IDLE:
69  case TDS_READING:
70  break;
71  default:
72  assert(invalid_state);
73  }
74 
75  assert(tds->conn);
76 
77 #if ENABLE_ODBC_MARS
78  if (tds->state != TDS_DEAD)
80 #else
83 #endif
84 
85  /* test env */
87 
88  /* test buffers and positions */
89  tds_check_packet_extra(tds->send_packet);
90  tds_check_packet_extra(tds->recv_packet);
91 
92 #if ENABLE_ODBC_MARS
93  if (tds->conn->send_packets)
94  assert(tds->conn->send_pos <= tds->conn->send_packets->len);
95  if (tds->conn->recv_packet)
96  assert(tds->conn->recv_pos <= tds->conn->recv_packet->len);
97 #endif
98 
99  assert(tds->in_pos <= tds->in_len);
101  /* TODO remove blocksize from env and use out_len ?? */
102 /* assert(tds->out_pos <= tds->out_len); */
103 /* assert(tds->out_len == 0 || tds->out_buf != NULL); */
109 
110  assert(tds->in_buf == tds->recv_packet->buf || tds->in_buf == tds->recv_packet->buf + 16);
112 
113  /* test res_info */
114  if (tds->res_info)
116 
117  /* test num_comp_info, comp_info */
118  assert(tds->num_comp_info >= 0);
119  for (i = 0; i < tds->num_comp_info; ++i) {
120  assert(tds->comp_info);
122  }
123 
124  /* param_info */
125  if (tds->param_info)
127 
128  /* test cursors */
129  for (cur_cursor = tds->conn->cursors; cur_cursor != NULL; cur_cursor = cur_cursor->next)
130  tds_check_cursor_extra(cur_cursor);
131 
132  /* test dynamics */
133  for (cur_dyn = tds->conn->dyns; cur_dyn != NULL; cur_dyn = cur_dyn->next)
134  tds_check_dynamic_extra(cur_dyn);
135 
136  /* test tds_ctx */
138 
139  /* TODO test char_conv_count, char_convs */
140 
141  /* we can't have compute and no results */
142  assert(tds->num_comp_info == 0 || tds->res_info != NULL);
143 
144  /* we can't have normal and parameters results */
145  /* TODO too strict ?? */
146 /* assert(tds->param_info == NULL || tds->res_info == NULL); */
147 }
148 
149 void
151 {
152  assert(ctx);
153 }
154 
155 void
157 {
158  assert(env);
159 
160  assert(env->block_size >= 0 && env->block_size <= 65536);
161 }
162 
163 void
165 {
166  int size;
168  int varint_ok;
169  int column_varint_size;
170 
171  assert(column);
172  column_varint_size = column->column_varint_size;
173 
174  /* 8 is for varchar(max) or similar */
175  assert(column_varint_size == 8 ||
176  (column_varint_size < 5 && column_varint_size != 3));
177 
178  assert(column->column_scale <= column->column_prec);
179  assert(column->column_prec <= MAXPRECISION);
180 
181  /* I don't like this that much... freddy77 */
182  if (column->column_type == 0)
183  return;
184  assert(column->funcs);
185  assert(column->column_type > 0);
186 
187  /* specific checks, if true fully checked */
188  if (column->funcs->check(column))
189  return;
190 
191  /* check type and server type same or SQLNCHAR -> SQLCHAR */
192 #define SPECIAL(ttype, server_type, varint) \
193  if (column->column_type == ttype && column->on_server.column_type == server_type && column_varint_size == varint) {} else
194  SPECIAL(SYBTEXT, XSYBVARCHAR, 8)
195  SPECIAL(SYBTEXT, XSYBNVARCHAR, 8)
196  SPECIAL(SYBIMAGE, XSYBVARBINARY, 8)
197  assert(tds_get_cardinal_type(column->on_server.column_type, column->column_usertype) == column->column_type
198  || (tds_get_conversion_type(column->on_server.column_type, column->column_size) == column->column_type
199  && column_varint_size == 1 && is_fixed_type(column->column_type)));
200 
201  varint_ok = 0;
202  if (column_varint_size == 8) {
203  if (column->on_server.column_type == XSYBVARCHAR
204  || column->on_server.column_type == XSYBVARBINARY
205  || column->on_server.column_type == XSYBNVARCHAR)
206  varint_ok = 1;
207  } else if (is_blob_type(column->column_type)) {
208  assert(column_varint_size >= 4);
209  } else if (column->column_type == SYBVARIANT) {
210  assert(column_varint_size == 4);
211  }
212  conn.tds_version = 0x500;
213  varint_ok = varint_ok || tds_get_varint_size(&conn, column->on_server.column_type) == column_varint_size;
214  conn.tds_version = 0x700;
215  varint_ok = varint_ok || tds_get_varint_size(&conn, column->on_server.column_type) == column_varint_size;
216  assert(varint_ok);
217 
218  assert(!is_numeric_type(column->column_type));
219  if (!is_blob_type(column->column_type)) {
220  /*
221  * Skip for BLOBs, whose reported maximum may have
222  * been merely nominal, and doesn't really matter
223  * because their storage is generally allocated
224  * separately, based on actual result sizes.
225  */
226  assert(column->column_cur_size <= column->column_size);
227  }
228 
229  /* check size of fixed type correct */
230  size = tds_get_size_by_type(column->column_type);
231  /* these peculiar types are variable but have only a possible size */
232  if ((size > 0 && (column->column_type != SYBBITN && column->column_type != SYBDATEN && column->column_type != SYBTIMEN))
233  || column->column_type == SYBVOID) {
234  /* check macro */
235  assert(is_fixed_type(column->column_type));
236  /* check current size */
237  assert(size == column->column_size);
238  /* check cases where server need nullable types */
239  if (column->column_type != column->on_server.column_type && (column->column_type != SYBINT8 || column->on_server.column_type != SYB5INT8)) {
240  assert(!is_fixed_type(column->on_server.column_type));
241  assert(column_varint_size == 1);
242  assert(column->column_size == column->column_cur_size || column->column_cur_size == -1);
243  } else {
244  assert(column_varint_size == 0
245  || (column->column_type == SYBUNIQUE && column_varint_size == 1));
246  assert(column->column_size == column->column_cur_size
247  || (column->column_type == SYBUNIQUE && column->column_cur_size == -1));
248  }
249  assert(column->column_size == column->on_server.column_size);
250  } else {
251  assert(!is_fixed_type(column->column_type));
252  assert(is_char_type(column->column_type) || (column->on_server.column_size == column->column_size || column->on_server.column_size == 0));
253  assert(column_varint_size != 0);
254  }
255 
256  /* check size of nullable types (ie intN) it's supported */
257  if (tds_get_conversion_type(column->column_type, 4) != column->column_type) {
258  /* check macro */
259  assert(is_nullable_type(column->column_type));
260  /* check that size it's correct for this type of nullable */
261  assert(tds_get_conversion_type(column->column_type, column->column_size) != column->column_type);
262  /* check current size */
263  assert(column->column_size >= column->column_cur_size || column->column_cur_size == -1);
264  /* check same type and size on server */
265  assert(column->column_type == column->on_server.column_type);
266  assert(column->column_size == column->on_server.column_size);
267  }
268 }
269 
270 void
272 {
273  int i;
274 
275  assert(res_info);
276  assert(res_info->num_cols >= 0);
277  assert(res_info->ref_count > 0);
278  for (i = 0; i < res_info->num_cols; ++i) {
279  assert(res_info->columns);
280  tds_check_column_extra(res_info->columns[i]);
281  assert(res_info->columns[i]->column_data != NULL || res_info->row_size == 0);
282  }
283 
284  assert(res_info->row_size >= 0);
285 
286  assert(res_info->computeid >= 0);
287 
288  assert(res_info->by_cols >= 0);
289  assert(res_info->by_cols == 0 || res_info->bycolumns);
290 }
291 
292 void
293 tds_check_cursor_extra(const TDSCURSOR * cursor)
294 {
295  assert(cursor);
296 
297  assert(cursor->ref_count > 0);
298 
299  if (cursor->res_info)
301 }
302 
303 void
305 {
306  assert(dyn);
307 
308  assert(dyn->ref_count > 0);
309 
310  if (dyn->res_info)
312  if (dyn->params)
314 
315  assert(!dyn->emulated || dyn->query);
316 }
317 
318 #endif /* ENABLE_EXTRA_CHECKS */
static CS_CONNECTION * conn
Definition: ct_dynamic.c:25
CS_CONTEXT * ctx
Definition: t0006.c:12
@ SYBTIMEN
Definition: proto.h:226
@ SYBVARIANT
Definition: proto.h:200
@ SYB5INT8
Definition: proto.h:220
@ SYBUNIQUE
Definition: proto.h:199
@ XSYBNVARCHAR
Definition: proto.h:195
@ SYBDATEN
Definition: proto.h:219
@ XSYBVARCHAR
Definition: proto.h:194
@ XSYBVARBINARY
Definition: proto.h:197
#define TDS_IS_SOCKET_INVALID(s)
#define TDS_ADDITIONAL_SPACE
#define is_numeric_type(x)
Definition: tds.h:454
#define is_fixed_type(x)
Definition: tds.h:438
#define is_blob_type(x)
Definition: tds.h:443
#define tds_get_s(tds)
Definition: tds.h:1298
@ TDS_PENDING
cilent is waiting for data
Definition: tds.h:866
@ TDS_SENDING
client would send data
Definition: tds.h:865
@ TDS_READING
client is reading data
Definition: tds.h:867
@ TDS_WRITING
client is writing data
Definition: tds.h:864
@ TDS_IDLE
no data expected
Definition: tds.h:863
@ TDS_DEAD
no connection
Definition: tds.h:868
#define is_char_type(x)
Definition: tds.h:460
#define is_nullable_type(x)
Definition: tds.h:439
tds_sysdep_uint32_type TDS_UINT
Definition: tds.h:150
#define tds_get_ctx(tds)
Definition: tds.h:1294
#define MAXPRECISION
Definition: tds.h:470
static const char * column
Definition: stats.c:23
static HENV env
Definition: transaction2.c:38
#define SYBVOID
Definition: sybdb.h:198
#define SYBTEXT
Definition: sybdb.h:182
#define SYBINT8
Definition: sybdb.h:172
#define SYBIMAGE
Definition: sybdb.h:186
#define SYBBITN
Definition: sybdb.h:180
static TDSSOCKET * tds
Definition: collations.c:37
#define tds_check_resultinfo_extra
#define tds_get_cardinal_type
#define tds_check_env_extra
#define tds_get_size_by_type
#define tds_check_cursor_extra
#define tds_check_tds_extra
#define tds_check_column_extra
#define tds_get_conversion_type
#define tds_get_varint_size
#define tds_check_dynamic_extra
#define tds_check_context_extra
#define NULL
Definition: ncbistd.hpp:225
int i
if(yy_accept[yy_current_state])
const struct ncbi::grid::netcache::search::fields::SIZE size
#define assert(x)
Definition: srv_diag.hpp:58
Metadata about columns in regular and compute rows.
Definition: tds.h:761
unsigned char * column_data
Definition: tds.h:793
TDSENV env
environment is shared between all sessions
Definition: tds.h:1147
TDSCURSOR * cursors
linked list of cursors allocated for this connection contains only cursors allocated on the server
Definition: tds.h:1153
TDSDYNAMIC * dyns
list of dynamic allocated for this connection contains only dynamic allocated on the server
Definition: tds.h:1158
Holds informations about a cursor.
Definition: tds.h:1007
TDS_INT ref_count
reference counter so client can retain safely a pointer
Definition: tds.h:1009
TDSRESULTINFO * res_info
Definition: tds.h:1025
struct tds_cursor * next
next in linked list, keep first
Definition: tds.h:1008
Holds information for a dynamic (also called prepared) query.
Definition: tds.h:1047
struct tds_dynamic * next
next in linked list, keep first
Definition: tds.h:1048
TDS_INT ref_count
reference counter so client can retain safely a pointer
Definition: tds.h:1049
char * query
saved query, we need to know original query if prepare is impossible
Definition: tds.h:1079
TDSPARAMINFO * params
query parameters.
Definition: tds.h:1077
TDSPARAMINFO * res_info
query results
Definition: tds.h:1069
TDS_TINYINT emulated
this dynamic query cannot be prepared so libTDS have to construct a simple query.
Definition: tds.h:1063
Current environment as reported by the server.
Definition: tds.h:1033
short sid
Definition: tds.h:1125
unsigned len
Definition: tds.h:1126
unsigned char buf[1]
Definition: tds.h:1127
struct tds_packet * next
Definition: tds.h:1124
unsigned capacity
Definition: tds.h:1126
Hold information for any results.
Definition: tds.h:842
TDS_SMALLINT * bycolumns
Definition: tds.h:853
TDS_USMALLINT computeid
Definition: tds.h:846
TDSCOLUMN ** columns
Definition: tds.h:844
TDS_USMALLINT num_cols
Definition: tds.h:845
TDS_INT ref_count
Definition: tds.h:847
TDS_USMALLINT by_cols
Definition: tds.h:854
TDS_INT row_size
Definition: tds.h:851
Information for a server connection.
Definition: tds.h:1211
unsigned in_len
input buffer length
Definition: tds.h:1239
TDSCOMPUTEINFO ** comp_info
Definition: tds.h:1266
unsigned out_pos
current position in out_buf
Definition: tds.h:1238
unsigned char * out_buf
Output buffer.
Definition: tds.h:1230
TDSPACKET * send_packet
packet we are preparing to send
Definition: tds.h:1256
unsigned char * in_buf
Input buffer.
Definition: tds.h:1223
unsigned in_pos
current position in in_buf
Definition: tds.h:1237
TDS_STATE state
Definition: tds.h:1273
TDSCONNECTION conn[1]
Definition: tds.h:1215
TDSPACKET * recv_packet
Definition: tds.h:1254
TDSRESULTINFO * res_info
Definition: tds.h:1264
TDS_UINT num_comp_info
Definition: tds.h:1265
unsigned int out_buf_max
Maximum size of packet pointed by out_buf.
Definition: tds.h:1236
TDSPARAMINFO * param_info
Definition: tds.h:1267
Modified on Mon May 20 05:02:25 2024 by modify_doxy.py rev. 669887