通过libzdb连接数据库

原创
2016/06/22 19:25
阅读数 4.9K

一.引用博客一些用法介绍:

Libzdb挺强大, 支持MySQL Oracle SQLite PostgreSQL,支持C和C++ Object C,不能在Window下用(看源码是因为基于Linux线程机制编写实现)。

遗憾的是找个资料太费劲,只能到Libzdb官网:点此进入 ,今正看着上面英文文档,突然网站就登不进去了,才发现国内论坛其实搜不出什么资料。

本文主要介绍Libzdb函数使用,帮理解英文文档有困难的朋友做下翻译。

库结构如下 :

首先下载libzdb的源码安装包,解压,在目录下执行./configure  make make install 安装。。以我自己为例,装完后再/usr/local/lib下有对应库文件。

线程池根据URL对象创建,URL对象通过char* 形式的URL生成,url中已经包含数据库类型,数据库名 用户密码等参数。形如:

database://[user:password@][host][:port]/database[?propertyName1][=propertyValue1]

MYSQL访问:

mysql://localhost:3306/test?user=root&password=swordfish
mysql://root:swordfish@localhost:3306/test

ORACLE访问:

oracle://localhost:1521/test?user=scott&password=tiger

oracle:///servicename?user=scott&password=tiger

SQLITE访问:

sqlite:///var/sqlite/test.db?synchronous=normal&heap_limit=8000&foreign_keys=on

PostgreSQL访问:

postgresql://root:swordfish@localhost/test?use-ssl=true

postgresql://localhost:5432/test?user=root&password=swordfish

 

2、

开启连接池

ConnectionPool_new(URL_T url) 根据URL生成连接池对象ConnectionPool_T,

ConnectionPool_start(ConnectionPool_T t); 开启数据库连接池(默认连接池大小为5),如果想自定义,需在开启前使用ConnectionPool_setInitialConnections函数设置。用法如下:

从数据库池中获取一个连接(此时活动连接+1):Connection_T ConnectionPool_getConnection (T P);

使用完毕后将连接放回连接池(此时活动连接-1):void  Connection_close (Connection_T C)

或者voidConnectionPool_returnConnection (T P, Connection_T connection)

 

3、

获取连接之后,执行数据库SQL语句:

(具体看官网介绍)

此处T 代表 Connection_T , Connection_execute 用于执行数据库插入、更新、删除等操作。Connection_executeQuery用于数据库查询,返回结果集。

4、

游标移动至结果集下一行intResultSet_next (ResultSet_T R), 结果无下一行则返回false ,否则返回true。关于结果集其他操作函数如下 :

代码实例:

    #include<stdio.h>  
    #include<stdlib.h>  
    #include<string.h>  
    #include<sys/types.h>  
    #include<zdb/zdb.h>  
    #include<zdb/Exception.h>  
    #include<zdb/Connection.h>  
    #include<zdb/URL.h>  
    /* 
     * 作者:搁浅的贝 
     * 编译方式:gcc main.c -I /usr/local/include/zdb/ -o main -lzdb  
     * */  
    int main(int agc,char** argv)  
    {  
        URL_T url = URL_new("mysql://localhost/AllinpayDB?user=root&password=root");  
        if(url==NULL)  
        {  
            printf("URL parse ERROR!\n");  
            return 0;  
        }  
        ConnectionPool_T pool = ConnectionPool_new(url);  
        //设置初始化连接数目  
        ConnectionPool_setInitialConnections(pool,20);  
        //开启线程池  
        ConnectionPool_start(pool);  
        //从线程池中取出连接(活动连接数+1)  
        Connection_T con = ConnectionPool_getConnection(pool);  
        //执行SQL语句,返回结果集  
        ResultSet_T result = Connection_executeQuery(con, "select * from AlipayTrans");  
        //输出全部连接数目  
        printf("ALL NUMBE:%d\n",ConnectionPool_size(pool));  
        //输出活动连接数目  
        printf("ACTIVE NUMBER:%d\n",ConnectionPool_active(pool));  
        while(ResultSet_next(result)) //游标滑到下一行  
        {  
            //获取列名 ResultSet_getColumnName  
            //获取列值 ResultSet_getString  
            printf("column: %s\n",ResultSet_getColumnName(result,2));  
            //根据列名获取值ResultSet_getStringByName  
            printf("%s\n ",ResultSet_getStringByName(result,"result_code"));  
            //根据列索引获取列值 [注意索引是从1开始不是0]  
            printf("%s\n ",ResultSet_getString(result,3));  
        }  
        //关闭连接(活动连接-1)  
        Connection_close(con);  
        //将连接池与数据库分离  
        ConnectionPool_stop(pool);  
        ConnectionPool_free(&pool);    
        URL_free(&url);   
        return 0;  
    }  

二.官网手册摘录用法实例以及简单翻译:

ZDB from DBS:

1.connection.h
connect_execute(): 执行返回无结果集sql 语句
Connection_executeQuery() : is used to execute a sql select statement and return a result set. 这个方法之只能handle values which can be exprssed as c_strings的sql语句。关于C_string:http://www.cprogramming.com/tutorial/lesson9.html
Connection_prepareStatement():用于执行非cstring类型的sql语句,如大对象二进制语句。 is used to obtain a PreparedStatement object。A PreparedStatement "lives" until the Connection is returned to the Connection Pool.

 2. 关于结果集关闭
  A ResultSet lives until the
  next call to Connection execute or until the Connection is returned
  to the Connection Pool. If an error occur during execution, an SQLException is thrown.

3.关于开启事务
Any SQL statement that changes the database (basically, any SQL command other than SELECT) will automatically start a transaction if one is not already in effect. Automatically started transactions are committed at the conclusion of the command.

4.关于Connection_prepareStatement()
PreparedStatement 是之前编译的好的用于后续执行的二进制文件。
A PreparedStatement is created by calling Connection_prepareStatement().
两个例子:
Result Sets:

Here is another example where we use a Prepared Statement to execute a query which returns a Result Set:
PreparedStatement_T p = Connection_prepareStatement(con, "SELECT id FROM employee WHERE name LIKE ?");
PreparedStatement_setString(p, 1, "%Kaoru%");
ResultSet_T r = PreparedStatement_executeQuery(p);
while (ResultSet_next(r))
       printf("employee.id = %d\n", ResultSet_getInt(r, 1));

A ResultSet returned from PreparedStatement_executeQuery() "lives" until the Prepared Statement is executed again or until the Connection is returned to the Connection Pool.

A PreparedStatement can be reused. That is, the method PreparedStatement_execute() can be called one or more times to execute the same statement. Clients can also set new in parameter values and re-execute the statement as shown in this example:

PreparedStatement_T p = Connection_prepareStatement(con, "INSERT INTO employee(name, picture) VALUES(?, ?)");
for (int i = 0; employees[i].name; i++)
{
       PreparedStatement_setString(p, 1, employees[i].name);
       PreparedStatement_setBlob(p, 2, employees[i].picture, employees[i].picture_size);
       PreparedStatement_execute(p);
}

5.Result
A ResultSet is created by executing a SQL SELECT statement using either Connection_executeQuery() or PreparedStatement_executeQuery().

A ResultSet maintains a cursor pointing to its current row of data. Initially the cursor is positioned before the first row.
可以用循环来编译结果集,但是这样的话只能从头至尾执行一次,故一般可用序号或者名字来具体获取对应的字段值,用序号的方法,编号从1开始。

6.关于上文提到Cstring文章的简单翻译。

在C++中有两种类型字符串(strings):C-style strings and C++-style strings。本文将讨论C-strings.

C-style strings are really arrays,但是string类型还有一些独有的函数,如adding to strings, finding the length of strings, and also of checking to see if strings match。
字符串的定义为:anything that contains more than one character strung together。例如:"this".单个字符尽管一般被当做字符串使用,但是不是字符串,Strings are arrays of chars. String literals are words surrounded by double quotation marks,例如:"This is a static string"。
用char string[50],即可声明一个长度为50的字符串,字符使用长度为49.因为字符串以占一个字符的空字符结尾:'\0'.
注意:char *arry也是一个字符串,比如:arry = new char[256],which allows you to access arry just as if it were an array.删除该字符串语法为:delete [] arry; 这将释放前面声明占用的256字节的内存。

Strings are useful for holding all types of long input.如果想输入姓名等,可以用你字符串类型,如用cin>>进行输入一个字符串,但是这种输入方式在读到一个空格时将结束输入。为处理这种情况,可以用cin.getline函数进行输入。Technically cin是一个类(类似于结构体),你可以调用其中的成员函数。而最重要的便是如何去使用这些函数。

getline函数的原型为:istream& getline(char *buffer, int length, char terminal_char);
char *buffer是一个指向字符数组第一个元素的指针(The char *buffer is a pointer to the first element of the character array, so that it can actually be used to access the array.)int length是输入字符串的最大长度。 char terminal_char表示当用户输入该字符时函数退出。要注意的是,改截止字符是不会被输入的。(Keep in mind that it will discard whatever the terminal character is.)

用一种情形是调用时没有输入截止字符,如cin.getline(arry,50).此时 '\n' is the way of actually telling the compiler you mean a new line,即'\n'就是截止符。

eg:

#include <iostram>
using namespace std;

int main()
{
    char string[256]; //a nice long string;

    cout<<"please input a long string:";
    cin.getline(string, 256, '\n');  //input goes into string

    cout  <<"your long string was:"<<string<<endl;
    cin.get();

}

Remember that you are actually passing the address of the array when you pass string because arrays do not require an address operator (&) to be used to pass their address。(当你调用函数时,当你输入string时,其实传递给函数的是一个地址,因为数组是不需要取地址符 &的)

cstring是一个包含了很多对字符串操作函数的头文件,其中字符串比较函数strcmp 便是其一:
        
int strcmp ( const char *s1, const char *s2 )

        strcmp will accept two strings. It will return an integer. This integer will either be:
            Negative if s1 is less than s2.
            Zero if s1 and s2 are equal.
            Positive if s1 is greater than s2。

Strcmp函数是区分大小写的(case sensitive)。Strcmp also passes the address of the character array to the function to allow it to be accessed.(字符串也可以传递字符数组地址)。

char *strcat ( char *dest, const char *src );
  连接函数,其将第二个字符串内容加到第一个字符串后,并返回一个指向黏贴完之后的整个字符串的指针,改函数假定了有一个足够长的空间去存取黏贴完之后的字符串。(t returns a pointer to the concatenated string. Beware this function, it assumes that dest is large enough to hold the entire contents of src as well as its own contents. )

  char *strcpy ( char *dest, const char *src );
拷贝函数:which means it copies the entire contents of src into dest. The contents of dest after strcpy will be exactly the same as src such that strcmp ( dest, src ) will return 0.

size_t strlen ( const char *s );

字符串长度函数,长度值是减去'\0'的长度(strlen will return the length of a string, minus the terminating character ('\0').)。size_t是一个非负整数。
 

eg:

#include <iostram>   //for cout
#include <cstring>    //for the string  function

using namespace std;

int main( )
{
    char name[50];
    char lastname[50];
    char fullname[100]; //big enough to contain the name and lastname.

    cout <<"please enter your name:";
    cin.getline(name, 50);

    if (strcmp(name, "julinene")==0) //equal strings
        cout <<"that's my name 2."<<endl;
    else
        cout<<"that is not my name."<<endl;
    
    if ((strcmp(name," ")==0)
         cout <<"the name inputed is invalid"<<endl;
            
    //find the length of the name

    cout<<"your name is "<<strlen(name)<<"letters long\n";

    cout <<"your last name:";
    cin.getline(lastname, 50);
    fullname[0] ='\0';  //strcat searches for '\0' to cat after

    strcat(fullname,name);  //copy name into fullname
    strcat(fullname, " ");  //separate the name by space
    strcat(fullname,lastname);
    cout<<"your fullname is"<<fullname<<endl;    


    cin.get();

    return 0;
}

但是以上方法有一定问题,即会依赖于Null结束符。 The above string functions all rely on the existence of a null terminator at the end of a string. This isn't always a safe bet. Moreover, some of them, noticeably strcat, rely on the fact that the destination string can hold the entire string being appended onto the end. Although it might seem like you'll never make that sort of mistake, historically, problems based on accidentally writing off the end of an array in a function like strcat, have been a major problem。

故一般是通过strncpy等函数来进行操作。

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
1 收藏
0
分享
返回顶部
顶部