Line data Source code
1 : #include "common.h"
2 : #include <assert.h>
3 :
4 : struct type
5 : {
6 : SQLSMALLINT type;
7 : const char *name;
8 : unsigned flags;
9 : };
10 :
11 : #define FLAG_C 1
12 : #define FLAG_SQL 2
13 :
14 : #define TYPE_C(s) {s, #s, FLAG_C }
15 : #define TYPE_SQL(s) {s, #s, FLAG_SQL }
16 : #define TYPE_BOTH(s,s2) {s, #s, FLAG_SQL|FLAG_C }
17 : /*
18 : * Same define with test for constants
19 : * #define TYPE_BOTH(s,s2) {s, #s, (FLAG_SQL|FLAG_C)+((1/!(s-s2))-1) }
20 : */
21 : static const struct type types[] = {
22 : TYPE_BOTH(SQL_C_CHAR, SQL_CHAR),
23 : TYPE_BOTH(SQL_C_LONG, SQL_INTEGER),
24 : TYPE_BOTH(SQL_C_SHORT, SQL_SMALLINT),
25 : TYPE_BOTH(SQL_C_FLOAT, SQL_REAL),
26 : TYPE_BOTH(SQL_C_DOUBLE, SQL_DOUBLE),
27 : TYPE_BOTH(SQL_C_NUMERIC, SQL_NUMERIC),
28 : TYPE_C(SQL_C_DEFAULT),
29 : TYPE_C(SQL_C_DATE),
30 : TYPE_C(SQL_C_TIME),
31 : /* MS ODBC do not support SQL_TIMESTAMP for IPD type while we support it */
32 : /* TYPE_C(SQL_C_TIMESTAMP), */
33 : TYPE_BOTH(SQL_C_TIMESTAMP, SQL_TIMESTAMP),
34 : TYPE_BOTH(SQL_C_TYPE_DATE, SQL_TYPE_DATE),
35 : TYPE_BOTH(SQL_C_TYPE_TIME, SQL_TYPE_TIME),
36 : TYPE_BOTH(SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP),
37 : TYPE_C(SQL_C_INTERVAL_YEAR),
38 : TYPE_C(SQL_C_INTERVAL_MONTH),
39 : TYPE_C(SQL_C_INTERVAL_DAY),
40 : TYPE_C(SQL_C_INTERVAL_HOUR),
41 : TYPE_C(SQL_C_INTERVAL_MINUTE),
42 : TYPE_C(SQL_C_INTERVAL_SECOND),
43 : TYPE_C(SQL_C_INTERVAL_YEAR_TO_MONTH),
44 : TYPE_C(SQL_C_INTERVAL_DAY_TO_HOUR),
45 : TYPE_C(SQL_C_INTERVAL_DAY_TO_MINUTE),
46 : TYPE_C(SQL_C_INTERVAL_DAY_TO_SECOND),
47 : TYPE_C(SQL_C_INTERVAL_HOUR_TO_MINUTE),
48 : TYPE_C(SQL_C_INTERVAL_HOUR_TO_SECOND),
49 : TYPE_C(SQL_C_INTERVAL_MINUTE_TO_SECOND),
50 : TYPE_BOTH(SQL_C_BINARY, SQL_BINARY),
51 : TYPE_BOTH(SQL_C_BIT, SQL_BIT),
52 : TYPE_C(SQL_C_SBIGINT),
53 : TYPE_C(SQL_C_UBIGINT),
54 : TYPE_BOTH(SQL_C_TINYINT, SQL_TINYINT),
55 : TYPE_C(SQL_C_SLONG),
56 : TYPE_C(SQL_C_SSHORT),
57 : TYPE_C(SQL_C_STINYINT),
58 : TYPE_C(SQL_C_ULONG),
59 : TYPE_C(SQL_C_USHORT),
60 : TYPE_C(SQL_C_UTINYINT),
61 : TYPE_BOTH(SQL_C_GUID, SQL_GUID),
62 :
63 : TYPE_SQL(SQL_BIGINT),
64 : TYPE_SQL(SQL_VARBINARY),
65 : TYPE_SQL(SQL_LONGVARBINARY),
66 : TYPE_SQL(SQL_VARCHAR),
67 : TYPE_SQL(SQL_LONGVARCHAR),
68 : TYPE_SQL(SQL_DECIMAL),
69 : TYPE_SQL(SQL_FLOAT),
70 : {0, NULL}
71 : };
72 :
73 : static const char *
74 : get_type_name(SQLSMALLINT type)
75 : {
76 472 : const struct type *p = types;
77 :
78 17448 : for (; p->name; ++p)
79 18392 : if (p->type == type)
80 : return p->name;
81 : return "(unknown)";
82 : }
83 :
84 : static int result = 0;
85 :
86 : static void
87 : check_msg(int check, const char *msg)
88 : {
89 720 : if (check)
90 : return;
91 0 : fprintf(stderr, "Check failed: %s\n", msg);
92 0 : result = 1;
93 : }
94 :
95 : int
96 8 : main(void)
97 : {
98 : const struct type *p;
99 : char buf[16];
100 : SQLINTEGER ind;
101 : SQLLEN lind;
102 : SQLHDESC desc;
103 :
104 8 : odbc_connect();
105 :
106 : /*
107 : * test setting two time a descriptor
108 : * success all user allocated are ARD or APD so type cheching can be done
109 : * TODO freeing descriptor dissociate it from statements
110 : */
111 :
112 : /* test C types */
113 368 : for (p = types; p->name; ++p) {
114 360 : if (SQL_SUCCEEDED
115 : (SQLBindParameter(odbc_stmt, 1, SQL_PARAM_INPUT, p->type, SQL_VARCHAR, (SQLUINTEGER) (-1), 0, buf, 16, &lind))) {
116 : SQLSMALLINT concise_type, type, code;
117 : SQLHDESC desc;
118 :
119 304 : concise_type = type = code = 0;
120 :
121 : /* get APD */
122 304 : SQLGetStmtAttr(odbc_stmt, SQL_ATTR_APP_PARAM_DESC, &desc, sizeof(desc), &ind);
123 :
124 304 : CHKGetDescField(desc, 1, SQL_DESC_TYPE, &type, sizeof(SQLSMALLINT), &ind, "S");
125 304 : CHKGetDescField(desc, 1, SQL_DESC_CONCISE_TYPE, &concise_type, sizeof(SQLSMALLINT), &ind, "S");
126 304 : CHKGetDescField(desc, 1, SQL_DESC_DATETIME_INTERVAL_CODE, &code, sizeof(SQLSMALLINT), &ind, "S");
127 912 : printf("Setted type %s -> [%d (%s), %d (%s), %d]\n",
128 : p->name, (int) concise_type, get_type_name(concise_type), (int) type, get_type_name(type), code);
129 608 : check_msg(p->flags & FLAG_C, "Type not C successed to be set in APD");
130 : } else {
131 : SQLSMALLINT concise_type, type, code;
132 : SQLHDESC desc;
133 :
134 56 : concise_type = type = code = 0;
135 :
136 56 : fprintf(stderr, "Error setting type %d (%s)\n", (int) p->type, p->name);
137 :
138 56 : concise_type = p->type;
139 56 : SQLGetStmtAttr(odbc_stmt, SQL_ATTR_APP_PARAM_DESC, &desc, sizeof(desc), &ind);
140 56 : if (SQL_SUCCEEDED
141 : (SQLSetDescField(desc, 1, SQL_DESC_CONCISE_TYPE, TDS_INT2PTR(concise_type), sizeof(SQLSMALLINT))))
142 : {
143 0 : CHKGetDescField(desc, 1, SQL_DESC_TYPE, &type, sizeof(SQLSMALLINT), &ind, "S");
144 0 : CHKGetDescField(desc, 1, SQL_DESC_CONCISE_TYPE, &concise_type, sizeof(SQLSMALLINT), &ind, "S");
145 0 : CHKGetDescField(desc, 1, SQL_DESC_DATETIME_INTERVAL_CODE, &code, sizeof(SQLSMALLINT), &ind, "S");
146 0 : printf("Setted type %s -> [%d (%s), %d (%s), %d]\n",
147 : p->name,
148 : (int) concise_type, get_type_name(concise_type), (int) type, get_type_name(type), code);
149 0 : check_msg(p->flags & FLAG_C, "Type not C successed to be set in APD");
150 : } else {
151 56 : check_msg(!(p->flags & FLAG_C), "Type C failed to be set in APD");
152 : }
153 : }
154 : }
155 :
156 8 : printf("\n\n");
157 :
158 : /* test SQL types */
159 8 : SQLGetStmtAttr(odbc_stmt, SQL_ATTR_IMP_PARAM_DESC, &desc, sizeof(desc), &ind);
160 368 : for (p = types; p->name; ++p) {
161 360 : SQLSMALLINT concise_type = p->type;
162 :
163 360 : if (SQL_SUCCEEDED
164 : (SQLSetDescField(desc, 1, SQL_DESC_CONCISE_TYPE, TDS_INT2PTR(concise_type), sizeof(SQLSMALLINT)))) {
165 : SQLSMALLINT concise_type, type, code;
166 :
167 168 : concise_type = type = code = 0;
168 :
169 168 : CHKGetDescField(desc, 1, SQL_DESC_TYPE, &type, sizeof(SQLSMALLINT), &ind, "S");
170 168 : CHKGetDescField(desc, 1, SQL_DESC_CONCISE_TYPE, &concise_type, sizeof(SQLSMALLINT), &ind, "S");
171 168 : CHKGetDescField(desc, 1, SQL_DESC_DATETIME_INTERVAL_CODE, &code, sizeof(SQLSMALLINT), &ind, "S");
172 504 : printf("Setted type %s -> [%d (%s), %d (%s), %d]\n",
173 : p->name, (int) concise_type, get_type_name(concise_type), (int) type, get_type_name(type), code);
174 336 : check_msg(p->flags & FLAG_SQL, "Type not SQL successed to be set in IPD");
175 : } else {
176 192 : fprintf(stderr, "Error setting type %d (%s)\n", (int) p->type, p->name);
177 192 : check_msg(!(p->flags & FLAG_SQL), "Type SQL failed to be set in IPD");
178 : }
179 : }
180 :
181 8 : odbc_disconnect();
182 :
183 8 : return result;
184 : }
|