1 #if !defined(_MERLIN_DB_WRAP_H_INCLUDED)
2 #define _MERLIN_DB_WRAP_H_INCLUDED 1
5 #include <stdint.h> /* standard fixed-sized integers */
6 #include <stddef.h> /* size_t on Linux */
9 #if ! defined(DB_WRAP_CONFIG_ENABLE_LIBDBI)
10 # define DB_WRAP_CONFIG_ENABLE_LIBDBI 0
13 enum db_wrap_constants
{
18 /** Signifies that looping over a result set has successfully
19 reached the end of the set.
22 /** Signifies that some argument is illegal. */
23 DB_WRAP_E_BAD_ARG
= 2,
24 /** Signifies that some argument is not of the required type. */
25 DB_WRAP_E_TYPE_ERROR
= 3,
26 /** Signifies an allocation error. */
27 DB_WRAP_E_ALLOC_ERROR
= 4,
29 Signifies an unknown error, probably coming from an underying API
30 (*ahem*libdbi*ahem*) which cannot, for reasons of its own, tell us
34 DB_WRAP_E_UNKNOWN_ERROR
= 5,
37 This code signifies that the caller should check the database
38 error data via db_wrap_api::error_message().
40 DB_WRAP_E_CHECK_DB_ERROR
= 6,
41 /** Signifies an unsupported operation. */
46 authentication errors, connection errors, etc., etc., etc., etc.
47 We don't need to cover every code of every underlying db, but
51 typedef enum db_wrap_constants db_wrap_constants
;
54 Internal implementation data for the db_wrap
55 and db_wrap_result APIs. Holds implementation-specific
60 Arbitrary implementation-dependent data.
65 Wrapper-specific type ID specifier. May have any internal
66 value, as long as all instances of a given wrapper class have
67 the same value. This is used internally to ensure that the
68 various functions are only passed values of the proper concrete
73 /** Convenience typedef. */
74 typedef struct db_wrap_impl db_wrap_impl
;
76 /** Empty-initialized db_wrap_impl object. */
77 #define db_wrap_impl_empty_m {NULL,NULL}
79 /** Empty-initialized db_wrap_impl object. */
80 extern const db_wrap_impl db_wrap_impl_empty
;
82 struct db_wrap_result
;
84 /** Convenience typedef. */
85 typedef struct db_wrap_result db_wrap_result
;
88 /** Convenience typedef. */
89 typedef struct db_wrap db_wrap
;
91 This type holds the "vtbl" (member functions) for db_wrap
92 objects. All instances for a given db wrapper back-end share a
93 single instance of this class.
96 /** Must connect to the underlying database and return 0 on succes. */
97 int (*connect
)(db_wrap
*db
);
99 Must quote the first len bytes of the given string as SQL, add
100 SQL quote characters around it, write the quoted string to
101 *src, and return the number of bytes encoded by this
102 function. If this function returns 0 then the client must not
103 use *str, otherwise he must free it using
104 free_string(). Implementations are free to use a custom
105 allocator, which is why the client MUST use free_string() to
108 Implementations may optionally accept (len==0) as an indicator
109 that they should use strlen() to count the length of src.
111 ACHTUNG: this is itended for use with individual SQL statement
112 parts, not whole SQL statements.
114 size_t (*sql_quote
)(db_wrap
*db
, char const *src
, size_t len
, /*@out@*/ char **dest
);
117 Frees a string allocated by sql_quote(). Results are undefined
118 if the string came from another source. It must return 0 on
119 success. It must, like free(), it must gracefully ignore
122 int (*free_string
)(db_wrap
*db
, char *str
);
125 Must initialize a result object for the given db from the first
126 len bytes of the given sql, and populte the given result object
127 with the results. Must return 0 on success, non-zero on error.
129 On success the caller must eventually clean up the result with
130 result->api->finalize(result).
132 Implementations may optionally stream (len==0) as an indicator
133 that they should use strlen() to count the length of src.
135 int (*query_result
)(db_wrap
*db
, char const *sql
, size_t len
, struct db_wrap_result
**tgt
);
138 Must return the last error information associated with the
141 IFF the dest parameter is non null then it must point *dest at
142 the error string and set *len (if it is not NULL) to the length the message.
144 IFF errorCode is not null then it must assign *errorCode to the
145 driver-dependent error code.
147 Implementation must allow arbitrary combinations of NULL for the dest/len/errorCode
148 parameters, to allow clients to specify exactly which information they're
151 Returns 0 on success (meaning that it fetched the info
152 from the underlying driver). On success *dest and/or *len
153 and/or *errorCode may be set to 0 if the driver has no error to
154 report. Some drivers may return other strings on error (sqlite3
155 infamously uses "not an error" for this case).
157 It is ASSUMED that the underlying driver owns the returned string,
158 and this API allows the lifetime of the returned bytes to expire
159 at the next call into the underlying driver. Thus clients must copy
164 - sqlite3 infamously uses the error string "not an error" when
165 there is no error, instead of using a NULL/empty string. When sqlite3
166 is used together with this API then this API _might_ convert that
167 to a null/empty string, but whether it does this or not is a bit
168 uncertain due to documentation deficiencies in the underlying
169 sqlite3 abstraction code.
171 int (*error_info
)(db_wrap
*db
, char const **dest
, size_t *len
, int *errorCode
);
174 Sets a driver-specific option to the given value. The exact
175 type of val is driver-specific, and the client must be sure to
176 pass a pointer to the proper type.
178 Returns 0 on success.
180 int (*option_set
)(db_wrap
*db
, char const *key
, void const *val
);
182 Gets a driver-specific option and assigns its value to
183 *val. The exact type of val is driver-specific, and the client
184 must be sure to pass a pointer to the proper type.
186 For string options, the caller must pass a (char const **),
187 which will be pointed to the option bytes, which are owned by
188 the wrapper object and have no designated lifetime. To be safe,
189 the caller should copy the bytes if needed beyond the next call
190 to the call into the db.
192 For integer options, the caller must pass a (int*), which will be
193 assigned the option's value by this function.
195 Returns 0 on success.
197 int (*option_get
)(db_wrap
*db
, char const *key
, void *val
);
200 Must return non-zero (true) if the db object is connected, or
201 false if !db or db is not connected. A return value of true is
202 NOT a guaranty that the connection actually works at the
203 moment, but that a connection has, at some point, been
206 TODO: reconsider whether this operation is really needed. It's
207 here because the sql.{c, h} APIs have it, but we may not need
210 char(*is_connected
)(db_wrap
*db
);
213 Must free up any dynamic resources used by db, but must not
214 free db itself. Not all backends will have a distinction betwen
215 cleanup() and finalize(), but some will.
217 Implementations must call impl.dtor(impl.data). They may, IFF
218 they will only be dynamically allocated, defer that call to the
219 finalize() implementation, but such an implementation may not
220 work with stack- or custom-allocated db_wrap objects.
222 int (*cleanup
)(db_wrap
*db
);
224 Must call cleanup() and then free the db object using a
225 mechanism appropriate for its allocation.
227 int (*finalize
)(db_wrap
*db
);
230 * Commit a started transaction. Should do nothing if autocommit
233 int (*commit
)(db_wrap
*db
);
236 * Set autocommit status for the connection
238 int (*set_auto_commit
)(db_wrap
*db
, int set
);
240 typedef struct db_wrap_api db_wrap_api
;
242 Wrapper for a database connection object. These objects must be
243 initialized using a backend-specific initialization/constructor
244 function and freed using their finalize() member.
246 This class defines only the interface. Concrete implementations
247 must be provided which provide the features called for by the
252 The "virtual" member functions of this class. It is illegal for
253 this to be NULL, and all instances for a given database
254 back-end typically share a pointer to the same immutable
257 db_wrap_api
const *api
;
259 Implementation-specific private details.
263 /** Empty-initialized db_wrap object. */
264 extern const db_wrap db_wrap_empty
;
265 /** Empty-initialized db_wrap object. */
266 #define db_wrap_empty_m { \
268 db_wrap_impl_empty_m \
272 This type holds the "vtbl" (member functions) for
273 db_wrap_result objects. All results for a given
274 db wrapper back-end share a single instance of
277 struct db_wrap_result_api
{
278 /** Must "step" the cursor one position and return:
280 - DB_WRAP_E_OK on success.
281 - DB_WRAP_E_DONE if we have reached the end without an error.
282 - Any other value on error
284 FIXME: replace these values with an enum. i HATE these semantics,
285 but i can't think of an alternative without adding another member
286 function like "is_okay()". These semantics were adopted from
287 sqlite3, which uses something very similar.
290 int (*step
)(db_wrap_result
*self
);
293 Must fetch an integer value at the given query index position (0-based!),
294 write its value to *val, and return 0 on success.
296 Reminder: some db API use 0-based indexes for fetching fields
297 by index and some use 1-based. This API uses 0-based because in
298 my experience that is most common (though 1-base is commonly
299 used in bind() APIs and 1-based also makes sense for
302 int (*get_int32_ndx
)(db_wrap_result
*self
, unsigned int ndx
, int32_t *val
);
305 Must fetch an integer value at the given query index position (0-based!),
306 write its value to *val, and return 0 on success.
308 int (*get_int64_ndx
)(db_wrap_result
*self
, unsigned int ndx
, int64_t *val
);
311 Must fetch an double value at the given query index position (0-based!),
312 write its value to *val, and return 0 on success.
315 int (*get_double_ndx
)(db_wrap_result
*self
, unsigned int ndx
, double *val
);
318 Must fetch a string value at the given query index position
319 (0-based!), write its value to *val, write its length to *len,
320 and return 0 on success. len may be NULL, in which case
321 the length is not stored.
323 The ownership of the returned string belongs to the self object
324 (or, more correctly, the underlying driver) and those bytes
325 may be invalidated by ANY non-get-by-index operations on this
326 result set. Thus the user must copy them if needed for further
329 If the fetched string has a length of 0, implementations must
330 assign *val to NULL, *len (if not NULL) to 0, and return 0.
332 int (*get_string_ndx
)(db_wrap_result
*self
, unsigned int ndx
, char const **val
, size_t *len
);
335 Must return the number of result rows for the given result set
336 by assinging that value to *num and returning 0. If it cannot
337 determine this then *num must not be modified and non-0 must be
340 int (*num_rows
)(db_wrap_result
*self
, size_t *num
);
343 Must free all resources associated with self and then
344 deallocate self in a manner appropriate to its allocation
347 int (*finalize
)(db_wrap_result
*self
);
351 Missing functions which we will/might eventually need:
355 - get column name by index
357 - get values by column name? Seems like overkill for this project.
363 typedef struct db_wrap_result_api db_wrap_result_api
;
365 Wraps the basic functionality of "db result" objects, for looping
368 struct db_wrap_result
{
369 db_wrap_result_api
const *api
;
373 - cursor reset(). Rarely used.
375 - fetch column by name?
377 - get list of column names? i think(?) this has to come from the
378 prepared statement, not the result?
383 /** Empty-initialized db_wrap_result object. */
384 #define db_wrap_result_empty_m {\
386 db_wrap_impl_empty_m/*impl*/ \
388 /** Empty-initialized db_wrap_result object. */
389 extern const db_wrap_result db_wrap_result_empty
;
392 A helper type for db-specific functions which need to take some
393 common information in their initialization routine(s).
395 struct db_wrap_conn_params
{
398 char const *username
;
399 char const *password
;
401 char const *conn_str
;
403 typedef struct db_wrap_conn_params db_wrap_conn_params
;
404 /** Empty-initialized db_wrap_conn_params object. */
405 #define db_wrap_conn_params_empty_m { \
406 NULL/*host*/,0/*port*/,NULL/*user*/,NULL/*password*/,NULL/*dbname*/,NULL/*conn_str*/ \
408 /** Empty-initialized db_wrap_conn_params object. */
409 extern const db_wrap_conn_params db_wrap_conn_params_empty
;
412 Runs a query which is expected to return no results, e.g. a CREATE TABLE
415 Returns 0 on success.
417 int db_wrap_query_exec(db_wrap
*db
, char const *sql
, size_t len
);
420 Runs a query which is expected to return exactly 1 int32-compatible result.
421 On success 0 is returned and *tgt is set to its value. If the query returns no
422 results then *tgt is set to 0.
424 int db_wrap_query_int32(db_wrap
*db
, char const *sql
, size_t len
, int32_t *tgt
);
427 Identical to db_wrap_query_int32(), but takes an int64_t instead.
429 int db_wrap_query_int64(db_wrap
*db
, char const *sql
, size_t len
, int64_t *tgt
);
432 Identical to db_wrap_query_int32(), but takes a double instead.
434 int db_wrap_query_double(db_wrap
*db
, char const *sql
, size_t len
, double *tgt
);
437 A convenience wrapper for db_wrap_result::get_string_ndx(), with
438 the same argument and string ownership conventions.
440 Returns 0 on success.
442 int db_wrap_query_string(db_wrap
*db
, char const *sql
, size_t len
, char const **tgt
, size_t *tgtLen
);
445 Functions like db_wrap_result_api::get_string_ndx(), but copies the
446 bytes of the string. The caller must free the string using free().
448 Returns 0 on success. On error neither sql nor len are not modified.
453 int db_wrap_result_string_copy_ndx(db_wrap_result
*res
, unsigned int ndx
, char **sql
, size_t *len
);
457 A generic front-end for loading db_wrap back-ends.
459 driver must be a driver name string, as defined by the concrete
460 back-end implementation. The current strings are "supported" (that
461 is, we have code for them. Whether or not they work on your box is
462 another question entirely)...
464 "dbi:mysql", "dbi:sqlite3"
467 The param object contains basic connection parameters for the db
468 connection. This function does NOT perform the connection, only the
471 Returns 0 on success, non-0 on error. On success ownership of *tgt
472 is transfered to the caller, who must eventually free it with
473 (*tgt)->api->finalize(*tgt). On error ownership of *tgt is not modified
474 and the object need not be freed.
476 On error, any number of things could be wrong, for example:
478 - One or more arguments are NULL.
480 - The driver string is unknown.
482 - The driver string is known but the underlying library is missing
483 or cannot load the driver dynamically. e.g. passing "dbi:postgres"
484 will fail if the local libdbi cannot load the "postgres" driver.
486 int db_wrap_driver_init(char const *driver
, db_wrap_conn_params
const *param
, db_wrap
**tgt
);
489 #endif /* _MERLIN_DB_WRAP_H_INCLUDED */