And a few others assorted questions.
I'm trying to implement connecting to Access via C++. Using Codeblocks as my IDE.
I got the source code from this site :
http://www.powerbasic.com/support/pbforums/showthread.php?t=24912&highlight=Using+ODBC+Direct
[code#include "windows.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "odbcinst.h"
#include "sql.h" //ODBC header file
#include "sqlext.h" //ODBC header file
//
typedef struct tagSQL //This type helps with some 'grungy' initialization work
{ //in setting up an ODBC environment
SQLCHAR szCnIn[512];
SQLCHAR szCnOut[512];
short int iBytes;
SWORD swStrLen;
SQLHENV hEnvr;
SQLHDBC hConn;
unsigned int blnConnected;
}SQL,*lpSql;
//
typedef struct tagDiagRec //ODBC functions return wonderful error information
{ //and this type helps in setting it up. I have
SQLINTEGER iNativeErrPtr; //found this the best way to do it, and
SQLSMALLINT iTextLenPtr; //believe me, you need this error info!
SQLCHAR szErrMsg[512];
SQLCHAR szErrCode[8];
}DIAGNOSTICRECORD;
//
//
void ODBCConnect(SQLCHAR *szDB,lpSql sql) //Fairly ugly stuff in here and you want to try
{ //to keep your application as isolated from it
DIAGNOSTICRECORD dr; //as possible. After you have the connection
char lpBuffer[512]; //set up all you need is one function to get
DWORD nBufLen=512; //a statement handle, 'SQLAllocHandle()' to use
UINT iResult; //SQL statements to Select, Update, and Insert data
//
SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&sql->hEnvr);
SQLSetEnvAttr(sql->hEnvr,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);
SQLAllocHandle(SQL_HANDLE_DBC,sql->hEnvr,&sql->hConn); //returns handle to connection
strcpy(sql->szCnIn,"DRIVER=Microsoft Access Driver (*.mdb);DBQ="); //move string to buffer
GetCurrentDirectory(nBufLen,lpBuffer);
printf("lpBuffer=%s\n",lpBuffer);
strcat(sql->szCnIn,lpBuffer);
strcat(sql->szCnIn,"\\");
strcat(sql->szCnIn,szDB);
strcat(sql->szCnIn,";");
printf("sql->szCnIn = %s\n",sql->szCnIn);
iResult=
SQLDriverConnect //this is the big connection function
(
sql->hConn, //we just obtained sql->hConn above in last SQLAllocHandle() call
NULL, //handle to a window is optional
sql->szCnIn, //here is the connection string we just built
(SQLSMALLINT)strlen(sql->szCnIn), //here it wants the length of the connection string
sql->szCnOut, //if the function succeeds it will return to us the Conn str it used
512, //this is the length of the output buffer for the Conn str
&sql->swStrLen, //this is the number of bytes it actually returned
SQL_DRIVER_NOPROMPT //I'm telling it to fail rather than prompt me for more Conn info
);
if(!iResult)
sql->blnConnected=TRUE; //return TRUE if connection attempt was successful
else
{
SQLGetDiagRec //if the connection attempt fails we'll call this function
( //to obtain an explanation for the failure
SQL_HANDLE_DBC,
sql->hConn,
1,
dr.szErrCode,
&dr.iNativeErrPtr,
dr.szErrMsg,
512,
&dr.iTextLenPtr
);
printf("dr.szErrCode = %s\n",dr.szErrCode);
printf("dr.szErrMsg = %s\n",dr.szErrMsg);
sql->blnConnected=FALSE; //return FALSE if connection fails
SQLDisconnect(sql->hConn);
SQLFreeHandle(SQL_HANDLE_DBC ,sql->hConn);
SQLFreeHandle(SQL_HANDLE_ENV,sql->hEnvr);
}
}
//
//
void ODBCDisconnect(lpSql sql) //Disconnect from data source, and
{ //release connection and environment
SQLDisconnect(sql->hConn); //handles
SQLFreeHandle(SQL_HANDLE_DBC,sql->hConn);
SQLFreeHandle(SQL_HANDLE_ENV,sql->hEnvr);
}
//
//
void InstallerError(void)
{
DWORD pErr;
SQLCHAR szErrMsg[512];
WORD cbMsgBuffer=512;
WORD cbRet;
WORD wErrNum=1;
//
while(SQLInstallerError(wErrNum,&pErr,szErrMsg,cbMsgBuffer,&cbRet)!=SQL_NO_DATA)
{
printf("%u\t%u\t%s\n",wErrNum,pErr,szErrMsg);
wErrNum++;
};
//
return;
}
//
//
UINT blnCreateDB(SQLCHAR *szDBName) //Uses SQLConfigDataSource() to create Jet database
{
SQLCHAR szCreate[24];
//
printf("szDBName=%s\n",szDBName);
strcpy(szCreate,"CREATE_DB=");
strcat(szCreate,szDBName);
printf("szCreate=%s\n",szCreate);
if(SQLConfigDataSource(0,ODBC_ADD_DSN,"Microsoft Access Driver (*.mdb)",szCreate))
{
printf("SQLConfigDataSource() returned TRUE\n");
return TRUE;
}
else
{
InstallerError();
return FALSE;
}
}
//
//
UINT blnMakeTable(lpSql sql) //Uses SQL Create Table statement to add table
{ //to database represented by sql->hConn
SQLCHAR szQuery[256];
SQLHSTMT hStmt;
//
strcpy(
szQuery,
"CREATE TABLE Table1 " \
"(" \
"Id LONG NOT NULL PRIMARY KEY," \
"Float_Point DOUBLE," \
"Date_Field DATETIME," \
"Text_Field CHAR(30)" \
");");
printf("%s\n",szQuery);
SQLAllocHandle(SQL_HANDLE_STMT,sql->hConn,&hStmt);
if(SQLExecDirect(hStmt,szQuery,SQL_NTS)==0)
{
puts("Table1 Successfully Created!");
SQLFreeHandle(SQL_HANDLE_STMT,hStmt);
return(TRUE);
}
else
{
puts("Table Creation Failure!"); //Here would be a good place to use
return(FALSE); //SQLGetDiagRec() if table creation fails
}
}
//
//
TIMESTAMP_STRUCT ParseDate(SQLCHAR *szDate,SQLCHAR *szFormat,SQLCHAR *szDelimiter)
{
UINT i=0,j=0,k=0; //PowerBASIC doesn't allow for the return of Types
TIMESTAMP_STRUCT ts; //but C does. Not really a big deal, in my mind.
SQLCHAR buf[3][8]; //buf[0] for month, buf[1] for day, buf[2] for year
SQLCHAR *p;
//
memset(buf,0,sizeof(buf)); //zero out buf[]
p=szDate; //set p equal to address of date string passed.
for(i=0;i<strlen(szDate);i++)
{
if(*p!=*szDelimiter) //move through date string stripping
{ //out numbers seperated by delimiters
buf[j][k++]=*p;
buf[j][k+1]='\0';
}
else
{
j++;
k=0;
}
p++;
}
if(!strcmpi(szFormat,"MDY")) //figure out what is suppossed to be
{ //in each buffer
ts.month=atoi(buf[0]);
ts.day=atoi(buf[1]);
ts.year=atoi(buf[2]);
}
if(!strcmpi(szFormat,"DMY"))
{
ts.day=atoi(buf[0]);
ts.month=atoi(buf[1]);
ts.year=atoi(buf[2]);
}
if(!strcmpi(szFormat,"YMD"))
{
ts.year=atoi(buf[0]);
ts.month=atoi(buf[1]);
ts.day=atoi(buf[2]);
}
return ts;
}
[/code]
To be continued....