MDAC 2.5 SDK - Visual FoxPro ODBC Driver


 

Using the Visual FoxPro ODBC Driver with Your C or C++ Application

Your C or C++ application communicates with Visual FoxPro data by sending a SQLExecute or SQLExecDirect statement to Visual FoxPro. This statement can contain the following:

For more information about SQL native to Visual FoxPro, see the Visual FoxPro documentation.

Example: Using the Visual FoxPro ODBC Driver with Your C or C++ Application

The following example uses the ODBC C API to retrieve data stored in the last_name field in the employee table in the Microsoft® Visual FoxPro sample database named TasTrade. This database is provided with Visual FoxPro and is installed by default in the following location:

c:\vfp\samples\mainsamp\data\tastrade.dbc

The example displays one last name at a time, allowing you to click OK on the message box to see the next last name. It is assumed that a data source named Tastrade has been set up to use the Tastrade.dbc database.

Note   Error checking should be performed on all ODBC API calls; this example excludes error checking for the sake of brevity.

#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <stdlib.h>
#include <mbstring.h>

#define MAX_DATA 100
#define MYSQLSUCCESS(rc) ((rc==SQL_SUCCESS)||(rc==SQL_SUCCESS_WITH_INFO))

class direxec
{
   RETCODE rc;        // ODBC return code
   HENV henv;         // Environment   
   HDBC hdbc;         // Connection handle
   HSTMT hstmt;       // Statement handle
   unsigned char szData[MAX_DATA];   // Returned data storage
   SDWORD cbData;     // Output length of data
   unsigned char chr_ds_name[SQL_MAX_DSN_LENGTH];   // Data source name

public:
   direxec();           // Constructor
   void sqlconn();      // Allocate env, stat, and conn
   void sqlexec(unsigned char *);   // Execute SQL statement
   void sqldisconn();   // Free pointers to env, stat, conn,
                        // and disconnect
   void error_out();    // Displays errors
};

// Constructor initializes the string chr_ds_name with the 
// data source name.
direxec::direxec()
{
   _mbscpy(chr_ds_name,(const unsigned char *)"tastrade");
}

// Allocate environment handle, allocate connection handle, 
// connect to data source, and allocate statement handle.
void direxec::sqlconn(void)
{
   SQLAllocEnv(&henv);
   SQLAllocConnect(henv,&hdbc);
   rc=SQLConnect(hdbc,chr_ds_name,SQL_NTS,NULL,0,NULL,0);
   
   // Deallocate handles, display error message, and exit.
   if (!MYSQLSUCCESS(rc))
   {
      SQLFreeEnv(henv);
      SQLFreeConnect(hdbc);
      error_out();
      exit(-1);
   }

   rc=SQLAllocStmt(hdbc,&hstmt);

}

// Execute SQL command with SQLExecDirect() ODBC API.
void direxec::sqlexec(unsigned char * cmdstr)
{
   rc=SQLExecDirect(hstmt,cmdstr,SQL_NTS);
   if (!MYSQLSUCCESS(rc))  //Error
   {
      error_out();
      // Deallocate handles and disconnect.
      SQLFreeStmt(hstmt,SQL_DROP);
      SQLDisconnect(hdbc);
      SQLFreeConnect(hdbc);
      SQLFreeEnv(henv);
      exit(-1);    
   }
   else
   {
      for (rc=SQLFetch(hstmt); rc == SQL_SUCCESS; rc=SQLFetch(hstmt))
      {
         SQLGetData(hstmt,1,SQL_C_CHAR,szData,sizeof(szData),&cbData);
         // In this example, the data is returned in a messagebox 
         // for simplicity. However, normally the SQLBindCol() ODBC API
         // could be called to bind individual rows of data and assign 
         // for a rowset. 
         MessageBox(NULL,(const char *)szData,"ODBC",MB_OK);
      }
   }
}

// Free the statement handle, disconnect, free the connection handle, and
// free the environment handle.
void direxec::sqldisconn(void)
{
   SQLFreeStmt(hstmt,SQL_DROP);
   SQLDisconnect(hdbc);
   SQLFreeConnect(hdbc);
   SQLFreeEnv(henv);
}

// Display error message in a message box that has an OK button.
void direxec::error_out(void)
{
   unsigned char szSQLSTATE[10];
   SDWORD nErr;
   unsigned char msg[SQL_MAX_MESSAGE_LENGTH+1];
   SWORD cbmsg;

   while(SQLError(0,0,hstmt,szSQLSTATE,&nErr,msg,sizeof(msg),&cbmsg)== 
   SQL_SUCCESS)
   {
      wsprintf((char *)szData,"Error:\nSQLSTATE=%s,Native 
      error=%ld,msg='%s'",
         szSQLSTATE,nErr,msg);
      MessageBox(NULL,(const char *)szData,"ODBC Error",MB_OK);

   }

}

int WINAPI WinMain (HANDLE hInstance, HANDLE hPrevInstance,
                    LPSTR lpszCmdLine, int nCmdShow)
{
   // Declare an instance of the direxec object.
   direxec x;
   
   // Allocate handles, and connect.
   x.sqlconn();

   // Execute SQL command "SELECT last_name FROM employee".
   x.sqlexec((UCHAR FAR *)"SELECT last_name FROM employee");

   // Free handles, and disconnect.
   x.sqldisconn();
   
   // Return success code; example executed successfully.
   return (TRUE);
}