1 /*-------
2  * Module:			odbcapi30.c
3  *
4  * Description:		This module contains routines related to ODBC 3.0
5  *			most of their implementations are temporary
6  *			and must be rewritten properly.
7  *			2001/07/23	inoue
8  *
9  * Classes:			n/a
10  *
11  * API functions:	SQLAllocHandle, SQLBindParam, SQLCloseCursor,
12 			SQLColAttribute, SQLCopyDesc, SQLEndTran,
13 			SQLFetchScroll, SQLFreeHandle, SQLGetDescField,
14 			SQLGetDescRec, SQLGetDiagField, SQLGetDiagRec,
15 			SQLGetEnvAttr, SQLGetConnectAttr, SQLGetStmtAttr,
16 			SQLSetConnectAttr, SQLSetDescField, SQLSetDescRec,
17 			SQLSetEnvAttr, SQLSetStmtAttr, SQLBulkOperations
18  *-------
19  */
20 
21 #include "psqlodbc.h"
22 #include "misc.h"
23 
24 #include <stdio.h>
25 #include <string.h>
26 
27 #include "environ.h"
28 #include "connection.h"
29 #include "statement.h"
30 #include "pgapifunc.h"
31 
32 /*	SQLAllocConnect/SQLAllocEnv/SQLAllocStmt -> SQLAllocHandle */
33 RETCODE		SQL_API
SQLAllocHandle(SQLSMALLINT HandleType,SQLHANDLE InputHandle,SQLHANDLE * OutputHandle)34 SQLAllocHandle(SQLSMALLINT HandleType,
35 			   SQLHANDLE InputHandle, SQLHANDLE * OutputHandle)
36 {
37 	RETCODE		ret;
38 	ConnectionClass	*conn;
39 
40 	MYLOG(0, "Entering\n");
41 	switch (HandleType)
42 	{
43 		case SQL_HANDLE_ENV:
44 			ret = PGAPI_AllocEnv(OutputHandle);
45 			break;
46 		case SQL_HANDLE_DBC:
47 			ENTER_ENV_CS((EnvironmentClass *) InputHandle);
48 			ret = PGAPI_AllocConnect(InputHandle, OutputHandle);
49 			LEAVE_ENV_CS((EnvironmentClass *) InputHandle);
50 			break;
51 		case SQL_HANDLE_STMT:
52 			conn = (ConnectionClass *) InputHandle;
53 			CC_examine_global_transaction(conn);
54 			ENTER_CONN_CS(conn);
55 			ret = PGAPI_AllocStmt(InputHandle, OutputHandle, PODBC_EXTERNAL_STATEMENT | PODBC_INHERIT_CONNECT_OPTIONS);
56 			if (*OutputHandle)
57 				((StatementClass *) (*OutputHandle))->external = 1;
58 			LEAVE_CONN_CS(conn);
59 			break;
60 		case SQL_HANDLE_DESC:
61 			conn = (ConnectionClass *) InputHandle;
62 			CC_examine_global_transaction(conn);
63 			ENTER_CONN_CS(conn);
64 			ret = PGAPI_AllocDesc(InputHandle, OutputHandle);
65 			LEAVE_CONN_CS(conn);
66 MYLOG(DETAIL_LOG_LEVEL, "OutputHandle=%p\n", *OutputHandle);
67 			break;
68 		default:
69 			ret = SQL_ERROR;
70 			break;
71 	}
72 	return ret;
73 }
74 
75 /*	SQLBindParameter/SQLSetParam -> SQLBindParam */
76 RETCODE		SQL_API
SQLBindParam(HSTMT StatementHandle,SQLUSMALLINT ParameterNumber,SQLSMALLINT ValueType,SQLSMALLINT ParameterType,SQLULEN LengthPrecision,SQLSMALLINT ParameterScale,PTR ParameterValue,SQLLEN * StrLen_or_Ind)77 SQLBindParam(HSTMT StatementHandle,
78 			 SQLUSMALLINT ParameterNumber, SQLSMALLINT ValueType,
79 			 SQLSMALLINT ParameterType, SQLULEN LengthPrecision,
80 			 SQLSMALLINT ParameterScale, PTR ParameterValue,
81 			 SQLLEN *StrLen_or_Ind)
82 {
83 	RETCODE			ret;
84 	StatementClass	*stmt = (StatementClass *) StatementHandle;
85 	int			BufferLength = 512;		/* Is it OK ? */
86 
87 	MYLOG(0, "Entering\n");
88 	ENTER_STMT_CS(stmt);
89 	SC_clear_error(stmt);
90 	StartRollbackState(stmt);
91 	ret = PGAPI_BindParameter(StatementHandle, ParameterNumber, SQL_PARAM_INPUT, ValueType, ParameterType, LengthPrecision, ParameterScale, ParameterValue, BufferLength, StrLen_or_Ind);
92 	ret = DiscardStatementSvp(stmt,ret, FALSE);
93 	LEAVE_STMT_CS(stmt);
94 	return ret;
95 }
96 
97 /*	New function */
98 RETCODE		SQL_API
SQLCloseCursor(HSTMT StatementHandle)99 SQLCloseCursor(HSTMT StatementHandle)
100 {
101 	StatementClass	*stmt = (StatementClass *) StatementHandle;
102 	RETCODE	ret;
103 
104 	MYLOG(0, "Entering\n");
105 	if (SC_connection_lost_check(stmt, __FUNCTION__))
106 		return SQL_ERROR;
107 
108 	ENTER_STMT_CS(stmt);
109 	SC_clear_error(stmt);
110 	StartRollbackState(stmt);
111 	ret = PGAPI_FreeStmt(StatementHandle, SQL_CLOSE);
112 	ret = DiscardStatementSvp(stmt,ret, FALSE);
113 	LEAVE_STMT_CS(stmt);
114 	return ret;
115 }
116 
117 #ifndef	UNICODE_SUPPORTXX
118 /*	SQLColAttributes -> SQLColAttribute */
119 SQLRETURN	SQL_API
SQLColAttribute(SQLHSTMT StatementHandle,SQLUSMALLINT ColumnNumber,SQLUSMALLINT FieldIdentifier,SQLPOINTER CharacterAttribute,SQLSMALLINT BufferLength,SQLSMALLINT * StringLength,SQLLEN * NumericAttribute)120 SQLColAttribute(SQLHSTMT StatementHandle,
121 				SQLUSMALLINT ColumnNumber,
122 				SQLUSMALLINT FieldIdentifier,
123 				SQLPOINTER CharacterAttribute,
124 				SQLSMALLINT BufferLength,
125 				SQLSMALLINT *StringLength,
126 #if defined(_WIN64) || defined(SQLCOLATTRIBUTE_SQLLEN)
127 				SQLLEN *NumericAttribute
128 #else
129 				SQLPOINTER NumericAttribute
130 #endif
131 			)
132 {
133 	RETCODE	ret;
134 	StatementClass	*stmt = (StatementClass *) StatementHandle;
135 
136 	MYLOG(0, "Entering\n");
137 	if (SC_connection_lost_check(stmt, __FUNCTION__))
138 		return SQL_ERROR;
139 
140 	ENTER_STMT_CS(stmt);
141 	SC_clear_error(stmt);
142 	StartRollbackState(stmt);
143 	ret = PGAPI_ColAttributes(StatementHandle, ColumnNumber,
144 					   FieldIdentifier, CharacterAttribute, BufferLength,
145 							   StringLength, NumericAttribute);
146 	ret = DiscardStatementSvp(stmt,ret, FALSE);
147 	LEAVE_STMT_CS(stmt);
148 	return ret;
149 }
150 #endif /* UNICODE_SUPPORTXX */
151 
152 /*	new function */
153 RETCODE		SQL_API
SQLCopyDesc(SQLHDESC SourceDescHandle,SQLHDESC TargetDescHandle)154 SQLCopyDesc(SQLHDESC SourceDescHandle,
155 			SQLHDESC TargetDescHandle)
156 {
157 	RETCODE	ret;
158 
159 	MYLOG(0, "Entering\n");
160 	ret = PGAPI_CopyDesc(SourceDescHandle, TargetDescHandle);
161 	return ret;
162 }
163 
164 /*	SQLTransact -> SQLEndTran */
165 RETCODE		SQL_API
SQLEndTran(SQLSMALLINT HandleType,SQLHANDLE Handle,SQLSMALLINT CompletionType)166 SQLEndTran(SQLSMALLINT HandleType, SQLHANDLE Handle,
167 		   SQLSMALLINT CompletionType)
168 {
169 	RETCODE	ret;
170 
171 	MYLOG(0, "Entering\n");
172 	switch (HandleType)
173 	{
174 		case SQL_HANDLE_ENV:
175 			ENTER_ENV_CS((EnvironmentClass *) Handle);
176 			ret = PGAPI_Transact(Handle, SQL_NULL_HDBC, CompletionType);
177 			LEAVE_ENV_CS((EnvironmentClass *) Handle);
178 			break;
179 		case SQL_HANDLE_DBC:
180 			CC_examine_global_transaction((ConnectionClass *) Handle);
181 			ENTER_CONN_CS((ConnectionClass *) Handle);
182 			CC_clear_error((ConnectionClass *) Handle);
183 			ret = PGAPI_Transact(SQL_NULL_HENV, Handle, CompletionType);
184 			LEAVE_CONN_CS((ConnectionClass *) Handle);
185 			break;
186 		default:
187 			ret = SQL_ERROR;
188 			break;
189 	}
190 	return ret;
191 }
192 
193 /*	SQLExtendedFetch -> SQLFetchScroll */
194 RETCODE		SQL_API
SQLFetchScroll(HSTMT StatementHandle,SQLSMALLINT FetchOrientation,SQLLEN FetchOffset)195 SQLFetchScroll(HSTMT StatementHandle,
196 			   SQLSMALLINT FetchOrientation, SQLLEN FetchOffset)
197 {
198 	CSTR func = "SQLFetchScroll";
199 	StatementClass *stmt = (StatementClass *) StatementHandle;
200 	RETCODE		ret = SQL_SUCCESS;
201 	IRDFields	*irdopts = SC_get_IRDF(stmt);
202 	SQLUSMALLINT *rowStatusArray = irdopts->rowStatusArray;
203 	SQLULEN *pcRow = irdopts->rowsFetched;
204 	SQLLEN	bkmarkoff = 0;
205 
206 	MYLOG(0, "Entering %d," FORMAT_LEN "\n", FetchOrientation, FetchOffset);
207 	if (SC_connection_lost_check(stmt, __FUNCTION__))
208 		return SQL_ERROR;
209 
210 	ENTER_STMT_CS(stmt);
211 	SC_clear_error(stmt);
212 	StartRollbackState(stmt);
213 	if (FetchOrientation == SQL_FETCH_BOOKMARK)
214 	{
215 		if (stmt->options.bookmark_ptr)
216 		{
217 			bkmarkoff = FetchOffset;
218 			FetchOffset = *((Int4 *) stmt->options.bookmark_ptr);
219 MYLOG(0, "bookmark=" FORMAT_LEN " FetchOffset = " FORMAT_LEN "\n", FetchOffset, bkmarkoff);
220 		}
221 		else
222 		{
223 			SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Bookmark isn't specifed yet", func);
224 			ret = SQL_ERROR;
225 		}
226 	}
227 	if (SQL_SUCCESS == ret)
228 	{
229 		ARDFields	*opts = SC_get_ARDF(stmt);
230 
231 		ret = PGAPI_ExtendedFetch(StatementHandle, FetchOrientation, FetchOffset,
232 				pcRow, rowStatusArray, bkmarkoff, opts->size_of_rowset);
233 		stmt->transition_status = STMT_TRANSITION_FETCH_SCROLL;
234 	}
235 	ret = DiscardStatementSvp(stmt,ret, FALSE);
236 	LEAVE_STMT_CS(stmt);
237 	if (ret != SQL_SUCCESS)
238 		MYLOG(0, "leaving return = %d\n", ret);
239 	return ret;
240 }
241 
242 /*	SQLFree(Connect/Env/Stmt) -> SQLFreeHandle */
243 RETCODE		SQL_API
SQLFreeHandle(SQLSMALLINT HandleType,SQLHANDLE Handle)244 SQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle)
245 {
246 	RETCODE		ret;
247 	StatementClass *stmt;
248 	ConnectionClass *conn = NULL;
249 
250 	MYLOG(0, "Entering\n");
251 
252 	switch (HandleType)
253 	{
254 		case SQL_HANDLE_ENV:
255 			ret = PGAPI_FreeEnv(Handle);
256 			break;
257 		case SQL_HANDLE_DBC:
258 			ret = PGAPI_FreeConnect(Handle);
259 			break;
260 		case SQL_HANDLE_STMT:
261 			stmt = (StatementClass *) Handle;
262 
263 			if (stmt)
264 			{
265 				conn = stmt->hdbc;
266 				if (conn)
267 					ENTER_CONN_CS(conn);
268 			}
269 
270 			ret = PGAPI_FreeStmt(Handle, SQL_DROP);
271 
272 			if (conn)
273 				LEAVE_CONN_CS(conn);
274 
275 			break;
276 		case SQL_HANDLE_DESC:
277 			ret = PGAPI_FreeDesc(Handle);
278 			break;
279 		default:
280 			ret = SQL_ERROR;
281 			break;
282 	}
283 	return ret;
284 }
285 
286 #ifndef	UNICODE_SUPPORTXX
287 /*	new function */
288 RETCODE		SQL_API
SQLGetDescField(SQLHDESC DescriptorHandle,SQLSMALLINT RecNumber,SQLSMALLINT FieldIdentifier,PTR Value,SQLINTEGER BufferLength,SQLINTEGER * StringLength)289 SQLGetDescField(SQLHDESC DescriptorHandle,
290 				SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
291 				PTR Value, SQLINTEGER BufferLength,
292 				SQLINTEGER *StringLength)
293 {
294 	RETCODE	ret;
295 
296 	MYLOG(0, "Entering\n");
297 	ret = PGAPI_GetDescField(DescriptorHandle, RecNumber, FieldIdentifier,
298 			Value, BufferLength, StringLength);
299 	return ret;
300 }
301 
302 /*	new function */
303 RETCODE		SQL_API
SQLGetDescRec(SQLHDESC DescriptorHandle,SQLSMALLINT RecNumber,SQLCHAR * Name,SQLSMALLINT BufferLength,SQLSMALLINT * StringLength,SQLSMALLINT * Type,SQLSMALLINT * SubType,SQLLEN * Length,SQLSMALLINT * Precision,SQLSMALLINT * Scale,SQLSMALLINT * Nullable)304 SQLGetDescRec(SQLHDESC DescriptorHandle,
305 			  SQLSMALLINT RecNumber, SQLCHAR *Name,
306 			  SQLSMALLINT BufferLength, SQLSMALLINT *StringLength,
307 			  SQLSMALLINT *Type, SQLSMALLINT *SubType,
308 			  SQLLEN *Length, SQLSMALLINT *Precision,
309 			  SQLSMALLINT *Scale, SQLSMALLINT *Nullable)
310 {
311 	MYLOG(0, "Entering\n");
312 	MYLOG(0, "Error not implemented\n");
313 	return SQL_ERROR;
314 }
315 
316 /*	new function */
317 RETCODE		SQL_API
SQLGetDiagField(SQLSMALLINT HandleType,SQLHANDLE Handle,SQLSMALLINT RecNumber,SQLSMALLINT DiagIdentifier,PTR DiagInfo,SQLSMALLINT BufferLength,SQLSMALLINT * StringLength)318 SQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
319 				SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier,
320 				PTR DiagInfo, SQLSMALLINT BufferLength,
321 				SQLSMALLINT *StringLength)
322 {
323 	RETCODE	ret;
324 
325 	MYLOG(0, "Entering Handle=(%u,%p) Rec=%d Id=%d info=(%p,%d)\n", HandleType, Handle, RecNumber, DiagIdentifier, DiagInfo, BufferLength);
326 	ret = PGAPI_GetDiagField(HandleType, Handle, RecNumber, DiagIdentifier,
327 				DiagInfo, BufferLength, StringLength);
328 	return ret;
329 }
330 
331 /*	SQLError -> SQLDiagRec */
332 RETCODE		SQL_API
SQLGetDiagRec(SQLSMALLINT HandleType,SQLHANDLE Handle,SQLSMALLINT RecNumber,SQLCHAR * Sqlstate,SQLINTEGER * NativeError,SQLCHAR * MessageText,SQLSMALLINT BufferLength,SQLSMALLINT * TextLength)333 SQLGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
334 			  SQLSMALLINT RecNumber, SQLCHAR *Sqlstate,
335 			  SQLINTEGER *NativeError, SQLCHAR *MessageText,
336 			  SQLSMALLINT BufferLength, SQLSMALLINT *TextLength)
337 {
338 	RETCODE	ret;
339 
340 	MYLOG(0, "Entering\n");
341 	ret = PGAPI_GetDiagRec(HandleType, Handle, RecNumber, Sqlstate,
342 			NativeError, MessageText, BufferLength, TextLength);
343 	return ret;
344 }
345 #endif /* UNICODE_SUPPORTXX */
346 
347 /*	new function */
348 RETCODE		SQL_API
SQLGetEnvAttr(HENV EnvironmentHandle,SQLINTEGER Attribute,PTR Value,SQLINTEGER BufferLength,SQLINTEGER * StringLength)349 SQLGetEnvAttr(HENV EnvironmentHandle,
350 			  SQLINTEGER Attribute, PTR Value,
351 			  SQLINTEGER BufferLength, SQLINTEGER *StringLength)
352 {
353 	RETCODE	ret;
354 	EnvironmentClass *env = (EnvironmentClass *) EnvironmentHandle;
355 
356 	MYLOG(0, "Entering " FORMAT_INTEGER "\n", Attribute);
357 	ENTER_ENV_CS(env);
358 	ret = SQL_SUCCESS;
359 	switch (Attribute)
360 	{
361 		case SQL_ATTR_CONNECTION_POOLING:
362 			*((unsigned int *) Value) = EN_is_pooling(env) ? SQL_CP_ONE_PER_DRIVER : SQL_CP_OFF;
363 			break;
364 		case SQL_ATTR_CP_MATCH:
365 			*((unsigned int *) Value) = SQL_CP_RELAXED_MATCH;
366 			break;
367 		case SQL_ATTR_ODBC_VERSION:
368 			*((unsigned int *) Value) = EN_is_odbc2(env) ? SQL_OV_ODBC2 : SQL_OV_ODBC3;
369 			break;
370 		case SQL_ATTR_OUTPUT_NTS:
371 			*((unsigned int *) Value) = SQL_TRUE;
372 			break;
373 		default:
374 			env->errornumber = CONN_INVALID_ARGUMENT_NO;
375 			ret = SQL_ERROR;
376 	}
377 	LEAVE_ENV_CS(env);
378 	return ret;
379 }
380 
381 #ifndef	UNICODE_SUPPORTXX
382 /*	SQLGetConnectOption -> SQLGetconnectAttr */
383 RETCODE		SQL_API
SQLGetConnectAttr(HDBC ConnectionHandle,SQLINTEGER Attribute,PTR Value,SQLINTEGER BufferLength,SQLINTEGER * StringLength)384 SQLGetConnectAttr(HDBC ConnectionHandle,
385 				  SQLINTEGER Attribute, PTR Value,
386 				  SQLINTEGER BufferLength, SQLINTEGER *StringLength)
387 {
388 	RETCODE	ret;
389 
390 	MYLOG(0, "Entering " FORMAT_UINTEGER "\n", Attribute);
391 	CC_examine_global_transaction((ConnectionClass*) ConnectionHandle);
392 	ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
393 	CC_clear_error((ConnectionClass *) ConnectionHandle);
394 	ret = PGAPI_GetConnectAttr(ConnectionHandle, Attribute,Value,
395 			BufferLength, StringLength);
396 	LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
397 	return ret;
398 }
399 
400 /*	SQLGetStmtOption -> SQLGetStmtAttr */
401 RETCODE		SQL_API
SQLGetStmtAttr(HSTMT StatementHandle,SQLINTEGER Attribute,PTR Value,SQLINTEGER BufferLength,SQLINTEGER * StringLength)402 SQLGetStmtAttr(HSTMT StatementHandle,
403 			   SQLINTEGER Attribute, PTR Value,
404 			   SQLINTEGER BufferLength, SQLINTEGER *StringLength)
405 {
406 	RETCODE	ret;
407 	StatementClass	*stmt = (StatementClass *) StatementHandle;
408 
409 	MYLOG(0, "Entering Handle=%p " FORMAT_INTEGER "\n", StatementHandle, Attribute);
410 	ENTER_STMT_CS(stmt);
411 	SC_clear_error(stmt);
412 	StartRollbackState(stmt);
413 	ret = PGAPI_GetStmtAttr(StatementHandle, Attribute, Value,
414 			BufferLength, StringLength);
415 	ret = DiscardStatementSvp(stmt,ret, FALSE);
416 	LEAVE_STMT_CS(stmt);
417 	return ret;
418 }
419 
420 /*	SQLSetConnectOption -> SQLSetConnectAttr */
421 RETCODE		SQL_API
SQLSetConnectAttr(HDBC ConnectionHandle,SQLINTEGER Attribute,PTR Value,SQLINTEGER StringLength)422 SQLSetConnectAttr(HDBC ConnectionHandle,
423 				  SQLINTEGER Attribute, PTR Value,
424 				  SQLINTEGER StringLength)
425 {
426 	RETCODE	ret;
427 	ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
428 
429 	MYLOG(0, "Entering " FORMAT_INTEGER "\n", Attribute);
430 	CC_examine_global_transaction(conn);
431 	ENTER_CONN_CS(conn);
432 	CC_clear_error(conn);
433 	ret = PGAPI_SetConnectAttr(ConnectionHandle, Attribute, Value,
434 				  StringLength);
435 	LEAVE_CONN_CS(conn);
436 	return ret;
437 }
438 
439 /*	new function */
440 RETCODE		SQL_API
SQLSetDescField(SQLHDESC DescriptorHandle,SQLSMALLINT RecNumber,SQLSMALLINT FieldIdentifier,PTR Value,SQLINTEGER BufferLength)441 SQLSetDescField(SQLHDESC DescriptorHandle,
442 				SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
443 				PTR Value, SQLINTEGER BufferLength)
444 {
445 	RETCODE		ret;
446 
447 	MYLOG(0, "Entering h=%p rec=%d field=%d val=%p\n", DescriptorHandle, RecNumber, FieldIdentifier, Value);
448 	ret = PGAPI_SetDescField(DescriptorHandle, RecNumber, FieldIdentifier,
449 				Value, BufferLength);
450 	return ret;
451 }
452 
453 /*	new fucntion */
454 RETCODE		SQL_API
SQLSetDescRec(SQLHDESC DescriptorHandle,SQLSMALLINT RecNumber,SQLSMALLINT Type,SQLSMALLINT SubType,SQLLEN Length,SQLSMALLINT Precision,SQLSMALLINT Scale,PTR Data,SQLLEN * StringLength,SQLLEN * Indicator)455 SQLSetDescRec(SQLHDESC DescriptorHandle,
456 			  SQLSMALLINT RecNumber, SQLSMALLINT Type,
457 			  SQLSMALLINT SubType, SQLLEN Length,
458 			  SQLSMALLINT Precision, SQLSMALLINT Scale,
459 			  PTR Data, SQLLEN *StringLength,
460 			  SQLLEN *Indicator)
461 {
462 	MYLOG(0, "Entering\n");
463 	MYLOG(0, "Error not implemented\n");
464 	return SQL_ERROR;
465 }
466 #endif /* UNICODE_SUPPORTXX */
467 
468 /*	new function */
469 RETCODE		SQL_API
SQLSetEnvAttr(HENV EnvironmentHandle,SQLINTEGER Attribute,PTR Value,SQLINTEGER StringLength)470 SQLSetEnvAttr(HENV EnvironmentHandle,
471 			  SQLINTEGER Attribute, PTR Value,
472 			  SQLINTEGER StringLength)
473 {
474 	RETCODE	ret;
475 	EnvironmentClass *env = (EnvironmentClass *) EnvironmentHandle;
476 
477 	MYLOG(0, "Entering att=" FORMAT_INTEGER "," FORMAT_ULEN "\n", Attribute, (SQLULEN) Value);
478 	ENTER_ENV_CS(env);
479 	switch (Attribute)
480 	{
481 		case SQL_ATTR_CONNECTION_POOLING:
482 			switch ((ULONG_PTR) Value)
483 			{
484 				case SQL_CP_OFF:
485 					EN_unset_pooling(env);
486 					ret = SQL_SUCCESS;
487 					break;
488 #if defined(WIN_MULTITHREAD_SUPPORT) || defined(POSIX_MULTITHREAD_SUPPORT)
489 				case SQL_CP_ONE_PER_DRIVER:
490 					EN_set_pooling(env);
491 					ret = SQL_SUCCESS;
492 					break;
493 #endif /* WIN_MULTITHREAD_SUPPORT */
494 				default:
495 					ret = SQL_SUCCESS_WITH_INFO;
496 			}
497 			break;
498 		case SQL_ATTR_CP_MATCH:
499 			/* *((unsigned int *) Value) = SQL_CP_RELAXED_MATCH; */
500 			ret = SQL_SUCCESS;
501 			break;
502 		case SQL_ATTR_ODBC_VERSION:
503 			if (SQL_OV_ODBC2 == CAST_UPTR(SQLUINTEGER, Value))
504 				EN_set_odbc2(env);
505 			else
506 				EN_set_odbc3(env);
507 			ret = SQL_SUCCESS;
508 			break;
509 		case SQL_ATTR_OUTPUT_NTS:
510 			if (SQL_TRUE == CAST_UPTR(SQLUINTEGER, Value))
511 				ret = SQL_SUCCESS;
512 			else
513 				ret = SQL_SUCCESS_WITH_INFO;
514 			break;
515 		default:
516 			env->errornumber = CONN_INVALID_ARGUMENT_NO;
517 			ret = SQL_ERROR;
518 	}
519 	if (SQL_SUCCESS_WITH_INFO == ret)
520 	{
521 		env->errornumber = CONN_OPTION_VALUE_CHANGED;
522 		env->errormsg = "SetEnv changed to ";
523 	}
524 	LEAVE_ENV_CS(env);
525 	return ret;
526 }
527 
528 #ifndef	UNICODE_SUPPORTXX
529 /*	SQLSet(Param/Scroll/Stmt)Option -> SQLSetStmtAttr */
530 RETCODE		SQL_API
SQLSetStmtAttr(HSTMT StatementHandle,SQLINTEGER Attribute,PTR Value,SQLINTEGER StringLength)531 SQLSetStmtAttr(HSTMT StatementHandle,
532 			   SQLINTEGER Attribute, PTR Value,
533 			   SQLINTEGER StringLength)
534 {
535 	StatementClass *stmt = (StatementClass *) StatementHandle;
536 	RETCODE	ret;
537 
538 	MYLOG(0, "Entering Handle=%p " FORMAT_INTEGER "," FORMAT_ULEN "\n", StatementHandle, Attribute, (SQLULEN) Value);
539 	ENTER_STMT_CS(stmt);
540 	SC_clear_error(stmt);
541 	StartRollbackState(stmt);
542 	ret = PGAPI_SetStmtAttr(StatementHandle, Attribute, Value, StringLength);
543 	ret = DiscardStatementSvp(stmt,ret, FALSE);
544 	LEAVE_STMT_CS(stmt);
545 	return ret;
546 }
547 #endif /* UNICODE_SUPPORTXX */
548 
549 #define SQL_FUNC_ESET(pfExists, uwAPI) \
550 		(*(((UWORD*) (pfExists)) + ((uwAPI) >> 4)) \
551 			|= (1 << ((uwAPI) & 0x000F)) \
552 				)
553 RETCODE		SQL_API
PGAPI_GetFunctions30(HDBC hdbc,SQLUSMALLINT fFunction,SQLUSMALLINT FAR * pfExists)554 PGAPI_GetFunctions30(HDBC hdbc, SQLUSMALLINT fFunction, SQLUSMALLINT FAR * pfExists)
555 {
556 	ConnectionClass	*conn = (ConnectionClass *) hdbc;
557 	ConnInfo	*ci = &(conn->connInfo);
558 
559 MYLOG(DETAIL_LOG_LEVEL, "lie=%d\n", ci->drivers.lie);
560 	CC_examine_global_transaction(conn);
561 	CC_clear_error(conn);
562 	if (fFunction != SQL_API_ODBC3_ALL_FUNCTIONS)
563 		return SQL_ERROR;
564 	memset(pfExists, 0, sizeof(UWORD) * SQL_API_ODBC3_ALL_FUNCTIONS_SIZE);
565 
566 	/* SQL_FUNC_ESET(pfExists, SQL_API_SQLALLOCCONNECT); 1 deprecated */
567 	/* SQL_FUNC_ESET(pfExists, SQL_API_SQLALLOCENV); 2 deprecated */
568 	/* SQL_FUNC_ESET(pfExists, SQL_API_SQLALLOCSTMT); 3 deprecated */
569 
570 	/*
571 	 * for (i = SQL_API_SQLBINDCOL; i <= 23; i++) SQL_FUNC_ESET(pfExists,
572 	 * i);
573 	 */
574 	SQL_FUNC_ESET(pfExists, SQL_API_SQLBINDCOL);		/* 4 */
575 	SQL_FUNC_ESET(pfExists, SQL_API_SQLCANCEL);		/* 5 */
576 	SQL_FUNC_ESET(pfExists, SQL_API_SQLCOLATTRIBUTE);	/* 6 */
577 	SQL_FUNC_ESET(pfExists, SQL_API_SQLCONNECT);		/* 7 */
578 	SQL_FUNC_ESET(pfExists, SQL_API_SQLDESCRIBECOL);	/* 8 */
579 	SQL_FUNC_ESET(pfExists, SQL_API_SQLDISCONNECT);		/* 9 */
580 	/* SQL_FUNC_ESET(pfExists, SQL_API_SQLERROR);  10 deprecated */
581 	SQL_FUNC_ESET(pfExists, SQL_API_SQLEXECDIRECT);		/* 11 */
582 	SQL_FUNC_ESET(pfExists, SQL_API_SQLEXECUTE);		/* 12 */
583 	SQL_FUNC_ESET(pfExists, SQL_API_SQLFETCH);	/* 13 */
584 	/* SQL_FUNC_ESET(pfExists, SQL_API_SQLFREECONNECT); 14 deprecated */
585 	/* SQL_FUNC_ESET(pfExists, SQL_API_SQLFREEENV); 15 deprecated */
586 	SQL_FUNC_ESET(pfExists, SQL_API_SQLFREESTMT);		/* 16 */
587 	SQL_FUNC_ESET(pfExists, SQL_API_SQLGETCURSORNAME);	/* 17 */
588 	SQL_FUNC_ESET(pfExists, SQL_API_SQLNUMRESULTCOLS);	/* 18 */
589 	SQL_FUNC_ESET(pfExists, SQL_API_SQLPREPARE);		/* 19 */
590 	SQL_FUNC_ESET(pfExists, SQL_API_SQLROWCOUNT);		/* 20 */
591 	SQL_FUNC_ESET(pfExists, SQL_API_SQLSETCURSORNAME);	/* 21 */
592 	/* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETPARAM); 22 deprecated */
593 	/* SQL_FUNC_ESET(pfExists, SQL_API_SQLTRANSACT); 23 deprecated */
594 
595 	/*
596 	 * for (i = 40; i < SQL_API_SQLEXTENDEDFETCH; i++)
597 	 * SQL_FUNC_ESET(pfExists, i);
598 	 */
599 	SQL_FUNC_ESET(pfExists, SQL_API_SQLCOLUMNS);		/* 40 */
600 	SQL_FUNC_ESET(pfExists, SQL_API_SQLDRIVERCONNECT);	/* 41 */
601 	/* SQL_FUNC_ESET(pfExists, SQL_API_SQLGETCONNECTOPTION); 42 deprecated */
602 	SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDATA);		/* 43 */
603 	SQL_FUNC_ESET(pfExists, SQL_API_SQLGETFUNCTIONS);	/* 44 */
604 	SQL_FUNC_ESET(pfExists, SQL_API_SQLGETINFO);		/* 45 */
605 	/* SQL_FUNC_ESET(pfExists, SQL_API_SQLGETSTMTOPTION); 46 deprecated */
606 	SQL_FUNC_ESET(pfExists, SQL_API_SQLGETTYPEINFO);	/* 47 */
607 	SQL_FUNC_ESET(pfExists, SQL_API_SQLPARAMDATA);		/* 48 */
608 	SQL_FUNC_ESET(pfExists, SQL_API_SQLPUTDATA);		/* 49 */
609 
610 	/* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETCONNECTIONOPTION); 50 deprecated */
611 	/* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSTMTOPTION); 51 deprecated */
612 	SQL_FUNC_ESET(pfExists, SQL_API_SQLSPECIALCOLUMNS);	/* 52 */
613 	SQL_FUNC_ESET(pfExists, SQL_API_SQLSTATISTICS);		/* 53 */
614 	SQL_FUNC_ESET(pfExists, SQL_API_SQLTABLES);		/* 54 */
615 	if (ci->drivers.lie)
616 		SQL_FUNC_ESET(pfExists, SQL_API_SQLBROWSECONNECT);	/* 55 */
617 	if (ci->drivers.lie)
618 		SQL_FUNC_ESET(pfExists, SQL_API_SQLCOLUMNPRIVILEGES);	/* 56 */
619 	SQL_FUNC_ESET(pfExists, SQL_API_SQLDATASOURCES);	/* 57 */
620 	if (SUPPORT_DESCRIBE_PARAM(ci) || ci->drivers.lie)
621 		SQL_FUNC_ESET(pfExists, SQL_API_SQLDESCRIBEPARAM); /* 58 */
622 	SQL_FUNC_ESET(pfExists, SQL_API_SQLEXTENDEDFETCH); /* 59 deprecated ? */
623 
624 	/*
625 	 * for (++i; i < SQL_API_SQLBINDPARAMETER; i++)
626 	 * SQL_FUNC_ESET(pfExists, i);
627 	 */
628 	SQL_FUNC_ESET(pfExists, SQL_API_SQLFOREIGNKEYS);	/* 60 */
629 	SQL_FUNC_ESET(pfExists, SQL_API_SQLMORERESULTS);	/* 61 */
630 	SQL_FUNC_ESET(pfExists, SQL_API_SQLNATIVESQL);		/* 62 */
631 	SQL_FUNC_ESET(pfExists, SQL_API_SQLNUMPARAMS);		/* 63 */
632 	/* SQL_FUNC_ESET(pfExists, SQL_API_SQLPARAMOPTIONS); 64 deprecated */
633 	SQL_FUNC_ESET(pfExists, SQL_API_SQLPRIMARYKEYS);	/* 65 */
634 	SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURECOLUMNS);	/* 66 */
635 	SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURES);		/* 67 */
636 	SQL_FUNC_ESET(pfExists, SQL_API_SQLSETPOS);		/* 68 */
637 	/* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSCROLLOPTIONS); 69 deprecated */
638 	SQL_FUNC_ESET(pfExists, SQL_API_SQLTABLEPRIVILEGES);	/* 70 */
639 	/* SQL_FUNC_ESET(pfExists, SQL_API_SQLDRIVERS); */	/* 71 */
640 	SQL_FUNC_ESET(pfExists, SQL_API_SQLBINDPARAMETER);	/* 72 */
641 
642 	SQL_FUNC_ESET(pfExists, SQL_API_SQLALLOCHANDLE);	/* 1001 */
643 	SQL_FUNC_ESET(pfExists, SQL_API_SQLBINDPARAM);		/* 1002 */
644 	SQL_FUNC_ESET(pfExists, SQL_API_SQLCLOSECURSOR);	/* 1003 */
645 	SQL_FUNC_ESET(pfExists, SQL_API_SQLCOPYDESC);		/* 1004 */
646 	SQL_FUNC_ESET(pfExists, SQL_API_SQLENDTRAN);		/* 1005 */
647 	SQL_FUNC_ESET(pfExists, SQL_API_SQLFREEHANDLE);		/* 1006 */
648 	SQL_FUNC_ESET(pfExists, SQL_API_SQLGETCONNECTATTR);	/* 1007 */
649 	SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDESCFIELD);	/* 1008 */
650 	if (ci->drivers.lie)
651 	{
652 		SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDESCREC); /* 1009 not implemented yet */
653 	}
654 	SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDIAGFIELD); /* 1010 minimal implementation */
655 	SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDIAGREC);		/* 1011 */
656 	SQL_FUNC_ESET(pfExists, SQL_API_SQLGETENVATTR);		/* 1012 */
657 	SQL_FUNC_ESET(pfExists, SQL_API_SQLGETSTMTATTR);	/* 1014 */
658 	SQL_FUNC_ESET(pfExists, SQL_API_SQLSETCONNECTATTR);	/* 1016 */
659 	SQL_FUNC_ESET(pfExists, SQL_API_SQLSETDESCFIELD);	/* 1017 */
660 	if (ci->drivers.lie)
661 	{
662 		SQL_FUNC_ESET(pfExists, SQL_API_SQLSETDESCREC); /* 1018 not implemented yet */
663 	}
664 	SQL_FUNC_ESET(pfExists, SQL_API_SQLSETENVATTR);		/* 1019 */
665 	SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSTMTATTR);	/* 1020 */
666 	SQL_FUNC_ESET(pfExists, SQL_API_SQLFETCHSCROLL);	/* 1021 */
667 	if (0 != (ALLOW_BULK_OPERATIONS & ci->updatable_cursors))
668 		SQL_FUNC_ESET(pfExists, SQL_API_SQLBULKOPERATIONS);	/* 24 */
669 
670 	return SQL_SUCCESS;
671 }
672 
673 RETCODE	SQL_API
SQLBulkOperations(HSTMT hstmt,SQLSMALLINT operation)674 SQLBulkOperations(HSTMT hstmt, SQLSMALLINT operation)
675 {
676 	RETCODE	ret;
677 	StatementClass	*stmt = (StatementClass *) hstmt;
678 
679 	if (SC_connection_lost_check(stmt, __FUNCTION__))
680 		return SQL_ERROR;
681 
682 	ENTER_STMT_CS(stmt);
683 	MYLOG(0, "Entering Handle=%p %d\n", hstmt, operation);
684 	SC_clear_error(stmt);
685 	StartRollbackState(stmt);
686 	ret = PGAPI_BulkOperations(hstmt, operation);
687 	ret = DiscardStatementSvp(stmt,ret, FALSE);
688 	LEAVE_STMT_CS(stmt);
689 	return ret;
690 }
691