[Previous] [Next] [Contents]

From the client application point of view EasySQL is generally represented by a C++ class ``easysql'' and it's interface methods. Appropriated database description is read and driver is loaded into address space of application when an instance of that class is created; and likewise, it is unloaded when an instance is destroyed.

This may look like this:

#include <easysql/easysql.h>

...

int
main()
{ easysql sql("mydb");
...
}

In that case driver will be unloaded automatically when main()'s scope will be leaved.

Easysql's access methods may be separated into three layers: recommended and mostly used layer, sometimes usable layer and non recommended, but available for complex programming projects layer. The rest of this chapter describes all access methods grouped by layers. If you want to just refresh a description of exact function in mind - use alphabetical index of all access methods.

easysql::easysql(char const *dbname)

Creates an instance of an easysql class, loads ``dbname'' database description (see run-time configuration) and loads/activates appropriate driver. No real connection to engine is established.

When there is no database description with given name found constructor tries to load driver with that name and without any options set. It's usable for general utilities like SQL monitors and alike..

Any options like host name, real SQL internal database name, user name, password connection type and so on usually specified in database description; and so there is any demand to hard code that things (though it is possible through reset/ option methods).

easysql::~easysql()

Used when it's required to destroy an instance of easysql class -- both automatically, or by a call to `delete' operator.

If the connection to engine is established, it is closed. Then all internal data structures are destroyed and then easysql instance itself is destroyed also. All data from not yet rfree'd queries are destroyed (and any attempt to use such data will result in segment violation or at least illegal data will be returned). EasySQL checks and reports to log-file any non rfree'd data at destroying time to help debug such situations.

easysql::operator bool()

Returns true in case of driver is successfully loaded and installed, all internal easysql data structures are Ok and an EasySQL engine are ready to be used. It doesn't check connection to engine (and it's usually not required to check connection state - it's EasySQL business) -- see easysql::connection_ok() instead.

char const *easysql::error_text()

A way to retrieve a text of last error happened. When there was no error NULL is returned. Error text is one line of free style zero terminated text without '\n' or '\t' embedded (it should be so at least, but badly written driver may broke this convention).

An error text is not cleaned by a call to error_text, so the same message may be retrieved more, than once.

An example:

...
easysql sql("mydb");
if(!sql)
 { printf("SQL error: %s\n",sql.error_text());
   exit(1);
 }
...

esqlResult easysql::query(char const *q, ...)

Sends an SQL query ``q'' to engine and then fetches a results, if a query was supposed to return any. esqlResult is a type castable to ``void *'', so a NULL returned in case of an error or no results. To distinguish between an error and an absence of results a call to error_text may be used.

To fetch real rows of results an easysql::row() method have to be used.

Each data reference got from query (except NULL) have to be freed by a call to easysql::rfree.

Hint: If you have an already prepared string, which may potentially have %'s included use the following construct:

char const *query=...;  // prepared query with possible %'s
sql.query("%s",query);

esqlRow easysql::row(esqlResult res)

Supplied by a ``res'' argument (previously fetched by means of easysql::query) this method returns a sequential rows of data. Each row returned is castable to ``char const * const *'' type, and may be treated like that (despite the fact, that for now it is an object of that type, only guaranteed operation in future releases is cast from ``esqlResult'' to ``char const * const *'', you are warned).

There is no way in current release of EasySQL to rewind data or by any other way change a sequence in which data are returned. May be such methods will be added on demand.

Any internal SQL types of data are converted to zero terminated strings before returning. So, an integer 123 will be represented as a string "123", an SQL NULL value is represented as NULL pointer returned. There is no way to fetch a BLOB of unknown size by means of EasySQL for now, thought it's not a problem to add such a feature -- just ask me. ``rfree''.

An index of fields returned by ``row'' method is only valid upon next call to ``row'' - so, if you need returned data for longer time then copy it.

If a NULL is returned from ``row'' it means no more rows in query results or invalid results has been supplied. You may distinguish between that situations by a call to error_text().

bool easysql::rfree(esqlResult res)

Frees query results. Any strings, that were returned using ``row'' method, will be invalid after call to this method. Be careful to copy required data before.

It is usually a good practice to rfree any data that you need no more -- both for `nice' programming and for freeing memory occupied.

char const *easysql::string(char const *str, char *buf)

When using strings in SQL queries it is required to escape some characters (usually at least quotes). This is a method, by which it's very suitable to do. Just pass a string to be inserted or be compared with to ``string'' method and an escaped version of it will be the result (you may skip ``buf'' parameter in that simple case).

An example:

char const *name=...;
unsigned id=...;
sql.query("update test set name='%s' where id=%lu",sql.string(name),id);
..

A result returned is stored in internal dynamically allocated buffer of an arbitrary size, so it's safe to give a string of any length. But every string given will be placed into only one buffer, so th next call will override previously returned value. This is an incorrect piece of code for this reason:

char const *name=...;
char const *value=...;
unsigned id=...;
sql.query("update test set name='%s',value='%s' where id=%lu",
          sql.string(name),
          sql.string(value),
          id);
..

To solve this conflict a second argument may be used - if it is given, that it's supposed to be buffer of adequate size and converted string will be placed there instead of internal buffer. If you do not want to think of required buffer size just make it twice as big, as ``str'' length plus one character.

This is correct implementation of above example (assuming that there may be no NULLs in value):

char const *name=...;
char const *value=...;
char buf[strlen(value)+1];
unsigned id=...;
sql.query("update test set name='%s',value='%s' where id=%lu",
          sql.string(name),
          sql.string(value,buf),
          id);
..

For those who interested -- every driver may provide it's own set of symbols to be escaped and how they should be escaped. You need not worry about it.

bool easysql::option(char const *name, char const *value)

A driver of exact database may accept options. By their means database name, SQL server host, connection type and so on are usually specified. What options to accept is only a driver's business, but some common examples you may see in `` Databases configuration'' chapter.

``name'' is an option name and ``value'' is a value. If name is NULL it is ignored.

An example:

easysql mysql("mysql");
mysql.option("database","test");
mysql.option("username","foo");
mysql.option("password","bar");
...

bool easysql::option(char const *value)

The same as above, but accepts one string in form of "name=value name1=value1"; no escapes allowed and therefor no spaces allowed in names and values.

An example (with the same effect as above):

easysql mysql("mysql");
mysql.option("database=test username=foo password=bar");
...

void easysql::reset()

``Easysql'' class stores some options, internal flags and variables which may be flushed to default values by this method. It's suitable (and required) if you have been already using ``easysql'' instance with some other parameters and now want to use it for another connection.

Only thing that is not flushed by this method is driver itself, because there is no way to change driver after creating an instance of ``easysql''.

bool easysql::driver_ok()

This method may be used to check driver's consistency. Though it's recommended to use casting of easysql to boolean type instead.

char const *easysql::driver_status()

One line of free style textual representation of driver's status. A text and length of string is up to driver implementor's decision -- usually some 40..60 characters of "Engine operates Ok", "1234 queries processes" etc; NULL is never returned.

char const *easysql::driver_version()

One text line, consisting of two to four space separated fields -- driver's name, driver's version, engine API version on which driver is based and a version of real SQL engine used. Only driver's name and version are always returned.

An example:

easysql sql("mydb");
printf("Driver info:\n"
       " Version: %s\n",sql.driver_version()";
printf(" Status:  %s\n",sql.driver_status()";
...
Driver info:
 Version: mysql 1.0 3.0.30
 Status:  Running threads: 3 Questions: 1735 Reloads: 1 Open tables: 12

unsigned easysql::set_retry_delay(unsigned d)

EasySQL is designed to automatically retry failed queries/connect attempts by default every 60 seconds. It's very suitable for small programs, because it gives a possibility to not check return codes at all and assume, that they are always Ok. In case of serious database failure worst thing that can happen is an application sitting in memory and waiting for database waking up. You may easily notice the fact by records in log file, fix a problem and application will finish as there was no failure at all.

Disadvantage of such technique may be seen in dynamic environment (web server for example), where such sleeping processes will fork and fork until no space will be available in system tables. In that case it's better to report a failure when it happens and then stop an application.

An ``set_retry_delay'' method is a way, by which you can switch between the two above behaviors. When ``d'' is greater then zero, then a retrying technique is used and a value of ``d'' is used as a delay in seconds between delays. When it's equal to zero no retries are performed and all failures are reported as they happened.

An old value of delay is returned from this method.

bool easysql::connect()

By this method driver may be forced to establish connection. If the connection is already established nothing has happened and positive result is returned.

It's not required to use this method because when required the connection will be established automatically.

bool easysql::drop()

By this method driver may be forced to drop connection. If the connection is not established nothing has happened and positive result is returned.

It's may be of some use to drop connection when you will be in no need for a long period of time. Then, when required it will be automatically reestablished.

bool easysql::connection_ok()

Returns true if connection is established and alive and false overwise. Not all drivers allows to check is connection alive or not.

esqlResult easysql::_query(char const *q, va_list ap)

This is nearly the same method as described above, but is more suitable to use from a user designed front end libraries. For example if you have a function which accepts unknown number of arguments you may define they as an ``va_list ap'' and pass to this method.


[Previous] [Next] [Contents]