1 /* Test sp_cursorprepare / sp_cursorexecute usage to support SELECT FOR UPDATE
2  * This test compiles and works fine with SQL Server Native Client, and uses
3  * the sp_cursor* API Server Cursors ...
4  */
5 
6 #include "common.h"
7 
8 static void
exec_direct(const char * stmt)9 exec_direct(const char *stmt)
10 {
11 	SQLHSTMT odbc_stmt = SQL_NULL_HSTMT;
12 
13 	CHKAllocHandle(SQL_HANDLE_STMT, (SQLHANDLE) odbc_conn, (SQLHANDLE *) & odbc_stmt, "S");
14 	odbc_command(stmt);
15 	CHKFreeHandle(SQL_HANDLE_STMT, (SQLHANDLE) odbc_stmt, "S");
16 }
17 
18 int
main(int argc,char ** argv)19 main(int argc, char **argv)
20 {
21 	char buff[64];
22 	SQLLEN ind;
23 
24 	odbc_use_version3 = 1;
25 	odbc_connect();
26 
27 	odbc_check_cursor();
28 
29 	exec_direct("CREATE TABLE #t1 ( k INT, c VARCHAR(20))");
30 	exec_direct("INSERT INTO #t1 VALUES (1, 'aaa')");
31 
32 	odbc_reset_statement();
33 
34 	CHKSetStmtAttr(SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_LOCK, SQL_IS_UINTEGER, "S");
35 
36 	CHKSetCursorName(T("c112"), SQL_NTS, "S");
37 
38 	CHKSetConnectAttr(SQL_ATTR_AUTOCOMMIT, TDS_INT2PTR(SQL_AUTOCOMMIT_OFF), 0, "S");
39 
40 	CHKPrepare(T("SELECT * FROM #t1 FOR UPDATE"), SQL_NTS, "S");
41 
42 	CHKExecute("S");
43 
44 	CHKFetch("S");
45 
46 	exec_direct("UPDATE #t1 SET c = 'xxx' WHERE CURRENT OF c112");
47 
48 	CHKCloseCursor("SI");
49 
50 	CHKEndTran(SQL_HANDLE_DBC, odbc_conn, SQL_COMMIT, "S");
51 
52 	CHKSetConnectAttr(SQL_ATTR_AUTOCOMMIT, TDS_INT2PTR(SQL_AUTOCOMMIT_ON), 0, "S");
53 
54 	CHKExecDirect(T("SELECT c FROM #t1 WHERE k = 1"), SQL_NTS, "S");
55 
56 	CHKFetch("S");
57 
58 	CHKGetData(1, SQL_C_CHAR, buff, sizeof(buff), &ind, "S");
59 
60 	printf(">> New value after update = [%s] (should be [xxx]) \n", buff);
61 
62 	CHKFreeHandle(SQL_HANDLE_STMT, (SQLHANDLE) odbc_stmt, "S");
63 	odbc_stmt = SQL_NULL_HSTMT;
64 
65 	odbc_disconnect();
66 
67 	return 0;
68 }
69