This manual is for yada (yet another database abstraction) version 0.9.1.
Yada is a c library that abstracts SQL databases aiming at allowing transparent use of multiple databases. The goal in mind is to make a common interface to multiple databases, thus stopping the need for application developers to write different modules for each SQL backend they want to support. It's also useful for caching data in different database types.
To accomplish this, it uses a compatibility layer of functions to bind input and output variables, prepare statements, and retrieve data. Functionality and concept are somewhat like perl's DBI, and hopefully somewhat improved.
Currently there are modules for MySQL, Oracle, PostgreSQL, and SQLite3. Most features work in most modules, but all don't work everywhere yet, so please see the file README.modules from the source distribution for details.
The latest version of yada is always available via http from http://oss.devit.com/yada or via ftp from ftp://ftp.devit.com/yada/.
We welcome bug reports and suggestions for any aspect of yada, please email them to yada@devit.com.
For bug reports, please include enough information for us to reproduce the problem. Generally speaking, that means:
When in doubt whether something is needed or not, include it. It's better to include too much than to leave out something important.
Patches are most welcome; if possible, please make them with `diff -c' and include ChangeLog entries.
When sending patches, if possible please do not encode or split them in any way; it's much easier to deal with one plain text message, however large, than many small ones.
To use the default options, simply type
./configure
make
make install
configure with options you want
Some notable ones are:
Currently supported database types:
There are a few options for defining the proper locations for database libraries. --with-db_type, the default, will search common installation locations. If you set --with-db_type=DIR it will look in DIR/include and DIR/lib for headers and libraries respectively. To get more specific, you may use --with-db_type-incdir=DIR --with-db_type-libdir=DIR to set each of the directories where the files can be found.
When configure is done, to install simply:
make
make install
To use yada, you must first initialize the library with
yada_init
() which will return a pointer to a yada
object. The object may then be used to call the other functions as pointers
from the base obj (i.e., yada->connect()
).
If at any time a yada function returns an error, error code may be checked at
yada->error
and error message at yada->errmsg
,
except for yada_init()
, in which case error will be stored in errno.
yada_t* yada_init(char *dbstr, unsigned int flags)
Initializes the yada library and returns a pointer to a yada object of the
database type specified in db_str
, a string made up of database
type:[type specific connection options]. Once this is done, the other
functions may be called from this base obj (i.e., yada->connect()
).
int connect(yada_t *yada, char *user, char *pass)
Attempts to connect to the database defined in the db_str
passed to
yada_init()
, using user and pass if needed by the database type being
connected to.
void disconnect(yada_t *yada)
Disconnect from the database.
void destroy(yada_t* yada)
Closes the database connection, frees all memory used by yada, and therefore invalidates the yada struct.
void free(yada_t *yada, yada_rc_t *yada_rc)
Frees the resource pointed to by yada_rc.
void freeall(yada_t *yada, int type)
Frees all memory used by yada resources of type type, an OR-able set of Resource types. If type is -1, it will free all resources.
These functions prepare a string for execution, allowing mapping of input variables to be passed to execute. Preparing will be done either by native database prepares, or by yada prepare.
Yada prepare is a bit less strict that most databases are, so it's possible to put a placeholder anywhere, including SQL commands or table names.
yada_rc_t* prepare(yada_t *yada, char *str, int strlen)
Prepares a string for execution using the native database prepared statements if available, if not falls back to yprepare().
yada_rc_t* preparef(yada_t *yada, char *format, ...)
Creates a string from format and it's arguments using standard printf tokens and then uses it to prepares a statement. Uses the database's native prepared statements if available, if not falls back to ypreparef().
yada_rc_t* yprepare(yada_t *yada, char *str, int strlen)
Prepares a string for execution using yada prepared statements.
yada_rc_t* ypreparef(yada_t *yada, char *format, ...)
Creates a string from format and it's arguments using standard printf tokens and then uses it to prepares a statement. Uses the yada prepared statements.
yada_rc_t* xprepare(yada_t *yada, int flags, char *str, ...)
Extensible prepare, uses flags options to decide how to prepare the statement. This is for future use, as right now the only flag combinations can be done with the above 4 statements.
int execute(yada_t *yada, void *magic, ...)
yada_rc*
if magic is a prepared yada_rc*
, placeholder variables should follow
Executes the statement, doesn't not return results so it shouldn't be used for select type statements;
yada_rc_t* query(yada_t *yada, void *magic, ...)
yada_rc*
)
if magic is a prepared resource, placeholder variables should follow
Executes the statement and returns a result set resource
char* dumpexec(yada_t *yada, int *retlen, yada_rc_t *prep, ...)
Note only works with yprepared statements
Functions exactly the same as execute, only instead of executing the statement once it's compiled, it returns it as a string.
yada_rc_t* bind(yada_t *yada, char *map, ...)
Makes a mapping of variables to results. It expects pointers to actual storage space to put the variable into, or if the type is preceded by `p', expects a pointer to a pointer which will be set to the retrieved data that will be stored internally.
For example, to bind directly to an int and as a pointer to a string, you would do something like this:
brc = yada->bind(yada, "?d?ps", (int *)&i, (char **)&str);
See Token types, for a list of the supported variables types.
See fetch, for information on how fetch treats these variables when a column is null, see
int fetch(yada_t *yada, yada_rc_t *res, yada_rc_t *bindset)
Retrieves the next row of results into the variables mapped by bindset.
int trx(yada_t* yada, int flags)
Begins a transaction, flags (currently unused) will allow you to start different types of transactions.
int commit(yada_t* yada)
Commit the current transaction causing any changes made to be saved.
int rollback(yada_t* yada, int flags)
Rollback the current transaction undoing any transactional changes.
Read only variables available on the yada struct.
int error
Error code of the last error that occurred.
char *errmsg
Error message for the last error that occurred.
prepare()
query()
bind()
Yada tokens are used to define variable types in both prepare()
and
bind()
. Tokens are specified with a question mark (`?') followed
by the letter for the type. To specify the variable is a pointer, use a
question mark followed by a `p' and then followed by the type letter.
Currently this is only used in bind()
.
Token types are as follows:
char*
string,
and an unsigned long
length. Whenever you need to pass the string
variable, you should pass the length variable next. When used with
bind()
and an execute function is called, the len variable is always an
unsigned long
and never a pointer, even if the binary string is a
pointer (`?pb').
char*
Escaped variables are the same as the variable, except any characters needing escaping are escaped (this differs with the type of database it is).
This is where the documentation and internal API description for making yada modules will go. Until then, grab an already made module and start from there, the code is fairly well documented.
Here is a simple example showing how to do a basic prepared insert, and bind to an output variable. For more examples, see test/yada_test.c in the source distribution.
int intcol; yada_t *yada; yada_rc_t *brc, *res, *stmt; /* init and connect to yada */ if(!(yada = yada_init("mysql:localhost", 0))) { errmsg("Failed to initialize yada: %s\n", strerror(errno)); return(1); } /* prepare insert statement */ if(!(stmt = yada->yprepare(yada, "insert into test (intcol) values (?d)", 0))) { errmsg("Failed to prepare insert: %s\n", yada->errmsg); yada->destroy(yada); return(1); } /* bind column to intcol */ if(!(brc = yada->bind(yada, "?d", &intcol))) { } /* connect to database */ if(!yada->connect(yada, "scott", "tiger")) { errmsg("Failed to connect: %s\n", yada->errmsg); yada->destroy(yada); return(1); } /* insert a row */ if(yada->execute(yada, stmt, 5) == -1) { errmsg("Failed to insert: %s\n", yada->errmsg); yada->destroy(yada); return(1); } /* free prepared insert statement */ yada->free(stmt); /* query all rows */ if(!(res = yada->query(yada, "select intcol from yada_test", 0))) { errmsg("Failed to insert: %s\n", yada->errmsg); yada->destroy(yada); return(1); } /* fetch rows one at a time */ while(yada->fetch(yada, res, brc)) printf("intcol: %d\n", intcol); /* check for error */ if(yada->error) { errmsg("error fetching row: %s", yada->errmsg); yada->destroy(yada); return(1); } /* disconnect and free everything */ yada->destroy(yada); return(0);
bind
: Result retrievalcommit
: trxconnect
: yada_initdestroy
: disconnectdisconnect
: connectdumpexec
: queryerrmsg
: errorerror
: Variablesexecute
: Statement executionfetch
: bindfree
: destroyfreeall
: freeprepare
: Statement preparationpreparef
: preparequery
: executerollback
: committrx
: Transactionsxprepare
: ypreparefYADA_BINDSET
: Resource typesyada_init
: Control functionsYADA_RESULT
: Resource typesYADA_STATEMENT
: Resource typesyprepare
: preparefypreparef
: yprepare