4
* $Id: RS-DBI.h,v 1.6 2003/11/04 15:57:14 dj Exp $
6
* Copyright (C) 1999-2002 The Omega Project for Statistical Computing.
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License as published by the Free Software Foundation; either
11
* version 2 of the License, or (at your option) any later version.
13
* This library is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
/* The following include file defines a number of C macros that hide
24
* differences between R and S (e.g., the macro for type "Sint" expand
25
* to "long" in the case of S and to int in the case of R, etc.)
34
/* Microsoft Visual C++ uses int _getpid() */
37
#define getpid _getpid
45
/* We now define 4 important data structures:
46
* RS_DBI_manager, RS_DBI_connection, RS_DBI_resultSet, and
47
* RS_DBI_fields, corresponding to dbManager, dbConnection,
48
* dbResultSet, and list of field descriptions.
50
/* In R/S a dbObject is a foreign reference consisting of a vector
51
* of 1, 2 or 3 integers. In the C implementation we use these
52
* R/S vectors as handles (we could have use pointers).
54
typedef enum enum_dbi_exception {
61
/* dbObject handles are simple S/R integer vectors of 1, 2, or 3 integers
62
* the *_ID macros extract the appropriate scalar.
65
#define Mgr_Handle s_object
66
#define Con_Handle s_object
67
#define Res_Handle s_object
68
#define Db_Handle s_object /* refers to any one of the above */
69
/* The integer value for the following enum's needs to equal
70
* GET_LENGTH(handle) for the various handles.
72
typedef enum enum_handle_type {
73
MGR_HANDLE_TYPE = 1, /* dbManager handle */
74
CON_HANDLE_TYPE = 2, /* dbConnection handle */
75
RES_HANDLE_TYPE = 3 /* dbResult handle */
78
#define MGR_ID(handle) INT_EL((handle),0) /* the actual scalar mgr id */
79
#define CON_ID(handle) INT_EL((handle),1)
80
#define RES_ID(handle) INT_EL((handle),2)
82
/* First, the following fully describes the field output by a select
83
* (or select-like) statement, and the mappings from the internal
84
* database types to S classes. This structure contains the info we need
85
* to build the R/S list (or data.frame) that will receive the SQL
86
* output. It still needs some work to handle arbitrty BLOB's (namely
87
* methods to map BLOBs into user-defined S objects).
88
* Each element is an array of num_fields, this flds->Sclass[3] stores
89
* the S class for the 4th output fields.
91
typedef struct st_sdbi_fields {
93
char **name; /* DBMS field names */
94
Sint *type; /* DBMS internal types */
95
Sint *length; /* DBMS lengths in bytes */
96
Sint *precision; /* DBMS num of digits for numeric types */
97
Sint *scale; /* DBMS num of decimals for numeric types */
98
Sint *nullOk; /* DBMS indicator for DBMS' NULL type */
99
Sint *isVarLength; /* DBMS variable-length char type */
100
Stype *Sclass; /* R/S class (type) -- may be overriden */
101
/* TODO: Need a table of fun pointers to converters */
104
typedef struct st_sdbi_exception {
105
DBI_EXCEPTION exceptionType; /* one of RS_DBI_WARN, RS_RBI_ERROR, etc */
106
int errorNum; /* SQL error number (possibly driver-dependent*/
107
char *errorMsg; /* SQL error message */
110
/* The RS-DBI resultSet consists of a pointer to the actual DBMS
111
* resultSet (e.g., MySQL, Oracle) possibly NULL, plus the fields
112
* defined by the RS-DBI implementation.
114
typedef struct st_sdbi_resultset {
115
void *drvResultSet; /* the actual (driver's) cursor/result set */
116
void *drvData; /* a pointer to driver-specific data */
117
Sint managerId; /* the 3 *Id's are used for */
118
Sint connectionId; /* validating stuff coming from S */
120
Sint isSelect; /* boolean for testing SELECTs */
121
char *statement; /* SQL statement */
122
Sint rowsAffected; /* used by non-SELECT statements */
123
Sint rowCount; /* rows fetched so far (SELECT-types)*/
124
Sint completed; /* have we fetched all rows? */
125
RS_DBI_fields *fields;
128
/* A dbConnection consists of a pointer to the actual implementation
129
* (MySQL, Oracle, etc.) connection plus a resultSet and other
130
* goodies used by the RS-DBI implementation.
131
* The connection parameters (user, password, database name, etc.) are
132
* defined by the actual driver -- we just set aside a void pointer.
135
typedef struct st_sdbi_connection {
136
void *conParams; /* pointer to connection params (host, user, etc)*/
137
void *drvConnection; /* pointer to the actual DBMS connection struct*/
138
void *drvData; /* to be used at will by individual drivers */
139
RS_DBI_resultSet **resultSets; /* vector to result set ptrs */
141
Sint length; /* max num of concurrent resultSets */
142
Sint num_res; /* num of open resultSets */
143
Sint counter; /* total number of queries */
146
RS_DBI_exception *exception;
150
typedef struct st_sdbi_manager {
151
char *drvName; /* what driver are we implementing?*/
152
void *drvData; /* to be used by the drv implementation*/
153
RS_DBI_connection **connections; /* list of dbConnections */
154
Sint *connectionIds; /* array of connectionIds */
155
Sint length; /* max num of concurrent connections */
156
Sint num_con; /* num of opened connections */
157
Sint counter; /* num of connections handled so far*/
158
Sint fetch_default_rec; /* default num of records per fetch */
159
Sint managerId; /* typically, process id */
160
RS_DBI_exception *exception;
163
/* All RS_DBI functions and their signatures */
165
/* Note: the following alloc functions allocate the space for the
166
* corresponding manager, connection, resultSet; they all
167
* return handles. All DBI functions (free/get/etc) use the handle
168
* to work with the various dbObjects.
170
Mgr_Handle *RS_DBI_allocManager(const char *drvName, Sint max_con,
171
Sint fetch_default_rec,
173
void RS_DBI_freeManager(Mgr_Handle *mgrHandle);
174
RS_DBI_manager *RS_DBI_getManager(Db_Handle *handle);
175
Mgr_Handle *RS_DBI_asMgrHandle(Sint pid);
176
s_object *RS_DBI_managerInfo(Mgr_Handle *mgrHandle);
179
Con_Handle *RS_DBI_allocConnection(Mgr_Handle *mgrHandle,
181
void RS_DBI_freeConnection(Con_Handle *conHandle);
182
RS_DBI_connection *RS_DBI_getConnection(Db_Handle *handle);
183
Con_Handle *RS_DBI_asConHandle(Sint mgrId, Sint conId);
184
s_object *RS_DBI_connectionInfo(Con_Handle *con_Handle);
187
Res_Handle *RS_DBI_allocResultSet(Con_Handle *conHandle);
188
void RS_DBI_freeResultSet(Res_Handle *rsHandle);
189
RS_DBI_resultSet *RS_DBI_getResultSet(Res_Handle *rsHandle);
190
Res_Handle *RS_DBI_asResHandle(Sint pid, Sint conId, Sint resId);
191
s_object *RS_DBI_resultSetInfo(Res_Handle *rsHandle);
194
s_object *RS_DBI_validHandle(Db_Handle *handle); /* callable from S/R */
195
int is_validHandle(Db_Handle *handle, HANDLE_TYPE handleType);
197
/* a simple object database (mapping table) -- it uses simple linear
198
* search (we don't expect to have more than a handful of simultaneous
199
* connections and/or resultSets. If this is not the case, we could
200
* use a hash table, but I doubt it's worth it (famous last words!).
201
* These are used for storing/retrieving object ids, such as
202
* connection ids from the manager object, and resultSet ids from a
203
* connection object; of course, this is transparent to the various
204
* drivers -- they should deal with handles exclusively.
206
Sint RS_DBI_newEntry(Sint *table, Sint length);
207
Sint RS_DBI_lookup(Sint *table, Sint length, Sint obj_id);
208
Sint RS_DBI_listEntries(Sint *table, Sint length, Sint *entries);
209
void RS_DBI_freeEntry(Sint *table, Sint indx);
211
/* description of the fields in a result set */
212
RS_DBI_fields *RS_DBI_allocFields(int num_fields);
213
s_object *RS_DBI_getFieldDescriptions(RS_DBI_fields *flds);
214
void RS_DBI_freeFields(RS_DBI_fields *flds);
216
/* we (re)allocate the actual output list in here (with the help of
217
* RS_DBI_fields). This should be some kind of R/S "relation"
218
* table, not a dataframe nor a list.
220
void RS_DBI_allocOutput(s_object *output,
224
void RS_DBI_makeDataFrame(s_object *data);
226
/* TODO: We need to elevate RS_DBI_errorMessage to either
227
* dbManager and/or dbConnection methods. I still need to
228
* go back and re-code the error-handling throughout, darn!
230
void RS_DBI_errorMessage(char *msg, DBI_EXCEPTION exceptionType);
231
void RS_DBI_setException(Db_Handle *handle,
232
DBI_EXCEPTION exceptionType,
234
const char *errorMsg);
235
/* utility funs (copy strings, convert from R/S types to string, etc.*/
236
char *RS_DBI_copyString(const char *str);
237
char *RS_DBI_nCopyString(const char *str, size_t len, int del_blanks);
239
/* We now define a generic data type name-Id mapping struct
240
* and initialize the RS_dataTypeTable[]. Each driver could
241
* define similar table for generating friendly type names
248
/* return the primitive type name for a primitive type id */
249
char *RS_DBI_getTypeName(Sint typeCode, const struct data_types table[]);
250
/* same, but callable from S/R and vectorized */
251
s_object *RS_DBI_SclassNames(s_object *types);
253
s_object *RS_DBI_createNamedList(char **names,
257
s_object *RS_DBI_copyFields(RS_DBI_fields *flds);
259
void RS_na_set(void *ptr, Stype type);
260
int RS_is_na(void *ptr, Stype type);
261
extern const struct data_types RS_dataTypeTable[];
266
#endif /* _RS_DBI_H */