COMMON.CPP

//----------------------------------------------------------------------------- 
// Microsoft OLE DB TABLECOPY Sample
// Copyright (C) 1996 By Microsoft Corporation.
//
// @doc
//
// @module COMMON.CPP
//
//-----------------------------------------------------------------------------

/////////////////////////////////////////////////////////////////////////////
// Include
//
/////////////////////////////////////////////////////////////////////////////
#include "winmain.h"
#include "common.h"
#include "tablecopy.h"
#include "table.h"


/////////////////////////////////////////////////////////////////////////////
// Defines
//
/////////////////////////////////////////////////////////////////////////////

//Displays values like VALUE as VALUE , L"VALUE"
#define VALUE_WCHAR(value) value, L#value

typedef struct _TYPEMAP
{
DBTYPEwType;// The sql type value
WCHAR*pwszTypeName;// Name for display
} TYPEMAP;

TYPEMAP rgDBTypes[] =
{
VALUE_WCHAR(DBTYPE_I1),
VALUE_WCHAR(DBTYPE_I2),
VALUE_WCHAR(DBTYPE_I4),
VALUE_WCHAR(DBTYPE_I8),
VALUE_WCHAR(DBTYPE_UI1),
VALUE_WCHAR(DBTYPE_UI2),
VALUE_WCHAR(DBTYPE_UI4),
VALUE_WCHAR(DBTYPE_UI8),
VALUE_WCHAR(DBTYPE_R4),
VALUE_WCHAR(DBTYPE_R8),
VALUE_WCHAR(DBTYPE_CY),
VALUE_WCHAR(DBTYPE_DECIMAL),
VALUE_WCHAR(DBTYPE_NUMERIC),
VALUE_WCHAR(DBTYPE_BOOL),
VALUE_WCHAR(DBTYPE_ERROR),
VALUE_WCHAR(DBTYPE_UDT),
VALUE_WCHAR(DBTYPE_VARIANT),
VALUE_WCHAR(DBTYPE_IDISPATCH),
VALUE_WCHAR(DBTYPE_IUNKNOWN),
VALUE_WCHAR(DBTYPE_GUID),
VALUE_WCHAR(DBTYPE_DATE),
VALUE_WCHAR(DBTYPE_DBDATE),
VALUE_WCHAR(DBTYPE_DBTIME),
VALUE_WCHAR(DBTYPE_DBTIMESTAMP),
VALUE_WCHAR(DBTYPE_BSTR),
VALUE_WCHAR(DBTYPE_STR),
VALUE_WCHAR(DBTYPE_WSTR),
VALUE_WCHAR(DBTYPE_BYTES),
};



/////////////////////////////////////////////////////////////////////////////
// HRESULT ConvertToMBCS
//
/////////////////////////////////////////////////////////////////////////////
HRESULT ConvertToMBCS(WCHAR* pwsz, CHAR* psz, ULONG cbStrLen)
{
ASSERT(pwsz && psz);

//Convert the string to MBCS
INT iResult = WideCharToMultiByte(CP_ACP, 0, pwsz, -1, psz, cbStrLen, NULL, NULL);
return iResult ? S_OK : E_FAIL;
}

/////////////////////////////////////////////////////////////////////////////
// HRESULT ConvertToWCHAR
//
/////////////////////////////////////////////////////////////////////////////
HRESULT ConvertToWCHAR(CHAR* psz, WCHAR* pwsz, ULONG cbStrLen)
{
ASSERT(psz && pwsz);

//Convert the string to MBCS
INT iResult = MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, cbStrLen);
return iResult ? S_OK : E_FAIL;
}


/////////////////////////////////////////////////////////////////////////////
// WCHAR* wcsDuplicate
//
/////////////////////////////////////////////////////////////////////////////
WCHAR* wcsDuplicate(WCHAR* pwsz)
{
ASSERT(pwsz);
ULONG cLen= wcslen(pwsz);

//Allocate space for the string
WCHAR* pwszBuffer = NULL;
SAFE_ALLOC(pwszBuffer, WCHAR, cLen+1);

//Now copy the string
wcscpy(pwszBuffer, pwsz);

CLEANUP:
return pwszBuffer;
}


/////////////////////////////////////////////////////////////////////////////
// BOOL GetQuotedID
//
/////////////////////////////////////////////////////////////////////////////
BOOL GetQuotedID(
WCHAR* pwszOutBuff,// User's output buffer
WCHAR* pwszInBuff,// User's input buffer
WCHAR* pwszQuote,// QUOTE Character
WCHAR* pwszSeperator // SEPERATOR Character
)
{
ASSERT(pwszOutBuff && pwszInBuff);

WCHAR pwsz[MAX_NAME_LEN*2];
WCHAR* pwszItr = pwsz;

ULONG cQuoteLen = pwszQuote ? wcslen(pwszQuote) : 0;
ULONG cSepLen= pwszSeperator ? wcslen(pwszSeperator) : 0;

//Put on front delimeter
if(pwszQuote)
wcscpy(pwszItr, pwszQuote);
pwszItr += cQuoteLen;

//Copy from Source to Temp
while(*pwszInBuff!=EOL)
{
//If we have a seperator char, we need to quote both pieces
if(pwszSeperator && wcsncmp(pwszInBuff, pwszSeperator, cSepLen)==0)
{
// "dbo.authors -> "dbo"."authors
wcscat(pwszItr, pwszQuote);//Ending Quote
wcscat(pwszItr, pwszSeperator);//Seperator
wcscat(pwszItr, pwszQuote);//Beginning Quote
pwszItr += cQuoteLen + cSepLen + cQuoteLen;
}
else
{
*pwszItr = *pwszInBuff;//Actual Character
pwszItr++;
}

pwszInBuff++;
*pwszItr = EOL;
}

//Put on the Tail delimeter
if(pwszQuote)
wcscat(pwszItr, pwszQuote);

//Give back to the user
wcscpy(pwszOutBuff, pwsz);
return TRUE;
}


/////////////////////////////////////////////////////////////////////////////
// BOOL MakeAlphaNumeric
//
/////////////////////////////////////////////////////////////////////////////
BOOL MakeAlphaNumeric(
WCHAR* pwszBuffer,// buffer to translate
WCHAR wchReplace// New character for unallowed
)
{
ASSERT(pwszBuffer && wchReplace);

while(pwszBuffer[0])
{
// If the character is not a normal alpha numeric value
// replace it with an acceptable one
if(!iswalnum(pwszBuffer[0]))
pwszBuffer[0] = wchReplace;

pwszBuffer++;
}

return TRUE;
}


/////////////////////////////////////////////////////////////////////////////
// ULONG GetCreateParams
//
/////////////////////////////////////////////////////////////////////////////
ULONG GetCreateParams(WCHAR* pwszCreateParam)
{
ASSERT(pwszCreateParam);

ULONGulType = 0;

if(wcsstr(pwszCreateParam, L"precision") || wcsstr(pwszCreateParam, L"PRECISION"))
ulType |= CP_PRECISION;
if(wcsstr(pwszCreateParam, L"scale") || wcsstr(pwszCreateParam, L"SCALE"))
ulType |= CP_SCALE;
if(wcsstr(pwszCreateParam, L"length") || wcsstr(pwszCreateParam, L"LENGTH"))
ulType |= CP_LENGTH;
if(wcsstr(pwszCreateParam, L"max length") || wcsstr(pwszCreateParam, L"MAX LENGTH"))
ulType |= CP_LENGTH;

return ulType;
}


/////////////////////////////////////////////////////////////////////////////
// BOOL IsVariableType
//
/////////////////////////////////////////////////////////////////////////////
BOOL IsVariableType(DBTYPE wType)
{
//According to OLEDB Spec Appendix A (Variable-Length Data Types)
switch(wType)
{
case DBTYPE_STR:
case DBTYPE_WSTR:
case DBTYPE_BYTES:
return TRUE;
}
return FALSE;
}


/////////////////////////////////////////////////////////////////////////////
// BOOL IsFixedType
//
/////////////////////////////////////////////////////////////////////////////
BOOL IsFixedType(DBTYPE wType)
{
return !IsVariableType(wType);
}

/////////////////////////////////////////////////////////////////////////////
// BOOL IsNumericType
//
/////////////////////////////////////////////////////////////////////////////
BOOL IsNumericType(DBTYPE wType)
{
//According to OLEDB Spec Appendix A (Variable-Length Data Types)
switch(wType)
{
case DBTYPE_I1:
case DBTYPE_I2:
case DBTYPE_I4:
case DBTYPE_I8:
case DBTYPE_UI1:
case DBTYPE_UI2:
case DBTYPE_UI4:
case DBTYPE_UI8:
case DBTYPE_R4:
case DBTYPE_R8:
case DBTYPE_CY:
case DBTYPE_DECIMAL:
case DBTYPE_NUMERIC:
return TRUE;
}
return FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// WCHAR* GetDBTypeName
//
/////////////////////////////////////////////////////////////////////////////
WCHAR* GetDBTypeName(DBTYPE wType)
{
// Do a table look-up on the type
for(ULONG i=0; i<NUMELE(rgDBTypes); i++)
{
if(wType == rgDBTypes[i].wType)
return rgDBTypes[i].pwszTypeName;
}

ASSERT(!"Type not in rgSqlType list");
return NULL;
}


/////////////////////////////////////////////////////////////////////////////
// BOOL GetPromotedType
//
/////////////////////////////////////////////////////////////////////////////
BOOL GetPromotedType(DBTYPE* pwType)
{
ASSERT(pwType);

switch(*pwType)
{

// Integer family
case DBTYPE_BOOL:
*pwType = DBTYPE_I1;
break;

case DBTYPE_I1:
case DBTYPE_UI1:
*pwType = DBTYPE_I2;
break;

case DBTYPE_I2:
case DBTYPE_UI2:
*pwType = DBTYPE_I4;
break;

case DBTYPE_I4:
case DBTYPE_UI4:
case DBTYPE_CY:
*pwType = DBTYPE_I8;
break;

case DBTYPE_I8:
case DBTYPE_UI8:
*pwType = DBTYPE_NUMERIC;
break;


// Floating-point type family. FLOAT and DOUBLE actually
// have the same precision, so do a mutual promotion (that
// is, allow FLOAT to become DOUBLE and DOUBLE to become
// FLOAT) before going to CHAR.
//
case DBTYPE_R4:
*pwType = DBTYPE_R8;
break;

// Fixed-point exact numerics. Ordering of the two types
// is unimportant--for our purposes they have exactly the
// same semantics.
//
case DBTYPE_NUMERIC:
*pwType = DBTYPE_DECIMAL;
break;

case DBTYPE_DECIMAL:
*pwType = DBTYPE_R8;
break;


// Binary types
case DBTYPE_BYTES:
*pwType = DBTYPE_STR;
break;

// Date/Time family
case DBTYPE_DATE:
case DBTYPE_DBTIME:
case DBTYPE_DBDATE:
*pwType = DBTYPE_DBTIMESTAMP;
break;

case DBTYPE_R8:
case DBTYPE_DBTIMESTAMP:
*pwType = DBTYPE_BYTES;
break;

//we don't support any other types
default:
ASSERT(0);
return FALSE;
}

return TRUE;
}



///////////////////////////////////////////////////////////////
// BOOL FreeBindings
//
///////////////////////////////////////////////////////////////
BOOL FreeBindings(ULONG cBindings, DBBINDING* rgBindings)
{
//Need to walk the array and free any pObject structures
for(ULONG i=0; i<cBindings; i++)
SAFE_FREE(rgBindings[i].pObject);

//Now we can free the outer struct
SAFE_FREE(rgBindings);
return TRUE;
}


///////////////////////////////////////////////////////////////
// Static Strings Messages
//
///////////////////////////////////////////////////////////////

extern WCHAR wsz_ERROR[]= L"OLEDB TableCopy - Error";
extern WCHAR wsz_SUCCESS[]= L"OLEDB TableCopy - Success";
extern WCHAR wsz_WARNING[]= L"OLEDB TableCopy - Warning";
extern WCHAR wsz_CANCEL[]= L"OLEDB TableCopy - Cancel";
extern WCHAR wsz_ERRORINFO[]= L"OLEDB TableCopy - IErrorInfo";

//Copying Status
extern WCHAR wsz_COPYING[] = L"Copying records";
extern WCHAR wsz_COPIED_RECORDS[]= L"%lu records copied";
extern WCHAR wsz_COPY_SUCCESS[]= L"Copy succeeded, %lu records copied!";
extern WCHAR wsz_COPY_FAILURE[]= L"Copy failed!";
extern WCHAR wsz_CANCEL_OP[]= L"Do you want to cancel?";

//Tables
extern WCHAR wsz_CREATE_TABLE[]= L"CREATE TABLE ";
extern WCHAR wsz_DROP_TABLE_[]= L"DROP TABLE %s ";
extern WCHAR wsz_ASK_DROP_TABLE_[] = L"Table %s already exists. Would you like to drop it?";
extern WCHAR wsz_SAME_TABLE_NAME[] = L"Target table name must be different on the same DataSource";

//Indexes
extern WCHAR wsz_CREATE_INDEX_[]= L"CREATE%sINDEX ";
extern WCHAR wsz_UNIQUE_INDEX[]= L" UNIQUE ";
extern WCHAR wsz_INDEX_DESC[] = L" DESC ";
extern WCHAR wsz_INDEX_FAILED_[]= L"INDEX %s failed to be created. Would you like to Continue?";

//Columns
extern WCHAR wsz_TYPE_FORMAT_[]= L"%-20s \t%-20s \t[%s]";
extern WCHAR wsz_COLUMN_FORMAT_[]= L"%-20s \t[%s]";
extern WCHAR wsz_NO_TYPE_MATCH_[]= L"Target Data type not found for %s type";
extern WCHAR wsz_NO_TYPE_FOUND_[]= L"Source Data type not found for %s type";

extern WCHAR wsz_CONNECT_STRING_[]= L"DSN=%s, UID=%s, PWD=%s, (%s %s)";
extern WCHAR wsz_NOT_CONNECTED[]= L"Press Connect to establish a connection";
extern WCHAR wsz_FROM_TABLE_DSN_[]= L"From: %s in %s";
extern WCHAR wsz_TO_TABLE_DSN_[]= L"To: %s in %s";

extern WCHAR wsz_PROVIDER_STRING_[]= L"%s %s %s";
extern WCHAR wsz_NO_PROVIDER[]= L"";

extern WCHAR wsz_INVALID_VALUE_[]= L"Invalid Value '%s' specified. Please specify a value >= %lu and <= %lu.";
extern WCHAR wsz_READONLY_DATASOURCE_[]= L"Datasource %s is read only and not valid as a target.";

//Query
extern WCHAR wsz_SHOW_SQL_TITLE[]= L"OLEDB TableCopy - ICommand::Execute Query";
extern WCHAR wsz_SHOW_SQL_[]= L"DSN = %s\n\nSQL = %s";
extern WCHAR wsz_SELECT[]= L" SELECT ";
extern WCHAR wsz_FROM[]= L" FROM ";
extern WCHAR wsz_BOGUS_WHERE[]= L" WHERE 0 = 1";
extern WCHAR wsz_INSERT_INTO[]= L"INSERT INTO ";
extern WCHAR wsz_VALUES_CLAUSE[]= L" ) VALUES ( ";
extern WCHAR wsz_PARAM[]= L"?";
extern WCHAR wsz_PRIMARY_KEY[]= L" PRIMARY KEY";

//General String Values
extern WCHAR wsz_COMMA[]= L", ";
extern WCHAR wsz_LPAREN[]= L" ( ";
extern WCHAR wsz_RPAREN[]= L" ) ";
extern WCHAR wsz_SPACE[]= L" ";