summaryrefslogtreecommitdiff
path: root/src/interfaces/odbc/statement.h
blob: ae2df856b2572af682062af45efece8d0aa8d600 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

/* File:            statement.h
 *
 * Description:     See "statement.c"
 *
 * Comments:        See "notice.txt" for copyright and license information.
 *
 */

#ifndef __STATEMENT_H__
#define __STATEMENT_H__

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "psqlodbc.h"
#include "bind.h"

#ifndef WIN32
#include "iodbc.h"
#include "isql.h"
#else
#include <windows.h>
#include <sql.h>
#endif


#ifndef FALSE
#define FALSE	(BOOL)0
#endif
#ifndef TRUE
#define TRUE	(BOOL)1
#endif

typedef enum {
    STMT_ALLOCATED,     /* The statement handle is allocated, but not used so far */
    STMT_READY,         /* the statement is waiting to be executed */
    STMT_PREMATURE,     /* ODBC states that it is legal to call e.g. SQLDescribeCol before
                           a call to SQLExecute, but after SQLPrepare. To get all the necessary
                           information in such a case, we simply execute the query _before_ the
                           actual call to SQLExecute, so that statement is considered to be "premature".
                        */   
    STMT_FINISHED,      /* statement execution has finished */
    STMT_EXECUTING      /* statement execution is still going on */
} STMT_Status;

#define STMT_TRUNCATED -2
#define STMT_INFO_ONLY -1 /* not an error message, just a notification to be returned by SQLError */
#define STMT_OK 0 /* will be interpreted as "no error pending" */
#define STMT_EXEC_ERROR 1
#define STMT_STATUS_ERROR 2
#define STMT_SEQUENCE_ERROR 3
#define STMT_NO_MEMORY_ERROR 4
#define STMT_COLNUM_ERROR 5
#define STMT_NO_STMTSTRING 6
#define STMT_ERROR_TAKEN_FROM_BACKEND 7
#define STMT_INTERNAL_ERROR 8
#define STMT_STILL_EXECUTING 9
#define STMT_NOT_IMPLEMENTED_ERROR 10
#define STMT_BAD_PARAMETER_NUMBER_ERROR 11
#define STMT_OPTION_OUT_OF_RANGE_ERROR 12
#define STMT_INVALID_COLUMN_NUMBER_ERROR 13
#define STMT_RESTRICTED_DATA_TYPE_ERROR 14
#define STMT_INVALID_CURSOR_STATE_ERROR 15
#define STMT_OPTION_VALUE_CHANGED 16
#define STMT_CREATE_TABLE_ERROR 17
#define STMT_NO_CURSOR_NAME 18
#define STMT_INVALID_CURSOR_NAME 19
#define STMT_INVALID_ARGUMENT_NO 20
#define STMT_ROW_OUT_OF_RANGE 21
#define STMT_OPERATION_CANCELLED 22
#define STMT_INVALID_CURSOR_POSITION 23
#define STMT_VALUE_OUT_OF_RANGE 24
#define STMT_OPERATION_INVALID 25
#define STMT_PROGRAM_TYPE_OUT_OF_RANGE 26
#define STMT_BAD_ERROR 27

/* statement types */
enum {
	STMT_TYPE_UNKNOWN = -2,
	STMT_TYPE_OTHER = -1,
	STMT_TYPE_SELECT = 0,
	STMT_TYPE_INSERT,
	STMT_TYPE_UPDATE,
	STMT_TYPE_DELETE,
	STMT_TYPE_CREATE,
	STMT_TYPE_ALTER,
	STMT_TYPE_DROP,
	STMT_TYPE_GRANT,
	STMT_TYPE_REVOKE,
};

#define STMT_UPDATE(stmt)	(stmt->statement_type > STMT_TYPE_SELECT)


/*	Parsing status */
enum {
	STMT_PARSE_NONE = 0,
	STMT_PARSE_COMPLETE,
	STMT_PARSE_INCOMPLETE,
	STMT_PARSE_FATAL,
};

/*	Result style */
enum {
	STMT_FETCH_NONE = 0,
	STMT_FETCH_NORMAL,
	STMT_FETCH_EXTENDED,
};

typedef struct {
	COL_INFO		*col_info;		/* cached SQLColumns info for this table */
	char 			name[MAX_TABLE_LEN+1];
	char			alias[MAX_TABLE_LEN+1];
} TABLE_INFO;

typedef struct {
	TABLE_INFO  	*ti;			/* resolve to explicit table names */
	int				precision;
	int				display_size;
	int				length;
	int				type;
	char			nullable;
	char			func;
	char			expr;
	char			quote;
	char			dquote;
	char			numeric;
	char			dot[MAX_TABLE_LEN+1];
	char			name[MAX_COLUMN_LEN+1];
	char			alias[MAX_COLUMN_LEN+1];
} FIELD_INFO;


/********	Statement Handle	***********/
struct StatementClass_ {
    ConnectionClass *hdbc;		/* pointer to ConnectionClass this statement belongs to */
    QResultClass *result;		/* result of the current statement */
	HSTMT FAR *phstmt;
	StatementOptions options;

    STMT_Status status;
    char *errormsg;
    int errornumber;

    /* information on bindings */
    BindInfoClass *bindings;	/* array to store the binding information */
	BindInfoClass bookmark;
    int bindings_allocated;

    /* information on statement parameters */
    int parameters_allocated;
    ParameterInfoClass *parameters;

	Int4 currTuple;				/* current absolute row number (GetData, SetPos, SQLFetch) */
	int  save_rowset_size;		/* saved rowset size in case of change/FETCH_NEXT */
	int  rowset_start;			/* start of rowset (an absolute row number) */
	int  bind_row;				/* current offset for Multiple row/column binding */
	int  last_fetch_count;      /* number of rows retrieved in last fetch/extended fetch */
	int  current_col;			/* current column for GetData -- used to handle multiple calls */
	int  lobj_fd;				/* fd of the current large object */

    char *statement;			/* if non--null pointer to the SQL statement that has been executed */

	TABLE_INFO	**ti;
	FIELD_INFO	**fi;
	int			nfld;
	int			ntab;

	int parse_status;

    int statement_type;			/* According to the defines above */
	int data_at_exec;			/* Number of params needing SQLPutData */
	int current_exec_param;		/* The current parameter for SQLPutData */

	char put_data;				/* Has SQLPutData been called yet? */

	char errormsg_created;		/* has an informative error msg been created?  */
	char manual_result;			/* Is the statement result manually built? */
	char prepare;				/* is this statement a prepared statement or direct */

	char internal;				/* Is this statement being called internally? */

	char cursor_name[MAX_CURSOR_LEN+1];

	char stmt_with_params[STD_STATEMENT_LEN];		/* statement after parameter substitution */

};

#define SC_get_conn(a)    (a->hdbc)
#define SC_get_Result(a)  (a->result);

/*	options for SC_free_params() */
#define STMT_FREE_PARAMS_ALL				0
#define STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY	1

/*	Statement prototypes */
StatementClass *SC_Constructor(void);
void InitializeStatementOptions(StatementOptions *opt);
char SC_Destructor(StatementClass *self);
int statement_type(char *statement);
char parse_statement(StatementClass *stmt);
void SC_pre_execute(StatementClass *self);
char SC_unbind_cols(StatementClass *self);
char SC_recycle_statement(StatementClass *self);

void SC_clear_error(StatementClass *self);
char SC_get_error(StatementClass *self, int *number, char **message);
char *SC_create_errormsg(StatementClass *self);
RETCODE SC_execute(StatementClass *self);
RETCODE SC_fetch(StatementClass *self);
void SC_free_params(StatementClass *self, char option);
void SC_log_error(char *func, char *desc, StatementClass *self);
unsigned long SC_get_bookmark(StatementClass *self);


#endif