Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 9e3382d

Browse files
committed
Replace old PostODBC driver with new one...
This one is based on an older PostODBC driver, rewritten and maintained by InsightDist(?)
1 parent d4d26f9 commit 9e3382d

37 files changed

+12152
-0
lines changed

src/interfaces/odbc/bind.c

Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
1+
2+
/* Module: bind.c
3+
*
4+
* Description: This module contains routines related to binding
5+
* columns and parameters.
6+
*
7+
* Classes: BindInfoClass, ParameterInfoClass
8+
*
9+
* API functions: SQLBindParameter, SQLBindCol, SQLDescribeParam, SQLNumParams,
10+
* SQLParamOptions(NI)
11+
*
12+
* Comments: See "notice.txt" for copyright and license information.
13+
*
14+
*/
15+
#include "bind.h"
16+
#include "environ.h"
17+
#include "statement.h"
18+
#include "qresult.h"
19+
#include "pgtypes.h"
20+
#include <stdlib.h>
21+
#include <malloc.h>
22+
#include <sql.h>
23+
#include <sqlext.h>
24+
25+
// Bind parameters on a statement handle
26+
27+
RETCODE SQL_API SQLBindParameter(
28+
HSTMT hstmt,
29+
UWORD ipar,
30+
SWORD fParamType,
31+
SWORD fCType,
32+
SWORD fSqlType,
33+
UDWORD cbColDef,
34+
SWORD ibScale,
35+
PTR rgbValue,
36+
SDWORD cbValueMax,
37+
SDWORD FAR *pcbValue)
38+
{
39+
StatementClass *stmt = (StatementClass *) hstmt;
40+
41+
if( ! stmt)
42+
return SQL_INVALID_HANDLE;
43+
44+
if(stmt->parameters_allocated < ipar) {
45+
ParameterInfoClass *old_parameters;
46+
int i, old_parameters_allocated;
47+
48+
old_parameters = stmt->parameters;
49+
old_parameters_allocated = stmt->parameters_allocated;
50+
51+
stmt->parameters = (ParameterInfoClass *) malloc(sizeof(ParameterInfoClass)*(ipar));
52+
if ( ! stmt->parameters) {
53+
stmt->errornumber = STMT_NO_MEMORY_ERROR;
54+
stmt->errormsg = "Could not allocate memory for statement parameters";
55+
return SQL_ERROR;
56+
}
57+
58+
stmt->parameters_allocated = ipar;
59+
60+
// copy the old parameters over
61+
for(i = 0; i < old_parameters_allocated; i++) {
62+
// a structure copy should work
63+
stmt->parameters[i] = old_parameters[i];
64+
}
65+
66+
// get rid of the old parameters, if there were any
67+
if(old_parameters)
68+
free(old_parameters);
69+
70+
// zero out the newly allocated parameters (in case they skipped some,
71+
// so we don't accidentally try to use them later)
72+
for(; i < stmt->parameters_allocated; i++) {
73+
stmt->parameters[i].buflen = 0;
74+
stmt->parameters[i].buffer = 0;
75+
stmt->parameters[i].used = 0;
76+
stmt->parameters[i].paramType = 0;
77+
stmt->parameters[i].CType = 0;
78+
stmt->parameters[i].SQLType = 0;
79+
stmt->parameters[i].precision = 0;
80+
stmt->parameters[i].scale = 0;
81+
stmt->parameters[i].data_at_exec = FALSE;
82+
stmt->parameters[i].EXEC_used = NULL;
83+
stmt->parameters[i].EXEC_buffer = NULL;
84+
}
85+
}
86+
87+
ipar--; /* use zero based column numbers for the below part */
88+
89+
// store the given info
90+
stmt->parameters[ipar].buflen = cbValueMax;
91+
stmt->parameters[ipar].buffer = rgbValue;
92+
stmt->parameters[ipar].used = pcbValue;
93+
stmt->parameters[ipar].paramType = fParamType;
94+
stmt->parameters[ipar].CType = fCType;
95+
stmt->parameters[ipar].SQLType = fSqlType;
96+
stmt->parameters[ipar].precision = cbColDef;
97+
stmt->parameters[ipar].scale = ibScale;
98+
99+
/* If rebinding a parameter that had data-at-exec stuff in it,
100+
then free that stuff
101+
*/
102+
if (stmt->parameters[ipar].EXEC_used) {
103+
free(stmt->parameters[ipar].EXEC_used);
104+
stmt->parameters[ipar].EXEC_used = NULL;
105+
}
106+
107+
if (stmt->parameters[ipar].EXEC_buffer) {
108+
free(stmt->parameters[ipar].EXEC_buffer);
109+
stmt->parameters[ipar].EXEC_buffer = NULL;
110+
}
111+
112+
if (pcbValue && *pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET)
113+
stmt->parameters[ipar].data_at_exec = TRUE;
114+
else
115+
stmt->parameters[ipar].data_at_exec = FALSE;
116+
117+
118+
return SQL_SUCCESS;
119+
}
120+
121+
// - - - - - - - - -
122+
123+
// Associate a user-supplied buffer with a database column.
124+
RETCODE SQL_API SQLBindCol(
125+
HSTMT hstmt,
126+
UWORD icol,
127+
SWORD fCType,
128+
PTR rgbValue,
129+
SDWORD cbValueMax,
130+
SDWORD FAR *pcbValue)
131+
{
132+
StatementClass *stmt = (StatementClass *) hstmt;
133+
Int2 numcols;
134+
135+
mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol);
136+
137+
if ( ! stmt)
138+
return SQL_INVALID_HANDLE;
139+
140+
if (icol < 1) {
141+
/* currently we do not support bookmarks */
142+
stmt->errormsg = "Bookmarks are not currently supported.";
143+
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
144+
return SQL_ERROR;
145+
}
146+
147+
icol--; /* use zero based col numbers */
148+
149+
SC_clear_error(stmt);
150+
151+
if( ! stmt->result) {
152+
stmt->errormsg = "Can't bind columns with a NULL query result structure.";
153+
stmt->errornumber = STMT_SEQUENCE_ERROR;
154+
return SQL_ERROR;
155+
}
156+
157+
if( stmt->status == STMT_EXECUTING) {
158+
stmt->errormsg = "Can't bind columns while statement is still executing.";
159+
stmt->errornumber = STMT_SEQUENCE_ERROR;
160+
return SQL_ERROR;
161+
}
162+
163+
numcols = QR_NumResultCols(stmt->result);
164+
165+
mylog("SQLBindCol: numcols = %d\n", numcols);
166+
167+
if (icol >= numcols) {
168+
stmt->errornumber = STMT_COLNUM_ERROR;
169+
stmt->errormsg = "Column number too big";
170+
return SQL_ERROR;
171+
}
172+
173+
if ( ! stmt->bindings) {
174+
stmt->errormsg = "Bindings were not allocated properly.";
175+
stmt->errornumber = STMT_SEQUENCE_ERROR;
176+
return SQL_ERROR;
177+
}
178+
179+
if ((cbValueMax == 0) || (rgbValue == NULL)) {
180+
/* we have to unbind the column */
181+
stmt->bindings[icol].buflen = 0;
182+
stmt->bindings[icol].buffer = NULL;
183+
stmt->bindings[icol].used = NULL;
184+
stmt->bindings[icol].returntype = SQL_C_CHAR;
185+
} else {
186+
/* ok, bind that column */
187+
stmt->bindings[icol].buflen = cbValueMax;
188+
stmt->bindings[icol].buffer = rgbValue;
189+
stmt->bindings[icol].used = pcbValue;
190+
stmt->bindings[icol].returntype = fCType;
191+
}
192+
193+
return SQL_SUCCESS;
194+
}
195+
196+
// - - - - - - - - -
197+
198+
// Returns the description of a parameter marker.
199+
200+
RETCODE SQL_API SQLDescribeParam(
201+
HSTMT hstmt,
202+
UWORD ipar,
203+
SWORD FAR *pfSqlType,
204+
UDWORD FAR *pcbColDef,
205+
SWORD FAR *pibScale,
206+
SWORD FAR *pfNullable)
207+
{
208+
StatementClass *stmt = (StatementClass *) hstmt;
209+
210+
if( ! stmt)
211+
return SQL_INVALID_HANDLE;
212+
213+
if( (ipar < 1) || (ipar > stmt->parameters_allocated) ) {
214+
stmt->errormsg = "Invalid parameter number for SQLDescribeParam.";
215+
stmt->errornumber = STMT_BAD_PARAMETER_NUMBER_ERROR;
216+
return SQL_ERROR;
217+
}
218+
219+
ipar--;
220+
221+
if(pfSqlType)
222+
*pfSqlType = stmt->parameters[ipar].SQLType;
223+
224+
if(pcbColDef)
225+
*pcbColDef = stmt->parameters[ipar].precision;
226+
227+
if(pibScale)
228+
*pibScale = stmt->parameters[ipar].scale;
229+
230+
if(pfNullable)
231+
*pfNullable = pgtype_nullable(stmt->parameters[ipar].paramType);
232+
233+
return SQL_SUCCESS;
234+
}
235+
236+
// - - - - - - - - -
237+
238+
// Sets multiple values (arrays) for the set of parameter markers.
239+
240+
RETCODE SQL_API SQLParamOptions(
241+
HSTMT hstmt,
242+
UDWORD crow,
243+
UDWORD FAR *pirow)
244+
{
245+
return SQL_ERROR;
246+
}
247+
248+
// - - - - - - - - -
249+
250+
// Returns the number of parameter markers.
251+
252+
RETCODE SQL_API SQLNumParams(
253+
HSTMT hstmt,
254+
SWORD FAR *pcpar)
255+
{
256+
StatementClass *stmt = (StatementClass *) hstmt;
257+
unsigned int i;
258+
259+
// I guess this is the number of actual parameter markers
260+
// in the statement, not the number of parameters that are bound.
261+
// why does this have to be driver-specific?
262+
263+
if(!stmt)
264+
return SQL_INVALID_HANDLE;
265+
266+
if(!stmt->statement) {
267+
// no statement has been allocated
268+
*pcpar = 0;
269+
stmt->errormsg = "SQLNumParams called with no statement ready.";
270+
stmt->errornumber = STMT_SEQUENCE_ERROR;
271+
return SQL_ERROR;
272+
} else {
273+
*pcpar = 0;
274+
for(i=0; i < strlen(stmt->statement); i++) {
275+
if(stmt->statement[i] == '?')
276+
(*pcpar)++;
277+
}
278+
279+
return SQL_SUCCESS;
280+
}
281+
}
282+
283+
/********************************************************************
284+
* Bindings Implementation
285+
*/
286+
BindInfoClass *
287+
create_empty_bindings(int num_columns)
288+
{
289+
BindInfoClass *new_bindings;
290+
int i;
291+
292+
new_bindings = (BindInfoClass *)malloc(num_columns * sizeof(BindInfoClass));
293+
if(!new_bindings) {
294+
return 0;
295+
}
296+
297+
for(i=0; i < num_columns; i++) {
298+
new_bindings[i].buflen = 0;
299+
new_bindings[i].buffer = NULL;
300+
new_bindings[i].used = NULL;
301+
}
302+
303+
return new_bindings;
304+
}
305+
306+
void
307+
extend_bindings(StatementClass *stmt, int num_columns)
308+
{
309+
BindInfoClass *new_bindings;
310+
int i;
311+
312+
mylog("in extend_bindings\n");
313+
314+
/* if we have too few, allocate room for more, and copy the old */
315+
/* entries into the new structure */
316+
if(stmt->bindings_allocated < num_columns) {
317+
318+
new_bindings = create_empty_bindings(num_columns);
319+
320+
if(stmt->bindings) {
321+
for(i=0; i<stmt->bindings_allocated; i++)
322+
new_bindings[i] = stmt->bindings[i];
323+
324+
free(stmt->bindings);
325+
}
326+
327+
stmt->bindings = new_bindings; // null indicates error
328+
329+
} else {
330+
/* if we have too many, make sure the extra ones are emptied out */
331+
/* so we don't accidentally try to use them for anything */
332+
for(i = num_columns; i < stmt->bindings_allocated; i++) {
333+
stmt->bindings[i].buflen = 0;
334+
stmt->bindings[i].buffer = NULL;
335+
stmt->bindings[i].used = NULL;
336+
}
337+
}
338+
339+
mylog("exit extend_bindings\n");
340+
}

src/interfaces/odbc/bind.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
2+
/* File: bind.h
3+
*
4+
* Description: See "bind.c"
5+
*
6+
* Comments: See "notice.txt" for copyright and license information.
7+
*
8+
*/
9+
10+
#ifndef __BIND_H__
11+
#define __BIND_H__
12+
13+
#include "psqlodbc.h"
14+
15+
/*
16+
* BindInfoClass -- stores information about a bound column
17+
*/
18+
struct BindInfoClass_ {
19+
Int4 buflen; /* size of buffer */
20+
char *buffer; /* pointer to the buffer */
21+
Int4 *used; /* used space in the buffer (for strings not counting the '\0') */
22+
Int2 returntype; /* kind of conversion to be applied when returning (SQL_C_DEFAULT, SQL_C_CHAR...) */
23+
};
24+
25+
/*
26+
* ParameterInfoClass -- stores information about a bound parameter
27+
*/
28+
struct ParameterInfoClass_ {
29+
Int4 buflen;
30+
char *buffer;
31+
Int4 *used;
32+
Int2 paramType;
33+
Int2 CType;
34+
Int2 SQLType;
35+
UInt4 precision;
36+
Int2 scale;
37+
Int4 *EXEC_used;
38+
char *EXEC_buffer;
39+
char data_at_exec;
40+
};
41+
42+
BindInfoClass *create_empty_bindings(int num_columns);
43+
void extend_bindings(StatementClass *stmt, int num_columns);
44+
45+
#endif

0 commit comments

Comments
 (0)