Click here to Skip to main content
15,867,453 members
Articles / Database Development / SQL Server
Article

OpenClient++: C++ wrapper for Sybase Open Client library

Rate me:
Please Sign up or sign in to vote.
4.22/5 (13 votes)
21 Nov 2004MPL4 min read 134.3K   2.5K   24   31
OpenClient++ is a thread safe, cross platform C++ wrapper for Sybase Open Client API.

Introduction

Sybase Open Client is the interface (API) between client applications and Sybase database server. In fact, it allows client applications to communicate to any database server which supports Tabular Data Stream (TDS) protocol. Currently, Microsoft SQL server and Sybase database server support TDS protocol. Open Client API can be thought of having two components.

  1. Programming Interface component implemented in C programming language which allows a user to build applications to communicate to Server. It contains Client-Library, DB-Library and CS-Library.
    • DB-Library, a collection of routines for use in writing client applications. DB-Library includes a bulk copy library and the two-phase commit special library.
    • Client-Library, a collection of routines for use in writing client applications. Client-Library is a new library, designed to accommodate cursors and other advanced features in the SYBASE 10.0 product line.
    • CS-Library, a collection of utility routines that are useful to both client and server applications. All Client-Library applications will include at least one call to CS-Library, because Client-Library routines use a structure which is allocated in CS-Library.
  2. Open Client Network services includes network library which provides support for specific network protocols such as TCP/IP or DCENet. For more information, see www.sybase.com.

Tabular Data Stream protocol was developed by Sybase to provide client-server communication between Sybase client and Server. You can get protocol specifications from Sybase or see www.freetds.org.

OpenClient++

I wanted to learn the Open Client library to access Sybase ASE server (12_5) from my client application. The best way I found was to implement C++ wrapper which can provide thread safe, cross platform interface similar to MySQL++ or other database library. Current version of OpenClient++ library provides following features using Client-Library (CT_LIB and CS_LIB routines):

  • C++ API
  • Thread Safe access
  • Cross platform (Windows and Linux)
  • Error Handling: it provides error handling using C++ Exception handling as well as traditional way where return values of function call is checked. Exception handling can be enabled/disabled at library level or individual class level.
  • Following SQL commands are supported:
    1. SELECT
    2. UPDATE
    3. DELETE
    4. INSERT
    5. COMPUTE: SUM, COUNT, MIN, MAX, AVG
  • Good documentation generated using DOxygen.

Interface Design:

Following classes are implemented to develop this library.

  1. Context:
    • Context: It is a singleton class which provides the instance of itself. It stores CS_CONTEXT structure and provides thread safe access context of client-library. It provides methods to set the debug level, enabled/disable exception handling, and call back function settings for error handling.
    • ContextException: It is an exception class for Context class. It is derives from the standard "Exception" class.
  2. Connection:
    • Connection: It’s a wrapper class for CS_CONNECTION structure. It stores connection parameters and establishes connection with server.
    • ConnectException: It is an exception class for Connection class. It is derived from the standard "Exception" class.
  3. Command:
    • Command: It’s a wrapper class for CS_COMMAND structure. It stores the SQL command string and type of command. It also builds and executes the commands using ct_command() and ct_send() functions of Client-Library.
    • CommandException: It is an exception class for Command class. It is derived from the standard "Exception" class.
  4. Query:
    • Query: It executes the command string, processes the result received from the server, and stores it into a RecordSet.
    • QueryException: It is an exception class for Query class. It is derived from the standard "Exception" class.
  5. Record Set:
    • Record: It’s a wrapper class for COLUMN_DATA structure. It stores information about columns and its value.
    • RecordSet: It stores the Record class objects, number of row updates, query success/failure, transaction ID and command ID.
  6. Utility classes:
    • Mutex: It provides the synchronized access to Context class object. It is implemented in two different header files.
      1. Mutex.h: Mutex class implementation for Linux.
      2. MutexWin.h: Mutex class implementation for Windows.
    • template<class T> Lock: It provides the guard lock functionality for Mutex class which avoids indefinite mutex locking in error condition.

Here is the diagram showing relationship among the classes:

Class Digram

Usage:

The simple usage of this library involves the following steps:

  • Set up the environment variables: get the instance of Context class which is a singleton class and set the environment variables like debug level, exception handling and error display. It provides the default call back functions to display the errors on the terminal. You can write your own custom call back functions and set it to context.
  • Connect to the server: connection class provides multiple constructor and connect() methods to pass connection information.
  • Create a Query Object: Connection class provides the method GetQuery() which creates the Query object by setting this as member variable.
  • Send a Command: Query object provides the method Execute() to send a command to the Server, it processes the result received from the server, stores into RecordSet, and returns the RecordSet object.
  • Result Processing: RecordSet object provides GetRecordsCount() method which returns total number of Records available. It provides GetRecord(index) method to retrieve the Record class object using which you can retrieve field name and value.
int main()
{
    try {
        // Get the context instance
        Context* pInstance = Context::GetInstance();
        std::cout << "Initialized the Context" << std::endl;
        
    }catch(ContextException &e) {
        std::cout << e.what() << std::endl;
        return -1;
    }
    try {
        // Set the debug level to all
        pInstance->SetDebugLevel(CS_DBG_ALL);
        // Set the call back handles for CS, CT and SRV libs
        pInstance->SetCallbackHandler(Context::CS_LIB,csmsg_callback);
        pInstance->SetCallbackHandler(Context::CT_LIB,ctmsg_callback);
        pInstance->SetCallbackHandler(Context::SRV_LIB, servermsg_callback);
    }catch(ContextException &e) {
        std::cout << e.what() << std::endl;
    }
    
    // Initialize the connection object
    Connection oConn("TestDB", "username", "password", "servername");
    try {
        // connect to server
        oConn.Connect();
    }catch (ConnectionException &e) {
        std::cout << e.what() << std::endl;
        return -1;
    }
    
    // Get the instance of Query class
    Query q = oConn.GetQuery();
    
    try {
        char sCommandBuff[256] = "";
        string sCmd;
        // execute the command untill userinput is "q"
        while(sCmd != "q") {
            std::cout << ">";
            std::cin.getline(sCommandBuff, 256);
            string sCmd = sCommandBuff;
            if(sCmd == "q")
                break;
            
            // Execute the query
            RecordSet &result = q.Execute(sCmd);
            if(result.IsSuccess()) {
                for(int i =0; i < result.GetRecordsCount(); i++) {
                    // Get the record
                    Record *pRecord = result.GetRecord(i);
                    if(!pRecord)
                      continue;
                    for(int j =0 ; j < pRecord->GetFieldsCount(); j++) {
                        std::cout << "Column:"
                                  << result.GetFieldName(j) 
                                  << "    Value:" 
                                  << pRecord->GetFieldValue(j) 
                                  << std::endl;
                    }
                 }
                 
                 std::cout << result.GetMessage()<< std::endl;
                 std::cout << "Result:"<<(bool)result
                            << " NumRows:" << result.GetRowsRead() 
                            << " CmdNum:" << result.GetCommandId()
                            << "Transaction Id:" 
                            << result.GetTransState() << std::endl;
             }else {
                 // print failure condition
                 std::cout << result.GetMessage() << std::endl;
                 std::cout << "Result:"<<(bool)result
                            << " NumRows:" << result.GetRowsRead() 
                            << " CmdNum:" << result.GetCommandId()
                            << "Transaction Id:" 
                            << result.GetTransState() << std::endl;
             }
                    
        } // while end
     
     }catch (QueryException &e) {
         std::cout << e.what() << std::endl;
    }
      return 0;
}

References:

Your comments, suggestions and rating for this article are appreciated.

License

This article, along with any associated source code and files, is licensed under The Mozilla Public License 1.1 (MPL 1.1)


Written By
Software Developer
United States United States
Rohit Joshi is a software engineer working for a telecom company in USA. He has development expirience using C, C++ ,C#, VoiceXML, ASR, IMAP, LDAP, HTTP, SIP, H323 on unix/linux and platforms.

Comments and Discussions

 
QuestionWhile using this library multi threaded application threads hangs and in dbx we found that this is using async function. Pin
Member 124115394-Nov-16 0:45
Member 124115394-Nov-16 0:45 
QuestionWhich is better? Pin
neeraj khan1-Aug-16 14:22
neeraj khan1-Aug-16 14:22 
QuestionUnix makefile Pin
rameshmelam31-Aug-08 19:05
rameshmelam31-Aug-08 19:05 
AnswerRe: Unix makefile Pin
Rohit Joshi5-Sep-08 13:26
Rohit Joshi5-Sep-08 13:26 
GeneralRe: Unix makefile Pin
rameshmelam14-Sep-08 11:50
rameshmelam14-Sep-08 11:50 
GeneralRe: Unix makefile Pin
HL HL2-Dec-11 21:43
HL HL2-Dec-11 21:43 
QuestionHow can I find the open client version Pin
RoarkDude31-Jul-08 10:03
RoarkDude31-Jul-08 10:03 
AnswerRe: How can I find the open client version Pin
Rohit Joshi5-Sep-08 13:27
Rohit Joshi5-Sep-08 13:27 
QuestionWhat type of license is applicable on this. Pin
rmerchant22-Jul-08 14:42
rmerchant22-Jul-08 14:42 
Rohit,

I would appreciate if you could specify what type of license is applied on this peice of work. Currently it is too generic.

RM.
AnswerRe: What type of license is applicable on this. Pin
Rohit Joshi23-Jul-08 2:11
Rohit Joshi23-Jul-08 2:11 
QuestionDo I need the libct.dll to use this wrapper? Pin
AnneZ25-Sep-07 9:23
AnneZ25-Sep-07 9:23 
AnswerRe: Do I need the libct.dll to use this wrapper? Pin
Rohit Joshi26-Sep-07 4:46
Rohit Joshi26-Sep-07 4:46 
AnswerRe: Do I need the libct.dll to use this wrapper? Pin
Rohit Joshi26-Sep-07 4:47
Rohit Joshi26-Sep-07 4:47 
GeneralRe: Do I need the libct.dll to use this wrapper? Pin
AnneZ26-Sep-07 5:02
AnneZ26-Sep-07 5:02 
GeneralRe: Do I need the libct.dll to use this wrapper? Pin
Rohit Joshi27-Sep-07 8:44
Rohit Joshi27-Sep-07 8:44 
GeneralRe: Do I need the libct.dll to use this wrapper? Pin
mindplaytm25-Oct-07 9:37
mindplaytm25-Oct-07 9:37 
GeneralRe: Do I need the libct.dll to use this wrapper? Pin
ttttnht19-Jun-08 6:05
ttttnht19-Jun-08 6:05 
QuestionCould you send me a project? Pin
hubei_121820-Jul-07 18:22
hubei_121820-Jul-07 18:22 
Generala problem Pin
hubei_121820-Jul-07 18:17
hubei_121820-Jul-07 18:17 
GeneralMemory leak Pin
Lukasz Kurylo17-Apr-07 23:51
Lukasz Kurylo17-Apr-07 23:51 
GeneralRe: Memory leak Pin
Rohit Joshi18-Apr-07 3:30
Rohit Joshi18-Apr-07 3:30 
GeneralRe: Memory leak Pin
dave_dave19-Mar-12 22:28
dave_dave19-Mar-12 22:28 
GeneralQuestion about wrapper Pin
vasjos15-Nov-05 8:26
vasjos15-Nov-05 8:26 
GeneralMore methods Pin
elecoest29-Apr-05 1:52
elecoest29-Apr-05 1:52 
GeneralAnything like this in C# Pin
Pink Floyd7-Apr-05 7:54
Pink Floyd7-Apr-05 7:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.