Line data Source code
1 : #include "common.h"
2 : #include <assert.h>
3 :
4 : /* Test using array binding */
5 :
6 : static const char *test_query = NULL;
7 : static int trunc = 0;
8 : static int record_bind = 0;
9 :
10 : typedef struct
11 : {
12 : SQLUINTEGER id;
13 : SQLLEN id_len;
14 : SQLLEN desc_len;
15 : } Record;
16 :
17 : static void
18 32 : query_test(const char* expected, const char *expected_status)
19 : {
20 : #define ARRAY_SIZE 10
21 :
22 32 : ODBC_BUF *odbc_buf = NULL;
23 : SQLUINTEGER *ids;
24 : SQLCHAR *descs;
25 : SQLLEN *id_lens, *desc_lens;
26 : SQLULEN processed;
27 : SQLUSMALLINT i, statuses[ARRAY_SIZE];
28 32 : int desc_len = trunc ? 4 : 51;
29 32 : int rec_size = 0;
30 32 : Record *rec = NULL;
31 : char status[20];
32 :
33 32 : assert(odbc_stmt != SQL_NULL_HSTMT);
34 32 : odbc_reset_statement();
35 :
36 32 : SQLSetStmtAttr(odbc_stmt, SQL_ATTR_ROW_STATUS_PTR, statuses, 0);
37 32 : SQLSetStmtAttr(odbc_stmt, SQL_ATTR_ROW_ARRAY_SIZE, (void *) ARRAY_SIZE, 0);
38 32 : SQLSetStmtAttr(odbc_stmt, SQL_ATTR_ROWS_FETCHED_PTR, &processed, 0);
39 32 : SQLSetStmtAttr(odbc_stmt, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0);
40 :
41 32 : if (!record_bind) {
42 16 : ids = (SQLUINTEGER *) ODBC_GET(sizeof(SQLUINTEGER) * ARRAY_SIZE);
43 16 : descs = (SQLCHAR *) ODBC_GET(sizeof(SQLCHAR) * ARRAY_SIZE * desc_len);
44 16 : desc_lens = (SQLLEN *) ODBC_GET(sizeof(SQLLEN) * ARRAY_SIZE);
45 16 : id_lens = (SQLLEN *) ODBC_GET(sizeof(SQLLEN) * ARRAY_SIZE);
46 16 : assert(descs && ids && desc_lens && id_lens);
47 : } else {
48 16 : rec_size = (sizeof(Record) + (sizeof(SQLCHAR) * desc_len + sizeof(SQLLEN) - 1)) & ~(sizeof(SQLLEN) - 1);
49 16 : SQLSetStmtAttr(odbc_stmt, SQL_ATTR_ROW_BIND_TYPE, TDS_INT2PTR(rec_size), 0);
50 16 : rec = (Record *) ODBC_GET(rec_size * ARRAY_SIZE);
51 16 : ids = &rec->id;
52 16 : id_lens = &rec->id_len;
53 16 : desc_lens = &rec->desc_len;
54 16 : descs = (SQLCHAR *) (((char *) rec) + sizeof(Record));
55 : }
56 : #define REC(f,n) (((char*)f)+rec_size*(n))
57 : #define DESCS(n) (rec ? (SQLCHAR*)REC(descs,n): (descs+(n)*desc_len))
58 : #define IDS(n) *(rec ? (SQLUINTEGER*)REC(ids,n) : &ids[n])
59 : #define ID_LENS(n) *(rec ? (SQLLEN*)REC(id_lens,n) : &id_lens[n])
60 : #define DESC_LENS(n) *(rec ? (SQLLEN*)REC(desc_lens,n) : &desc_lens[n])
61 :
62 32 : processed = ARRAY_SIZE + 1;
63 352 : for (i = 0; i < ARRAY_SIZE; i++) {
64 320 : statuses[i] = SQL_ROW_UPDATED;
65 320 : IDS(i) = i * 132;
66 320 : sprintf((char *) DESCS(i), "aaa");
67 320 : ID_LENS(i) = 0;
68 320 : DESC_LENS(i) = -i;
69 : }
70 :
71 32 : SQLBindCol(odbc_stmt, 1, SQL_C_ULONG, &IDS(0), 0, &ID_LENS(0));
72 32 : SQLBindCol(odbc_stmt, 2, SQL_C_CHAR, DESCS(0), desc_len, &DESC_LENS(0));
73 :
74 32 : CHKExecDirect(T(test_query), SQL_NTS, "S");
75 :
76 32 : CHKFetch(expected);
77 :
78 32 : assert(processed <= ARRAY_SIZE);
79 :
80 288 : for (i = 0; i < processed; ++i) {
81 : char buf[128];
82 :
83 288 : sprintf(buf, "%crow number %d", 'a' + i, i * 13);
84 288 : if (trunc)
85 80 : buf[3] = 0;
86 288 : if (IDS(i) != i + 1 || strcmp((char *) DESCS(i), buf) != 0) {
87 0 : fprintf(stderr, "Invalid result\n\tgot '%d|%s'\n\texpected '%d|%s'\n", (int) IDS(i), DESCS(i), i + 1, buf);
88 0 : exit(1);
89 : }
90 :
91 288 : switch (statuses[i]) {
92 208 : case SQL_ROW_SUCCESS:
93 208 : status[i] = 'V';
94 208 : break;
95 :
96 0 : case SQL_ROW_SUCCESS_WITH_INFO:
97 0 : status[i] = 'v';
98 0 : break;
99 :
100 80 : case SQL_ROW_ERROR:
101 80 : status[i] = '!';
102 80 : break;
103 :
104 0 : case SQL_ROW_NOROW:
105 0 : status[i] = ' ';
106 0 : break;
107 :
108 0 : default:
109 0 : fprintf(stderr, "Invalid status returned\n");
110 0 : exit(1);
111 : }
112 : }
113 32 : status[i] = 0;
114 :
115 32 : if (expected_status && strcmp(expected_status, status) != 0) {
116 0 : fprintf(stderr, "Invalid status\n\tgot '%s'\n\texpected '%s'\n", status, expected_status);
117 0 : exit(1);
118 : }
119 :
120 32 : ODBC_FREE();
121 32 : }
122 :
123 : int
124 8 : main(void)
125 : {
126 : int i;
127 :
128 8 : odbc_use_version3 = 1;
129 8 : odbc_connect();
130 :
131 8 : odbc_command("CREATE TABLE #odbc_test(i INT, t TEXT)");
132 88 : for (i = 0; i < 10; ++i) {
133 : char buf[128];
134 :
135 80 : sprintf(buf, "INSERT INTO #odbc_test(i, t) VALUES(%d, '%crow number %d')", i + 1, 'a' + i, i * 13);
136 80 : odbc_command(buf);
137 : }
138 :
139 8 : odbc_reset_statement();
140 :
141 8 : test_query = "SELECT * FROM #odbc_test ORDER BY i";
142 8 : printf("test line %d\n", __LINE__);
143 8 : query_test("S", "VVVVVVVVVV");
144 :
145 8 : test_query = "SELECT * FROM #odbc_test WHERE i < 7 ORDER BY i";
146 8 : printf("test line %d\n", __LINE__);
147 8 : query_test("S", "VVVVVV");
148 :
149 : /* binding row */
150 8 : test_query = "SELECT * FROM #odbc_test ORDER BY i";
151 8 : record_bind = 1;
152 8 : printf("test line %d\n", __LINE__);
153 8 : query_test("S", "VVVVVVVVVV");
154 :
155 : /* row and truncation */
156 8 : trunc = 1;
157 8 : printf("test line %d\n", __LINE__);
158 8 : query_test("I", "!!!!!!!!!!");
159 :
160 : /* TODO bind offset, SQLGetData, no bind, error */
161 :
162 8 : odbc_disconnect();
163 :
164 8 : printf("Success!.\n");
165 : return 0;
166 : }
|