Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1042186
  • 博文数量: 162
  • 博客积分: 3887
  • 博客等级: 中校
  • 技术积分: 1617
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-06 19:05
文章分类

全部博文(162)

文章存档

2015年(4)

2014年(7)

2013年(10)

2012年(16)

2011年(89)

2010年(36)

分类: C/C++

2011-06-21 14:55:26

通过ODBC学习,现总结其主要函数调用方法。
#include
#include
#include
#include
#include
#include
#include

#define SUCCEED 1
#define FAIL -1
#define MAX_STRING_LEN    800

#define MAX(p,q) (((p) >= (q)) ? (p) : (q))

typedef char**        ZBX_ODBC_ROW;

typedef struct zbx_odbc_dbh_s
{
    SQLHENV        henv;
    SQLHDBC        hdbc;
    unsigned short    connected;
    SQLHSTMT    hstmt;
    SQLSMALLINT     col_num;
    ZBX_ODBC_ROW    row_data;
    SQLINTEGER    *data_len;
} ZBX_ODBC_DBH;

typedef ZBX_ODBC_DBH*        ZBX_ODBC_RESULT;

int        odbc_DBconnect(ZBX_ODBC_DBH *pdbh, const char *db_name, const char *user, const char *pass);
void        odbc_DBclose(ZBX_ODBC_DBH *pdbh);

int    odbc_DBexecute(ZBX_ODBC_DBH *pdbh, const char *query);
ZBX_ODBC_RESULT odbc_DBselect(ZBX_ODBC_DBH *pdbh, const char *query);
ZBX_ODBC_ROW    odbc_DBfetch(ZBX_ODBC_RESULT pdbh);


void    *zbx_malloc(void *old, size_t size)
{
    register int max_attempts;
    void *ptr = NULL;

/*    Old pointer must be NULL */
    if(old != NULL)
    {     
        assert(0);
    }


    for(
        max_attempts = 10, size = MAX(size, 1);
        max_attempts > 0 && !ptr;
        ptr = malloc(size),
        max_attempts--
    );

    if (ptr)
    {

        return ptr;
    }

    exit(FAIL);

    /* Program will never reach this point. */
    return ptr;
}


static void odbc_free_row_data(ZBX_ODBC_DBH *pdbh)
{
    SQLSMALLINT i;

    if(pdbh->row_data)
    {
        for(i = 0; i < pdbh->col_num; i++)
            free(pdbh->row_data[i]);

        free(pdbh->row_data);
        pdbh->row_data = NULL;
    }
    if(pdbh->data_len)
    {
        free(pdbh->data_len);
        pdbh->data_len = NULL;
    }
    pdbh->col_num = 0;
}

void    odbc_DBclose(ZBX_ODBC_DBH *pdbh)
{
    if(pdbh->hstmt)
    {
        SQLFreeHandle(SQL_HANDLE_STMT, pdbh->hstmt);
        pdbh->hstmt = NULL;
    }

    if(pdbh->hdbc)
    {
        if(pdbh->connected)
        {
            SQLDisconnect(pdbh->hdbc);
        }

        SQLFreeHandle(SQL_HANDLE_DBC, pdbh->hdbc);
        pdbh->hdbc = NULL;
    }

    if(pdbh->henv)
    {
        SQLFreeHandle(SQL_HANDLE_ENV, pdbh->henv);
        pdbh->henv = NULL;
    }

    odbc_free_row_data(pdbh);
}

int    odbc_DBconnect(ZBX_ODBC_DBH *pdbh, const char *db_dsn, const char *user, const char *pass)
{
    SQLCHAR
        err_stat[10],
        err_msg[100];

    SQLINTEGER
        err_int;

    SQLSMALLINT
        err_msg_len;

    SQLRETURN    retcode;


    memset(pdbh, 0 , sizeof(ZBX_ODBC_DBH));

    printf("ODBC connect [%s] [%s]", db_dsn, user);

    /*Allocate environment handle */
    retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(pdbh->henv));
    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
    {
        printf("%s","failed environment handle allocation.");
    }
    else
    {
        /* Set the ODBC version environment attribute */
        retcode = SQLSetEnvAttr(pdbh->henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
        if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
        {
            printf("%s","failed ODBC version setting.");
        }
        else
        {
            /* Allocate connection handle */
            retcode = SQLAllocHandle(SQL_HANDLE_DBC, pdbh->henv, &(pdbh->hdbc));
            if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
            {
                printf("%s","failed connection handle allocation.");
            }
            else
            {
                /* Set login timeout to 5 seconds. */
                SQLSetConnectAttr(pdbh->hdbc, (SQLINTEGER)SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, (SQLINTEGER)0);

                /* Connect to data source */
                retcode = SQLConnect(pdbh->hdbc,
                    (SQLCHAR*) db_dsn, SQL_NTS,
                    (SQLCHAR*) user, SQL_NTS,
                    (SQLCHAR*) pass, SQL_NTS
                    );
                if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
                {

                    SQLGetDiagRec(SQL_HANDLE_DBC,
                            pdbh->hdbc,
                            1,
                            err_stat,
                            &err_int,
                            err_msg,
                            sizeof(err_msg),
                            &err_msg_len
                            );

                    printf("failed connection [%s] (%d)", err_msg, err_int);
                }
                else
                {
                    pdbh->connected = 1;

                    /* Allocate statement handle */
                    retcode = SQLAllocHandle(SQL_HANDLE_STMT, pdbh->hdbc, &(pdbh->hstmt));

                    if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
                    {
                        return SUCCEED;
                    }
                    else
                    {
                        SQLFreeHandle(SQL_HANDLE_STMT, pdbh->hstmt);
                        pdbh->hstmt = NULL;
                    }
                    SQLDisconnect(pdbh->hdbc);
                }
                SQLFreeHandle(SQL_HANDLE_DBC, pdbh->hdbc);
                pdbh->hdbc = NULL;
            }
        }
        SQLFreeHandle(SQL_HANDLE_ENV, pdbh->henv);
        pdbh->henv = NULL;
    }

    printf( "Failed to connect to DSN '%s' : Error: ", db_dsn);
    return FAIL; /* error */
}


int    odbc_DBexecute(ZBX_ODBC_DBH *pdbh, const char *query)
{
    SQLCHAR
        err_stat[10],
        err_msg[100];

    SQLINTEGER
        err_int;

    SQLSMALLINT
        err_msg_len;

    SQLRETURN    retcode;

    //clean_odbc_strerror();

    odbc_free_row_data(pdbh);

    retcode = SQLExecDirect(pdbh->hstmt, (SQLCHAR*) query, SQL_NTS);

    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) goto lbl_err_exit;

    return SUCCEED;

lbl_err_exit:

    SQLGetDiagRec(SQL_HANDLE_STMT,
            pdbh->hstmt,
            1,
            err_stat,
            &err_int,
            err_msg,
            sizeof(err_msg),
            &err_msg_len
            );

    printf("Failed select execution [%s] (%d)", err_msg, err_int);


    return FAIL;
}

void    rtrim_spaces(char *c)
{
    int i,len;

    len = (int)strlen(c);
    for(i=len-1;i>=0;i--)
    {
        if( c[i] == ' ')
        {
            c[i]=0;
        }
        else    break;
    }
}

ZBX_ODBC_ROW    odbc_DBfetch(ZBX_ODBC_RESULT pdbh)
{
    SQLCHAR
        err_stat[10],
        err_msg[100];

    SQLINTEGER
        err_int;

    SQLSMALLINT
        err_msg_len;

    SQLRETURN    retcode;
    SQLSMALLINT     i;

    if(pdbh == NULL)    return NULL;

    //clean_odbc_strerror();

    printf("ODBC fetch\n");

    retcode = SQLFetch(pdbh->hstmt);
    if (retcode == SQL_ERROR) goto lbl_err_exit;

    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
    {
        printf("odbc_DBfetch [end of rows received]");
        return NULL;
    }

    for(i=0; i < pdbh->col_num; i++)
    {
        rtrim_spaces(pdbh->row_data[i]);
        printf("Fetched [%i col]: %s\n", i, pdbh->row_data[i]);
    }

    return pdbh->row_data;

lbl_err_exit:

    SQLGetDiagRec(SQL_HANDLE_STMT,
            pdbh->hstmt,
            1,
            err_stat,
            &err_int,
            err_msg,
            sizeof(err_msg),
            &err_msg_len
            );

    printf("Failed data fetching [%s] (%d)", err_msg, err_int);

    return NULL;
}

ZBX_ODBC_RESULT    odbc_DBselect(ZBX_ODBC_DBH *pdbh, const char *query)
{
    SQLCHAR err_stat[10],err_msg[100];

    SQLINTEGER err_int;

    SQLSMALLINT
        err_msg_len;

    SQLRETURN    retcode;
    SQLSMALLINT
        i = 0,
        col_num = 0;

    //clean_odbc_strerror();

    odbc_free_row_data(pdbh);

    printf( "ODBC select [%s]", query);

    retcode = SQLExecDirect(pdbh->hstmt, (SQLCHAR*) query, SQL_NTS);

    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) goto lbl_err_exit;

    retcode = SQLNumResultCols(pdbh->hstmt, &col_num);
    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) goto lbl_err_exit;

    pdbh->col_num  = col_num;

    pdbh->row_data = zbx_malloc(pdbh->row_data, sizeof(char*) * col_num);
    memset(pdbh->row_data, 0, sizeof(char*) * col_num);

    pdbh->data_len = zbx_malloc(pdbh->data_len, sizeof(SQLINTEGER) * col_num);
    memset(pdbh->data_len, 0, sizeof(SQLINTEGER) * col_num);

    for(i=0; i < col_num; i++)
    {
        pdbh->row_data[i] = zbx_malloc(pdbh->row_data[i], MAX_STRING_LEN);
        SQLBindCol(pdbh->hstmt, i+1, SQL_C_CHAR, pdbh->row_data[i], MAX_STRING_LEN, &pdbh->data_len[i]);
    }

    printf("selected %i cols\n", col_num);

    return (ZBX_ODBC_RESULT) pdbh;

lbl_err_exit:

    SQLGetDiagRec(SQL_HANDLE_STMT,
            pdbh->hstmt,
            1,
            err_stat,
            &err_int,
            err_msg,
            sizeof(err_msg),
            &err_msg_len
            );

    printf("Failed selection [%s] (%d)", err_msg, err_int);

    return NULL;
}
#include
#include

int main(int argc, char *argv[])
{
    pid_t pid;
    ZBX_ODBC_DBH    dbh;
    ZBX_ODBC_ROW    row;
    pid = fork();
    if(!pid)
    {
    char
        *db_dsn = NULL,
        *db_user = NULL,
        *db_pass = NULL,
        *db_sql = NULL;


    int    ret;

        db_dsn    = strdup("mysql");;
        db_user = strdup("nagios");
        db_pass = strdup("123456");
        db_sql  = strdup("show status like 'Aborted_clients'");

        if( SUCCEED == odbc_DBconnect(&dbh, db_dsn, db_user, db_pass) )
        {
            if( NULL != (row = odbc_DBfetch(odbc_DBselect(&dbh, db_sql))) )
            {
                printf("row0:%s,row1:%s\n", row[0], row[1]);
                    ret = SUCCEED;
            }
            else
            {
                printf("Error1\n");
            }
            odbc_DBclose(&dbh);
        }
        else
        {
            printf("Error2\n");
        }

        free(db_dsn);
        free(db_user);
        free(db_pass);
        free(db_sql);

    }
    return 0;
}

阅读(2941) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~