1 /*-------
2  * Module:			pgapi30.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:	PGAPI_ColAttribute, PGAPI_GetDiagRec,
12 			PGAPI_GetConnectAttr, PGAPI_GetStmtAttr,
13 			PGAPI_SetConnectAttr, PGAPI_SetStmtAttr
14  *-------
15  */
16 
17 #include "psqlodbc.h"
18 #include "misc.h"
19 
20 #include <stdio.h>
21 #include <string.h>
22 
23 
24 #include "environ.h"
25 #include "connection.h"
26 #include "statement.h"
27 #include "descriptor.h"
28 #include "qresult.h"
29 #include "pgapifunc.h"
30 #include "loadlib.h"
31 #include "dlg_specific.h"
32 
33 
34 /*	SQLError -> SQLDiagRec */
35 RETCODE		SQL_API
PGAPI_GetDiagRec(SQLSMALLINT HandleType,SQLHANDLE Handle,SQLSMALLINT RecNumber,SQLCHAR * Sqlstate,SQLINTEGER * NativeError,SQLCHAR * MessageText,SQLSMALLINT BufferLength,SQLSMALLINT * TextLength)36 PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
37 				 SQLSMALLINT RecNumber, SQLCHAR *Sqlstate,
38 				 SQLINTEGER *NativeError, SQLCHAR *MessageText,
39 				 SQLSMALLINT BufferLength, SQLSMALLINT *TextLength)
40 {
41 	RETCODE		ret;
42 
43 	MYLOG(0, "entering type=%d rec=%d\n", HandleType, RecNumber);
44 	switch (HandleType)
45 	{
46 		case SQL_HANDLE_ENV:
47 			ret = PGAPI_EnvError(Handle, RecNumber, Sqlstate,
48 					NativeError, MessageText,
49 					BufferLength, TextLength, 0);
50 			break;
51 		case SQL_HANDLE_DBC:
52 			ret = PGAPI_ConnectError(Handle, RecNumber, Sqlstate,
53 					NativeError, MessageText, BufferLength,
54 					TextLength, 0);
55 			break;
56 		case SQL_HANDLE_STMT:
57 			ret = PGAPI_StmtError(Handle, RecNumber, Sqlstate,
58 					NativeError, MessageText, BufferLength,
59 					TextLength, 0);
60 			break;
61 		case SQL_HANDLE_DESC:
62 			ret = PGAPI_DescError(Handle, RecNumber, Sqlstate,
63 					NativeError,
64 					MessageText, BufferLength,
65 					TextLength, 0);
66 			break;
67 		default:
68 			ret = SQL_ERROR;
69 	}
70 	MYLOG(0, "leaving %d\n", ret);
71 	return ret;
72 }
73 
74 /*
75  *	Minimal implementation.
76  *
77  */
78 RETCODE		SQL_API
PGAPI_GetDiagField(SQLSMALLINT HandleType,SQLHANDLE Handle,SQLSMALLINT RecNumber,SQLSMALLINT DiagIdentifier,PTR DiagInfoPtr,SQLSMALLINT BufferLength,SQLSMALLINT * StringLengthPtr)79 PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
80 				   SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier,
81 				   PTR DiagInfoPtr, SQLSMALLINT BufferLength,
82 				   SQLSMALLINT *StringLengthPtr)
83 {
84 	RETCODE		ret = SQL_ERROR, rtn;
85 	ConnectionClass	*conn;
86 	StatementClass	*stmt;
87 	SQLLEN		rc;
88 	SQLSMALLINT	pcbErrm;
89 	ssize_t		rtnlen = -1;
90 	int		rtnctype = SQL_C_CHAR;
91 
92 	MYLOG(0, "entering rec=%d\n", RecNumber);
93 	switch (HandleType)
94 	{
95 		case SQL_HANDLE_ENV:
96 			switch (DiagIdentifier)
97 			{
98 				case SQL_DIAG_CLASS_ORIGIN:
99 				case SQL_DIAG_SUBCLASS_ORIGIN:
100 				case SQL_DIAG_CONNECTION_NAME:
101 				case SQL_DIAG_SERVER_NAME:
102 					rtnlen = 0;
103 					if (DiagInfoPtr && BufferLength > rtnlen)
104 					{
105 						ret = SQL_SUCCESS;
106 						*((char *) DiagInfoPtr) = '\0';
107 					}
108 					else
109 						ret = SQL_SUCCESS_WITH_INFO;
110 					break;
111 				case SQL_DIAG_MESSAGE_TEXT:
112 					ret = PGAPI_EnvError(Handle, RecNumber,
113 										 NULL, NULL, DiagInfoPtr,
114 										 BufferLength, StringLengthPtr, 0);
115 					break;
116 				case SQL_DIAG_NATIVE:
117 					rtnctype = SQL_C_LONG;
118 					ret = PGAPI_EnvError(Handle, RecNumber,
119 										 NULL, (SQLINTEGER *) DiagInfoPtr, NULL,
120 										 0, NULL, 0);
121 					break;
122 				case SQL_DIAG_NUMBER:
123 					rtnctype = SQL_C_LONG;
124 					ret = PGAPI_EnvError(Handle, RecNumber,
125 										 NULL, NULL, NULL,
126 										 0, NULL, 0);
127 					if (SQL_SUCCEEDED(ret))
128 					{
129 						*((SQLINTEGER *) DiagInfoPtr) = 1;
130 					}
131 					break;
132 				case SQL_DIAG_SQLSTATE:
133 					rtnlen = 5;
134 					ret = PGAPI_EnvError(Handle, RecNumber,
135 										 DiagInfoPtr, NULL, NULL,
136 										 0, NULL, 0);
137 					if (SQL_SUCCESS_WITH_INFO == ret)
138 						ret = SQL_SUCCESS;
139 					break;
140 				case SQL_DIAG_RETURNCODE: /* driver manager returns */
141 					break;
142 				case SQL_DIAG_CURSOR_ROW_COUNT:
143 				case SQL_DIAG_ROW_COUNT:
144 				case SQL_DIAG_DYNAMIC_FUNCTION:
145 				case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
146 					/* options for statement type only */
147 					break;
148 			}
149 			break;
150 		case SQL_HANDLE_DBC:
151 			conn = (ConnectionClass *) Handle;
152 			switch (DiagIdentifier)
153 			{
154 				case SQL_DIAG_CLASS_ORIGIN:
155 				case SQL_DIAG_SUBCLASS_ORIGIN:
156 				case SQL_DIAG_CONNECTION_NAME:
157 					rtnlen = 0;
158 					if (DiagInfoPtr && BufferLength > rtnlen)
159 					{
160 						ret = SQL_SUCCESS;
161 						*((char *) DiagInfoPtr) = '\0';
162 					}
163 					else
164 						ret = SQL_SUCCESS_WITH_INFO;
165 					break;
166 				case SQL_DIAG_SERVER_NAME:
167 					rtnlen = strlen(CC_get_DSN(conn));
168 					if (DiagInfoPtr)
169 					{
170 						strncpy_null(DiagInfoPtr, CC_get_DSN(conn), BufferLength);
171 						ret = (BufferLength > rtnlen ? SQL_SUCCESS : SQL_SUCCESS_WITH_INFO);
172 					}
173 					else
174 						ret = SQL_SUCCESS_WITH_INFO;
175 					break;
176 				case SQL_DIAG_MESSAGE_TEXT:
177 					ret = PGAPI_ConnectError(Handle, RecNumber,
178 											 NULL, NULL, DiagInfoPtr,
179 											 BufferLength, StringLengthPtr, 0);
180 					break;
181 				case SQL_DIAG_NATIVE:
182 					rtnctype = SQL_C_LONG;
183 					ret = PGAPI_ConnectError(Handle, RecNumber,
184 											 NULL, (SQLINTEGER *) DiagInfoPtr, NULL,
185 											 0, NULL, 0);
186 					break;
187 				case SQL_DIAG_NUMBER:
188 					rtnctype = SQL_C_LONG;
189 					ret = PGAPI_ConnectError(Handle, RecNumber,
190 											 NULL, NULL, NULL,
191 											 0, NULL, 0);
192 					if (SQL_SUCCEEDED(ret))
193 					{
194 						*((SQLINTEGER *) DiagInfoPtr) = 1;
195 					}
196 					break;
197 				case SQL_DIAG_SQLSTATE:
198 					rtnlen = 5;
199 					ret = PGAPI_ConnectError(Handle, RecNumber,
200 											 DiagInfoPtr, NULL, NULL,
201 											 0, NULL, 0);
202 					if (SQL_SUCCESS_WITH_INFO == ret)
203 						ret = SQL_SUCCESS;
204 					break;
205 				case SQL_DIAG_RETURNCODE: /* driver manager returns */
206 					break;
207 				case SQL_DIAG_CURSOR_ROW_COUNT:
208 				case SQL_DIAG_ROW_COUNT:
209 				case SQL_DIAG_DYNAMIC_FUNCTION:
210 				case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
211 					/* options for statement type only */
212 					break;
213 			}
214 			break;
215 		case SQL_HANDLE_STMT:
216 			conn = (ConnectionClass *) SC_get_conn(((StatementClass *) Handle));
217 			switch (DiagIdentifier)
218 			{
219 				case SQL_DIAG_CLASS_ORIGIN:
220 				case SQL_DIAG_SUBCLASS_ORIGIN:
221 				case SQL_DIAG_CONNECTION_NAME:
222 					rtnlen = 0;
223 					if (DiagInfoPtr && BufferLength > rtnlen)
224 					{
225 						ret = SQL_SUCCESS;
226 						*((char *) DiagInfoPtr) = '\0';
227 					}
228 					else
229 						ret = SQL_SUCCESS_WITH_INFO;
230 					break;
231 				case SQL_DIAG_SERVER_NAME:
232 					rtnlen = strlen(CC_get_DSN(conn));
233 					if (DiagInfoPtr)
234 					{
235 						strncpy_null(DiagInfoPtr, CC_get_DSN(conn), BufferLength);
236 						ret = (BufferLength > rtnlen ? SQL_SUCCESS : SQL_SUCCESS_WITH_INFO);
237 					}
238 					else
239 						ret = SQL_SUCCESS_WITH_INFO;
240 					break;
241 				case SQL_DIAG_MESSAGE_TEXT:
242 					ret = PGAPI_StmtError(Handle, RecNumber,
243 										  NULL, NULL, DiagInfoPtr,
244 										  BufferLength, StringLengthPtr, 0);
245 					break;
246 				case SQL_DIAG_NATIVE:
247 					rtnctype = SQL_C_LONG;
248 					ret = PGAPI_StmtError(Handle, RecNumber,
249 										  NULL, (SQLINTEGER *) DiagInfoPtr, NULL,
250 										  0, NULL, 0);
251 					break;
252 				case SQL_DIAG_NUMBER:
253 					rtnctype = SQL_C_LONG;
254 					*((SQLINTEGER *) DiagInfoPtr) = 0;
255 					ret = SQL_NO_DATA_FOUND;
256 					stmt = (StatementClass *) Handle;
257 					rtn = PGAPI_StmtError(Handle, -1, NULL,
258 						 NULL, NULL, 0, &pcbErrm, 0);
259 					switch (rtn)
260 					{
261 						case SQL_SUCCESS:
262 						case SQL_SUCCESS_WITH_INFO:
263 							ret = SQL_SUCCESS;
264 							if (pcbErrm > 0 && stmt->pgerror)
265 
266 								*((SQLINTEGER *) DiagInfoPtr) = (pcbErrm  - 1)/ stmt->pgerror->recsize + 1;
267 							break;
268 						default:
269 							break;
270 					}
271 					break;
272 				case SQL_DIAG_SQLSTATE:
273 					rtnlen = 5;
274 					ret = PGAPI_StmtError(Handle, RecNumber,
275 										  DiagInfoPtr, NULL, NULL,
276 										  0, NULL, 0);
277 					if (SQL_SUCCESS_WITH_INFO == ret)
278 						ret = SQL_SUCCESS;
279 					break;
280 				case SQL_DIAG_CURSOR_ROW_COUNT:
281 					rtnctype = SQL_C_LONG;
282 					stmt = (StatementClass *) Handle;
283 					rc = -1;
284 					if (stmt->status == STMT_FINISHED)
285 					{
286 						QResultClass *res = SC_get_Curres(stmt);
287 
288 						/*if (!res)
289 							return SQL_ERROR;*/
290 						if (stmt->proc_return > 0)
291 							rc = 0;
292 						else if (res && QR_NumResultCols(res) > 0 && !SC_is_fetchcursor(stmt))
293 							rc = QR_get_num_total_tuples(res) - res->dl_count;
294 					}
295 					*((SQLLEN *) DiagInfoPtr) = rc;
296 MYLOG(DETAIL_LOG_LEVEL, "rc=" FORMAT_LEN "\n", rc);
297 					ret = SQL_SUCCESS;
298 					break;
299 				case SQL_DIAG_ROW_COUNT:
300 					rtnctype = SQL_C_LONG;
301 					stmt = (StatementClass *) Handle;
302 					*((SQLLEN *) DiagInfoPtr) = stmt->diag_row_count;
303 					ret = SQL_SUCCESS;
304 					break;
305                                 case SQL_DIAG_ROW_NUMBER:
306 					rtnctype = SQL_C_LONG;
307 					*((SQLLEN *) DiagInfoPtr) = SQL_ROW_NUMBER_UNKNOWN;
308 					ret = SQL_SUCCESS;
309 					break;
310                                 case SQL_DIAG_COLUMN_NUMBER:
311 					rtnctype = SQL_C_LONG;
312 					*((SQLINTEGER *) DiagInfoPtr) = SQL_COLUMN_NUMBER_UNKNOWN;
313 					ret = SQL_SUCCESS;
314 					break;
315 				case SQL_DIAG_RETURNCODE: /* driver manager returns */
316 					break;
317 			}
318 			break;
319 		case SQL_HANDLE_DESC:
320 			conn = DC_get_conn(((DescriptorClass *) Handle));
321 			switch (DiagIdentifier)
322 			{
323 				case SQL_DIAG_CLASS_ORIGIN:
324 				case SQL_DIAG_SUBCLASS_ORIGIN:
325 				case SQL_DIAG_CONNECTION_NAME:
326 					rtnlen = 0;
327 					if (DiagInfoPtr && BufferLength > rtnlen)
328 					{
329 						ret = SQL_SUCCESS;
330 						*((char *) DiagInfoPtr) = '\0';
331 					}
332 					else
333 						ret = SQL_SUCCESS_WITH_INFO;
334 					break;
335 				case SQL_DIAG_SERVER_NAME:
336 					rtnlen = strlen(CC_get_DSN(conn));
337 					if (DiagInfoPtr)
338 					{
339 						strncpy_null(DiagInfoPtr, CC_get_DSN(conn), BufferLength);
340 						ret = (BufferLength > rtnlen ? SQL_SUCCESS : SQL_SUCCESS_WITH_INFO);
341 					}
342 					else
343 						ret = SQL_SUCCESS_WITH_INFO;
344 					break;
345 				case SQL_DIAG_MESSAGE_TEXT:
346 				case SQL_DIAG_NATIVE:
347 				case SQL_DIAG_NUMBER:
348 					break;
349 				case SQL_DIAG_SQLSTATE:
350 					rtnlen = 5;
351 					ret = PGAPI_DescError(Handle, RecNumber,
352 										  DiagInfoPtr, NULL, NULL,
353 										  0, NULL, 0);
354 					if (SQL_SUCCESS_WITH_INFO == ret)
355 						ret = SQL_SUCCESS;
356 					break;
357 				case SQL_DIAG_RETURNCODE: /* driver manager returns */
358 					break;
359 				case SQL_DIAG_CURSOR_ROW_COUNT:
360 				case SQL_DIAG_ROW_COUNT:
361 				case SQL_DIAG_DYNAMIC_FUNCTION:
362 				case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
363 					rtnctype = SQL_C_LONG;
364 					/* options for statement type only */
365 					break;
366 			}
367 			break;
368 		default:
369 			ret = SQL_ERROR;
370 	}
371 	if (SQL_C_LONG == rtnctype)
372 	{
373 		if (SQL_SUCCESS_WITH_INFO == ret)
374 			ret = SQL_SUCCESS;
375 		if (StringLengthPtr)
376 			*StringLengthPtr = sizeof(SQLINTEGER);
377 	}
378 	else if (rtnlen >= 0)
379 	{
380 		if (rtnlen >= BufferLength)
381 		{
382 			if (SQL_SUCCESS == ret)
383 				ret = SQL_SUCCESS_WITH_INFO;
384 			if (BufferLength > 0)
385 				((char *) DiagInfoPtr) [BufferLength - 1] = '\0';
386 		}
387 		if (StringLengthPtr)
388 			*StringLengthPtr = (SQLSMALLINT) rtnlen;
389 	}
390 	MYLOG(0, "leaving %d\n", ret);
391 	return ret;
392 }
393 
394 /*	SQLGetConnectOption -> SQLGetconnectAttr */
395 RETCODE		SQL_API
PGAPI_GetConnectAttr(HDBC ConnectionHandle,SQLINTEGER Attribute,PTR Value,SQLINTEGER BufferLength,SQLINTEGER * StringLength)396 PGAPI_GetConnectAttr(HDBC ConnectionHandle,
397 					 SQLINTEGER Attribute, PTR Value,
398 					 SQLINTEGER BufferLength, SQLINTEGER *StringLength)
399 {
400 	ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
401 	RETCODE	ret = SQL_SUCCESS;
402 	SQLINTEGER	len = 4;
403 
404 	MYLOG(0, "entering " FORMAT_INTEGER "\n", Attribute);
405 	switch (Attribute)
406 	{
407 		case SQL_ATTR_ASYNC_ENABLE:
408 			*((SQLINTEGER *) Value) = SQL_ASYNC_ENABLE_OFF;
409 			break;
410 		case SQL_ATTR_AUTO_IPD:
411 			*((SQLINTEGER *) Value) = SQL_FALSE;
412 			break;
413 		case SQL_ATTR_CONNECTION_DEAD:
414 			*((SQLUINTEGER *) Value) = CC_not_connected(conn);
415 			break;
416 		case SQL_ATTR_CONNECTION_TIMEOUT:
417 			*((SQLUINTEGER *) Value) = 0;
418 			break;
419 		case SQL_ATTR_METADATA_ID:
420 			*((SQLUINTEGER *) Value) = conn->stmtOptions.metadata_id;
421 			break;
422 		case SQL_ATTR_PGOPT_DEBUG:
423 			*((SQLINTEGER *) Value) = conn->connInfo.drivers.debug;
424 			break;
425 		case SQL_ATTR_PGOPT_COMMLOG:
426 			*((SQLINTEGER *) Value) = conn->connInfo.drivers.commlog;
427 			break;
428 		case SQL_ATTR_PGOPT_PARSE:
429 			*((SQLINTEGER *) Value) = conn->connInfo.drivers.parse;
430 			break;
431 		case SQL_ATTR_PGOPT_USE_DECLAREFETCH:
432 			*((SQLINTEGER *) Value) = conn->connInfo.drivers.use_declarefetch;
433 			break;
434 		case SQL_ATTR_PGOPT_SERVER_SIDE_PREPARE:
435 			*((SQLINTEGER *) Value) = conn->connInfo.use_server_side_prepare;
436 			break;
437 		case SQL_ATTR_PGOPT_FETCH:
438 			*((SQLINTEGER *) Value) = conn->connInfo.drivers.fetch_max;
439 			break;
440 		case SQL_ATTR_PGOPT_UNKNOWNSIZES:
441 			*((SQLINTEGER *) Value) = conn->connInfo.drivers.unknown_sizes;
442 			break;
443 		case SQL_ATTR_PGOPT_TEXTASLONGVARCHAR:
444 			*((SQLINTEGER *) Value) = conn->connInfo.drivers.text_as_longvarchar;
445 			break;
446 		case SQL_ATTR_PGOPT_UNKNOWNSASLONGVARCHAR:
447 			*((SQLINTEGER *) Value) = conn->connInfo.drivers.unknowns_as_longvarchar;
448 			break;
449 		case SQL_ATTR_PGOPT_BOOLSASCHAR:
450 			*((SQLINTEGER *) Value) = conn->connInfo.drivers.bools_as_char;
451 			break;
452 		case SQL_ATTR_PGOPT_MAXVARCHARSIZE:
453 			*((SQLINTEGER *) Value) = conn->connInfo.drivers.max_varchar_size;
454 			break;
455 		case SQL_ATTR_PGOPT_MAXLONGVARCHARSIZE:
456 			*((SQLINTEGER *) Value) = conn->connInfo.drivers.max_longvarchar_size;
457 			break;
458 		case SQL_ATTR_PGOPT_MSJET:
459 			*((SQLINTEGER *) Value) = conn->ms_jet;
460 			break;
461 		case SQL_ATTR_PGOPT_BATCHSIZE:
462 			*((SQLINTEGER *) Value) = conn->connInfo.batch_size;
463 			break;
464 		case SQL_ATTR_PGOPT_IGNORETIMEOUT:
465 			*((SQLINTEGER *) Value) = conn->connInfo.ignore_timeout;
466 			break;
467 		default:
468 			ret = PGAPI_GetConnectOption(ConnectionHandle, (UWORD) Attribute, Value, &len, BufferLength);
469 	}
470 	if (StringLength)
471 		*StringLength = len;
472 	return ret;
473 }
474 
475 static SQLHDESC
descHandleFromStatementHandle(HSTMT StatementHandle,SQLINTEGER descType)476 descHandleFromStatementHandle(HSTMT StatementHandle, SQLINTEGER descType)
477 {
478 	StatementClass	*stmt = (StatementClass *) StatementHandle;
479 
480 	switch (descType)
481 	{
482 		case SQL_ATTR_APP_ROW_DESC:		/* 10010 */
483 			return (HSTMT) stmt->ard;
484 		case SQL_ATTR_APP_PARAM_DESC:		/* 10011 */
485 			return (HSTMT) stmt->apd;
486 		case SQL_ATTR_IMP_ROW_DESC:		/* 10012 */
487 			return (HSTMT) stmt->ird;
488 		case SQL_ATTR_IMP_PARAM_DESC:		/* 10013 */
489 			return (HSTMT) stmt->ipd;
490 	}
491 	return (HSTMT) 0;
492 }
493 
column_bindings_set(ARDFields * opts,int cols,BOOL maxset)494 static  void column_bindings_set(ARDFields *opts, int cols, BOOL maxset)
495 {
496 	int	i;
497 
498 	if (cols == opts->allocated)
499 		return;
500 	if (cols > opts->allocated)
501 	{
502 		extend_column_bindings(opts, cols);
503 		return;
504 	}
505 	if (maxset)	return;
506 
507 	for (i = opts->allocated; i > cols; i--)
508 		reset_a_column_binding(opts, i);
509 	opts->allocated = cols;
510 	if (0 == cols)
511 	{
512 		free(opts->bindings);
513 		opts->bindings = NULL;
514 	}
515 }
516 
517 static RETCODE SQL_API
ARDSetField(DescriptorClass * desc,SQLSMALLINT RecNumber,SQLSMALLINT FieldIdentifier,PTR Value,SQLINTEGER BufferLength)518 ARDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
519 			SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
520 {
521 	RETCODE		ret = SQL_SUCCESS;
522 	ARDFields	*opts = &(desc->ardf);
523 	SQLSMALLINT	row_idx;
524 	BOOL		unbind = TRUE;
525 
526 	switch (FieldIdentifier)
527 	{
528 		case SQL_DESC_ARRAY_SIZE:
529 			opts->size_of_rowset = CAST_UPTR(SQLULEN, Value);
530 			return ret;
531 		case SQL_DESC_ARRAY_STATUS_PTR:
532 			opts->row_operation_ptr = Value;
533 			return ret;
534 		case SQL_DESC_BIND_OFFSET_PTR:
535 			opts->row_offset_ptr = Value;
536 			return ret;
537 		case SQL_DESC_BIND_TYPE:
538 			opts->bind_size = CAST_UPTR(SQLUINTEGER, Value);
539 			return ret;
540 		case SQL_DESC_COUNT:
541 			column_bindings_set(opts, CAST_PTR(SQLSMALLINT, Value), FALSE);
542 			return ret;
543 
544 		case SQL_DESC_TYPE:
545 		case SQL_DESC_DATETIME_INTERVAL_CODE:
546 		case SQL_DESC_CONCISE_TYPE:
547 			column_bindings_set(opts, RecNumber, TRUE);
548 			break;
549 	}
550 	if (RecNumber < 0 || RecNumber > opts->allocated)
551 	{
552 		DC_set_error(desc, DESC_INVALID_COLUMN_NUMBER_ERROR, "invalid column number");
553 		return SQL_ERROR;
554 	}
555 	if (0 == RecNumber) /* bookmark column */
556 	{
557 		BindInfoClass	*bookmark = ARD_AllocBookmark(opts);
558 
559 		switch (FieldIdentifier)
560 		{
561 			case SQL_DESC_DATA_PTR:
562 				bookmark->buffer = Value;
563 				break;
564 			case SQL_DESC_INDICATOR_PTR:
565 				bookmark->indicator = Value;
566 				break;
567 			case SQL_DESC_OCTET_LENGTH_PTR:
568 				bookmark->used = Value;
569 				break;
570 			default:
571 				DC_set_error(desc, DESC_INVALID_COLUMN_NUMBER_ERROR, "invalid column number");
572 				ret = SQL_ERROR;
573 		}
574 		return ret;
575 	}
576 	row_idx = RecNumber - 1;
577 	switch (FieldIdentifier)
578 	{
579 		case SQL_DESC_TYPE:
580 			opts->bindings[row_idx].returntype = CAST_PTR(SQLSMALLINT, Value);
581 			break;
582 		case SQL_DESC_DATETIME_INTERVAL_CODE:
583 			switch (opts->bindings[row_idx].returntype)
584 			{
585 				case SQL_DATETIME:
586 				case SQL_C_TYPE_DATE:
587 				case SQL_C_TYPE_TIME:
588 				case SQL_C_TYPE_TIMESTAMP:
589 				switch ((LONG_PTR) Value)
590 				{
591 					case SQL_CODE_DATE:
592 						opts->bindings[row_idx].returntype = SQL_C_TYPE_DATE;
593 						break;
594 					case SQL_CODE_TIME:
595 						opts->bindings[row_idx].returntype = SQL_C_TYPE_TIME;
596 						break;
597 					case SQL_CODE_TIMESTAMP:
598 						opts->bindings[row_idx].returntype = SQL_C_TYPE_TIMESTAMP;
599 						break;
600 				}
601 				break;
602 			}
603 			break;
604 		case SQL_DESC_CONCISE_TYPE:
605 			opts->bindings[row_idx].returntype = CAST_PTR(SQLSMALLINT, Value);
606 			break;
607 		case SQL_DESC_DATA_PTR:
608 			unbind = FALSE;
609 			opts->bindings[row_idx].buffer = Value;
610 			break;
611 		case SQL_DESC_INDICATOR_PTR:
612 			unbind = FALSE;
613 			opts->bindings[row_idx].indicator = Value;
614 			break;
615 		case SQL_DESC_OCTET_LENGTH_PTR:
616 			unbind = FALSE;
617 			opts->bindings[row_idx].used = Value;
618 			break;
619 		case SQL_DESC_OCTET_LENGTH:
620 			opts->bindings[row_idx].buflen = CAST_PTR(SQLLEN, Value);
621 			break;
622 		case SQL_DESC_PRECISION:
623 			opts->bindings[row_idx].precision = CAST_PTR(SQLSMALLINT, Value);
624 			break;
625 		case SQL_DESC_SCALE:
626 			opts->bindings[row_idx].scale = CAST_PTR(SQLSMALLINT, Value);
627 			break;
628 		case SQL_DESC_ALLOC_TYPE: /* read-only */
629 		case SQL_DESC_DATETIME_INTERVAL_PRECISION:
630 		case SQL_DESC_LENGTH:
631 		case SQL_DESC_NUM_PREC_RADIX:
632 		default:ret = SQL_ERROR;
633 			DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
634 				"invalid descriptor identifier");
635 	}
636 	if (unbind)
637 		opts->bindings[row_idx].buffer = NULL;
638 	return ret;
639 }
640 
parameter_bindings_set(APDFields * opts,int params,BOOL maxset)641 static  void parameter_bindings_set(APDFields *opts, int params, BOOL maxset)
642 {
643 	int	i;
644 
645 	if (params == opts->allocated)
646 		return;
647 	if (params > opts->allocated)
648 	{
649 		extend_parameter_bindings(opts, params);
650 		return;
651 	}
652 	if (maxset)	return;
653 
654 	for (i = opts->allocated; i > params; i--)
655 		reset_a_parameter_binding(opts, i);
656 	opts->allocated = params;
657 	if (0 == params)
658 	{
659 		free(opts->parameters);
660 		opts->parameters = NULL;
661 	}
662 }
663 
parameter_ibindings_set(IPDFields * opts,int params,BOOL maxset)664 static  void parameter_ibindings_set(IPDFields *opts, int params, BOOL maxset)
665 {
666 	int	i;
667 
668 	if (params == opts->allocated)
669 		return;
670 	if (params > opts->allocated)
671 	{
672 		extend_iparameter_bindings(opts, params);
673 		return;
674 	}
675 	if (maxset)	return;
676 
677 	for (i = opts->allocated; i > params; i--)
678 		reset_a_iparameter_binding(opts, i);
679 	opts->allocated = params;
680 	if (0 == params)
681 	{
682 		free(opts->parameters);
683 		opts->parameters = NULL;
684 	}
685 }
686 
687 static RETCODE SQL_API
APDSetField(DescriptorClass * desc,SQLSMALLINT RecNumber,SQLSMALLINT FieldIdentifier,PTR Value,SQLINTEGER BufferLength)688 APDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
689 			SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
690 {
691 	RETCODE		ret = SQL_SUCCESS;
692 	APDFields	*opts = &(desc->apdf);
693 	SQLSMALLINT	para_idx;
694 	BOOL		unbind = TRUE;
695 
696 	switch (FieldIdentifier)
697 	{
698 		case SQL_DESC_ARRAY_SIZE:
699 			opts->paramset_size = CAST_UPTR(SQLUINTEGER, Value);
700 			return ret;
701 		case SQL_DESC_ARRAY_STATUS_PTR:
702 			opts->param_operation_ptr = Value;
703 			return ret;
704 		case SQL_DESC_BIND_OFFSET_PTR:
705 			opts->param_offset_ptr = Value;
706 			return ret;
707 		case SQL_DESC_BIND_TYPE:
708 			opts->param_bind_type = CAST_UPTR(SQLUINTEGER, Value);
709 			return ret;
710 		case SQL_DESC_COUNT:
711 			parameter_bindings_set(opts, CAST_PTR(SQLSMALLINT, Value), FALSE);
712 			return ret;
713 
714 		case SQL_DESC_TYPE:
715 		case SQL_DESC_DATETIME_INTERVAL_CODE:
716 		case SQL_DESC_CONCISE_TYPE:
717 			parameter_bindings_set(opts, RecNumber, TRUE);
718 			break;
719 	}
720 	if (RecNumber <=0)
721 	{
722 MYLOG(DETAIL_LOG_LEVEL, "RecN=%d allocated=%d\n", RecNumber, opts->allocated);
723 		DC_set_error(desc, DESC_BAD_PARAMETER_NUMBER_ERROR,
724 				"bad parameter number");
725 		return SQL_ERROR;
726 	}
727 	if (RecNumber > opts->allocated)
728 	{
729 MYLOG(DETAIL_LOG_LEVEL, "RecN=%d allocated=%d\n", RecNumber, opts->allocated);
730 		parameter_bindings_set(opts, RecNumber, TRUE);
731 		/* DC_set_error(desc, DESC_BAD_PARAMETER_NUMBER_ERROR,
732 				"bad parameter number");
733 		return SQL_ERROR;*/
734 	}
735 	para_idx = RecNumber - 1;
736 	switch (FieldIdentifier)
737 	{
738 		case SQL_DESC_TYPE:
739 			opts->parameters[para_idx].CType = CAST_PTR(SQLSMALLINT, Value);
740 			break;
741 		case SQL_DESC_DATETIME_INTERVAL_CODE:
742 			switch (opts->parameters[para_idx].CType)
743 			{
744 				case SQL_DATETIME:
745 				case SQL_C_TYPE_DATE:
746 				case SQL_C_TYPE_TIME:
747 				case SQL_C_TYPE_TIMESTAMP:
748 				switch ((LONG_PTR) Value)
749 				{
750 					case SQL_CODE_DATE:
751 						opts->parameters[para_idx].CType = SQL_C_TYPE_DATE;
752 						break;
753 					case SQL_CODE_TIME:
754 						opts->parameters[para_idx].CType = SQL_C_TYPE_TIME;
755 						break;
756 					case SQL_CODE_TIMESTAMP:
757 						opts->parameters[para_idx].CType = SQL_C_TYPE_TIMESTAMP;
758 						break;
759 				}
760 				break;
761 			}
762 			break;
763 		case SQL_DESC_CONCISE_TYPE:
764 			opts->parameters[para_idx].CType = CAST_PTR(SQLSMALLINT, Value);
765 			break;
766 		case SQL_DESC_DATA_PTR:
767 			unbind = FALSE;
768 			opts->parameters[para_idx].buffer = Value;
769 			break;
770 		case SQL_DESC_INDICATOR_PTR:
771 			unbind = FALSE;
772 			opts->parameters[para_idx].indicator = Value;
773 			break;
774 		case SQL_DESC_OCTET_LENGTH:
775 			opts->parameters[para_idx].buflen = CAST_PTR(Int4, Value);
776 			break;
777 		case SQL_DESC_OCTET_LENGTH_PTR:
778 			unbind = FALSE;
779 			opts->parameters[para_idx].used = Value;
780 			break;
781 		case SQL_DESC_PRECISION:
782 			opts->parameters[para_idx].precision = CAST_PTR(SQLSMALLINT, Value);
783 			break;
784 		case SQL_DESC_SCALE:
785 			opts->parameters[para_idx].scale = CAST_PTR(SQLSMALLINT, Value);
786 			break;
787 		case SQL_DESC_ALLOC_TYPE: /* read-only */
788 		case SQL_DESC_DATETIME_INTERVAL_PRECISION:
789 		case SQL_DESC_LENGTH:
790 		case SQL_DESC_NUM_PREC_RADIX:
791 		default:ret = SQL_ERROR;
792 			DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
793 				"invaid descriptor identifier");
794 	}
795 	if (unbind)
796 		opts->parameters[para_idx].buffer = NULL;
797 
798 	return ret;
799 }
800 
801 static RETCODE SQL_API
IRDSetField(DescriptorClass * desc,SQLSMALLINT RecNumber,SQLSMALLINT FieldIdentifier,PTR Value,SQLINTEGER BufferLength)802 IRDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
803 			SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
804 {
805 	RETCODE		ret = SQL_SUCCESS;
806 	IRDFields	*opts = &(desc->irdf);
807 
808 	switch (FieldIdentifier)
809 	{
810 		case SQL_DESC_ARRAY_STATUS_PTR:
811 			opts->rowStatusArray = (SQLUSMALLINT *) Value;
812 			break;
813 		case SQL_DESC_ROWS_PROCESSED_PTR:
814 			opts->rowsFetched = (SQLULEN *) Value;
815 			break;
816 		case SQL_DESC_ALLOC_TYPE: /* read-only */
817 		case SQL_DESC_COUNT: /* read-only */
818 		case SQL_DESC_AUTO_UNIQUE_VALUE: /* read-only */
819 		case SQL_DESC_BASE_COLUMN_NAME: /* read-only */
820 		case SQL_DESC_BASE_TABLE_NAME: /* read-only */
821 		case SQL_DESC_CASE_SENSITIVE: /* read-only */
822 		case SQL_DESC_CATALOG_NAME: /* read-only */
823 		case SQL_DESC_CONCISE_TYPE: /* read-only */
824 		case SQL_DESC_DATETIME_INTERVAL_CODE: /* read-only */
825 		case SQL_DESC_DATETIME_INTERVAL_PRECISION: /* read-only */
826 		case SQL_DESC_DISPLAY_SIZE: /* read-only */
827 		case SQL_DESC_FIXED_PREC_SCALE: /* read-only */
828 		case SQL_DESC_LABEL: /* read-only */
829 		case SQL_DESC_LENGTH: /* read-only */
830 		case SQL_DESC_LITERAL_PREFIX: /* read-only */
831 		case SQL_DESC_LITERAL_SUFFIX: /* read-only */
832 		case SQL_DESC_LOCAL_TYPE_NAME: /* read-only */
833 		case SQL_DESC_NAME: /* read-only */
834 		case SQL_DESC_NULLABLE: /* read-only */
835 		case SQL_DESC_NUM_PREC_RADIX: /* read-only */
836 		case SQL_DESC_OCTET_LENGTH: /* read-only */
837 		case SQL_DESC_PRECISION: /* read-only */
838 		case SQL_DESC_ROWVER: /* read-only */
839 		case SQL_DESC_SCALE: /* read-only */
840 		case SQL_DESC_SCHEMA_NAME: /* read-only */
841 		case SQL_DESC_SEARCHABLE: /* read-only */
842 		case SQL_DESC_TABLE_NAME: /* read-only */
843 		case SQL_DESC_TYPE: /* read-only */
844 		case SQL_DESC_TYPE_NAME: /* read-only */
845 		case SQL_DESC_UNNAMED: /* read-only */
846 		case SQL_DESC_UNSIGNED: /* read-only */
847 		case SQL_DESC_UPDATABLE: /* read-only */
848 		default:ret = SQL_ERROR;
849 			DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
850 				"invalid descriptor identifier");
851 	}
852 	return ret;
853 }
854 
855 static RETCODE SQL_API
IPDSetField(DescriptorClass * desc,SQLSMALLINT RecNumber,SQLSMALLINT FieldIdentifier,PTR Value,SQLINTEGER BufferLength)856 IPDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
857 			SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
858 {
859 	RETCODE		ret = SQL_SUCCESS;
860 	IPDFields	*ipdopts = &(desc->ipdf);
861 	SQLSMALLINT	para_idx;
862 
863 	switch (FieldIdentifier)
864 	{
865 		case SQL_DESC_ARRAY_STATUS_PTR:
866 			ipdopts->param_status_ptr = (SQLUSMALLINT *) Value;
867 			return ret;
868 		case SQL_DESC_ROWS_PROCESSED_PTR:
869 			ipdopts->param_processed_ptr = (SQLULEN *) Value;
870 			return ret;
871 		case SQL_DESC_COUNT:
872 			parameter_ibindings_set(ipdopts, CAST_PTR(SQLSMALLINT, Value), FALSE);
873 			return ret;
874 		case SQL_DESC_UNNAMED: /* only SQL_UNNAMED is allowed */
875 			if (SQL_UNNAMED !=  CAST_PTR(SQLSMALLINT, Value))
876 			{
877 				ret = SQL_ERROR;
878 				DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
879 					"invalid descriptor identifier");
880 				return ret;
881 			}
882 		case SQL_DESC_NAME:
883 		case SQL_DESC_TYPE:
884 		case SQL_DESC_DATETIME_INTERVAL_CODE:
885 		case SQL_DESC_CONCISE_TYPE:
886 			parameter_ibindings_set(ipdopts, RecNumber, TRUE);
887 			break;
888 	}
889 	if (RecNumber <= 0 || RecNumber > ipdopts->allocated)
890 	{
891 MYLOG(DETAIL_LOG_LEVEL, "RecN=%d allocated=%d\n", RecNumber, ipdopts->allocated);
892 		DC_set_error(desc, DESC_BAD_PARAMETER_NUMBER_ERROR,
893 				"bad parameter number");
894 		return SQL_ERROR;
895 	}
896 	para_idx = RecNumber - 1;
897 	switch (FieldIdentifier)
898 	{
899 		case SQL_DESC_TYPE:
900 			if (ipdopts->parameters[para_idx].SQLType != CAST_PTR(SQLSMALLINT, Value))
901 			{
902 				reset_a_iparameter_binding(ipdopts, RecNumber);
903 				ipdopts->parameters[para_idx].SQLType = CAST_PTR(SQLSMALLINT, Value);
904 			}
905 			break;
906 		case SQL_DESC_DATETIME_INTERVAL_CODE:
907 			switch (ipdopts->parameters[para_idx].SQLType)
908 			{
909 				case SQL_DATETIME:
910 				case SQL_TYPE_DATE:
911 				case SQL_TYPE_TIME:
912 				case SQL_TYPE_TIMESTAMP:
913 				switch ((LONG_PTR) Value)
914 				{
915 					case SQL_CODE_DATE:
916 						ipdopts->parameters[para_idx].SQLType = SQL_TYPE_DATE;
917 						break;
918 					case SQL_CODE_TIME:
919 						ipdopts->parameters[para_idx].SQLType = SQL_TYPE_TIME;
920 						break;
921 					case SQL_CODE_TIMESTAMP:
922 						ipdopts->parameters[para_idx].SQLType = SQL_TYPE_TIMESTAMP;
923 						break;
924 				}
925 				break;
926 			}
927 			break;
928 		case SQL_DESC_CONCISE_TYPE:
929 			ipdopts->parameters[para_idx].SQLType = CAST_PTR(SQLSMALLINT, Value);
930 			break;
931 		case SQL_DESC_NAME:
932 			if (Value)
933 				STR_TO_NAME(ipdopts->parameters[para_idx].paramName, Value);
934 			else
935 				NULL_THE_NAME(ipdopts->parameters[para_idx].paramName);
936 			break;
937 		case SQL_DESC_PARAMETER_TYPE:
938 			ipdopts->parameters[para_idx].paramType = CAST_PTR(SQLSMALLINT, Value);
939 			break;
940 		case SQL_DESC_SCALE:
941 			ipdopts->parameters[para_idx].decimal_digits = CAST_PTR(SQLSMALLINT, Value);
942 			break;
943 		case SQL_DESC_UNNAMED: /* only SQL_UNNAMED is allowed */
944 			if (SQL_UNNAMED !=  CAST_PTR(SQLSMALLINT, Value))
945 			{
946 				ret = SQL_ERROR;
947 				DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
948 					"invalid descriptor identifier");
949 			}
950 			else
951 				NULL_THE_NAME(ipdopts->parameters[para_idx].paramName);
952 			break;
953 		case SQL_DESC_ALLOC_TYPE: /* read-only */
954 		case SQL_DESC_CASE_SENSITIVE: /* read-only */
955 		case SQL_DESC_DATETIME_INTERVAL_PRECISION:
956 		case SQL_DESC_FIXED_PREC_SCALE: /* read-only */
957 		case SQL_DESC_LENGTH:
958 		case SQL_DESC_LOCAL_TYPE_NAME: /* read-only */
959 		case SQL_DESC_NULLABLE: /* read-only */
960 		case SQL_DESC_NUM_PREC_RADIX:
961 		case SQL_DESC_OCTET_LENGTH:
962 		case SQL_DESC_PRECISION:
963 		case SQL_DESC_ROWVER: /* read-only */
964 		case SQL_DESC_TYPE_NAME: /* read-only */
965 		case SQL_DESC_UNSIGNED: /* read-only */
966 		default:ret = SQL_ERROR;
967 			DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
968 				"invalid descriptor identifier");
969 	}
970 	return ret;
971 }
972 
973 
974 static RETCODE SQL_API
ARDGetField(DescriptorClass * desc,SQLSMALLINT RecNumber,SQLSMALLINT FieldIdentifier,PTR Value,SQLINTEGER BufferLength,SQLINTEGER * StringLength)975 ARDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
976 			SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength,
977 			SQLINTEGER *StringLength)
978 {
979 	RETCODE		ret = SQL_SUCCESS;
980 	SQLLEN		ival = 0;
981 	SQLINTEGER	len, rettype = 0;
982 	PTR		ptr = NULL;
983 	const ARDFields	*opts = &(desc->ardf);
984 	SQLSMALLINT	row_idx;
985 
986 	len = sizeof(SQLINTEGER);
987 	if (0 == RecNumber) /* bookmark */
988 	{
989 		BindInfoClass	*bookmark = opts->bookmark;
990 		switch (FieldIdentifier)
991 		{
992 			case SQL_DESC_DATA_PTR:
993 				rettype = SQL_IS_POINTER;
994 				ptr = bookmark ? bookmark->buffer : NULL;
995 				break;
996 			case SQL_DESC_INDICATOR_PTR:
997 				rettype = SQL_IS_POINTER;
998 				ptr = bookmark ? bookmark->indicator : NULL;
999 				break;
1000 			case SQL_DESC_OCTET_LENGTH_PTR:
1001 				rettype = SQL_IS_POINTER;
1002 				ptr = bookmark ? bookmark->used : NULL;
1003 				break;
1004 		}
1005 		if (ptr)
1006 		{
1007 			*((void **) Value) = ptr;
1008 			if (StringLength)
1009 				*StringLength = len;
1010 			return ret;
1011 		}
1012 	}
1013 	switch (FieldIdentifier)
1014 	{
1015 		case SQL_DESC_ARRAY_SIZE:
1016 		case SQL_DESC_ARRAY_STATUS_PTR:
1017 		case SQL_DESC_BIND_OFFSET_PTR:
1018 		case SQL_DESC_BIND_TYPE:
1019 		case SQL_DESC_COUNT:
1020 			break;
1021 		default:
1022 			if (RecNumber <= 0 || RecNumber > opts->allocated)
1023 			{
1024 				DC_set_error(desc, DESC_INVALID_COLUMN_NUMBER_ERROR,
1025 					"invalid column number");
1026 				return SQL_ERROR;
1027 			}
1028 	}
1029 	row_idx = RecNumber - 1;
1030 	switch (FieldIdentifier)
1031 	{
1032 		case SQL_DESC_ARRAY_SIZE:
1033 			ival = opts->size_of_rowset;
1034 			break;
1035 		case SQL_DESC_ARRAY_STATUS_PTR:
1036 			rettype = SQL_IS_POINTER;
1037 			ptr = opts->row_operation_ptr;
1038 			break;
1039 		case SQL_DESC_BIND_OFFSET_PTR:
1040 			rettype = SQL_IS_POINTER;
1041 			ptr = opts->row_offset_ptr;
1042 			break;
1043 		case SQL_DESC_BIND_TYPE:
1044 			ival = opts->bind_size;
1045 			break;
1046 		case SQL_DESC_TYPE:
1047 			rettype = SQL_IS_SMALLINT;
1048 			switch (opts->bindings[row_idx].returntype)
1049 			{
1050 				case SQL_C_TYPE_DATE:
1051 				case SQL_C_TYPE_TIME:
1052 				case SQL_C_TYPE_TIMESTAMP:
1053 					ival = SQL_DATETIME;
1054 					break;
1055 				default:
1056 					ival = opts->bindings[row_idx].returntype;
1057 			}
1058 			break;
1059 		case SQL_DESC_DATETIME_INTERVAL_CODE:
1060 			rettype = SQL_IS_SMALLINT;
1061 			switch (opts->bindings[row_idx].returntype)
1062 			{
1063 				case SQL_C_TYPE_DATE:
1064 					ival = SQL_CODE_DATE;
1065 					break;
1066 				case SQL_C_TYPE_TIME:
1067 					ival = SQL_CODE_TIME;
1068 					break;
1069 				case SQL_C_TYPE_TIMESTAMP:
1070 					ival = SQL_CODE_TIMESTAMP;
1071 					break;
1072 				default:
1073 					ival = 0;
1074 					break;
1075 			}
1076 			break;
1077 		case SQL_DESC_CONCISE_TYPE:
1078 			rettype = SQL_IS_SMALLINT;
1079 			ival = opts->bindings[row_idx].returntype;
1080 			break;
1081 		case SQL_DESC_DATA_PTR:
1082 			rettype = SQL_IS_POINTER;
1083 			ptr = opts->bindings[row_idx].buffer;
1084 			break;
1085 		case SQL_DESC_INDICATOR_PTR:
1086 			rettype = SQL_IS_POINTER;
1087 			ptr = opts->bindings[row_idx].indicator;
1088 			break;
1089 		case SQL_DESC_OCTET_LENGTH_PTR:
1090 			rettype = SQL_IS_POINTER;
1091 			ptr = opts->bindings[row_idx].used;
1092 			break;
1093 		case SQL_DESC_COUNT:
1094 			rettype = SQL_IS_SMALLINT;
1095 			ival = opts->allocated;
1096 			break;
1097 		case SQL_DESC_OCTET_LENGTH:
1098 			ival = opts->bindings[row_idx].buflen;
1099 			break;
1100 		case SQL_DESC_ALLOC_TYPE: /* read-only */
1101 			rettype = SQL_IS_SMALLINT;
1102 			if (DC_get_embedded(desc))
1103 				ival = SQL_DESC_ALLOC_AUTO;
1104 			else
1105 				ival = SQL_DESC_ALLOC_USER;
1106 			break;
1107 		case SQL_DESC_PRECISION:
1108 			rettype = SQL_IS_SMALLINT;
1109 			ival = opts->bindings[row_idx].precision;
1110 			break;
1111 		case SQL_DESC_SCALE:
1112 			rettype = SQL_IS_SMALLINT;
1113 			ival = opts->bindings[row_idx].scale;
1114 			break;
1115 		case SQL_DESC_NUM_PREC_RADIX:
1116 			ival = 10;
1117 			break;
1118 		case SQL_DESC_DATETIME_INTERVAL_PRECISION:
1119 		case SQL_DESC_LENGTH:
1120 		default:
1121 			ret = SQL_ERROR;
1122 			DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
1123 				"invalid descriptor identifier");
1124 	}
1125 	switch (rettype)
1126 	{
1127 		case 0:
1128 		case SQL_IS_INTEGER:
1129 			len = sizeof(SQLINTEGER);
1130 			*((SQLINTEGER *) Value) = (SQLINTEGER) ival;
1131 			break;
1132 		case SQL_IS_SMALLINT:
1133 			len = sizeof(SQLSMALLINT);
1134 			*((SQLSMALLINT *) Value) = (SQLSMALLINT) ival;
1135 			break;
1136 		case SQL_IS_POINTER:
1137 			len = sizeof(SQLPOINTER);
1138 			*((void **) Value) = ptr;
1139 			break;
1140 	}
1141 
1142 	if (StringLength)
1143 		*StringLength = len;
1144 	return ret;
1145 }
1146 
1147 static RETCODE SQL_API
APDGetField(DescriptorClass * desc,SQLSMALLINT RecNumber,SQLSMALLINT FieldIdentifier,PTR Value,SQLINTEGER BufferLength,SQLINTEGER * StringLength)1148 APDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
1149 			SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength,
1150 			SQLINTEGER *StringLength)
1151 {
1152 	RETCODE		ret = SQL_SUCCESS;
1153 	SQLLEN		ival = 0;
1154 	SQLINTEGER	len, rettype = 0;
1155 	PTR		ptr = NULL;
1156 	const APDFields	*opts = (const APDFields *) &(desc->apdf);
1157 	SQLSMALLINT	para_idx;
1158 
1159 	len = sizeof(SQLINTEGER);
1160 	switch (FieldIdentifier)
1161 	{
1162 		case SQL_DESC_ARRAY_SIZE:
1163 		case SQL_DESC_ARRAY_STATUS_PTR:
1164 		case SQL_DESC_BIND_OFFSET_PTR:
1165 		case SQL_DESC_BIND_TYPE:
1166 		case SQL_DESC_COUNT:
1167 			break;
1168 		default:if (RecNumber <= 0 || RecNumber > opts->allocated)
1169 			{
1170 MYLOG(DETAIL_LOG_LEVEL, "RecN=%d allocated=%d\n", RecNumber, opts->allocated);
1171 				DC_set_error(desc, DESC_BAD_PARAMETER_NUMBER_ERROR,
1172 					"bad parameter number");
1173 				return SQL_ERROR;
1174 			}
1175 	}
1176 	para_idx = RecNumber - 1;
1177 	switch (FieldIdentifier)
1178 	{
1179 		case SQL_DESC_ARRAY_SIZE:
1180 			rettype = SQL_IS_LEN;
1181 			ival = opts->paramset_size;
1182 			break;
1183 		case SQL_DESC_ARRAY_STATUS_PTR:
1184 			rettype = SQL_IS_POINTER;
1185 			ptr = opts->param_operation_ptr;
1186 			break;
1187 		case SQL_DESC_BIND_OFFSET_PTR:
1188 			rettype = SQL_IS_POINTER;
1189 			ptr = opts->param_offset_ptr;
1190 			break;
1191 		case SQL_DESC_BIND_TYPE:
1192 			ival = opts->param_bind_type;
1193 			break;
1194 
1195 		case SQL_DESC_TYPE:
1196 			rettype = SQL_IS_SMALLINT;
1197 			switch (opts->parameters[para_idx].CType)
1198 			{
1199 				case SQL_C_TYPE_DATE:
1200 				case SQL_C_TYPE_TIME:
1201 				case SQL_C_TYPE_TIMESTAMP:
1202 					ival = SQL_DATETIME;
1203 					break;
1204 				default:
1205 					ival = opts->parameters[para_idx].CType;
1206 			}
1207 			break;
1208 		case SQL_DESC_DATETIME_INTERVAL_CODE:
1209 			rettype = SQL_IS_SMALLINT;
1210 			switch (opts->parameters[para_idx].CType)
1211 			{
1212 				case SQL_C_TYPE_DATE:
1213 					ival = SQL_CODE_DATE;
1214 					break;
1215 				case SQL_C_TYPE_TIME:
1216 					ival = SQL_CODE_TIME;
1217 					break;
1218 				case SQL_C_TYPE_TIMESTAMP:
1219 					ival = SQL_CODE_TIMESTAMP;
1220 					break;
1221 				default:
1222 					ival = 0;
1223 					break;
1224 			}
1225 			break;
1226 		case SQL_DESC_CONCISE_TYPE:
1227 			rettype = SQL_IS_SMALLINT;
1228 			ival = opts->parameters[para_idx].CType;
1229 			break;
1230 		case SQL_DESC_DATA_PTR:
1231 			rettype = SQL_IS_POINTER;
1232 			ptr = opts->parameters[para_idx].buffer;
1233 			break;
1234 		case SQL_DESC_INDICATOR_PTR:
1235 			rettype = SQL_IS_POINTER;
1236 			ptr = opts->parameters[para_idx].indicator;
1237 			break;
1238 		case SQL_DESC_OCTET_LENGTH:
1239 			ival = opts->parameters[para_idx].buflen;
1240 			break;
1241 		case SQL_DESC_OCTET_LENGTH_PTR:
1242 			rettype = SQL_IS_POINTER;
1243 			ptr = opts->parameters[para_idx].used;
1244 			break;
1245 		case SQL_DESC_COUNT:
1246 			rettype = SQL_IS_SMALLINT;
1247 			ival = opts->allocated;
1248 			break;
1249 		case SQL_DESC_ALLOC_TYPE: /* read-only */
1250 			rettype = SQL_IS_SMALLINT;
1251 			if (DC_get_embedded(desc))
1252 				ival = SQL_DESC_ALLOC_AUTO;
1253 			else
1254 				ival = SQL_DESC_ALLOC_USER;
1255 			break;
1256 		case SQL_DESC_NUM_PREC_RADIX:
1257 			ival = 10;
1258 			break;
1259 		case SQL_DESC_PRECISION:
1260 			rettype = SQL_IS_SMALLINT;
1261 			ival = opts->parameters[para_idx].precision;
1262 			break;
1263 		case SQL_DESC_SCALE:
1264 			rettype = SQL_IS_SMALLINT;
1265 			ival = opts->parameters[para_idx].scale;
1266 			break;
1267 		case SQL_DESC_DATETIME_INTERVAL_PRECISION:
1268 		case SQL_DESC_LENGTH:
1269 		default:ret = SQL_ERROR;
1270 			DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
1271 					"invalid descriptor identifer");
1272 	}
1273 	switch (rettype)
1274 	{
1275 		case SQL_IS_LEN:
1276 			len = sizeof(SQLLEN);
1277 			*((SQLLEN *) Value) = ival;
1278 			break;
1279 		case 0:
1280 		case SQL_IS_INTEGER:
1281 			len = sizeof(SQLINTEGER);
1282 			*((SQLINTEGER *) Value) = (SQLINTEGER) ival;
1283 			break;
1284 		case SQL_IS_SMALLINT:
1285 			len = sizeof(SQLSMALLINT);
1286 			*((SQLSMALLINT *) Value) = (SQLSMALLINT) ival;
1287 			break;
1288 		case SQL_IS_POINTER:
1289 			len = sizeof(SQLPOINTER);
1290 			*((void **) Value) = ptr;
1291 			break;
1292 	}
1293 
1294 	if (StringLength)
1295 		*StringLength = len;
1296 	return ret;
1297 }
1298 
1299 static RETCODE SQL_API
IRDGetField(DescriptorClass * desc,SQLSMALLINT RecNumber,SQLSMALLINT FieldIdentifier,PTR Value,SQLINTEGER BufferLength,SQLINTEGER * StringLength)1300 IRDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
1301 			SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength,
1302 			SQLINTEGER *StringLength)
1303 {
1304 	RETCODE		ret = SQL_SUCCESS;
1305 	SQLLEN		ival = 0;
1306 	SQLINTEGER	len = 0, rettype = 0;
1307 	PTR		ptr = NULL;
1308 	BOOL		bCallColAtt = FALSE;
1309 	const IRDFields	*opts = &(desc->irdf);
1310 
1311 	switch (FieldIdentifier)
1312 	{
1313 		case SQL_DESC_ARRAY_STATUS_PTR:
1314 			rettype = SQL_IS_POINTER;
1315 			ptr = opts->rowStatusArray;
1316 			break;
1317 		case SQL_DESC_ROWS_PROCESSED_PTR:
1318 			rettype = SQL_IS_POINTER;
1319 			ptr = opts->rowsFetched;
1320 			break;
1321 		case SQL_DESC_ALLOC_TYPE: /* read-only */
1322 			rettype = SQL_IS_SMALLINT;
1323 			ival = SQL_DESC_ALLOC_AUTO;
1324 			break;
1325 		case SQL_DESC_COUNT: /* read-only */
1326 		case SQL_DESC_AUTO_UNIQUE_VALUE: /* read-only */
1327 		case SQL_DESC_CASE_SENSITIVE: /* read-only */
1328 		case SQL_DESC_CONCISE_TYPE: /* read-only */
1329 		case SQL_DESC_DATETIME_INTERVAL_CODE: /* read-only */
1330 		case SQL_DESC_DATETIME_INTERVAL_PRECISION: /* read-only */
1331 		case SQL_DESC_DISPLAY_SIZE: /* read-only */
1332 		case SQL_DESC_FIXED_PREC_SCALE: /* read-only */
1333 		case SQL_DESC_LENGTH: /* read-only */
1334 		case SQL_DESC_NULLABLE: /* read-only */
1335 		case SQL_DESC_NUM_PREC_RADIX: /* read-only */
1336 		case SQL_DESC_OCTET_LENGTH: /* read-only */
1337 		case SQL_DESC_PRECISION: /* read-only */
1338 		case SQL_DESC_ROWVER: /* read-only */
1339 		case SQL_DESC_SCALE: /* read-only */
1340 		case SQL_DESC_SEARCHABLE: /* read-only */
1341 		case SQL_DESC_TYPE: /* read-only */
1342 		case SQL_DESC_UNNAMED: /* read-only */
1343 		case SQL_DESC_UNSIGNED: /* read-only */
1344 		case SQL_DESC_UPDATABLE: /* read-only */
1345 			bCallColAtt = TRUE;
1346 			break;
1347 		case SQL_DESC_BASE_COLUMN_NAME: /* read-only */
1348 		case SQL_DESC_BASE_TABLE_NAME: /* read-only */
1349 		case SQL_DESC_CATALOG_NAME: /* read-only */
1350 		case SQL_DESC_LABEL: /* read-only */
1351 		case SQL_DESC_LITERAL_PREFIX: /* read-only */
1352 		case SQL_DESC_LITERAL_SUFFIX: /* read-only */
1353 		case SQL_DESC_LOCAL_TYPE_NAME: /* read-only */
1354 		case SQL_DESC_NAME: /* read-only */
1355 		case SQL_DESC_SCHEMA_NAME: /* read-only */
1356 		case SQL_DESC_TABLE_NAME: /* read-only */
1357 		case SQL_DESC_TYPE_NAME: /* read-only */
1358 			rettype = SQL_NTS;
1359 			bCallColAtt = TRUE;
1360 			break;
1361 		default:
1362 			ret = SQL_ERROR;
1363 			DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
1364 				"invalid descriptor identifier");
1365 	}
1366 	if (bCallColAtt)
1367 	{
1368 		SQLSMALLINT	pcbL;
1369 		StatementClass	*stmt;
1370 
1371 		stmt = opts->stmt;
1372 		ret = PGAPI_ColAttributes(stmt, RecNumber,
1373 			FieldIdentifier, Value, (SQLSMALLINT) BufferLength,
1374 				&pcbL, &ival);
1375 		len = pcbL;
1376 	}
1377 	switch (rettype)
1378 	{
1379 		case 0:
1380 		case SQL_IS_INTEGER:
1381 			len = sizeof(SQLINTEGER);
1382 			*((SQLINTEGER *) Value) = (SQLINTEGER) ival;
1383 			break;
1384 		case SQL_IS_UINTEGER:
1385 			len = sizeof(SQLUINTEGER);
1386 			*((SQLUINTEGER *) Value) = (SQLUINTEGER) ival;
1387 			break;
1388 		case SQL_IS_SMALLINT:
1389 			len = sizeof(SQLSMALLINT);
1390 			*((SQLSMALLINT *) Value) = (SQLSMALLINT) ival;
1391 			break;
1392 		case SQL_IS_POINTER:
1393 			len = sizeof(SQLPOINTER);
1394 			*((void **) Value) = ptr;
1395 			break;
1396 		case SQL_NTS:
1397 			break;
1398 	}
1399 
1400 	if (StringLength)
1401 		*StringLength = len;
1402 	return ret;
1403 }
1404 
1405 static RETCODE SQL_API
IPDGetField(DescriptorClass * desc,SQLSMALLINT RecNumber,SQLSMALLINT FieldIdentifier,PTR Value,SQLINTEGER BufferLength,SQLINTEGER * StringLength)1406 IPDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
1407 			SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength,
1408 			SQLINTEGER *StringLength)
1409 {
1410 	RETCODE		ret = SQL_SUCCESS;
1411 	SQLINTEGER	ival = 0, len = 0, rettype = 0;
1412 	PTR		ptr = NULL;
1413 	const IPDFields	*ipdopts = (const IPDFields *) &(desc->ipdf);
1414 	SQLSMALLINT	para_idx;
1415 
1416 	switch (FieldIdentifier)
1417 	{
1418 		case SQL_DESC_ARRAY_STATUS_PTR:
1419 		case SQL_DESC_ROWS_PROCESSED_PTR:
1420 		case SQL_DESC_COUNT:
1421 			break;
1422 		default:if (RecNumber <= 0 || RecNumber > ipdopts->allocated)
1423 			{
1424 MYLOG(DETAIL_LOG_LEVEL, "RecN=%d allocated=%d\n", RecNumber, ipdopts->allocated);
1425 				DC_set_error(desc, DESC_BAD_PARAMETER_NUMBER_ERROR,
1426 					"bad parameter number");
1427 				return SQL_ERROR;
1428 			}
1429 	}
1430 	para_idx = RecNumber - 1;
1431 	switch (FieldIdentifier)
1432 	{
1433 		case SQL_DESC_ARRAY_STATUS_PTR:
1434 			rettype = SQL_IS_POINTER;
1435 			ptr = ipdopts->param_status_ptr;
1436 			break;
1437 		case SQL_DESC_ROWS_PROCESSED_PTR:
1438 			rettype = SQL_IS_POINTER;
1439 			ptr = ipdopts->param_processed_ptr;
1440 			break;
1441 		case SQL_DESC_UNNAMED:
1442 			rettype = SQL_IS_SMALLINT;
1443 			ival = NAME_IS_NULL(ipdopts->parameters[para_idx].paramName) ? SQL_UNNAMED : SQL_NAMED;
1444 			break;
1445 		case SQL_DESC_TYPE:
1446 			rettype = SQL_IS_SMALLINT;
1447 			switch (ipdopts->parameters[para_idx].SQLType)
1448 			{
1449 				case SQL_TYPE_DATE:
1450 				case SQL_TYPE_TIME:
1451 				case SQL_TYPE_TIMESTAMP:
1452 					ival = SQL_DATETIME;
1453 					break;
1454 				default:
1455 					ival = ipdopts->parameters[para_idx].SQLType;
1456 			}
1457 			break;
1458 		case SQL_DESC_DATETIME_INTERVAL_CODE:
1459 			rettype = SQL_IS_SMALLINT;
1460 			switch (ipdopts->parameters[para_idx].SQLType)
1461 			{
1462 				case SQL_TYPE_DATE:
1463 					ival = SQL_CODE_DATE;
1464 					break;
1465 				case SQL_TYPE_TIME:
1466 					ival = SQL_CODE_TIME;
1467 					break;
1468 				case SQL_TYPE_TIMESTAMP:
1469 					ival = SQL_CODE_TIMESTAMP;
1470 					break;
1471 				default:
1472 					ival = 0;
1473 			}
1474 			break;
1475 		case SQL_DESC_CONCISE_TYPE:
1476 			rettype = SQL_IS_SMALLINT;
1477 			ival = ipdopts->parameters[para_idx].SQLType;
1478 			break;
1479 		case SQL_DESC_COUNT:
1480 			rettype = SQL_IS_SMALLINT;
1481 			ival = ipdopts->allocated;
1482 			break;
1483 		case SQL_DESC_PARAMETER_TYPE:
1484 			rettype = SQL_IS_SMALLINT;
1485 			ival = ipdopts->parameters[para_idx].paramType;
1486 			break;
1487 		case SQL_DESC_PRECISION:
1488 			rettype = SQL_IS_SMALLINT;
1489 			switch (ipdopts->parameters[para_idx].SQLType)
1490 			{
1491 				case SQL_TYPE_DATE:
1492 				case SQL_TYPE_TIME:
1493 				case SQL_TYPE_TIMESTAMP:
1494 				case SQL_DATETIME:
1495 					ival = ipdopts->parameters[para_idx].decimal_digits;
1496 					break;
1497 			}
1498 			break;
1499 		case SQL_DESC_SCALE:
1500 			rettype = SQL_IS_SMALLINT;
1501 			switch (ipdopts->parameters[para_idx].SQLType)
1502 			{
1503 				case SQL_NUMERIC:
1504 					ival = ipdopts->parameters[para_idx].decimal_digits;
1505 					break;
1506 			}
1507 			break;
1508 		case SQL_DESC_ALLOC_TYPE: /* read-only */
1509 			rettype = SQL_IS_SMALLINT;
1510 			ival = SQL_DESC_ALLOC_AUTO;
1511 			break;
1512 		case SQL_DESC_CASE_SENSITIVE: /* read-only */
1513 		case SQL_DESC_DATETIME_INTERVAL_PRECISION:
1514 		case SQL_DESC_FIXED_PREC_SCALE: /* read-only */
1515 		case SQL_DESC_LENGTH:
1516 		case SQL_DESC_LOCAL_TYPE_NAME: /* read-only */
1517 		case SQL_DESC_NAME:
1518 		case SQL_DESC_NULLABLE: /* read-only */
1519 		case SQL_DESC_NUM_PREC_RADIX:
1520 		case SQL_DESC_OCTET_LENGTH:
1521 		case SQL_DESC_ROWVER: /* read-only */
1522 		case SQL_DESC_TYPE_NAME: /* read-only */
1523 		case SQL_DESC_UNSIGNED: /* read-only */
1524 		default:ret = SQL_ERROR;
1525 			DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
1526 				"invalid descriptor identifier");
1527 	}
1528 	switch (rettype)
1529 	{
1530 		case 0:
1531 		case SQL_IS_INTEGER:
1532 			len = sizeof(SQLINTEGER);
1533 			*((SQLINTEGER *) Value) = ival;
1534 			break;
1535 		case SQL_IS_SMALLINT:
1536 			len = sizeof(SQLSMALLINT);
1537 			*((SQLSMALLINT *) Value) = (SQLSMALLINT) ival;
1538 			break;
1539 		case SQL_IS_POINTER:
1540 			len = sizeof(SQLPOINTER);
1541 			*((void **)Value) = ptr;
1542 			break;
1543 	}
1544 
1545 	if (StringLength)
1546 		*StringLength = len;
1547 	return ret;
1548 }
1549 
1550 /*	SQLGetStmtOption -> SQLGetStmtAttr */
1551 RETCODE		SQL_API
PGAPI_GetStmtAttr(HSTMT StatementHandle,SQLINTEGER Attribute,PTR Value,SQLINTEGER BufferLength,SQLINTEGER * StringLength)1552 PGAPI_GetStmtAttr(HSTMT StatementHandle,
1553 				  SQLINTEGER Attribute, PTR Value,
1554 				  SQLINTEGER BufferLength, SQLINTEGER *StringLength)
1555 {
1556 	CSTR func = "PGAPI_GetStmtAttr";
1557 	StatementClass *stmt = (StatementClass *) StatementHandle;
1558 	RETCODE		ret = SQL_SUCCESS;
1559 	SQLINTEGER	len = 0;
1560 
1561 	MYLOG(0, "entering Handle=%p " FORMAT_INTEGER "\n", StatementHandle, Attribute);
1562 	switch (Attribute)
1563 	{
1564 		case SQL_ATTR_FETCH_BOOKMARK_PTR:	/* 16 */
1565 			*((void **) Value) = stmt->options.bookmark_ptr;
1566 			len = sizeof(SQLPOINTER);
1567 			break;
1568 		case SQL_ATTR_PARAM_BIND_OFFSET_PTR:	/* 17 */
1569 			*((SQLULEN **) Value) = SC_get_APDF(stmt)->param_offset_ptr;
1570 			len = sizeof(SQLPOINTER);
1571 			break;
1572 		case SQL_ATTR_PARAM_BIND_TYPE:	/* 18 */
1573 			*((SQLUINTEGER *) Value) = SC_get_APDF(stmt)->param_bind_type;
1574 			len = sizeof(SQLUINTEGER);
1575 			break;
1576 		case SQL_ATTR_PARAM_OPERATION_PTR:		/* 19 */
1577 			*((SQLUSMALLINT **) Value) = SC_get_APDF(stmt)->param_operation_ptr;
1578 			len = sizeof(SQLPOINTER);
1579 			break;
1580 		case SQL_ATTR_PARAM_STATUS_PTR: /* 20 */
1581 			*((SQLUSMALLINT **) Value) = SC_get_IPDF(stmt)->param_status_ptr;
1582 			len = sizeof(SQLPOINTER);
1583 			break;
1584 		case SQL_ATTR_PARAMS_PROCESSED_PTR:		/* 21 */
1585 			*((SQLULEN **) Value) = SC_get_IPDF(stmt)->param_processed_ptr;
1586 			len = sizeof(SQLPOINTER);
1587 			break;
1588 		case SQL_ATTR_PARAMSET_SIZE:	/* 22 */
1589 			*((SQLULEN *) Value) = SC_get_APDF(stmt)->paramset_size;
1590 			len = sizeof(SQLUINTEGER);
1591 			break;
1592 		case SQL_ATTR_ROW_BIND_OFFSET_PTR:		/* 23 */
1593 			*((SQLULEN **) Value) = SC_get_ARDF(stmt)->row_offset_ptr;
1594 			len = 4;
1595 			break;
1596 		case SQL_ATTR_ROW_OPERATION_PTR:		/* 24 */
1597 			*((SQLUSMALLINT **) Value) = SC_get_ARDF(stmt)->row_operation_ptr;
1598 			len = 4;
1599 			break;
1600 		case SQL_ATTR_ROW_STATUS_PTR:	/* 25 */
1601 			*((SQLUSMALLINT **) Value) = SC_get_IRDF(stmt)->rowStatusArray;
1602 			len = 4;
1603 			break;
1604 		case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */
1605 			*((SQLULEN **) Value) = SC_get_IRDF(stmt)->rowsFetched;
1606 			len = 4;
1607 			break;
1608 		case SQL_ATTR_ROW_ARRAY_SIZE:	/* 27 */
1609 			*((SQLULEN *) Value) = SC_get_ARDF(stmt)->size_of_rowset;
1610 			len = 4;
1611 			break;
1612 		case SQL_ATTR_APP_ROW_DESC:		/* 10010 */
1613 		case SQL_ATTR_APP_PARAM_DESC:	/* 10011 */
1614 		case SQL_ATTR_IMP_ROW_DESC:		/* 10012 */
1615 		case SQL_ATTR_IMP_PARAM_DESC:	/* 10013 */
1616 			len = 4;
1617 			*((HSTMT *) Value) = descHandleFromStatementHandle(StatementHandle, Attribute);
1618 			break;
1619 
1620 		case SQL_ATTR_CURSOR_SCROLLABLE:		/* -1 */
1621 			len = 4;
1622 			if (SQL_CURSOR_FORWARD_ONLY == stmt->options.cursor_type)
1623 				*((SQLUINTEGER *) Value) = SQL_NONSCROLLABLE;
1624 			else
1625 				*((SQLUINTEGER *) Value) = SQL_SCROLLABLE;
1626 			break;
1627 		case SQL_ATTR_CURSOR_SENSITIVITY:		/* -2 */
1628 			len = 4;
1629 			if (SQL_CONCUR_READ_ONLY == stmt->options.scroll_concurrency)
1630 				*((SQLUINTEGER *) Value) = SQL_INSENSITIVE;
1631 			else
1632 				*((SQLUINTEGER *) Value) = SQL_UNSPECIFIED;
1633 			break;
1634 		case SQL_ATTR_METADATA_ID:		/* 10014 */
1635 			*((SQLUINTEGER *) Value) = stmt->options.metadata_id;
1636 			break;
1637 		case SQL_ATTR_ENABLE_AUTO_IPD:	/* 15 */
1638 			*((SQLUINTEGER *) Value) = SQL_FALSE;
1639 			break;
1640 		case SQL_ATTR_AUTO_IPD:	/* 10001 */
1641 			/* case SQL_ATTR_ROW_BIND_TYPE: ** == SQL_BIND_TYPE(ODBC2.0) */
1642 			SC_set_error(stmt, DESC_INVALID_OPTION_IDENTIFIER, "Unsupported statement option (Get)", func);
1643 			return SQL_ERROR;
1644 		default:
1645 			ret = PGAPI_GetStmtOption(StatementHandle, (SQLSMALLINT) Attribute, Value, &len, BufferLength);
1646 	}
1647 	if (ret == SQL_SUCCESS && StringLength)
1648 		*StringLength = len;
1649 	return ret;
1650 }
1651 
1652 /*	SQLSetConnectOption -> SQLSetConnectAttr */
1653 RETCODE		SQL_API
PGAPI_SetConnectAttr(HDBC ConnectionHandle,SQLINTEGER Attribute,PTR Value,SQLINTEGER StringLength)1654 PGAPI_SetConnectAttr(HDBC ConnectionHandle,
1655 					 SQLINTEGER Attribute, PTR Value,
1656 					 SQLINTEGER StringLength)
1657 {
1658 	CSTR	func = "PGAPI_SetConnectAttr";
1659 	ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
1660 	RETCODE	ret = SQL_SUCCESS;
1661 	BOOL	unsupported = FALSE;
1662 	int	newValue;
1663 
1664 	MYLOG(0, "entering for %p: " FORMAT_INTEGER " %p\n", ConnectionHandle, Attribute, Value);
1665 	switch (Attribute)
1666 	{
1667 		case SQL_ATTR_METADATA_ID:
1668 			conn->stmtOptions.metadata_id = CAST_UPTR(SQLUINTEGER, Value);
1669 			break;
1670 		case SQL_ATTR_ANSI_APP:
1671 			if (SQL_AA_FALSE != CAST_PTR(SQLINTEGER, Value))
1672 			{
1673 				MYLOG(0, "the application is ansi\n");
1674 				if (CC_is_in_unicode_driver(conn)) /* the driver is unicode */
1675 					CC_set_in_ansi_app(conn); /* but the app is ansi */
1676 			}
1677 			else
1678 			{
1679 				MYLOG(0, "the application is unicode\n");
1680 			}
1681 			/*return SQL_ERROR;*/
1682 			return SQL_SUCCESS;
1683 		case SQL_ATTR_ENLIST_IN_DTC:
1684 #ifdef	WIN32
1685 #ifdef	_HANDLE_ENLIST_IN_DTC_
1686 			MYLOG(0, "SQL_ATTR_ENLIST_IN_DTC %p request received\n", Value);
1687 			if (conn->connInfo.xa_opt != 0)
1688 			{
1689 				/*
1690 				 *	When a new global transaction is about
1691 				 *	to begin, isolate the existent global
1692 				 *	transaction.
1693 				 */
1694 				if (NULL != Value && CC_is_in_global_trans(conn))
1695 					CALL_IsolateDtcConn(conn, TRUE);
1696 				return CALL_EnlistInDtc(conn, Value, conn->connInfo.xa_opt);
1697 			}
1698 #endif /* _HANDLE_ENLIST_IN_DTC_ */
1699 #endif /* WIN32 */
1700 			unsupported = TRUE;
1701 			break;
1702 		case SQL_ATTR_AUTO_IPD:
1703 			if (SQL_FALSE != Value)
1704 				unsupported = TRUE;
1705 			break;
1706 		case SQL_ATTR_ASYNC_ENABLE:
1707 		case SQL_ATTR_CONNECTION_DEAD:
1708 		case SQL_ATTR_CONNECTION_TIMEOUT:
1709 			unsupported = TRUE;
1710 			break;
1711 		case SQL_ATTR_PGOPT_DEBUG:
1712 			newValue = CAST_UPTR(SQLCHAR, Value);
1713 			if (newValue > 0)
1714 			{
1715 				logs_on_off(-1, conn->connInfo.drivers.debug, 0);
1716 				conn->connInfo.drivers.debug = newValue;
1717 				logs_on_off(1, conn->connInfo.drivers.debug, 0);
1718 				MYLOG(0, "debug => %d\n", conn->connInfo.drivers.debug);
1719 			}
1720 			else if (newValue == 0 && conn->connInfo.drivers.debug > 0)
1721 			{
1722 				MYLOG(0, "debug => %d\n", newValue);
1723 				logs_on_off(-1, conn->connInfo.drivers.debug, 0);
1724 				conn->connInfo.drivers.debug = newValue;
1725 				logs_on_off(1, 0, 0);
1726 			}
1727 			break;
1728 		case SQL_ATTR_PGOPT_COMMLOG:
1729 			newValue = CAST_UPTR(SQLCHAR, Value);
1730 			if (newValue > 0)
1731 			{
1732 				logs_on_off(-1, 0, conn->connInfo.drivers.commlog);
1733 				conn->connInfo.drivers.commlog = newValue;
1734 				logs_on_off(1, 0, conn->connInfo.drivers.commlog);
1735 				MYLOG(0, "commlog => %d\n", conn->connInfo.drivers.commlog);
1736 			}
1737 			else if (newValue == 0 && conn->connInfo.drivers.commlog > 0)
1738 			{
1739 				MYLOG(0, "commlog => %d\n", newValue);
1740 				logs_on_off(-1, 0, conn->connInfo.drivers.commlog);
1741 				conn->connInfo.drivers.debug = newValue;
1742 				logs_on_off(1, 0, 0);
1743 			}
1744 			break;
1745 		case SQL_ATTR_PGOPT_PARSE:
1746 			conn->connInfo.drivers.parse = CAST_UPTR(SQLCHAR, Value);
1747 			MYLOG(0, "parse => %d\n", conn->connInfo.drivers.parse);
1748 			break;
1749 		case SQL_ATTR_PGOPT_USE_DECLAREFETCH:
1750 			conn->connInfo.drivers.use_declarefetch = CAST_UPTR(SQLCHAR, Value);
1751 			ci_updatable_cursors_set(&conn->connInfo);
1752 			MYLOG(0, "declarefetch => %d\n", conn->connInfo.drivers.use_declarefetch);
1753 			break;
1754 		case SQL_ATTR_PGOPT_SERVER_SIDE_PREPARE:
1755 			conn->connInfo.use_server_side_prepare = CAST_UPTR(SQLCHAR, Value);
1756 			MYLOG(0, "server_side_prepare => %d\n", conn->connInfo.use_server_side_prepare);
1757 			break;
1758 		case SQL_ATTR_PGOPT_FETCH:
1759 			conn->connInfo.drivers.fetch_max = CAST_PTR(SQLINTEGER, Value);
1760 			MYLOG(0, "fetch => %d\n", conn->connInfo.drivers.fetch_max);
1761 			break;
1762 		case SQL_ATTR_PGOPT_UNKNOWNSIZES:
1763 			conn->connInfo.drivers.unknown_sizes = CAST_PTR(SQLINTEGER, Value);
1764 			MYLOG(0, "unknown_sizes => %d\n", conn->connInfo.drivers.unknown_sizes);
1765 			break;
1766 		case SQL_ATTR_PGOPT_TEXTASLONGVARCHAR:
1767 			conn->connInfo.drivers.text_as_longvarchar = CAST_PTR(SQLINTEGER, Value);
1768 			MYLOG(0, "text_as_longvarchar => %d\n", conn->connInfo.drivers.text_as_longvarchar);
1769 			break;
1770 		case SQL_ATTR_PGOPT_UNKNOWNSASLONGVARCHAR:
1771 			conn->connInfo.drivers.unknowns_as_longvarchar = CAST_PTR(SQLINTEGER, Value);
1772 			MYLOG(0, "unknowns_as_long_varchar => %d\n", conn->connInfo.drivers.unknowns_as_longvarchar);
1773 			break;
1774 		case SQL_ATTR_PGOPT_BOOLSASCHAR:
1775 			conn->connInfo.drivers.bools_as_char = CAST_PTR(SQLINTEGER, Value);
1776 			MYLOG(0, "bools_as_char => %d\n", conn->connInfo.drivers.bools_as_char);
1777 			break;
1778 		case SQL_ATTR_PGOPT_MAXVARCHARSIZE:
1779 			conn->connInfo.drivers.max_varchar_size = CAST_PTR(SQLINTEGER, Value);
1780 			MYLOG(0, "max_varchar_size => %d\n", conn->connInfo.drivers.max_varchar_size);
1781 			break;
1782 		case SQL_ATTR_PGOPT_MAXLONGVARCHARSIZE:
1783 			conn->connInfo.drivers.max_longvarchar_size = CAST_PTR(SQLINTEGER, Value);
1784 			MYLOG(0, "max_longvarchar_size => %d\n", conn->connInfo.drivers.max_longvarchar_size);
1785 			break;
1786 		case SQL_ATTR_PGOPT_WCSDEBUG:
1787 			conn->connInfo.wcs_debug = CAST_PTR(SQLINTEGER, Value);
1788 			MYLOG(0, "wcs_debug => %d\n", conn->connInfo.wcs_debug);
1789 			break;
1790 		case SQL_ATTR_PGOPT_MSJET:
1791 			conn->ms_jet = CAST_PTR(SQLINTEGER, Value);
1792 			MYLOG(0, "ms_jet => %d\n", conn->ms_jet);
1793 			break;
1794 		case SQL_ATTR_PGOPT_BATCHSIZE:
1795 			conn->connInfo.batch_size = CAST_PTR(SQLINTEGER, Value);
1796 			MYLOG(0, "batch size => %d\n", conn->connInfo.batch_size);
1797 			break;
1798 		case SQL_ATTR_PGOPT_IGNORETIMEOUT:
1799 			conn->connInfo.ignore_timeout = CAST_PTR(SQLINTEGER, Value);
1800 			MYLOG(0, "ignore_timeout => %d\n", conn->connInfo.ignore_timeout);
1801 			break;
1802 		default:
1803 			if (Attribute < 65536)
1804 				ret = PGAPI_SetConnectOption(ConnectionHandle, (SQLUSMALLINT) Attribute, (SQLLEN) Value);
1805 			else
1806 				unsupported = TRUE;
1807 	}
1808 	if (unsupported)
1809 	{
1810 		char	msg[64];
1811 		SPRINTF_FIXED(msg, "Couldn't set unsupported connect attribute " FORMAT_INTEGER, Attribute);
1812 		CC_set_error(conn, CONN_OPTION_NOT_FOR_THE_DRIVER, msg, func);
1813 		return SQL_ERROR;
1814 	}
1815 	return ret;
1816 }
1817 
1818 /*	new function */
1819 RETCODE		SQL_API
PGAPI_GetDescField(SQLHDESC DescriptorHandle,SQLSMALLINT RecNumber,SQLSMALLINT FieldIdentifier,PTR Value,SQLINTEGER BufferLength,SQLINTEGER * StringLength)1820 PGAPI_GetDescField(SQLHDESC DescriptorHandle,
1821 				   SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
1822 				   PTR Value, SQLINTEGER BufferLength,
1823 				   SQLINTEGER *StringLength)
1824 {
1825 	CSTR func = "PGAPI_GetDescField";
1826 	RETCODE		ret = SQL_SUCCESS;
1827 	DescriptorClass *desc = (DescriptorClass *) DescriptorHandle;
1828 
1829 	MYLOG(0, "entering h=%p rec=" FORMAT_SMALLI " field=" FORMAT_SMALLI " blen=" FORMAT_INTEGER "\n", DescriptorHandle, RecNumber, FieldIdentifier, BufferLength);
1830 	switch (DC_get_desc_type(desc))
1831 	{
1832 		case SQL_ATTR_APP_ROW_DESC:
1833 			ret = ARDGetField(desc, RecNumber, FieldIdentifier, Value, BufferLength, StringLength);
1834 			break;
1835 		case SQL_ATTR_APP_PARAM_DESC:
1836 			ret = APDGetField(desc, RecNumber, FieldIdentifier, Value, BufferLength, StringLength);
1837 			break;
1838 		case SQL_ATTR_IMP_ROW_DESC:
1839 			ret = IRDGetField(desc, RecNumber, FieldIdentifier, Value, BufferLength, StringLength);
1840 			break;
1841 		case SQL_ATTR_IMP_PARAM_DESC:
1842 			ret = IPDGetField(desc, RecNumber, FieldIdentifier, Value, BufferLength, StringLength);
1843 			break;
1844 		default:ret = SQL_ERROR;
1845 			DC_set_error(desc, DESC_INTERNAL_ERROR, "Error not implemented");
1846 	}
1847 	if (ret == SQL_ERROR)
1848 	{
1849 		if (!DC_get_errormsg(desc))
1850 		{
1851 			switch (DC_get_errornumber(desc))
1852 			{
1853 				case DESC_INVALID_DESCRIPTOR_IDENTIFIER:
1854 					DC_set_errormsg(desc, "can't SQLGetDescField for this descriptor identifier");
1855 					break;
1856 				case DESC_INVALID_COLUMN_NUMBER_ERROR:
1857 					DC_set_errormsg(desc, "can't SQLGetDescField for this column number");
1858 					break;
1859 				case DESC_BAD_PARAMETER_NUMBER_ERROR:
1860 					DC_set_errormsg(desc, "can't SQLGetDescField for this parameter number");
1861 					break;
1862 			}
1863 		}
1864 		DC_log_error(func, "", desc);
1865 	}
1866 	return ret;
1867 }
1868 
1869 /*	new function */
1870 RETCODE		SQL_API
PGAPI_SetDescField(SQLHDESC DescriptorHandle,SQLSMALLINT RecNumber,SQLSMALLINT FieldIdentifier,PTR Value,SQLINTEGER BufferLength)1871 PGAPI_SetDescField(SQLHDESC DescriptorHandle,
1872 				   SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
1873 				   PTR Value, SQLINTEGER BufferLength)
1874 {
1875 	CSTR func = "PGAPI_SetDescField";
1876 	RETCODE		ret = SQL_SUCCESS;
1877 	DescriptorClass *desc = (DescriptorClass *) DescriptorHandle;
1878 
1879 	MYLOG(0, "entering h=%p(%d) rec=" FORMAT_SMALLI " field=" FORMAT_SMALLI " val=%p," FORMAT_INTEGER "\n", DescriptorHandle, DC_get_desc_type(desc), RecNumber, FieldIdentifier, Value, BufferLength);
1880 	switch (DC_get_desc_type(desc))
1881 	{
1882 		case SQL_ATTR_APP_ROW_DESC:
1883 			ret = ARDSetField(desc, RecNumber, FieldIdentifier, Value, BufferLength);
1884 			break;
1885 		case SQL_ATTR_APP_PARAM_DESC:
1886 			ret = APDSetField(desc, RecNumber, FieldIdentifier, Value, BufferLength);
1887 			break;
1888 		case SQL_ATTR_IMP_ROW_DESC:
1889 			ret = IRDSetField(desc, RecNumber, FieldIdentifier, Value, BufferLength);
1890 			break;
1891 		case SQL_ATTR_IMP_PARAM_DESC:
1892 			ret = IPDSetField(desc, RecNumber, FieldIdentifier, Value, BufferLength);
1893 			break;
1894 		default:ret = SQL_ERROR;
1895 			DC_set_error(desc, DESC_INTERNAL_ERROR, "Error not implemented");
1896 	}
1897 	if (ret == SQL_ERROR)
1898 	{
1899 		if (!DC_get_errormsg(desc))
1900 		{
1901 			switch (DC_get_errornumber(desc))
1902 			{
1903 				case DESC_INVALID_DESCRIPTOR_IDENTIFIER:
1904 					DC_set_errormsg(desc, "can't SQLSetDescField for this descriptor identifier");
1905 					break;
1906 				case DESC_INVALID_COLUMN_NUMBER_ERROR:
1907 					DC_set_errormsg(desc, "can't SQLSetDescField for this column number");
1908 					break;
1909 				case DESC_BAD_PARAMETER_NUMBER_ERROR:
1910 					DC_set_errormsg(desc, "can't SQLSetDescField for this parameter number");
1911 					break;
1912 				break;
1913 			}
1914 		}
1915 		DC_log_error(func, "", desc);
1916 	}
1917 	return ret;
1918 }
1919 
1920 /*	SQLSet(Param/Scroll/Stmt)Option -> SQLSetStmtAttr */
1921 RETCODE		SQL_API
PGAPI_SetStmtAttr(HSTMT StatementHandle,SQLINTEGER Attribute,PTR Value,SQLINTEGER StringLength)1922 PGAPI_SetStmtAttr(HSTMT StatementHandle,
1923 				  SQLINTEGER Attribute, PTR Value,
1924 				  SQLINTEGER StringLength)
1925 {
1926 	RETCODE	ret = SQL_SUCCESS;
1927 	CSTR func = "PGAPI_SetStmtAttr";
1928 	StatementClass *stmt = (StatementClass *) StatementHandle;
1929 
1930 	MYLOG(0, "entering Handle=%p " FORMAT_INTEGER "," FORMAT_ULEN "(%p)\n", StatementHandle, Attribute, (SQLULEN) Value, Value);
1931 	switch (Attribute)
1932 	{
1933 		case SQL_ATTR_ENABLE_AUTO_IPD:	/* 15 */
1934 			if (SQL_FALSE == Value)
1935 				break;
1936 		case SQL_ATTR_CURSOR_SCROLLABLE:		/* -1 */
1937 		case SQL_ATTR_CURSOR_SENSITIVITY:		/* -2 */
1938 		case SQL_ATTR_AUTO_IPD:	/* 10001 */
1939 			SC_set_error(stmt, DESC_OPTION_NOT_FOR_THE_DRIVER, "Unsupported statement option (Set)", func);
1940 			return SQL_ERROR;
1941 		/* case SQL_ATTR_ROW_BIND_TYPE: ** == SQL_BIND_TYPE(ODBC2.0) */
1942 		case SQL_ATTR_IMP_ROW_DESC:	/* 10012 (read-only) */
1943 		case SQL_ATTR_IMP_PARAM_DESC:	/* 10013 (read-only) */
1944 
1945 			/*
1946 			 * case SQL_ATTR_PREDICATE_PTR: case
1947 			 * SQL_ATTR_PREDICATE_OCTET_LENGTH_PTR:
1948 			 */
1949 			SC_set_error(stmt, DESC_INVALID_OPTION_IDENTIFIER, "Unsupported statement option (Set)", func);
1950 			return SQL_ERROR;
1951 
1952 		case SQL_ATTR_METADATA_ID:		/* 10014 */
1953 			stmt->options.metadata_id = CAST_UPTR(SQLUINTEGER, Value);
1954 			break;
1955 		case SQL_ATTR_APP_ROW_DESC:		/* 10010 */
1956 			if (SQL_NULL_HDESC == Value)
1957 			{
1958 				stmt->ard = &(stmt->ardi);
1959 			}
1960 			else
1961 			{
1962 				stmt->ard = (DescriptorClass *) Value;
1963 MYLOG(DETAIL_LOG_LEVEL, "set ard=%p\n", stmt->ard);
1964 			}
1965 			break;
1966 		case SQL_ATTR_APP_PARAM_DESC:	/* 10011 */
1967 			if (SQL_NULL_HDESC == Value)
1968 			{
1969 				stmt->apd = &(stmt->apdi);
1970 			}
1971 			else
1972 			{
1973 				stmt->apd = (DescriptorClass *) Value;
1974 			}
1975 			break;
1976 		case SQL_ATTR_FETCH_BOOKMARK_PTR:		/* 16 */
1977 			stmt->options.bookmark_ptr = Value;
1978 			break;
1979 		case SQL_ATTR_PARAM_BIND_OFFSET_PTR:	/* 17 */
1980 			SC_get_APDF(stmt)->param_offset_ptr = (SQLULEN *) Value;
1981 			break;
1982 		case SQL_ATTR_PARAM_BIND_TYPE:	/* 18 */
1983 			SC_get_APDF(stmt)->param_bind_type = CAST_UPTR(SQLUINTEGER, Value);
1984 			break;
1985 		case SQL_ATTR_PARAM_OPERATION_PTR:		/* 19 */
1986 			SC_get_APDF(stmt)->param_operation_ptr = Value;
1987 			break;
1988 		case SQL_ATTR_PARAM_STATUS_PTR:			/* 20 */
1989 			SC_get_IPDF(stmt)->param_status_ptr = (SQLUSMALLINT *) Value;
1990 			break;
1991 		case SQL_ATTR_PARAMS_PROCESSED_PTR:		/* 21 */
1992 			SC_get_IPDF(stmt)->param_processed_ptr = (SQLULEN *) Value;
1993 			break;
1994 		case SQL_ATTR_PARAMSET_SIZE:	/* 22 */
1995 			SC_get_APDF(stmt)->paramset_size = CAST_UPTR(SQLULEN, Value);
1996 			break;
1997 		case SQL_ATTR_ROW_BIND_OFFSET_PTR:		/* 23 */
1998 			SC_get_ARDF(stmt)->row_offset_ptr = (SQLULEN *) Value;
1999 			break;
2000 		case SQL_ATTR_ROW_OPERATION_PTR:		/* 24 */
2001 			SC_get_ARDF(stmt)->row_operation_ptr = Value;
2002 			break;
2003 		case SQL_ATTR_ROW_STATUS_PTR:	/* 25 */
2004 			SC_get_IRDF(stmt)->rowStatusArray = (SQLUSMALLINT *) Value;
2005 			break;
2006 		case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */
2007 			SC_get_IRDF(stmt)->rowsFetched = (SQLULEN *) Value;
2008 			break;
2009 		case SQL_ATTR_ROW_ARRAY_SIZE:	/* 27 */
2010 			SC_get_ARDF(stmt)->size_of_rowset = CAST_UPTR(SQLULEN, Value);
2011 			break;
2012 		default:
2013 			return PGAPI_SetStmtOption(StatementHandle, (SQLUSMALLINT) Attribute, (SQLULEN) Value);
2014 	}
2015 	return ret;
2016 }
2017 
2018 /*	SQL_NEED_DATA callback for PGAPI_BulkOperations */
2019 typedef struct
2020 {
2021 	StatementClass	*stmt;
2022 	SQLSMALLINT	operation;
2023 	char		need_data_callback;
2024 	char		auto_commit_needed;
2025 	ARDFields	*opts;
2026 	int		idx, processed;
2027 }	bop_cdata;
2028 
2029 static
bulk_ope_callback(RETCODE retcode,void * para)2030 RETCODE	bulk_ope_callback(RETCODE retcode, void *para)
2031 {
2032 	CSTR func = "bulk_ope_callback";
2033 	RETCODE	ret = retcode;
2034 	bop_cdata *s = (bop_cdata *) para;
2035 	SQLULEN		global_idx;
2036 	ConnectionClass	*conn;
2037 	QResultClass	*res;
2038 	IRDFields	*irdflds;
2039 	PG_BM		pg_bm;
2040 
2041 	if (s->need_data_callback)
2042 	{
2043 		MYLOG(0, "entering in\n");
2044 		s->processed++;
2045 		s->idx++;
2046 	}
2047 	else
2048 	{
2049 		s->idx = s->processed = 0;
2050 	}
2051 	s->need_data_callback = FALSE;
2052 	res = SC_get_Curres(s->stmt);
2053 	for (; SQL_ERROR != ret && s->idx < s->opts->size_of_rowset; s->idx++)
2054 	{
2055 		if (SQL_ADD != s->operation)
2056 		{
2057 			pg_bm = SC_Resolve_bookmark(s->opts, s->idx);
2058 			QR_get_last_bookmark(res, s->idx, &pg_bm.keys);
2059 			global_idx = pg_bm.index;
2060 		}
2061 		/* Note opts->row_operation_ptr is ignored */
2062 		switch (s->operation)
2063 		{
2064 			case SQL_ADD:
2065 				ret = SC_pos_add(s->stmt, (UWORD) s->idx);
2066 				break;
2067 			case SQL_UPDATE_BY_BOOKMARK:
2068 				ret = SC_pos_update(s->stmt, (UWORD) s->idx, global_idx, &(pg_bm.keys));
2069 				break;
2070 			case SQL_DELETE_BY_BOOKMARK:
2071 				ret = SC_pos_delete(s->stmt, (UWORD) s->idx, global_idx, &(pg_bm.keys));
2072 				break;
2073 		}
2074 		if (SQL_NEED_DATA == ret)
2075 		{
2076 			bop_cdata *cbdata = (bop_cdata *) malloc(sizeof(bop_cdata));
2077 			if (!cbdata)
2078 			{
2079 				SC_set_error(s->stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for cbdata.", func);
2080 				return SQL_ERROR;
2081 			}
2082 			memcpy(cbdata, s, sizeof(bop_cdata));
2083 			cbdata->need_data_callback = TRUE;
2084 			if (0 == enqueueNeedDataCallback(s->stmt, bulk_ope_callback, cbdata))
2085 				ret = SQL_ERROR;
2086 			return ret;
2087 		}
2088 		s->processed++;
2089 	}
2090 	conn = SC_get_conn(s->stmt);
2091 	if (s->auto_commit_needed)
2092 		CC_set_autocommit(conn, TRUE);
2093 	irdflds = SC_get_IRDF(s->stmt);
2094 	if (irdflds->rowsFetched)
2095 		*(irdflds->rowsFetched) = s->processed;
2096 
2097 	if (res)
2098 		res->recent_processed_row_count = s->stmt->diag_row_count = s->processed;
2099 	return ret;
2100 }
2101 
2102 RETCODE	SQL_API
PGAPI_BulkOperations(HSTMT hstmt,SQLSMALLINT operationX)2103 PGAPI_BulkOperations(HSTMT hstmt, SQLSMALLINT operationX)
2104 {
2105 	CSTR func = "PGAPI_BulkOperations";
2106 	bop_cdata	s;
2107 	RETCODE		ret;
2108 	ConnectionClass	*conn;
2109 	BindInfoClass	*bookmark;
2110 
2111 	MYLOG(0, "entering operation = %d\n", operationX);
2112 	s.stmt = (StatementClass *) hstmt;
2113 	s.operation = operationX;
2114 	SC_clear_error(s.stmt);
2115 	s.opts = SC_get_ARDF(s.stmt);
2116 
2117 	s.auto_commit_needed = FALSE;
2118 	if (SQL_FETCH_BY_BOOKMARK != s.operation)
2119 	{
2120 		conn = SC_get_conn(s.stmt);
2121 		if (s.auto_commit_needed = (char) CC_does_autocommit(conn), s.auto_commit_needed)
2122 			CC_set_autocommit(conn, FALSE);
2123 	}
2124 	if (SQL_ADD != s.operation)
2125 	{
2126 		if (!(bookmark = s.opts->bookmark) || !(bookmark->buffer))
2127 		{
2128 			SC_set_error(s.stmt, DESC_INVALID_OPTION_IDENTIFIER, "bookmark isn't specified", func);
2129 			return SQL_ERROR;
2130 		}
2131 	}
2132 
2133 	/* StartRollbackState(s.stmt); */
2134 	if (SQL_FETCH_BY_BOOKMARK == operationX)
2135 		ret = SC_fetch_by_bookmark(s.stmt);
2136 	else
2137 	{
2138 		s.need_data_callback = FALSE;
2139 		ret = bulk_ope_callback(SQL_SUCCESS, &s);
2140 	}
2141 	return ret;
2142 }
2143