Listing 2: Function CColumns::MakeColumnListFromQuery
BOOL CColumns::MakeColumnListFromQuery()
{
BOOL bRtn=FALSE; // Assume we'll fail; allow reselect
RETCODE rc; // Return code from ODBC functions
CColumnInfo* pColInfo; // Data type output for each column
int index; // Index for columns
short iCols; // the number of columns in this query
HSTMT hStmt; // allocated and used in this function
// check if this object was constructed sans open CDatabase
if ( (m_hstmt == SQL_NULL_HSTMT) || (!m_pDatabase->IsOpen()) )
ThrowDBException(SQL_INVALID_HANDLE);
// <<--< it was, so toss cookies...
// safe to continue, so create a meta-data only query
ReplaceWhereClause();
// Get a HSTMT for use in this function
rc = ::SQLAllocStmt( m_pDatabase->m_hdbc, &hStmt );
if (SQL_NOTSUCCESSFUL(rc))
{
DecodeSQLError(rc, m_pDatabase->m_hdbc, hStmt, THIS_FILE, __LINE__);
goto cleanup;
}
// Execute the query and retrieve the results
rc = ::SQLExecDirect(hStmt,
(unsigned char*)
m_QueryNoWhere.GetBuffer(m_QueryNoWhere.GetLength()),
m_QueryNoWhere.GetLength());
if(SQL_NOTSUCCESSFUL(rc))
{
DecodeSQLError(rc, m_pDatabase->m_hdbc, hStmt,
THIS_FILE, __LINE__);
m_QueryNoWhere.ReleaseBuffer();
goto cleanup;
}
m_QueryNoWhere.ReleaseBuffer();
// how many columns are there in this select?
rc = ::SQLNumResultCols( hStmt, &iCols);
if(SQL_NOTSUCCESSFUL(rc))
{
DecodeSQLError(rc, m_pDatabase->m_hdbc, hStmt, THIS_FILE, __LINE__);
goto cleanup;
}
// make the CPtrArray large enough to hold all of the
// CColumnInfo *'s
// m_ColumnList.SetSize(iCols);
// now loop through the column set gathering facts about each one
// to store in a CColumnInfo class for each column. All the
// CColumnInfo classes will be added to the m_ColumnList
for(index = 0; index < iCols; index++)
{
pColInfo = new CColumnInfo;
if (pColInfo == NULL)
goto cleanup;
pColInfo->nColInRslt = index +1;
// get the SQL_xxx type (and related info) for the column
rc = ::SQLDescribeCol(hStmt,
(UWORD)(index + 1),
NULL,
0,
NULL,
&pColInfo->fSqlType,
&pColInfo->cbPrecision,
&pColInfo->ibScale,
&pColInfo->fNullable);
if(SQL_NOTSUCCESSFUL(rc))
{
DecodeSQLError(rc, m_pDatabase->m_hdbc, hStmt, THIS_FILE, __LINE__);
goto cleanup;
}
// Get the named type of the column for mapping
//
rc = ::SQLColAttributes(hStmt,
(UWORD)(index + 1),
SQL_COLUMN_TYPE_NAME,
&pColInfo->szNamedType,
sizeof(pColInfo->szNamedType),
NULL,
NULL);
if(SQL_NOTSUCCESSFUL(rc))
{
DecodeSQLError(rc, m_pDatabase->m_hdbc, hStmt, THIS_FILE, __LINE__);
goto cleanup;
}
// Get the display size in case this column gets converted to char
//
rc = ::SQLColAttributes(hStmt,
(UWORD)(index + 1),
SQL_COLUMN_DISPLAY_SIZE,
NULL,
sizeof(pColInfo->cbDspSize),
NULL,
&pColInfo->cbDspSize);
if(SQL_NOTSUCCESSFUL(rc))
{
DecodeSQLError(rc, m_pDatabase->m_hdbc, hStmt, THIS_FILE, __LINE__);
goto cleanup;
}
// Get the name of this column
//
rc = ::SQLColAttributes(hStmt,
(UWORD)(index + 1),
SQL_COLUMN_NAME,
&pColInfo->szColumnName,
sizeof(pColInfo->szColumnName),
NULL,
NULL);
if(SQL_NOTSUCCESSFUL(rc))
{
DecodeSQLError(rc, m_pDatabase->m_hdbc, hStmt, THIS_FILE, __LINE__);
goto cleanup;
}
// Get the name of the table containing this column
//
rc = ::SQLColAttributes(hStmt,
(UWORD)(index + 1),
SQL_COLUMN_TABLE_NAME,
&pColInfo->szFromTable,
sizeof(pColInfo->szFromTable),
NULL,
NULL);
if(SQL_NOTSUCCESSFUL(rc))
{
DecodeSQLError(rc, m_pDatabase->m_hdbc, hStmt, THIS_FILE, __LINE__);
goto cleanup;
}
// now that we have all the info we need on this column
// finish up by allocating storage for this column's local
// member variable and adding the finished CColumnInfo to
// the column list
if ( ! AllocStorageForColumnVar(pColInfo) )
goto cleanup;
if ( !(MapColumnSQLTypeToCType(pColInfo))
|| !(GetCreateParamCount(pColInfo)) )
goto cleanup;
AddColumnInfoToList(pColInfo);
}
// if we get here, all went well
if ( GenerateTableCreationString() )
bRtn = TRUE;
// Clean up the statement handle
//
cleanup:
SQLFreeStmt(hStmt, SQL_CLOSE);
SQLFreeStmt(hStmt, SQL_UNBIND);
return bRtn;
}
//End of File