Abstract:
C ++ is really not a worry-free task to operate on databases. On the one hand, C ++ uses C APIs for most database operations, such as those provided by MySQL and SQLite. Although its c API documentation is clear and detailed enough, there are still some problems, such as memory application, release, and result set traversal. Most people will slightly encapsulate the details of Capi. After all, common operations are nothing more than adding, deleting, modifying, and querying. On the other hand, there is no easy-to-use C ++ database operating framework, which makes it difficult to adapt the C ++ object-oriented Memory Model to the SQL dB relational model. I have seen exactly the ing framework between C ++ objects and SQL rows in several projects. Since then, I have been trying to complete a lightweight and practical db operation class library. Today, these databases have taken shape, namely ffdb.
Ffdb is just a very lightweight C ++ class library, but its functions are absolutely impressive. In a sense, it is somewhat pioneering. Ffdb is scalable. ffdb currently supports MySQL and SQLite, and it is easy to add other SQL support. Ffdb has the following functions:
- Ffdb encapsulates dB connections and unifies interfaces. Currently, ffdb has made considerable trade-offs. In most of my daily work, it fully satisfies the requirements.
- Ffdb encapsulates the differences between different SQL databases. When you need to change the database, you only need to modify the connection parameters instead of modifying all relevant API calls.Code.
- Ffdb provides a tool class ffcrud, which encapsulates crud operations on SQL dB. ffcrud ensures that operations on memory objects in C ++ are comfortable and easy to synchronize to DB.
Ffdb encapsulates dB connections
Connecting to SQL dB, ffdb provides a very simple syntax to connect to the SQLite code:
If(Ffdb. Connect ("SQLite: // tmp/test. DB") {Printf ("Connect error: % s, % d \ n", Ffdb. error_msg (), ffdb. is_connected ());Return 1;}
To connect to MySQL, you only need:
If(Ffdb. Connect ("MySQL: // 127.0.0.1: 3306/user/passwd/DB") {Printf ("Connect error: % s, % d \ n", Ffdb. error_msg (), ffdb. is_connected ());Return 1;}
Ffdb executes SQL
The SQL Execution interface in ffdb is:
IntExe_ SQL (Const String& SQL _, db_each_row_callback_ I * CB _ =Null );IntExe_ SQL (Const String& Amp; SQL _, vector <String>> &Ret_data _);IntExe_ SQL (Const String& Amp; SQL _, vector <String>>& Ret_data _, vector <String> & Col_names _);
The first version interface can customize how to obtain result set data by passing callback functions. Generally, to traverse the result set, you only need the second version of the interface to convert all the datasets into a string array. Users are left concerned about the details of memory allocation and release.
Ffdb shutdown and number of affected rows
VoidClose ();IntAffect_rows ();
Ffcrud enables addition, deletion, modification, and query of memory objects in SQL DB
Ffcrud is a template class. The important interfaces are as follows:
StringInsert_ SQL ()StringSelect_ SQL ()StringUpdate_ SQL ()StringDel_ SQL ()IntInsert (ffdb_t &Ffdb)Int Select(Ffdb_t &Ffdb)IntUpdate (ffdb_t &Ffdb)IntDel (ffdb_t & ffdb)
Xx_ SQL-related operations return the SQL string for which the related operations are to be executed. ffcrud is not limited to the use of ffdb. In this way, you can use this SQL statement for asynchronous execution in some cases. At the same time, ffcrud and ffdb can be perfectly combined. As long as the ffdb instance object is provided, the memory object data can be directly synchronized to the SQL dB.
How does ffcrud map memory objects to SQL DB?
Ffcrud_register_t maps memory objects to tables in SQL dB. During daily development, I found that the most annoying change is the correspondence between fields in the object and fields in the database. Use ffcrud_register_t to configure the ing as much as possible. If you want, you can read the ing from the configuration file.
Sample Code:
# Include " DB/ffdb. h " # Include " DB/ffcrud. h " Using Namespace Ff; # include <Stdio. h> Void Dump (vector < String >> & Ret_data ){ For (Size_t I = 0 ; I <ret_data.size (); ++ I) {printf ( " Row [% u] Begin ====== " , I ); For (Size_t J = 0 ; J <ret_data [I]. Size (); ++J) {printf ( " % S " , Ret_data [I] [J]. c_str ();} printf ( " ======= Row [% u] End \ n " , I);} ret_data.clear ();} Struct Foo_t: Public Ffcrud_t <foo_t> {Foo_t (): ( 167 ), B ( " Ddd " ), M_c ( 11.22 ){} Int A; String B; Double & C (){ Return M_c ;} Double M_c ;}; Int Main (Int Argc, Char * Argv []) {ffdb_t ffdb; foo_t Foo; vector <Vector < String > Ret_data; If (Ffdb. Connect ( " SQLite: //./test. DB " ) {Printf ( " Connect error: % s, % d \ n " , Ffdb. error_msg (), ffdb. is_connected ()); Return 1 ;} If (Ffdb.exe _ SQL ( " Create Table if not exists dumy (A int, C float, B varchar (200), primary key ()) " ) {Printf ( " EXE error: % s \ n " , Ffdb. error_msg ());} If (Ffdb.exe _ SQL (" Select * From dumy " , Ret_data) {printf ( " EXE error: % s \ n " , Ffdb. error_msg ();} dump (ret_data); ffcrud_register_t <Foo_t>: bind_table ( " Dumy " , " A " ). Def ( & Foo_t:, " A " ). Def ( & Foo_t: C, " C " ). Def ( & Foo_t: B, " B " ); Printf ( " Foo insert: <% S> \ n " , Foo. insert_ SQL (). c_str (); printf ( " Foo select: <% S> \ n " , Foo. select_ SQL (). c_str (); printf ( " Foo update: <% S> \ n " , Foo. update_ SQL (). c_str (); printf ( " Foo Delete: <% S> \ n " , Foo. del_ SQL (). c_str ()); If (FOO. insert (ffdb) {printf ( " Exist Foo insert: <% S> \ n " , Foo. insert_ SQL (). c_str ();} Foo. Select (Ffdb ); If (Ffdb.exe _ SQL ( " Select * From dumy " , Ret_data) {printf ( " EXE error: % s \ n " , Ffdb. error_msg ();} dump (ret_data); Foo. M_c = 23.99 ; If (Ffdb.exe _ SQL (FOO. update_ SQL (), ret_data) {printf ( " EXE error: % s \ n " , Ffdb. error_msg ());} If (Ffdb.exe _ SQL ( " Select * From dumy " , Ret_data) {printf ( " EXE error: % s \ n " , Ffdb. error_msg ();} dump (ret_data ); /* If (ffdb.exe _ SQL (FOO. del_ SQL (), ret_data) {printf ("EXE error: % s \ n", ffdb. error_msg ();} If (ffdb.exe _ SQL ("select * From dumy", ret_data) {printf ("EXE error: % s \ n", ffdb. error_msg ();} dump (ret_data ); */ // If (ffdb.exe _ SQL ("select c From Foo where a = 167 limit 1;", ret_data )) If (Ffdb.exe _ SQL (FOO. select_ SQL (), ret_data) {printf ( " EXE error: % s \ n " , Ffdb. error_msg ();} dump (ret_data); Foo. B + = " A " ; Foo. Update (ffdb, & Foo_t: B ); If (Ffdb.exe _ SQL (FOO. select_ SQL (), ret_data) {printf ( " EXE error: % s \ n " , Ffdb. error_msg ();} dump (ret_data ); Return 0 ;}
Source code:
Https://github.com/fanchy/fflib/tree/master/example/book/sqlite