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