1 /*
2  * Tests for deprecated functions.
3  */
4 
5 #include <string.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 
9 #include "common.h"
10 
11 void
print_cursor_type(SQLINTEGER cursor_type)12 print_cursor_type(SQLINTEGER cursor_type)
13 {
14 	printf("Cursor type is: ");
15 	if (cursor_type == SQL_CURSOR_FORWARD_ONLY)
16 		printf("forward\n");
17 	else if (cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
18 		printf("keyset driven\n");
19 	else if (cursor_type == SQL_CURSOR_DYNAMIC)
20 		printf("dynamic\n");
21 	else if (cursor_type == SQL_CURSOR_STATIC)
22 		printf("static\n");
23 	else
24 	{
25 		printf("unknown type of cursor: %d\n", cursor_type);
26 		exit(1);
27 	}
28 }
29 
30 void
print_access_type(SQLINTEGER access_type)31 print_access_type(SQLINTEGER access_type)
32 {
33 	printf("Access type is: ");
34 	if (access_type == SQL_MODE_READ_ONLY)
35 		printf("read-only\n");
36 	else if (access_type == SQL_MODE_READ_WRITE)
37 		printf("read-write\n");
38 	else
39 	{
40 		printf("Incorrect type of access\n");
41 		exit(1);
42 	}
43 }
44 
45 /* Array size for SQLParamOptions test */
46 #define ARRAY_SIZE	10
47 
48 int
main(int argc,char ** argv)49 main(int argc, char **argv)
50 {
51 	SQLRETURN rc;
52 	HSTMT hstmt = SQL_NULL_HSTMT;
53 	SQLHDBC conn2;
54 	SQLHENV env2;
55 	SQLSMALLINT val;
56 	SQLINTEGER valint;
57 	char buffer[256];
58 	char message[1000];
59 	int i;
60 
61 	/* Parameters for SQLParamOptions */
62 	SQLULEN nprocessed;
63 	SQLLEN int_ind_array[ARRAY_SIZE];
64 	SQLLEN str_ind_array[ARRAY_SIZE];
65 	SQLUSMALLINT status_array[ARRAY_SIZE];
66 	SQLUINTEGER int_array[ARRAY_SIZE];
67 	SQLCHAR str_array[ARRAY_SIZE][30];
68 
69 	/*
70 	 * SQLAllocConnect -> SQLAllocHandle
71 	 * SQLAllocEnv -> SQLAllocHandle
72 	 * Get a connection.
73 	 */
74 	printf("Check for SQLAllocEnv\n");
75 	rc = SQLAllocEnv(&env2);
76 	if (!SQL_SUCCEEDED(rc))
77 	{
78 		print_diag("SQLAllocEnv failed", SQL_HANDLE_ENV, env2);
79 		exit(1);
80 	}
81 	SQLSetEnvAttr(env2, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
82 	printf("Check for SQLAllocConnect\n");
83 	rc = SQLAllocConnect(env2, &conn2);
84 	if (!SQL_SUCCEEDED(rc))
85 	{
86 		print_diag("SQLAllocConnect failed", SQL_HANDLE_DBC, conn2);
87 		exit(1);
88 	}
89 
90 	snprintf(buffer, sizeof(buffer), "DSN=%s;", get_test_dsn());
91 
92 	rc = SQLDriverConnect(conn2, NULL, buffer, SQL_NTS,
93 						  NULL, 0, &val,
94 						  SQL_DRIVER_COMPLETE);
95 	if (!SQL_SUCCEEDED(rc))
96 	{
97 		print_diag("SQLDriverConnect failed", SQL_HANDLE_DBC, conn2);
98 		exit(1);
99 	}
100 
101 	/*
102 	 * SQLAllocStmt -> SQLAllocHandle
103 	 * Allocate a statement handle.
104 	 */
105 	printf("Check for SQLAllocStmt\n");
106 	rc = SQLAllocStmt(conn2, &hstmt);
107 	if (!SQL_SUCCEEDED(rc))
108 	{
109 		print_diag("SQLAllocStmt failed", SQL_HANDLE_DBC, conn2);
110 		exit(1);
111 	}
112 
113 	/*
114 	 * SQLSetConnectOption -> SQLSetConnectAttr
115 	 * SQLGetConnectOption -> SQLGetConnectAttr
116 	 * Test connection attribute.
117 	 */
118 	printf("Check for SQLSetConnectOption\n");
119 	rc = SQLSetConnectOption(conn2,
120 							 SQL_ATTR_ACCESS_MODE,
121 							 SQL_MODE_READ_WRITE);
122 	CHECK_STMT_RESULT(rc, "SQLSetConnectOption failed", hstmt);
123 	printf("Check for SQLGetConnectOption\n");
124 	rc = SQLGetConnectOption(conn2,
125 							 SQL_ATTR_ACCESS_MODE,
126 							 &valint);
127 	CHECK_STMT_RESULT(rc, "SQLGetConnectOption failed", hstmt);
128 	print_access_type(valint);
129 
130 	/*
131 	 * SQLError -> SQLGetDiagRec
132 	 * Trigger an error.
133 	 */
134 	printf("Check for SQLError\n");
135 	rc = SQLExecDirect(hstmt,
136 				(SQLCHAR *) "INSERT INTO table_not_here VALUES (1)",
137 				SQL_NTS);
138 	rc = SQLError(env2, conn2, hstmt, buffer, &valint,
139 				  message, 256, &val);
140 	CHECK_STMT_RESULT(rc, "SQLError failed", hstmt);
141 	printf("Error check: %s\n", (char *)message);
142 
143 	/*
144 	 * SQLSetParam[2] -> SQLBindParameter
145 	 * Test for set parameter, somewhat similar to last example.
146 	 */
147 	printf("Check for SQLSetParam\n");
148 	val = 100;
149 	SQLSetParam(hstmt, 1, SQL_C_SHORT, SQL_SMALLINT, 0, 0,
150 				&val, NULL);
151 	CHECK_STMT_RESULT(rc, "SQLSetParam failed", hstmt);
152 	rc = SQLExecDirect(hstmt, (SQLCHAR *) "SELECT ?::int AS foo", SQL_NTS);
153 	CHECK_STMT_RESULT(rc, "SQLExecDirect failed", hstmt);
154 	print_result(hstmt);
155 	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
156 	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
157 
158 	/*
159 	 * SQLGetStmtOption -> SQLGetStmtAttr
160 	 * SQLSetStmtOption -> SQLSetStmtAttr
161 	 * SQLSetScrollOptions -> SQLSetStmtAttr
162 	 * Test for statement and cursor options.
163 	 */
164 
165 	/* Pointer should be forward-only here */
166 	printf("Check for SQLGetStmtOption\n");
167 	rc = SQLGetStmtOption(hstmt, SQL_CURSOR_TYPE, &valint);
168 	CHECK_STMT_RESULT(rc, "SQLGetStmtOption failed", hstmt);
169 	print_cursor_type(valint);
170 
171 	/* Change it to static and check its new value */
172 	printf("Check for SQLSetStmtOption\n");
173 	rc = SQLSetStmtOption(hstmt, SQL_CURSOR_TYPE, SQL_CURSOR_STATIC);
174 	CHECK_STMT_RESULT(rc, "SQLSetStmtOption failed", hstmt);
175 	rc = SQLGetStmtOption(hstmt, SQL_CURSOR_TYPE, &valint);
176 	CHECK_STMT_RESULT(rc, "SQLGetStmtOption failed", hstmt);
177 	print_cursor_type(valint);
178 	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
179 	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
180 
181 	/* Change it now to dynamic using another function */
182 	printf("Check for SQLSetScrollOptions\n");
183 	rc = SQLSetScrollOptions(hstmt, SQL_CONCUR_READ_ONLY,
184 							SQL_SCROLL_FORWARD_ONLY, 1);
185 	CHECK_STMT_RESULT(rc, "SQLSetScrollOptions failed", hstmt);
186 	rc = SQLGetStmtOption(hstmt, SQL_CURSOR_TYPE, &valint);
187 	CHECK_STMT_RESULT(rc, "SQLGetStmtOption failed", hstmt);
188 	/*
189 	 *	The result on Windows is ununderstandable to me.
190 	 *	This deprecated-test doesn't seem to have much meaning.
191 	 *	So just suppress a diff output.
192 	 */
193 #ifdef	WIN32
194 	printf("Cursor type is: forward\n");
195 #else
196 	print_cursor_type(valint);
197 #endif
198 	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
199 	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
200 
201 	/*
202 	 * SQLColAttributes -> SQLColAttribute
203 	 * Test for column attributes. Return column attributes of
204 	 * a simple query.
205 	 */
206 	printf("Check for SQLColAttributes\n");
207 	rc = SQLExecDirect(hstmt,
208 			(SQLCHAR *) "SELECT '1'::int AS foo, 'foobar'::text AS bar",
209 			SQL_NTS);
210 	CHECK_STMT_RESULT(rc, "SQLExecDirect failed", hstmt);
211 	for (i = 0 ; i < 2; i++)
212 	{
213 		char buffer[64];
214 		rc = SQLColAttribute(hstmt, (SQLUSMALLINT) i + 1,
215 							 SQL_DESC_LABEL, buffer, 64, NULL, NULL);
216 		CHECK_STMT_RESULT(rc, "SQLColAttribute failed", hstmt);
217 		printf("Column %d: %s\n", i + 1, buffer);
218 	}
219 	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
220 	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
221 
222 	/*
223 	 * SQLParamOptions -> SQLSetStmtAttr
224 	 * Test for parameter options. SQLParamOptions is mapped using
225 	 * SQL_ATTR_PARAMS_PROCESSED_PTR and SQL_ATTR_PARAMSET_SIZE. Here
226 	 * we insert a set of values in a temporary table.
227 	 */
228 
229 	/* Fill in array values */
230 	for (i = 0; i < ARRAY_SIZE; i++)
231 	{
232 		int_array[i] = i;
233 		int_ind_array[i] = 0;
234 		sprintf(str_array[i], "column num %d", i);
235 		str_ind_array[i] = SQL_NTS;
236 	}
237 	printf("Check for SQLParamOptions\n");
238 	rc = SQLExecDirect(hstmt,
239 		   (SQLCHAR *) "CREATE TEMPORARY TABLE tmptable (i int4, t text)",
240 			   SQL_NTS);
241 	CHECK_STMT_RESULT(rc, "SQLExecDirect failed for table creation", hstmt);
242 
243 	rc = SQLParamOptions(hstmt, (SQLULEN) ARRAY_SIZE, &nprocessed);
244 	CHECK_STMT_RESULT(rc, "SQLParamOptions failed", hstmt);
245 
246 	/* Set some extra parameters */
247 	SQLSetStmtAttr(hstmt, SQL_ATTR_PARAM_BIND_TYPE, SQL_PARAM_BIND_BY_COLUMN, 0);
248 	SQLSetStmtAttr(hstmt, SQL_ATTR_PARAM_STATUS_PTR, status_array, 0);
249 
250 	/* Bind the parameter arrays. */
251 	SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 5, 0,
252 					 int_array, 0, int_ind_array);
253 	SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 29, 0,
254 					 str_array, 30, str_ind_array);
255 
256 	/* Execute and fetch statuses */
257 	rc = SQLExecDirect(hstmt,
258 			(SQLCHAR *) "INSERT INTO tmptable VALUES (?, ?)",
259 			SQL_NTS);
260 	CHECK_STMT_RESULT(rc, "SQLExecDirect failed", hstmt);
261 	printf("Status of execution\n");
262 	for (i = 0; i < nprocessed; i++)
263 	{
264 		switch (status_array[i])
265 		{
266 			case SQL_PARAM_SUCCESS:
267 			case SQL_PARAM_SUCCESS_WITH_INFO:
268 				break;
269 
270 			case SQL_PARAM_ERROR:
271 				printf("%d\tError\n", i);
272 				break;
273 
274 			case SQL_PARAM_UNUSED:
275 				printf("%d\tUnused\n", i);
276 				break;
277 
278 			case SQL_PARAM_DIAG_UNAVAILABLE:
279 				printf("%d\tDiag unavailable\n", i);
280 				break;
281 		}
282 	}
283 
284 	/*
285 	 * SQLFreeStmt(SQL_DROP) -> SQLFreeHandle
286 	 *
287 	 * Free the statement handle used. SQL_DROP is deprecated, other
288 	 * options are not.
289 	 */
290 	printf("Check for SQLFreeStmt\n");
291 	rc = SQLFreeStmt(hstmt, SQL_DROP);
292 	CHECK_STMT_RESULT(rc, "SQLFreeStmt with SQL_DROP failed", hstmt);
293 
294 	/*
295 	 * SQLFreeConnect -> SQLFreeHandle
296 	 * SQLFreeEnv -> SQLFreeHandle
297 	 * Disconnect and free connection.
298 	 */
299 	rc = SQLDisconnect(conn2);
300 	if (!SQL_SUCCEEDED(rc))
301 	{
302 		print_diag("SQLDisconnect failed", SQL_HANDLE_DBC, conn2);
303 		exit(1);
304 	}
305 	printf("Check for SQLFreeConnect\n");
306 	rc = SQLFreeConnect(conn2);
307 	if (!SQL_SUCCEEDED(rc))
308 	{
309 		print_diag("SQLFreeConnect failed", SQL_HANDLE_DBC, conn2);
310 		exit(1);
311 	}
312 	printf("Check for SQLFreeEnv\n");
313 	rc = SQLFreeEnv(env2);
314 	if (!SQL_SUCCEEDED(rc))
315 	{
316 		print_diag("SQLFreeEnv failed", SQL_HANDLE_ENV, env2);
317 		exit(1);
318 	}
319 
320 	/* Grab new connection and handle for the next tests */
321 	test_connect();
322 	rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt);
323 	if (!SQL_SUCCEEDED(rc))
324 	{
325 		print_diag("failed to allocate stmt handle", SQL_HANDLE_DBC, conn);
326 		exit(1);
327 	}
328 
329 	/*
330 	 * SQLTransact -> SQLEndTran
331 	 * Check transaction ROLLBACK using SQLTransact.
332 	 */
333 	printf("Check for SQLTransact\n");
334 
335 	/* First disable autocommit */
336 	rc = SQLSetConnectAttr(conn,
337 						   SQL_ATTR_AUTOCOMMIT,
338 						   (SQLPOINTER)SQL_AUTOCOMMIT_OFF,
339 						   SQL_IS_UINTEGER);
340 
341 	/* Insert a row and rollback it */
342 	rc = SQLExecDirect(hstmt,
343 			(SQLCHAR *) "INSERT INTO testtab1 VALUES (200, 'foo')",
344 			SQL_NTS);
345 	CHECK_STMT_RESULT(rc, "SQLExecDirect failed", hstmt);
346 	rc = SQLTransact(SQL_NULL_HENV, conn, SQL_ROLLBACK);
347 	CHECK_STMT_RESULT(rc, "SQLTransact failed", hstmt);
348 
349 	/* Now check that the row is not inserted */
350 	rc = SQLExecDirect(hstmt,
351 			(SQLCHAR *) "SELECT t FROM testtab1 WHERE id = 200",
352 			SQL_NTS);
353 	CHECK_STMT_RESULT(rc, "SQLExecDirect failed", hstmt);
354 	print_result(hstmt);
355 	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
356 	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
357 
358 	/* Clean up */
359 	test_disconnect();
360 
361 	return 0;
362 }
363