Line data Source code
1 : #include "common.h"
2 :
3 : /* Test cursors */
4 :
5 : #define SWAP_STMT(b) do { SQLHSTMT xyz = odbc_stmt; odbc_stmt = b; b = xyz; } while(0)
6 :
7 : static int mssql2005 = 0;
8 :
9 : static void
10 60 : Test0(int use_sql, const char *create_sql, const char *insert_sql, const char *select_sql)
11 : {
12 : #define ROWS 4
13 : #define C_LEN 10
14 :
15 : SQLUINTEGER n[ROWS];
16 : char c[ROWS][C_LEN];
17 : SQLLEN c_len[ROWS], n_len[ROWS];
18 :
19 : SQLUSMALLINT statuses[ROWS];
20 : SQLUSMALLINT i;
21 : SQLULEN num_row;
22 : SQLHSTMT stmt2;
23 :
24 : /* create test table */
25 60 : odbc_command("IF OBJECT_ID('tempdb..#test') IS NOT NULL DROP TABLE #test");
26 60 : odbc_command(create_sql);
27 420 : for (i = 1; i <= 6; ++i) {
28 : char sql_buf[80], data[10];
29 360 : memset(data, 'a' + (i - 1), sizeof(data));
30 360 : data[i] = 0;
31 360 : sprintf(sql_buf, insert_sql, data, i);
32 360 : odbc_command(sql_buf);
33 : }
34 :
35 : /* set cursor options */
36 60 : odbc_reset_statement();
37 60 : CHKSetStmtAttr(SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_ROWVER, 0, "S");
38 60 : CHKSetStmtAttr(SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_DYNAMIC, 0, "S");
39 60 : CHKSetStmtAttr(SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) ROWS, 0, "S");
40 60 : CHKSetStmtAttr(SQL_ATTR_ROW_STATUS_PTR, (SQLPOINTER) statuses, 0, "S");
41 60 : CHKSetStmtAttr(SQL_ATTR_ROWS_FETCHED_PTR, &num_row, 0, "S");
42 60 : CHKSetCursorName(T("C1"), SQL_NTS, "S");
43 :
44 : /* */
45 60 : CHKExecDirect(T(select_sql), SQL_NTS, "S");
46 :
47 : /* bind some rows at a time */
48 60 : CHKBindCol(1, SQL_C_ULONG, n, 0, n_len, "S");
49 60 : CHKBindCol(2, SQL_C_CHAR, c, C_LEN, c_len, "S");
50 :
51 : /* allocate an additional statement */
52 60 : CHKAllocStmt(&stmt2, "S");
53 :
54 240 : while (CHKFetchScroll(SQL_FETCH_NEXT, 0, "SNo") == SQL_SUCCESS) {
55 : /* print, just for debug */
56 360 : for (i = 0; i < num_row; ++i)
57 360 : printf("row %d i %d c %s\n", (int) (i + 1), (int) n[i], c[i]);
58 120 : printf("---\n");
59 :
60 : /* delete a row */
61 120 : i = 1;
62 120 : if (i > 0 && i <= num_row) {
63 120 : CHKSetPos(i, use_sql ? SQL_POSITION : SQL_DELETE, SQL_LOCK_NO_CHANGE, mssql2005 ? "SI": "S");
64 120 : if (use_sql) {
65 60 : SWAP_STMT(stmt2);
66 60 : CHKPrepare(T("DELETE FROM #test WHERE CURRENT OF C1"), SQL_NTS, "S");
67 60 : CHKExecute("S");
68 60 : SWAP_STMT(stmt2);
69 : }
70 : }
71 :
72 : /* update another row */
73 120 : i = 2;
74 120 : if (i > 0 && i <= num_row) {
75 120 : strcpy(c[i - 1], "foo");
76 120 : c_len[i - 1] = 3;
77 120 : if (strstr(select_sql, "#a") == NULL || use_sql) {
78 108 : CHKSetPos(i, use_sql ? SQL_POSITION : SQL_UPDATE, SQL_LOCK_NO_CHANGE, "S");
79 : } else {
80 : SQLTCHAR sqlstate[6];
81 : SQLTCHAR msg[256];
82 :
83 12 : n[i - 1] = 321;
84 12 : CHKSetPos(i, use_sql ? SQL_POSITION : SQL_UPDATE, SQL_LOCK_NO_CHANGE, "E");
85 :
86 12 : CHKGetDiagRec(SQL_HANDLE_STMT, odbc_stmt, 1, sqlstate, NULL, msg, TDS_VECTOR_SIZE(msg), NULL, "S");
87 12 : if (strstr(C(msg), "Invalid column name 'c'") == NULL) {
88 0 : fprintf(stderr, "Expected message not found at line %d\n", __LINE__);
89 0 : exit(1);
90 : }
91 : }
92 120 : if (use_sql) {
93 60 : SWAP_STMT(stmt2);
94 60 : CHKPrepare(T("UPDATE #test SET c=? WHERE CURRENT OF C1"), SQL_NTS, "S");
95 60 : CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, C_LEN, 0, c[i - 1], 0, NULL, "S");
96 60 : CHKExecute("S");
97 : /* FIXME this is not necessary for mssql driver */
98 60 : SQLMoreResults(odbc_stmt);
99 60 : SWAP_STMT(stmt2);
100 : }
101 : }
102 : }
103 :
104 60 : SWAP_STMT(stmt2);
105 60 : CHKFreeStmt(SQL_DROP, "S");
106 60 : SWAP_STMT(stmt2);
107 :
108 60 : odbc_reset_statement();
109 :
110 : /* test values */
111 60 : odbc_check_no_row("IF (SELECT COUNT(*) FROM #test) <> 4 SELECT 1");
112 60 : odbc_check_no_row("IF NOT EXISTS(SELECT * FROM #test WHERE i = 3 AND c = 'ccc') SELECT 1");
113 60 : odbc_check_no_row("IF NOT EXISTS(SELECT * FROM #test WHERE i = 4 AND c = 'dddd') SELECT 1");
114 60 : if (strstr(select_sql, "#a") == NULL || use_sql) {
115 54 : odbc_check_no_row("IF NOT EXISTS(SELECT * FROM #test WHERE i = 2 AND c = 'foo') SELECT 1");
116 54 : odbc_check_no_row("IF NOT EXISTS(SELECT * FROM #test WHERE i = 6 AND c = 'foo') SELECT 1");
117 : }
118 60 : }
119 :
120 : static void
121 12 : Test(int use_sql)
122 : {
123 12 : odbc_command_with_result(odbc_stmt, "DROP TABLE #a");
124 12 : odbc_command("CREATE TABLE #a(x int)");
125 12 : odbc_command("INSERT INTO #a VALUES(123)");
126 12 : Test0(use_sql, "CREATE TABLE #test(i int, c varchar(6))", "INSERT INTO #test(c, i) VALUES('%s', %d)", "SELECT x AS i, c FROM #test, #a");
127 :
128 12 : Test0(use_sql, "CREATE TABLE #test(i int, c varchar(6))", "INSERT INTO #test(c, i) VALUES('%s', %d)", "SELECT i, c FROM #test");
129 12 : if (odbc_db_is_microsoft()) {
130 12 : Test0(use_sql, "CREATE TABLE #test(i int identity(1,1), c varchar(6))", "INSERT INTO #test(c) VALUES('%s')", "SELECT i, c FROM #test");
131 12 : Test0(use_sql, "CREATE TABLE #test(i int primary key, c varchar(6))", "INSERT INTO #test(c, i) VALUES('%s', %d)", "SELECT i, c FROM #test");
132 : }
133 12 : Test0(use_sql, "CREATE TABLE #test(i int, c varchar(6))", "INSERT INTO #test(c, i) VALUES('%s', %d)", "SELECT i, c, c + 'xxx' FROM #test");
134 12 : }
135 :
136 : int
137 8 : main(int argc, char *argv[])
138 : {
139 8 : odbc_connect();
140 8 : odbc_check_cursor();
141 :
142 6 : if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x09000000u)
143 4 : mssql2005 = 1;
144 :
145 6 : Test(1);
146 :
147 6 : Test(0);
148 :
149 6 : odbc_disconnect();
150 : return 0;
151 : }
|