/*! \page backenddev Developing Your Own Backends Even if your database is not supported directly by one of the backends, take a look on \ref odbc "ODBC" backend, and see how well your database driver behaves with it. It may solve the problem for you. Before you begin make sure you are familiar with CppDB library and know how to use it. Take a look to the source code of existing backends, it is good to take a look on \ref postgresql "PostgreSQL" and \ref sqlite3 "Sqlite3" backends implementations. \section backenddev_what_needed What Need to Implement You need to implement following 3 classes: -# cppdb::backend::connection - the object that holds connection to the database - similar to cppdb::session. -# cppdb::backend::statement - the object that holds prepared (or unprepared) statement - similar to cppdb::statement -# cppdb::backend::result - the object that holds the result of query - similar to cppdb::result You may safely assume that: - As long as \ref cppdb::backend::result "result" exists, the \ref cppdb::backend::statement "statement" that created it would exist. - As long as \ref cppdb::backend::statement "statement" exists, the \ref cppdb::backend::connection "connection" that created it would exist. The frontend classes make sure that this happens. \section backend_ref_dynamic Making Loadable Module You need to implement a single entry point in your library with the \ref cppdb::backend::cppdb_backend_connect_function "following prototype". It is very important to make the entry point function \c extern \c "C" so it would be resolved using dlsym or GetProcAddress functions and it should be marked as "__declspec(dllexport)" if it is compiled as Windows DLL. It should be named it as \c cppdb_xyz_get_connection where \c xyz is the name of your backend. It should receive as a parameter a const reference to cppdb::connection_info returning newly created \ref cppdb::backend::connection "connection". For example, in sqlite3 backend this function looks like this: \code extern "C" { CPPDB_DRIVER_API cppdb::backend::connection *cppdb_sqlite3_get_connection(cppdb::connection_info const &cs) { return new cppdb::sqlite3_backend::connection(cs); } } \endcode The shared object or DLL themselves should be named as cppdb_xyz - so under Linux it would be libcppdb_xyz.so and under Windows MSVC it would be "cppdb_xyz.dll". It is also good idea to give it same soname as the libcppdb.so itself as it would allow keeping several backend versions for several versions of libcppdb in future as CppDB always tries to load a module as "libcppdb_xyz.so.V" and only then "libcppdb_xyz.so" where V is the current CppDB library soname. \section backend_ref_static Making Statically Linked only Module Of course if you want to link your module statically only, you do not have to create this single entry point function, you may derive from cppdb::backend::driver class such as its \ref cppdb::backend::driver::open() "open()" function would return a new connection object and \ref cppdb::backend::driver::in_use() "in_use()" function would always return true so the module would not be "unloaded". Such module can be installed using \ref cppdb::driver_manager driver_manager singleton class using its \ref cppdb::driver_manager::install_driver() "install_driver()" member function. For example: \code class my_cool_sql_driver { public: cppdb::backend::connection *open(cppdb::connection_info const &ci) { return new my_cool_sql::connection(ci); } bool in_use() { return true; } }; ... cppdb::driver_manager::instance().install_driver("mycoolsql",new my_cool_sql_driver()); \endcode Of course if you have the \c extern \c "C" function as shown above you can do the same trick using cppdb::backend::static_driver. \code extern "C" { cppdb::backend::connection *my_cool_sql_open(cppdb::connection_info const &ci) { return new my_cool_sql::connection(ci); } } ... cppdb::driver_manager::instance().install_driver("mycoolsql",new cppdb::backend::static_driver(my_cool_sql_open)); \endcode \section backend_tips Tips - Use functions from utils.h and numeric_util.h they are very helpful especially in converting data to and from textual representation. - When converting numbers to strings and backwards make sure you are using std::locale::classic(), otherwise when inserting 12345.678 you may accidentally get "12.345,678" which is probably not what you want. Do it as following: \code std::ostringstream ss; ss.imbue(std::locale::classic()); ss << number; std::string text_value = ss.str(); \endcode And do the same for parsing. - Try to reduce memory coping as much as possible when handing large texts and objects, remember that when std::string is binded it remains valid till actual statement execution so it is likely that you can just keep a reference on it rather then copying the string itself. - Don't bother too much about statements caching or connection pooling. Front-end classes do this for you. */