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

« back to all changes in this revision

Viewing changes to src/odbc/unittests/genparams.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
1
#include "common.h"
2
2
#include <assert.h>
 
3
#include <time.h>
3
4
 
4
5
/* Test various type from odbc and to odbc */
5
6
 
6
 
static char software_version[] = "$Id: genparams.c,v 1.9 2004/10/28 13:16:18 freddy77 Exp $";
 
7
static char software_version[] = "$Id: genparams.c,v 1.23 2008/01/08 09:33:32 freddy77 Exp $";
7
8
static void *no_unused_var_warn[] = { software_version, no_unused_var_warn };
8
9
 
 
10
#ifdef TDS_NO_DM
 
11
static const int tds_no_dm = 1;
 
12
#else
 
13
static const int tds_no_dm = 0;
 
14
#endif
 
15
 
 
16
static int precision = 18;
 
17
static int exec_direct = 0;
 
18
static int prepare_before = 0;
 
19
static int use_cursors = 0;
 
20
 
9
21
static void
10
22
Test(const char *type, const char *value_to_convert, SQLSMALLINT out_c_type, SQLSMALLINT out_sql_type, const char *expected)
11
23
{
15
27
        SQL_NUMERIC_STRUCT *num;
16
28
        int i;
17
29
 
18
 
        SQLFreeStmt(Statement, SQL_UNBIND);
19
 
        SQLFreeStmt(Statement, SQL_RESET_PARAMS);
 
30
        ResetStatement();
20
31
 
21
32
        /* build store procedure to test */
 
33
        Command(Statement, "IF OBJECT_ID('spTestProc') IS NOT NULL DROP PROC spTestProc");
22
34
        sprintf(sbuf, "CREATE PROC spTestProc @i %s OUTPUT AS SELECT @i = CONVERT(%s, '%s')", type, type, value_to_convert);
23
35
        Command(Statement, sbuf);
24
36
        memset(out_buf, 0, sizeof(out_buf));
25
37
 
 
38
        if (use_cursors) {
 
39
                ResetStatement();
 
40
                if (SQLSetStmtAttr(Statement, SQL_ATTR_CURSOR_SCROLLABLE, (SQLPOINTER) SQL_SCROLLABLE, 0) != SQL_SUCCESS)
 
41
                        ODBC_REPORT_ERROR("SQLSetStmtAttr error");
 
42
                if (SQLSetStmtAttr(Statement, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_DYNAMIC, 0) != SQL_SUCCESS)
 
43
                        ODBC_REPORT_ERROR("SQLSetStmtAttr error");
 
44
        }
 
45
 
26
46
        /* bind parameter */
27
 
        if (SQLBindParameter(Statement, 1, SQL_PARAM_OUTPUT, out_c_type, out_sql_type, 18, 0, out_buf, sizeof(out_buf), &out_len) !=
28
 
            SQL_SUCCESS)
29
 
                ODBC_REPORT_ERROR("Unable to bind input parameter");
30
 
 
31
 
        /* call store procedure */
32
 
        if (SQLExecDirect(Statement, "{call spTestProc(?)}", SQL_NTS) != SQL_SUCCESS)
33
 
                ODBC_REPORT_ERROR("Unable to execute store statement");
 
47
        if (exec_direct) {
 
48
                if (SQLBindParameter(Statement, 1, SQL_PARAM_OUTPUT, out_c_type, out_sql_type, precision, 0, out_buf,
 
49
                             sizeof(out_buf), &out_len) != SQL_SUCCESS)
 
50
                        ODBC_REPORT_ERROR("Unable to bind output parameter");
 
51
 
 
52
                /* call store procedure */
 
53
                if (SQLExecDirect(Statement, (SQLCHAR *) "{call spTestProc(?)}", SQL_NTS) != SQL_SUCCESS)
 
54
                        ODBC_REPORT_ERROR("Unable to execute store statement");
 
55
        } else {
 
56
                if (prepare_before && SQLPrepare(Statement, (SQLCHAR *) "{call spTestProc(?)}", SQL_NTS) != SQL_SUCCESS)
 
57
                        ODBC_REPORT_ERROR("SQLPrepare() failure!");
 
58
 
 
59
                if (SQLBindParameter(Statement, 1, SQL_PARAM_OUTPUT, out_c_type, out_sql_type, precision, 0, out_buf,
 
60
                             sizeof(out_buf), &out_len) != SQL_SUCCESS)
 
61
                        ODBC_REPORT_ERROR("Unable to bind output parameter");
 
62
 
 
63
                if (!prepare_before && SQLPrepare(Statement, (SQLCHAR *) "{call spTestProc(?)}", SQL_NTS) != SQL_SUCCESS)
 
64
                        ODBC_REPORT_ERROR("SQLPrepare() failure!");
 
65
 
 
66
                if (SQLExecute(Statement) != SQL_SUCCESS)
 
67
                        ODBC_REPORT_ERROR("SQLExecute() failure!");
 
68
        }
34
69
 
35
70
        /* test results */
36
71
        sbuf[0] = 0;
67
102
        char sbuf[1024];
68
103
        unsigned char out_buf[256];
69
104
        SQLLEN out_len = 0;
 
105
        const char *expected = value_to_convert;
 
106
        size_t value_len = strlen(value_to_convert);
 
107
        const char *p;
70
108
 
71
 
        SQLFreeStmt(Statement, SQL_UNBIND);
72
 
        SQLFreeStmt(Statement, SQL_RESET_PARAMS);
 
109
        ResetStatement();
73
110
 
74
111
        /* execute a select to get data as wire */
75
 
        sprintf(sbuf, "SELECT CONVERT(%s, '%s')", type, value_to_convert);
 
112
        if ((p = strstr(value_to_convert, " -> ")) != NULL) {
 
113
                value_len = p - value_to_convert;
 
114
                expected = p + 4;
 
115
        }
 
116
        sprintf(sbuf, "SELECT CONVERT(%s, '%.*s')", type, (int) value_len, value_to_convert);
76
117
        Command(Statement, sbuf);
77
118
        SQLBindCol(Statement, 1, out_c_type, out_buf, sizeof(out_buf), &out_len);
78
 
        if (SQLFetch(Statement) != SQL_SUCCESS)
 
119
        if (!SQL_SUCCEEDED(SQLFetch(Statement)))
79
120
                ODBC_REPORT_ERROR("Expected row");
80
121
        if (SQLFetch(Statement) != SQL_NO_DATA)
81
122
                ODBC_REPORT_ERROR("Row not expected");
83
124
                ODBC_REPORT_ERROR("Recordset not expected");
84
125
 
85
126
        /* create a table with a column of that type */
86
 
        SQLFreeStmt(Statement, SQL_UNBIND);
87
 
        SQLFreeStmt(Statement, SQL_RESET_PARAMS);
 
127
        ResetStatement();
88
128
        sprintf(sbuf, "CREATE TABLE #tmp_insert (col %s)", param_type);
89
129
        Command(Statement, sbuf);
90
130
 
 
131
        if (use_cursors) {
 
132
                ResetStatement();
 
133
                if (SQLSetStmtAttr(Statement, SQL_ATTR_CURSOR_SCROLLABLE, (SQLPOINTER) SQL_SCROLLABLE, 0) != SQL_SUCCESS)
 
134
                        ODBC_REPORT_ERROR("SQLSetStmtAttr error");
 
135
                if (SQLSetStmtAttr(Statement, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_DYNAMIC, 0) != SQL_SUCCESS)
 
136
                        ODBC_REPORT_ERROR("SQLSetStmtAttr error");
 
137
        }
 
138
 
91
139
        /* insert data using prepared statements */
92
140
        sprintf(sbuf, "INSERT INTO #tmp_insert VALUES(?)");
93
 
        if (SQLPrepare(Statement, sbuf, SQL_NTS) != SQL_SUCCESS)
94
 
                ODBC_REPORT_ERROR("SQLPrepare() failure!");
95
 
 
96
 
        out_len = 1;
97
 
        if (SQLBindParameter(Statement, 1, SQL_PARAM_INPUT, out_c_type, out_sql_type, 20, 0, out_buf, sizeof(out_buf), &out_len) !=
98
 
            SQL_SUCCESS)
99
 
                ODBC_REPORT_ERROR("Unable to bind input parameter");
100
 
 
101
 
        if (SQLExecute(Statement) != SQL_SUCCESS)
102
 
                ODBC_REPORT_ERROR("SQLExecute() failure!");
 
141
        if (exec_direct) {
 
142
                SQLRETURN rc;
 
143
 
 
144
                out_len = 1;
 
145
                if (SQLBindParameter(Statement, 1, SQL_PARAM_INPUT, out_c_type, out_sql_type, 20, 0, out_buf, sizeof(out_buf), &out_len) !=
 
146
                    SQL_SUCCESS)
 
147
                        ODBC_REPORT_ERROR("Unable to bind input parameter");
 
148
 
 
149
                rc = SQLExecDirect(Statement, (SQLCHAR *) sbuf, SQL_NTS);
 
150
                if (rc != SQL_SUCCESS && rc != SQL_NO_DATA)
 
151
                        ODBC_REPORT_ERROR("SQLExecDirect() failure!");
 
152
        } else {
 
153
                SQLRETURN rc;
 
154
 
 
155
                if (prepare_before && SQLPrepare(Statement, (SQLCHAR *) sbuf, SQL_NTS) != SQL_SUCCESS)
 
156
                        ODBC_REPORT_ERROR("SQLPrepare() failure!");
 
157
 
 
158
                out_len = 1;
 
159
                if (SQLBindParameter(Statement, 1, SQL_PARAM_INPUT, out_c_type, out_sql_type, 20, 0, out_buf, sizeof(out_buf), &out_len) !=
 
160
                    SQL_SUCCESS)
 
161
                        ODBC_REPORT_ERROR("Unable to bind input parameter");
 
162
 
 
163
                if (!prepare_before && SQLPrepare(Statement, (SQLCHAR *) sbuf, SQL_NTS) != SQL_SUCCESS)
 
164
                        ODBC_REPORT_ERROR("SQLPrepare() failure!");
 
165
 
 
166
                rc = SQLExecute(Statement);
 
167
                if (rc != SQL_SUCCESS && rc != SQL_NO_DATA)
 
168
                        ODBC_REPORT_ERROR("SQLExecute() failure!");
 
169
        }
103
170
 
104
171
        /* check is row is present */
105
 
        SQLFreeStmt(Statement, SQL_UNBIND);
106
 
        SQLFreeStmt(Statement, SQL_RESET_PARAMS);
107
 
        sprintf(sbuf, "SELECT * FROM #tmp_insert WHERE col = CONVERT(%s, '%s')", param_type, value_to_convert);
 
172
        ResetStatement();
 
173
        sprintf(sbuf, "SELECT * FROM #tmp_insert WHERE col = CONVERT(%s, '%s')", param_type, expected);
108
174
        Command(Statement, sbuf);
109
175
 
110
176
        if (SQLFetch(Statement) != SQL_SUCCESS)
116
182
        Command(Statement, "DROP TABLE #tmp_insert");
117
183
}
118
184
 
119
 
int
120
 
main(int argc, char *argv[])
 
185
static int big_endian = 1;
 
186
static char version[32];
 
187
 
 
188
static void
 
189
AllTests(void)
121
190
{
122
 
        int big_endian = 1;
123
 
 
124
 
        Connect();
125
 
 
126
 
        if (CommandWithResult(Statement, "drop proc spTestProc") != SQL_SUCCESS)
127
 
                printf("Unable to execute statement\n");
128
 
 
129
 
        if (((char *) &big_endian)[0] == 1)
130
 
                big_endian = 0;
 
191
        struct tm *ltime;
 
192
        char buf[80];
 
193
        time_t curr_time;
 
194
 
 
195
        SQLINTEGER y, m, d;
 
196
        char date[128];
 
197
 
 
198
        printf("use_cursors %d exec_direct %d prepare_before %d\n", use_cursors, exec_direct, prepare_before);
131
199
 
132
200
        /* FIXME why should return 38 0 as precision and scale ?? correct ?? */
 
201
        precision = 18;
133
202
        Test("NUMERIC(18,2)", "123", SQL_C_NUMERIC, SQL_NUMERIC, "18 0 1 7B");
 
203
        Test("DECIMAL(18,2)", "123", SQL_C_NUMERIC, SQL_DECIMAL, "18 0 1 7B");
 
204
        precision = 38;
 
205
        Test("NUMERIC(18,2)", "123", SQL_C_NUMERIC, SQL_NUMERIC, "38 0 1 7B");
134
206
        TestInput(SQL_C_LONG, "INTEGER", SQL_VARCHAR, "VARCHAR(20)", "12345");
135
207
        /* MS driver behavior for output parameters is different */
136
208
        if (driver_is_freetds())
137
209
                Test("VARCHAR(20)", "313233", SQL_C_BINARY, SQL_VARCHAR, "333133323333");
138
210
        else
139
211
                Test("VARCHAR(20)", "313233", SQL_C_BINARY, SQL_VARCHAR, "313233");
 
212
        /* FIXME our driver ignore precision for date */
 
213
        precision = 3;
140
214
        Test("DATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, SQL_TIMESTAMP, big_endian ? "0000949700FBAA2C" : "979400002CAAFB00");
141
215
        Test("SMALLDATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, SQL_TIMESTAMP,
142
216
             big_endian ? "0000949700FB9640" : "979400004096FB00");
 
217
        TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34");
 
218
 
 
219
        /* test timestamp millisecond round off */
 
220
        TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.001 -> 2005-07-22 09:51:34.000");
 
221
        TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.002 -> 2005-07-22 09:51:34.003");
 
222
        TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.003 -> 2005-07-22 09:51:34.003");
 
223
        TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.004 -> 2005-07-22 09:51:34.003");
 
224
        TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.005 -> 2005-07-22 09:51:34.007");
 
225
        TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.006 -> 2005-07-22 09:51:34.007");
 
226
 
 
227
        /* FIXME on ms driver first SQLFetch return SUCCESS_WITH_INFO for truncation error */
 
228
        TestInput(SQL_C_TYPE_DATE, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 13:02:03 -> 2005-07-22 00:00:00");
 
229
 
 
230
        /* replace date information with current date */
 
231
        time(&curr_time);
 
232
        ltime = localtime(&curr_time);
 
233
        y = ltime->tm_year + 1900;
 
234
        m = ltime->tm_mon + 1;
 
235
        d = ltime->tm_mday;
 
236
        /* server concept of data can be different so try ask to server */
 
237
        Command(Statement, "SELECT GETDATE()");
 
238
        SQLBindCol(Statement, 1, SQL_C_CHAR, date, sizeof(date), NULL);
 
239
        if (SQLFetch(Statement) == SQL_SUCCESS) {
 
240
                int a, b, c;
 
241
                if (sscanf(date, "%d-%d-%d", &a, &b, &c) == 3) {
 
242
                        y = a;
 
243
                        m = b;
 
244
                        d = c;
 
245
                }
 
246
        }
 
247
        SQLFetch(Statement);
 
248
        SQLMoreResults(Statement);
 
249
        SQLFreeStmt(Statement, SQL_UNBIND);
 
250
        sprintf(buf, "2003-07-22 13:02:03 -> %04d-%02d-%02d 13:02:03", (int) y, (int) m, (int) d);
 
251
        TestInput(SQL_C_TYPE_TIME, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", buf);
 
252
 
 
253
        TestInput(SQL_C_FLOAT,  "FLOAT", SQL_REAL, "FLOAT", "1234.25");
 
254
        TestInput(SQL_C_DOUBLE, "REAL", SQL_REAL, "FLOAT", "-1234.25");
 
255
        TestInput(SQL_C_FLOAT,  "REAL", SQL_REAL, "FLOAT", "1234.25");
 
256
        TestInput(SQL_C_DOUBLE, "FLOAT", SQL_REAL, "FLOAT", "-1234.25");
 
257
        TestInput(SQL_C_FLOAT,  "FLOAT", SQL_FLOAT, "FLOAT", "1234.25");
 
258
        TestInput(SQL_C_DOUBLE, "REAL", SQL_FLOAT, "FLOAT", "-1234.25");
 
259
        TestInput(SQL_C_FLOAT,  "FLOAT", SQL_DOUBLE, "FLOAT", "1234.25");
 
260
        TestInput(SQL_C_DOUBLE, "REAL", SQL_DOUBLE, "FLOAT", "-1234.25");
 
261
 
 
262
        TestInput(SQL_C_UTINYINT, "TINYINT", SQL_TINYINT, "TINYINT", "231");
 
263
 
 
264
        TestInput(SQL_C_NUMERIC, "NUMERIC(20,3)", SQL_NUMERIC, "NUMERIC(20,3)", "765432.2 -> 765432");
 
265
 
 
266
        TestInput(SQL_C_BIT, "BIT", SQL_BIT, "BIT", "0");
 
267
        TestInput(SQL_C_BIT, "BIT", SQL_BIT, "BIT", "1");
 
268
 
 
269
        TestInput(SQL_C_DOUBLE, "MONEY", SQL_DOUBLE, "MONEY", "123.34");
 
270
 
 
271
        /* TODO some Sybase versions */
 
272
        if (db_is_microsoft() && strncmp(version, "08.00.", 6) == 0) {
 
273
                Test("BIGINT", "-987654321065432", SQL_C_BINARY, SQL_BIGINT, big_endian ? "FFFC7DBBCF083228" : "283208CFBB7DFCFF");
 
274
                TestInput(SQL_C_SBIGINT, "BIGINT", SQL_BIGINT, "BIGINT", "-12345678901234");
 
275
        }
 
276
}
 
277
 
 
278
int
 
279
main(int argc, char *argv[])
 
280
{
 
281
        SQLSMALLINT version_len;
 
282
 
 
283
        use_odbc_version3 = 1;
 
284
        Connect();
 
285
 
 
286
        memset(version, 0, sizeof(version));
 
287
        SQLGetInfo(Connection, SQL_DBMS_VER, version, sizeof(version), &version_len);
 
288
 
 
289
        if (((char *) &big_endian)[0] == 1)
 
290
                big_endian = 0;
 
291
 
 
292
        for (use_cursors = 0; use_cursors <= 1; ++use_cursors) {
 
293
                if (use_cursors) {
 
294
                        if (!tds_no_dm || !driver_is_freetds())
 
295
                                ResetStatement();
 
296
                        CheckCursor();
 
297
                }
 
298
 
 
299
                exec_direct = 1;
 
300
                AllTests();
 
301
 
 
302
                exec_direct = 0;
 
303
                prepare_before = 1;
 
304
                AllTests();
 
305
 
 
306
                prepare_before = 0;
 
307
                AllTests();
 
308
        }
143
309
 
144
310
        Disconnect();
145
311
 
146
312
        printf("Done successfully!\n");
147
313
        return 0;
148
314
}
 
315