3.2. C语言使用ODBC方式连接到数据库(Linux)

本章节将介绍C程序通过ODBC连接到GBase 8s数据库的方式。
ODBC是CSDK的一部分,因此本操作依赖CSDK;同时ODBC依赖于操作系统的unixODBC。

3.2.1. 依赖包

[root@localhost ~]# yum install -y autoconf gcc gcc-c++ unixODBC unixODBC-devel  

3.2.2. 安装GBase ClientSDK

安装目录为/opt/gbase
参考:CSDK安装

在/etc/ld.so.conf.d目录下增加GBase 8s的库目录配置文件gbase8scsdk-x86_64.conf

[root@localhost ld.so.conf.d]# pwd
/etc/ld.so.conf.d
[root@localhost ld.so.conf.d]# more gbase8scsdk-x86_64.conf
/opt/gbase/lib
/opt/gbase/lib/cli
/opt/gbase/lib/esql

3.2.3. ODBC连接测试

3.2.3.1. 编译测试程序TestCOdbc.c

TestCOdbc.c内容如下:

/////////////////////////////////////////////////////////////
// GBase 8s ODBC Applicatin Examples
//

// TestCOdbcDemo "DSN=odbc1"
// TestCOdbcDemo "DRIVER=/opt/gbase/lib/cli/iclis09b.so;SERVER=gbase01;DATABASE=db1;HOST=x.x.x.x;PROTOCOL=onsoctcp;SERVICE=5555;UID=user1;PWD=xyz;";

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef _WIN32
#include <windows.h>
#define strdup _strdup
#endif

#ifdef DRIVER_MANAGER
#include "sql.h"
#include "sqlext.h"
#else
#include <infxcli.h>
#endif

void GetDiagRec(SQLRETURN rc, SQLSMALLINT htype, SQLHANDLE hndl, char *szMsgTag);
int ReadResult(SQLHDBC hdbc, char *SqlSelect);
void  MyServerSetup(SQLHDBC hdbc);


int main(int argc, char *argv[])
{
    // 可使用DSN,需配置好ODBCINI
    SQLCHAR     ConnStrIn[1024] = "DSN=odbc1";
    SQLHANDLE   henv = NULL;
    SQLHANDLE   hdbc = NULL;
    int         rc = 0;

    char   *MyLocalConnStr = "DRIVER=/opt/gbase/lib/cli/iclis09b.so;SERVER=srv1;DATABASE=xb1;HOST=xyz.abc.com;PROTOCOL=onsoctcp;SERVICE=5550;UID=user1;PWD=xyz;";

    if (argc == 1)
    {
        if (sizeof(int *) == 8)  // 64bit application
        {
            // 显示指定连接串
            MyLocalConnStr = "DRIVER=/opt/gbase/lib/cli/iclis09b.so;HOST=192.168.0.212;SERVER=gbase01;SERVICE=13633;PROTOCOL=onsoctcp;DATABASE=testdb;UID=gbasedbt;PWD=GBase123$%;DB_LOCALE=zh_CN.utf8;CLIENT_LOCALE=zh_CN.utf8;";
        }
        strcpy((char *)ConnStrIn, MyLocalConnStr);

    }
    else if (argc == 2)
    {
        strcpy( (char *)ConnStrIn,  argv[1] );
    }
    else
    {
        strcpy((char *)ConnStrIn, MyLocalConnStr);

        if (0)
        {
            printf("\n Usage option is :");
            printf("\n %s    <Connection String>", argv[0]);
            printf("\n Example :");
            printf("\n %s   \"DSN=MyOdbcDsnName; uid=MyUserName; pwd=MyPassword;\" ", argv[0]);
            printf("\n OR ");
            printf("\n %s  \"%s\" ", argv[0], MyLocalConnStr);
            printf("\n\n");
            exit(0);
        }
    }


    rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);

    rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);

    rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
    rc == 0 ? 0 : GetDiagRec(rc, SQL_HANDLE_ENV, henv, "SQLAllocHandle");

    printf("\n***************************************************\n");
    printf("\n Connecting with : \n [%s] \n", (char *)ConnStrIn);
    printf("\n***************************************************\n");

    rc = SQLDriverConnect(hdbc, NULL, ConnStrIn, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
    if (rc != 0)
    {
        printf("\n Connection Error (:- \n");
        GetDiagRec(rc, SQL_HANDLE_DBC, hdbc, "SQLDriverConnect");
        goto Exit;
    }
    else
    {
        printf("\n Connection Success! \n");
    }

    if (1)
    {
        // Try Basic Setup
        MyServerSetup(hdbc);
        ReadResult(hdbc, "SELECT * FROM t1");
    }


Exit:
    SQLDisconnect(hdbc);
    SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
    SQLFreeHandle(SQL_HANDLE_ENV, henv);

    return(0);
}


void GetDiagRec(SQLRETURN rc, SQLSMALLINT htype, SQLHANDLE hndl, char *szMsgTag)
{
    SQLCHAR message[SQL_MAX_MESSAGE_LENGTH + 1];
    SQLCHAR sqlstate[SQL_SQLSTATE_SIZE + 1];
    SQLINTEGER sqlcode = 0;
    SQLSMALLINT length = 0;

    if (szMsgTag == NULL)
    {
        szMsgTag = "---";
    }

    printf("\n %s: %d : ", szMsgTag, rc);
    if (rc >= 0)
    {
        printf(" OK [rc=%d] \n", rc);
    }
    else
    {
        int i = 1;
        printf(" FAILED : %i", rc);
        while (SQLGetDiagRec(htype,
            hndl,
            i,
            sqlstate,
            &sqlcode,
            message,
            SQL_MAX_MESSAGE_LENGTH + 1,
            &length) == SQL_SUCCESS)
        {
            printf("\n SQLSTATE          = %s", sqlstate);
            printf("\n Native Error Code = %ld", sqlcode);
            printf("\n %s", message);
            i++;
        }
        printf("\n-------------------------\n");
    }
}


void  MyServerSetup(SQLHDBC hdbc)
{
    SQLRETURN   rc = 0;
    SQLHSTMT    hstmt = NULL;    int         i = 0;

    static unsigned char *SetupSqls[] =
    {
        "DROP TABLE t1;",
        "CREATE TABLE t1 ( c1 INT, c2  char(15),  c3 FLOAT, c4 char(10) )",
        "INSERT INTO  t1 VALUES ( 1, 'aaa-1', 11.55, 'bbbb-1' );",
        "INSERT INTO  t1 VALUES ( 2, 'aaa-2', 12.55, 'bbbb-2' );",
        NULL,
    };

    rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
    rc == 0 ? 0 : GetDiagRec(rc, SQL_HANDLE_DBC, hdbc, "MyServerSetup::SQLAllocHandle::SQL_HANDLE_STMT");

    for (i = 0; SetupSqls[i] != NULL; ++i)
    {
        rc = SQLExecDirect(hstmt, SetupSqls[i], SQL_NTS);
        printf("\n[%d] %s", rc, SetupSqls[i]);
    }


    if (hstmt)
    {
        SQLFreeStmt(hstmt, SQL_CLOSE);
        SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
    }
}


int ReadResult(SQLHDBC hdbc, char *SqlSelect)
{
    SQLRETURN       rc = 0;
    SQLHSTMT        hstmt = NULL;
    SQLCHAR         ReadBuffer[1024];
    int             ReadBufferSize = sizeof(ReadBuffer) - 2;

    printf("\n\n ----ReadResult ----");


    rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
    rc == 0 ? 0 : GetDiagRec(rc, SQL_HANDLE_DBC, hdbc, "SQLAllocHandle:SQL_HANDLE_STMT");


    rc = SQLExecDirect(hstmt, SqlSelect, SQL_NTS);
    if ((rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO))
    {
        SQLSMALLINT     ColumnCount = 0;
        int             RowNum = 0;

        rc = SQLNumResultCols(hstmt, &ColumnCount);
        printf("\nNumber of colum in the result is %d ---\n", ColumnCount);


        while ((rc = SQLFetch(hstmt)) != SQL_NO_DATA)
        {
            SQLLEN StrLen_or_IndPtr = 0;
            int NumBytes = 0;
            int col = 0;

            ++RowNum;
            printf("\n\n -Fetching Row# %d-", RowNum);

            for (col = 1; col <= ColumnCount; ++col)
            {

                memset(ReadBuffer, 0, sizeof(ReadBuffer));
                StrLen_or_IndPtr = 0;

                rc = SQLGetData(hstmt, col, SQL_C_CHAR, ReadBuffer, ReadBufferSize, &StrLen_or_IndPtr);
                if (rc == SQL_NO_DATA)
                {
                    break;
                }
                if (rc < 0)
                {
                    GetDiagRec(rc, SQL_HANDLE_STMT, hstmt, "SQLGetData");
                    break;
                }

                NumBytes = (int)((StrLen_or_IndPtr > ReadBufferSize) || (StrLen_or_IndPtr == SQL_NO_TOTAL) ? ReadBufferSize : StrLen_or_IndPtr);

                ReadBuffer[NumBytes] = 0;
                printf("\nColum_%d = %s", col, ReadBuffer);
            }
        }

    }
    else
    {
        GetDiagRec(rc, SQL_HANDLE_STMT, hstmt, SqlSelect);
    }

    if (hstmt)
    {
        SQLFreeStmt(hstmt, SQL_CLOSE);
        rc = SQLFreeStmt(hstmt, SQL_UNBIND);
        rc = SQLFreeStmt(hstmt, SQL_RESET_PARAMS);
        SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
    }

    printf("\n");
    return (0);
}

3.2.3.2. 编写makefile文件

内容如下:

#gcc -g -m64 -I/work/csdk/incl/cli -c TestCOdbc.c
#gcc -g -m64 -o TestCOdbc TestCOdbc.o -L/work/csdk/lib/cli -lifdmr -lthcli


#GBASEDBTDIR=/work/csdk
ODBCLIB_DIR  = -L$(GBASEDBTDIR)/lib/cli   -lthcli

INCLDIR  = -I$(GBASEDBTDIR)/incl/cli
CFLAGS  = -g
CC = gcc
RM = rm

TARGET = TestCOdbc

all : $(TARGET)

$(TARGET) : $(TARGET).o
        $(CC) $(CFLAGS)  -m64 -o $(TARGET) $(TARGET).o  $(ODBCLIB_DIR)

$(TARGET).o : $(TARGET).c
        $(CC) $(CFLAGS) -m64 $(INCLDIR) -c $(TARGET).c

clean :
        $(RM) $(TARGET) $(TARGET).o

注意:需使用tab缩进makefile文件

3.2.3.3. 编译成可执行文件,并执行测试

[root@localhost c]# make
gcc -g -m64 -I/opt/gbase/incl/cli -c TestCOdbc.c
gcc -g  -m64 -o TestCOdbc TestCOdbc.o  -L/opt/gbase/lib/cli   -lthcli

使用DSN时使用:

TestCOdbc "DSN=testdb" 

使用程序内的字符串时:

TestCOdbc 

使用指定DSN-Less(自定义DSN字符串)时:

TestCOdbc "DRIVER=/opt/gbase/lib/cli/iclis09b.so;HOST=192.168.0.212;SERVER=gbase01;SERVICE=13633;PROTOCOL=onsoctcp;DATABASE=testdb;UID=gbasedbt;PWD=GBase123$%;DB_LOCALE=zh_CN.utf8;CLIENT_LOCALE=zh_CN.utf8;" 

方式进行测试。
测试输出:

[root@localhost c]# ./TestCOdbc

***************************************************

 Connecting with :
 [DRIVER=/opt/gbase/lib/cli/iclis09b.so;HOST=192.168.0.212;SERVER=gbase01;SERVICE=13633;PROTOCOL=onsoctcp;DATABASE=testdb;UID=gbasedbt;PWD=GBase123$%;DB_LOCALE=zh_CN.utf8;CLIENT_LOCALE=zh_CN.utf8;]

***************************************************

 Connection Success!

[-1] DROP TABLE t1;
[0] CREATE TABLE t1 ( c1 INT, c2  char(15),  c3 FLOAT, c4 char(10) )
[0] INSERT INTO  t1 VALUES ( 1, 'aaa-1', 11.55, 'bbbb-1' );
[0] INSERT INTO  t1 VALUES ( 2, 'aaa-2', 12.55, 'bbbb-2' );

 ----ReadResult ----
Number of colum in the result is 4 ---


 -Fetching Row# 1-
Colum_1 = 1
Colum_2 = aaa-1
Colum_3 = 11.55
Colum_4 = bbbb-1

 -Fetching Row# 2-
Colum_1 = 2
Colum_2 = aaa-2
Colum_3 = 12.55
Colum_4 = bbbb-2

最后更新日期:2025-08-19