options.c 8.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14

/* Module:          options.c
 *
 * Description:     This module contains routines for getting/setting
 *                  connection and statement options.
 *
 * Classes:         n/a
 *
 * API functions:   SQLSetConnectOption, SQLSetStmtOption, SQLGetConnectOption,
 *                  SQLGetStmtOption
 *
 * Comments:        See "notice.txt" for copyright and license information.
 *
 */
15

B
Byron Nikolaidis 已提交
16
#ifdef HAVE_CONFIG_H
17
#include "config.h"
B
Byron Nikolaidis 已提交
18 19
#endif

20
#include "psqlodbc.h"
B
Byron Nikolaidis 已提交
21

22
#ifndef WIN32
B
Byron Nikolaidis 已提交
23 24 25 26
#include "iodbc.h"
#include "isql.h"
#include "isqlext.h"
#else
27 28
#include <windows.h>
#include <sql.h>
29
#include <sqlext.h>
B
Byron Nikolaidis 已提交
30 31
#endif

32 33 34 35
#include "environ.h"
#include "connection.h"
#include "statement.h"

36 37 38 39

extern GLOBAL_VALUES globals;


40 41 42 43 44 45
/* Implements only SQL_AUTOCOMMIT */
RETCODE SQL_API SQLSetConnectOption(
        HDBC    hdbc,
        UWORD   fOption,
        UDWORD  vParam)
{
46
static char *func="SQLSetConnectOption";
47 48
ConnectionClass *conn = (ConnectionClass *) hdbc;

49 50
	mylog("%s: entering...\n", func);

B
Byron Nikolaidis 已提交
51 52
	if ( ! conn)  {
		CC_log_error(func, "", NULL);
53
		return SQL_INVALID_HANDLE;
B
Byron Nikolaidis 已提交
54 55
	}

56 57 58 59 60 61 62 63 64 65 66

	switch (fOption) {
	case SQL_AUTOCOMMIT:

		/*  Since we are almost always in a transaction, this is now ok.
			Even if we were, the logic will handle it by sending a commit
			after the statement.
		
		if (CC_is_in_trans(conn)) {
			conn->errormsg = "Cannot switch commit mode while a transaction is in progres";
			conn->errornumber = CONN_TRANSACT_IN_PROGRES;
B
Byron Nikolaidis 已提交
67
			CC_log_error(func, "", conn);
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
			return SQL_ERROR;
		}
		*/

		mylog("SQLSetConnectOption: AUTOCOMMIT: transact_status=%d, vparam=%d\n", conn->transact_status, vParam);

		switch(vParam) {
		case SQL_AUTOCOMMIT_OFF:
			CC_set_autocommit_off(conn);
			break;

		case SQL_AUTOCOMMIT_ON:
			CC_set_autocommit_on(conn);
			break;

		default:
			conn->errormsg = "Illegal parameter value for SQL_AUTOCOMMIT";
			conn->errornumber = CONN_INVALID_ARGUMENT_NO;
B
Byron Nikolaidis 已提交
86
			CC_log_error(func, "", conn);
87 88 89 90 91 92 93 94 95 96 97
			return SQL_ERROR;
		}

		break;

	case SQL_LOGIN_TIMEOUT:
		break;

	case SQL_ACCESS_MODE:
		break;

B
Byron Nikolaidis 已提交
98 99 100
	case SQL_TXN_ISOLATION:
		break;

101
	default:
B
Byron Nikolaidis 已提交
102
		{ 
B
Byron Nikolaidis 已提交
103 104
		char option[64];
		conn->errormsg = "Driver does not support setting this connect option";
105
		conn->errornumber = CONN_UNSUPPORTED_OPTION;
106
		sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
B
Byron Nikolaidis 已提交
107
		CC_log_error(func, option, conn);
108
		return SQL_ERROR;
B
Byron Nikolaidis 已提交
109
		}
110 111 112 113 114 115 116

	}    
	return SQL_SUCCESS;
}

//      -       -       -       -       -       -       -       -       -

117 118 119 120 121 122
/* This function just can tell you whether you are in Autcommit mode or not */
RETCODE SQL_API SQLGetConnectOption(
        HDBC    hdbc,
        UWORD   fOption,
        PTR     pvParam)
{
123
static char *func="SQLGetConnectOption";
124 125
ConnectionClass *conn = (ConnectionClass *) hdbc;

126 127
	mylog("%s: entering...\n", func);

B
Byron Nikolaidis 已提交
128 129
	if (! conn)  {
		CC_log_error(func, "", NULL);
130
		return SQL_INVALID_HANDLE;
B
Byron Nikolaidis 已提交
131
	}
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

	switch (fOption) {
	case SQL_AUTOCOMMIT:
		*((UDWORD *)pvParam) = (UDWORD)( CC_is_in_autocommit(conn) ?
						SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF);
		break;

	/* don't use qualifiers */
	case SQL_CURRENT_QUALIFIER:
		if(pvParam)
			strcpy(pvParam, "");

		break;

	default:
B
Byron Nikolaidis 已提交
147
		{
B
Byron Nikolaidis 已提交
148 149
		char option[64];
		conn->errormsg = "Driver does not support getting this connect option";
150
		conn->errornumber = CONN_UNSUPPORTED_OPTION;
B
Byron Nikolaidis 已提交
151 152
		sprintf(option, "fOption=%d", fOption);
		CC_log_error(func, option, conn);
153 154
		return SQL_ERROR;
		break;
B
Byron Nikolaidis 已提交
155
		}
156 157 158 159 160 161 162 163

	}    

	return SQL_SUCCESS;
}

//      -       -       -       -       -       -       -       -       -

164 165 166 167 168
RETCODE SQL_API SQLSetStmtOption(
        HSTMT   hstmt,
        UWORD   fOption,
        UDWORD  vParam)
{
169
static char *func="SQLSetStmtOption";
170
StatementClass *stmt = (StatementClass *) hstmt;
171
char changed = FALSE;
172

173 174
	mylog("%s: entering...\n", func);

175 176 177 178
    // thought we could fake Access out by just returning SQL_SUCCESS
    // all the time, but it tries to set a huge value for SQL_MAX_LENGTH
    // and expects the driver to reduce it to the real value

B
Byron Nikolaidis 已提交
179 180
	if( ! stmt) {
		SC_log_error(func, "", NULL);
181
		return SQL_INVALID_HANDLE;
B
Byron Nikolaidis 已提交
182
	}
183

184 185
	switch(fOption) {
	case SQL_QUERY_TIMEOUT:
186
		mylog("SetStmtOption: vParam = %d\n", vParam);
187 188 189 190 191 192 193
		//	"0" returned in SQLGetStmtOption
		break;

	case SQL_MAX_LENGTH:
		//	"4096" returned in SQLGetStmtOption
		break;

194 195 196 197 198 199
	case SQL_MAX_ROWS:
		mylog("SetStmtOption(): SQL_MAX_ROWS = %d, returning success\n", vParam);
		stmt->maxRows = vParam;
		return SQL_SUCCESS;
		break;

200 201
	case SQL_ROWSET_SIZE:
		mylog("SetStmtOption(): SQL_ROWSET_SIZE = %d\n", vParam);
202

203 204 205
		stmt->rowset_size = 1;		// only support 1 row at a time
		if (vParam != 1) 
			changed = TRUE;
206

207 208
		break;

209 210 211 212 213 214 215
	case SQL_KEYSET_SIZE:
		mylog("SetStmtOption(): SQL_KEYSET_SIZE = %d\n", vParam);
		if (globals.lie)
			stmt->keyset_size = vParam;
		else {
			stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
			stmt->errormsg = "Driver does not support keyset size option";
B
Byron Nikolaidis 已提交
216
			SC_log_error(func, "", stmt);
217 218 219 220
			return SQL_ERROR;
		}
		break;

221 222 223 224
	case SQL_CONCURRENCY:
		//	positioned update isn't supported so cursor concurrency is read-only
		mylog("SetStmtOption(): SQL_CONCURRENCY = %d\n", vParam);

225 226 227 228 229 230 231
		if (globals.lie)
			stmt->scroll_concurrency = vParam;
		else {
			stmt->scroll_concurrency = SQL_CONCUR_READ_ONLY;
			if (vParam != SQL_CONCUR_READ_ONLY)
				changed = TRUE;
		}
232 233 234 235 236 237 238
		break;
		
	case SQL_CURSOR_TYPE:
		//	if declare/fetch, then type can only be forward.
		//	otherwise, it can only be forward or static.
		mylog("SetStmtOption(): SQL_CURSOR_TYPE = %d\n", vParam);

239 240
		if (globals.lie)
			stmt->cursor_type = vParam;
241
		else {
242 243 244 245 246
			if (globals.use_declarefetch) {
				stmt->cursor_type = SQL_CURSOR_FORWARD_ONLY;
				if (vParam != SQL_CURSOR_FORWARD_ONLY) 
					changed = TRUE;
			}
247
			else {
248 249 250 251 252 253
				if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC)
					stmt->cursor_type = vParam;		// valid type
				else {
					stmt->cursor_type = SQL_CURSOR_STATIC;
					changed = TRUE;
				}
254 255 256 257 258 259
			}
		}
		break;

	case SQL_SIMULATE_CURSOR:
		stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
260
		stmt->errormsg = "Simulated positioned update/delete not supported.  Use the cursor library.";
B
Byron Nikolaidis 已提交
261
		SC_log_error(func, "", stmt);
262
		return SQL_ERROR;
263 264

    default:
B
Byron Nikolaidis 已提交
265
		{
B
Byron Nikolaidis 已提交
266
		char option[64];
267
		stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
B
Byron Nikolaidis 已提交
268
		stmt->errormsg = "Driver does not support setting this statement option";
269
		sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
B
Byron Nikolaidis 已提交
270
		SC_log_error(func, option, stmt);
271
        return SQL_ERROR;
B
Byron Nikolaidis 已提交
272
		}
273
    }
274

275 276 277 278 279 280 281
	if (changed) {
		stmt->errormsg = "Requested value changed.";
		stmt->errornumber = STMT_OPTION_VALUE_CHANGED;
		return SQL_SUCCESS_WITH_INFO;
	}
	else
		return SQL_SUCCESS;
282 283
}

284

285 286 287 288 289 290 291
//      -       -       -       -       -       -       -       -       -

RETCODE SQL_API SQLGetStmtOption(
        HSTMT   hstmt,
        UWORD   fOption,
        PTR     pvParam)
{
292
static char *func="SQLGetStmtOption";
293 294
StatementClass *stmt = (StatementClass *) hstmt;

295 296
	mylog("%s: entering...\n", func);

297 298 299 300
    // thought we could fake Access out by just returning SQL_SUCCESS
    // all the time, but it tries to set a huge value for SQL_MAX_LENGTH
    // and expects the driver to reduce it to the real value

B
Byron Nikolaidis 已提交
301 302
	if( ! stmt) {
		SC_log_error(func, "", NULL);
303
		return SQL_INVALID_HANDLE;
B
Byron Nikolaidis 已提交
304
	}
305 306 307 308 309 310 311 312 313 314 315 316 317

	switch(fOption) {
	case SQL_QUERY_TIMEOUT:
		// how long we wait on a query before returning to the
		// application (0 == forever)
		*((SDWORD *)pvParam) = 0;
		break;

	case SQL_MAX_LENGTH:
		// what is the maximum length that will be returned in
		// a single column
		*((SDWORD *)pvParam) = 4096;
		break;
318 319 320 321

	case SQL_MAX_ROWS:
		*((SDWORD *)pvParam) = stmt->maxRows;
		mylog("GetSmtOption: MAX_ROWS, returning %d\n", stmt->maxRows);
322
		break;
323

324 325 326 327 328
	case SQL_ROWSET_SIZE:
		mylog("GetStmtOption(): SQL_ROWSET_SIZE\n");
		*((SDWORD *)pvParam) = stmt->rowset_size;
		break;

329 330 331 332 333
	case SQL_KEYSET_SIZE:
		mylog("GetStmtOption(): SQL_KEYSET_SIZE\n");
		*((SDWORD *)pvParam) = stmt->keyset_size;
		break;

334 335 336
	case SQL_CONCURRENCY:
		mylog("GetStmtOption(): SQL_CONCURRENCY\n");
		*((SDWORD *)pvParam) = stmt->scroll_concurrency;
337 338
		break;

339 340 341 342 343 344 345
	case SQL_CURSOR_TYPE:
		mylog("GetStmtOption(): SQL_CURSOR_TYPE\n");
		*((SDWORD *)pvParam) = stmt->cursor_type;
		break;

	case SQL_SIMULATE_CURSOR:
		stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
346
		stmt->errormsg = "Simulated positioned update/delete not supported. Use the cursor library.";
B
Byron Nikolaidis 已提交
347
		SC_log_error(func, "", stmt);
348 349 350
		return SQL_ERROR;

	default:
B
Byron Nikolaidis 已提交
351
		{
B
Byron Nikolaidis 已提交
352
		char option[64];
353
		stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
B
Byron Nikolaidis 已提交
354
		stmt->errormsg = "Driver does not support getting this statement option";
B
Byron Nikolaidis 已提交
355 356
		sprintf(option, "fOption=%d", fOption);
		SC_log_error(func, option, stmt);
357
		return SQL_ERROR;
B
Byron Nikolaidis 已提交
358
		}
359 360 361
	}

	return SQL_SUCCESS;
362 363 364
}

//      -       -       -       -       -       -       -       -       -