O'Reilly Databases

oreilly.comSafari Books Online.Conferences.

We've expanded our coverage and improved our search! Search for all things Database across O'Reilly!

Search Search Tips

advertisement
AddThis Social Bookmark Button

Listen Print Discuss Subscribe to Databases Subscribe to Newsletters

Embedded SQL with Pro*C

by Sai Kiran Gummaraj
12/07/2006

In any application software, accessing a database system is almost inevitable. Some programming languages, such as Java and C++ with custom libraries, do a very good job of providing good programmer interfaces to access the database. What if you want to access a database using C or COBOL or FORTRAN? This is usually the case in firms that use legacy applications--commonly large banks. These firms phase out systems at a much slower pace than do companies in other industries, due to the systems being extremely critical: they perform electronic funds tracking. It's difficult to introduce new technologies while rolling out the older technology just to satisfy the thirst of technology evangelists. Such systems usually rely on old ways of accessing databases, including low-level database libraries such as OCI in case of Oracle, Sybase Open Client Connect Libraries, and Pro*C. It takes plenty of planning to move to newer generation systems; it takes years of parallel and phased development in order to phase out older implementations.

Database access mechanisms such as Pro*C will stay relevant for some time to come. Pro*C is a very programmer- and reviewer-friendly way of writing code to access a database. The pre-compilation stage turns Pro*C code into low-level structures and function calls. This paradigm provides quite a few advantages. First, it shields the programmer from the underlying API calls used to access the database. Second, the actual SQL statements and the host programming language code really mix very well to produce very readable and clear code. It's not perfect, but I appreciate it.

Embedded SQL is a superset of Sybase's T-SQL or Oracle's PL/SQL that lets you place SQL statements in application programs written in languages such as C and COBOL. Pro*C allows the C programmer to write database access code fast and with less of a learning curve. For people who are familiar with both C and SQL, this is a cakewalk. Its worth noting that there are differences between implementations of Pro*C across different database vendors due to the differences between database architectures, datatypes, etc. Each new release of a database may announce certain enhancements or changes to its Embedded SQL pre-compiler. It is best to track changes on this front by referring to the vendor database websites.

This article discusses the ways and means of writing Pro*C code to access and modify a database system. My test databases are mainly Sybase and Oracle, as these are in wide use in the same environments as Pro*C. Finally, it's worth noting that some people refer to Pro*C as Embedded SQL.

Ready? What does it take to connect to a Sybase database using conventional C API calls (such as using Sybase OpenClient Connect Libraries)?

Note: This code, dbCon.c, is the sample Sybase programming code available from Sybase.

/************************************************
 *                                              *
 * Filename : dbCon.c                           *
 *                                              *
 * This is function demonstrates the series of  *
 * steps it involves in opening a connection    *
 * to the Sybase database.                      *
 *                                              *
 * NOTE: Not all variables used are declared;   *
 * Such as context, connection etc. as this     *
 * is just a demo snippet.                      *
 *                                              *
 ***********************************************/

void dbConnect ()
{
    CS_INT        rc;
    CS_INT        *outlen;
    CS_INT        buf_len;
    CS_INT        msglimit;
    CS_INT        netdriver;

    /*-----------------------------------------*
     * Allocate a connection to the server     *
     *-----------------------------------------*/
    rc = ct_con_alloc (context, &connection);
    if (rc != CS_SUCCEED)
    {
        strncpy (msgstr, "CT_CONALLOC failed", \
            msg_size);
        no_errors_sw = FALSE ;
        error_out (rc);
    }

    /*-----------------------------------------*
     * Alter properties of the                 *
     * connection for user-id                  *
     *-----------------------------------------*/
    buf_len  = user_size;
    rc = ct_con_props (connection, (long)CS_SET,\
        (long)CS_USERNAME, username, buf_len,\
        outlen);
    if (rc != CS_SUCCEED)
    {
        strncpy (msgstr, "CT_CON_PROPS for \
            user-id failed",msg_size);
        no_errors_sw = FALSE ;
        error_out (rc);
    }

    /*-----------------------------------------*
     * Alter properties of the                 *
     * connection for password                 *
     *-----------------------------------------*/
    buf_len = pwd_size;
    rc = ct_con_props (connection, (long)CS_SET,\
        (long)CS_PASSWORD, pwd, buf_len, outlen);
    if (rc != CS_SUCCEED)
    {
        strncpy (msgstr, "CT_CON_PROPS for \
            password failed", msg_size);
        no_errors_sw = FALSE ;
        error_out (rc);
    }

    /*-----------------------------------------*
     * Alter properties of the                 *
     * connection for transaction              *
     *-----------------------------------------*/
    buf_len = tran_size;
    rc = ct_con_props (connection, (long)CS_SET,\
        (long)CS_TRANSACTION_NAME, tran,\
        buf_len, outlen);
    if (rc != CS_SUCCEED)
    {
        strncpy (msgstr, "CT_CON_PROPS for \
            transaction failed", msg_size);
        no_errors_sw = FALSE ;
        error_out (rc);
    }

    /*-----------------------------------------*
     * Alter properties of the connection      *
     * for network driver                      *
     *-----------------------------------------*/

    /*-----------------------------------------*
     * default value for non-recognized        *
     * driver name                             *
     *-----------------------------------------*/
    netdriver = 9999;

    /*-----------------------------------------*
     * if no netdriver entered,                *
     * default is LU62                         *
     *-----------------------------------------*/

    if (strncmp(driver,"         ",9) == 0  ?? \
        strncmp(driver,"LU62",4) == 0)
            netdriver = CS_LU62;
    else if (strncmp(driver,"INTERLINK",8) == 0)
        netdriver = CS_INTERLINK;
    else if (strncmp(driver,"IBMTCPIP",8) == 0)
        netdriver = CS_TCPIP;
    else if (strncmp(driver,"CPIC",4) == 0)
        netdriver = CS_NCPIC;

    rc = ct_con_props (connection, (long)CS_SET,\
        (long)CS_NET_DRIVER, (long)netdriver,\
        CS_UNUSED, outlen);
    if (rc != CS_SUCCEED)
    {
        strncpy (msgstr, "CT_CON_PROPS for \
            network driver failed",msg_size);
        no_errors_sw = FALSE ;
        error_out (rc);
    }

    /*-----------------------------------------*
     * Setup retrieval of All Messages         *
     *-----------------------------------------*/
    rc = ct_diag (connection, CS_INIT, \
        CS_UNUSED, CS_UNUSED, CS_NULL);
    if (rc != CS_SUCCEED)
    {
        strncpy (msgstr, "CT_DIAG CS_INIT \
            failed", msg_size);
        no_errors_sw = FALSE ;
        error_out (rc);
    }

    /*-----------------------------------------*
     * Set the upper limit of number           *
     * of messages                             *
     *-----------------------------------------*/
    msglimit = 5 ;
    rc = ct_diag (connection, CS_MSGLIMIT, \
        CS_ALLMSG_TYPE, CS_UNUSED, &msglimit);
    if (rc != CS_SUCCEED)
    {
        strncpy (msgstr, "CT_DIAG CS_MSGLIMIT \
            failed", msg_size);
        no_errors_sw = FALSE ;
        error_out (rc);
    }

    /*-----------------------------------------*
     * Open connection to the server           *
     * or CICS region                          *
     *-----------------------------------------*/
    rc = ct_connect (connection, servname, \
        server_size);
    if (rc != CS_SUCCEED)
    {
        strncpy (msgstr, "CT_CONNECT failed",\
            msg_size);
        no_errors_sw = FALSE ;
        error_out (rc);
    }
}

This code invokes quite a few APIs and performs plenty of error checking. How much simpler Pro*C makes this! Note that Pro*C source files have the extensions .PC or .pc. The Pro*C pre-compiler will produce the actual .c or .cpp files.

Pages: 1, 2, 3

Next Pagearrow




Tagged Articles

Be the first to post this article to del.icio.us

Sponsored Resources

  • Inside Lightroom

Related to this Article

Oracle PL/SQL for DBAs Oracle PL/SQL for DBAs
by Arup Nanda , Steven Feuerstein
October 2005
$39.95 USD

Understanding Oracle Clinical Understanding Oracle Clinical
by Joan M. Johnson
June 2009
$9.99 USD

Advertisement
O'Reilly Media

©2009, O'Reilly Media, Inc.
(707) 827-7000 / (800) 998-9938
All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.
About O'Reilly
Academic Solutions
Authors
Contacts
Customer Service
Jobs
Newsletters
O'Reilly Labs
Press Room
Privacy Policy
RSS Feeds
Terms of Service
User Groups
Writing for O'Reilly
Content Archive
Business Technology
Computer Technology
Google
Microsoft
Mobile
Network
Operating System
Digital Photography
Programming
Software
Web
Web Design
More O'Reilly Sites
O'Reilly Radar
Ignite
Tools of Change for Publishing
Digital Media
Inside iPhone
makezine.com
craftzine.com
hackszine.com
perl.com
xml.com

Partner Sites
InsideRIA
java.net
O'Reilly Insights on Forbes.com