/* $Header: svn://52.7.125.35/trunk/Dams/damgenrc/Indy/dgenobj.cpp 15714 2016-10-26 14:30:33Z gashford $ */
/*
	OMNIS Studio - Generic DAM session object
	Copyright (C) TigerLogic Corporataion 2010

FILENAME:	dgenobj.cpp

DESCRIPTION:	Implements the Generic DAM session functionality

DETAILS:	
	
*/
/* Changes
Date				Edit		Fault				Description
*/		

#include <extcomp.he> 
#include "dgenobj.hi"
#include "dgensta.hi"
#include "dgenworker.hi" //Worker support


//Objects provided by this component
ECOobject GenObjects[] = 
{
	cObject_GenericSess, 2000, 0, 0,
	cObject_GenericStat, 2001, 0, 0,
	cObject_StatementWorker, 2002, EXTD_OBJFLAG_WORKER, cRESWorkerGroup //Worker object support
};

//Parameters for any custom methods
ECOparam GenSessParamMethod2[] = 
{
	5000, fftCharacter, 0, 0,
	5001,	fftInteger, 0, 0
};

//Worker support
ECOproperty	StatementWorkerProps[] =
{
	WORKER_PROPS
};

ECOmethodEvent StatementWorkerFuncs[] =
{
	WORKER_FUNCS
};

//Session object properties
ECOproperty	sessionProps[] =
{
	DAM_OBJ_PROPS,
	cGenSessionPropName1,		cGenSessionPropName1,			fftCharacter,			0, 0, 0, 0,
	cGenSessionPropName2,		cGenSessionPropName2,			fftBoolean,				0, 0, 0, 0,
	cGenSessionPropName3,		cGenSessionPropName3,			fftInteger,			EXTD_FLAG_EDITRONLY, 0, 0, 0
};

//Session object methods
ECOmethodEvent sessionFuncs[] = 
{
	DAM_OBJ_FUNCS,
	cGenSessionMethod1,	cGenSessionMethod1, fftBoolean, 0, 0, 0, 0,
	cGenSessionMethod2,	cGenSessionMethod2, fftBoolean, 2, GenSessParamMethod2, 0, 0
};

//	##################################################################
//	PURPOSE:	Main entry point for Generic DAM objects
//	RETURN:		Status - qtrue/qfalse
//	DETAIL:	
extern "C" LRESULT OMNISWNDPROC GenericObjProc(HWND hwnd, UINT Msg,WPARAM wParam,LPARAM lParam,EXTCompInfo* eci)
{
	 // Initialize callback tables - THIS MUST BE DONE 
	ECOsetupCallbacks(hwnd, eci);		
	switch (Msg)
	{
		case ECM_GETCONSTNAME:  
		{
			return ECOreturnConstants( gInstLib, eci, cResConstStart, cResConstEnd );
		}
		case ECM_OBJCONSTRUCT:	//This is a message informing you to create a new object			
		{
			if ( eci->mCompId==cObject_GenericSess )
			{
				tqfDAMObjCont* object = (tqfDAMObjCont*)ECOfindNVObject( eci->mOmnisInstance, lParam );
				if ( !object )
				{
					tqfGenericDAMObj* damObj = new tqfGenericDAMObj(eci);
					tqfDAMObjCont* obj = new tqfDAMObjCont((qobjinst)lParam, damObj);
					ECOinsertNVObject( eci->mOmnisInstance, lParam, (void*)obj );
					return qtrue;
				}
			}
			else if ( eci->mCompId==cObject_GenericStat )
			{
				tqfDAMStatementCont* object = (tqfDAMStatementCont*)ECOfindNVObject( eci->mOmnisInstance, lParam );
				if ( !object )
				{
					tqfDAMStatementCont* obj = new tqfDAMStatementCont((qobjinst)lParam);
					ECOinsertNVObject( eci->mOmnisInstance, lParam, (void*)obj );
					return qtrue;
				}
			}
			else if (eci->mCompId == cObject_StatementWorker) //Worker support
			{
				StatementWorkerCont* object = (StatementWorkerCont*)ECOfindNVObject(eci->mOmnisInstance, lParam);
				if (!object)
				{
					genericWorker* worker = new genericWorker((qobjinst)lParam, eci);
					StatementWorkerCont* obj = new StatementWorkerCont((qobjinst)lParam, worker);
					ECOinsertNVObject(eci->mOmnisInstance, lParam, (void*)obj);
					return qtrue;
				}
			}
			return qfalse;
		}     
		case ECM_OBJDESTRUCT:	//This is a message informing you to delete the object				
		{
			if ( wParam==ECM_WPARAM_OBJINFO )
			{	
				void* object = ECOremoveNVObject( eci->mOmnisInstance, lParam );
				// Object found now figure out which object type it is
				if ( eci->mCompId==cObject_GenericSess )
				{
					tqfDAMObjCont* GenObj = (tqfDAMObjCont*)object;
					delete GenObj;
				}
				else if ( eci->mCompId==cObject_GenericStat)
				{
					tqfDAMStatementCont* PgSqlStat = (tqfDAMStatementCont*)object;
					delete PgSqlStat;
				}
				else if (eci->mCompId == cObject_StatementWorker) //Worker support
				{
					StatementWorkerCont* worker = (StatementWorkerCont*)object;
					delete worker;
				}
			}	
			return qtrue;
		}
		case ECM_CONNECT:
		{
			return ECOmakeConnectFlags(EXT_FLAG_LOADED|EXT_FLAG_ALWAYS_USABLE|EXT_FLAG_REMAINLOADED|EXT_FLAG_NVOBJECTS|EXT_FLAG_SESSION|EXT_FLAG_DAM); // rmm11466
		}
		case ECM_DISCONNECT:
		{
			return qtrue;
		}
		case ECM_GETPROPNAME:
		{
			if ( eci->mCompId==cObject_GenericSess )
				return ECOreturnProperties( gInstLib, eci, &sessionProps[0], tqfGenericDAMObj::propCount() );
			else if ( eci->mCompId==cObject_GenericStat )
				return ECOreturnProperties( gInstLib, eci, &statementProps[0], tqfGenericStatementObj::propCount() );
			else if (eci->mCompId == cObject_StatementWorker) //Worker support
				return ECOreturnProperties(gInstLib, eci, &StatementWorkerProps[0], StatementWorker::propCount()); 
		}
		case ECM_GETOBJECT:
		{
			return ECOreturnObjects(gInstLib,eci, &GenObjects[0], sizeof(GenObjects)/sizeof(GenObjects[0])); 
		}
		case ECM_GETMETHODNAME:
		{
			if ( eci->mCompId==cObject_GenericSess )
				return ECOreturnMethods( gInstLib, eci, &sessionFuncs[0], tqfGenericDAMObj::methodCount() );
			else if ( eci->mCompId==cObject_GenericStat )
				return ECOreturnMethods( gInstLib, eci, &statementFuncs[0], tqfGenericStatementObj::methodCount() );
			else if (eci->mCompId == cObject_StatementWorker) //Worker support
				return ECOreturnMethods(gInstLib, eci, &StatementWorkerFuncs[0], StatementWorker::methodCount());
			break;	
		}
		case ECM_PROPERTYCANASSIGN:  	/* Object: Is the property assignable (ie readonly?) */
		case ECM_SETPROPERTY: 				/* Object: Assignment to a property */
		case ECM_GETPROPERTY:					/* Object: Retrieve value from property */
		{
			void* object = (void*)ECOfindNVObject( eci->mOmnisInstance, lParam );
			if ( object )
			{ // Object found now figure out which object type it is
				if ( eci->mCompId==cObject_GenericSess )
				{
					tqfDAMObjCont* GenSess = (tqfDAMObjCont*)object;
					if ( GenSess->mObject )
						return GenSess->mObject->propertySupport( Msg, wParam, lParam, eci );
				}
				else if ( eci->mCompId==cObject_GenericStat )
				{
					tqfDAMStatementContPtr PgSqlStat = (tqfDAMStatementContPtr)object;
					if ( PgSqlStat->mObject )
						return PgSqlStat->mObject->propertySupport( Msg, wParam, lParam, eci );
				}
				else if (eci->mCompId == cObject_StatementWorker) //Worker support
				{
					StatementWorkerCont* worker = (StatementWorkerCont*)object;
					if (worker->mObject)
						return worker->mObject->propertySupport(Msg, wParam, lParam, eci);
				}
			}
			return 0L;
		}
		case ECM_METHODCALL:
		{
			void* object = (void*)ECOfindNVObject( eci->mOmnisInstance, lParam );
			if ( object )
			{ // Object found now figure out which object type it is
				if ( eci->mCompId==cObject_GenericSess )
				{
					tqfDAMObjCont* GenObj = (tqfDAMObjCont*)object;
					if ( GenObj->mObject )
						return GenObj->mObject->methodCall(eci);
				}
				else if ( eci->mCompId==cObject_GenericStat )
				{
					tqfDAMStatementCont* PgSqlStat = (tqfDAMStatementCont*)object;
					if ( PgSqlStat->mObject )
						return PgSqlStat->mObject->methodCall(eci);
				}	
				else if (eci->mCompId == cObject_StatementWorker) //Worker support
				{
					StatementWorkerCont* SqlStmtworker = (StatementWorkerCont*)object;
					if (SqlStmtworker->mObject)
						return SqlStmtworker->mObject->methodCall(eci);
				}
			}
			return qfalse;
		}                                                                 
	}

	// As a final result this must ALWAYS be called. It handles all other messages 
	// that this DAM component decides to ignore.
	return DAMdefWindowProc(hwnd,Msg,wParam,lParam,eci); 
}

//	##################################################################
//	PURPOSE:	Session constructor
//	RETURN:		None
//	DETAIL:		
tqfGenericDAMObj::tqfGenericDAMObj(EXTCompInfo *pEci):tqfDAMbaseObj(pEci) 
{	
	//Place a default string in mClientVersion- in lieu of an API call
	RESloadString(gInstLib, cResDefApiVersion, mClientVersion);

	mAllowsTransactions = qtrue; //=>DAM allows manual transaction mode
	mErrorInfo.setConnectionHandle(this); //Initialise error object

	//Initialise session object properties
	mProperty2 = qfalse;
	mProperty3 = 1234;
}

//	##################################################################
//	PURPOSE:	Session destructor
//	RETURN:		None
//	DETAIL:		Free environment and type table
tqfGenericDAMObj::~tqfGenericDAMObj()
{
	logoff();			// must call this to clear up statements
}

//	##################################################################
//	PURPOSE:	Return the implemetation's statement object id
//	RETURN:		Statement object id
//	DETAIL:		Required by DAM base class
qlong tqfGenericDAMObj::dGetStatementId()
{
	return cObject_GenericStat;
}

//	##################################################################
//	PURPOSE:	Logon session
//	RETURN:		Status - qtrue/qfalse
//	DETAIL:		Allocate connection handle. 
//						If logon successful then load server types
qbool tqfGenericDAMObj::dLogon(str255& pHostname, str255& pUsername, str255& pPassword)
{
	qbool rtnStatus = qtrue; 
	debugMsg(3,"Logging on to %s\n",pHostname.cString());

	if (rtnStatus == qtrue)
	{
		unicodeText uServerVersion((void *)"Database version 1.0 build 1000"); //Default database version
		mServerVersion = str255(uServerVersion.dataPtr()); 
	}
	return rtnStatus;
}

//	##################################################################
//	PURPOSE:	Logoff session
//	RETURN:		Status - qtrue/qfalse
//	DETAIL:		Disconnect and free connection handle
qbool tqfGenericDAMObj::dLogoff()
{
	debugMsg(3,"Logging off\n"); 
	qbool rtnStatus = qtrue;

	return rtnStatus;
}

//	##################################################################
//	PURPOSE:	Get count of methods provided by the session object
//	RETURN:		Method count
//	DETAIL:		
qshort tqfGenericDAMObj::methodCount()
{
	return sizeof(sessionFuncs)/sizeof(sessionFuncs[0]); 
}

//	##################################################################
//	PURPOSE:	Get count of properties provided by the session object
//	RETURN:		Property count
//	DETAIL:		
qshort tqfGenericDAMObj::propCount()
{
	return sizeof(sessionProps)/sizeof(sessionProps[0]);
}

//	##################################################################
//	PURPOSE:	Create a new statement object
//	RETURN:		Statement object ptr
//	DETAIL:		
tqfDAMStatementObjPtr tqfGenericDAMObj::dNewStatement()
{
	tqfDAMStatementObjPtr newObject = NULL;
	newObject = new tqfGenericStatementObj();
	return newObject;
}

//	##################################################################
//	PURPOSE:	Return the DAM's Type Table
//	RETURN:		DAM Type Table
//	DETAIL:		Required by the base class
DAMTypeTablePtr tqfGenericDAMObj::dGetTypeTable()
{
	return (DAMTypeTablePtr)&mTypeTable;
}

//	##################################################################
//	PURPOSE:	Set transaction mode
//	RETURN:		Status = qtrue/qfalse					
//	DETAIL:		
qbool tqfGenericDAMObj::dSetTranMode(eTranMode pTranMode)
{	
	debugMsg(3,"Setting transaction mode to %x\n",(qlong)pTranMode); 
	qbool rtnStatus = qtrue;

	if (rtnStatus == qtrue)
		mTransactionMode = pTranMode;
	
	return rtnStatus;
}

//	##################################################################
//	PURPOSE:	Return the  DAM's cursor commit behaviour
//	RETURN:		commitMode				
//	DETAIL:		
eCommitMode tqfGenericDAMObj::dGetCommitMode()
{
	eCommitMode commitMode = kCommitPreserve;
	return commitMode;
}

//	##################################################################
//	PURPOSE:	Return the DAM's cursor rollback behaviour
//	RETURN:		rollbackMode
//	DETAIL:	
eRollbackMode tqfGenericDAMObj::dGetRollbackMode()
{
	eRollbackMode rollbackMode = kRollbackPreserve;
	return rollbackMode;
}

//	##################################################################
//	PURPOSE:	Determine whether commit automatically starts a	transaction. 
//	RETURN:		Status = qtrue/qfalse					
//	DETAIL:		Return false here to enable $begin()in manual transaction mode.
//						Otherwise, server begins transactions automatically
qbool tqfGenericDAMObj::dUsesAutoBegin()
{
	return qfalse;
}

//	##################################################################
//	PURPOSE:	Issue a commit
//	RETURN:		Status = qtrue/qfalse					
//	DETAIL:		Doesn't do anything unless in kTranManual
qbool	tqfGenericDAMObj::dCommit()
{
	if (mTransactionMode == kTranManual)
	{
		//Implement a transaction commit here
	}
	return qtrue;
}

//	##################################################################
//	PURPOSE:	Issue a rollback
//	RETURN:		Status = qtrue/qfalse				
//	DETAIL:		No effect unless in kTranManual
qbool tqfGenericDAMObj::dRollback()
{
	if (mTransactionMode == kTranManual)
	{
		//Implement a transaction rollback here
	}
	return qtrue;
}

//	##################################################################
//	PURPOSE:	Assign the DAM's bind variable bind marker
//	RETURN:		Status = qtrue/qfalse					
//	DETAIL:		Called during $logon()
qbool tqfGenericDAMObj::dSetBindMarker()
{
	RESloadString(gInstLib, cResBindMarker, mStatementBindMarker);
	return qtrue;
}

//	##################################################################
//	PURPOSE:	Clear the currently cached error
//	RETURN:		Status = qtrue/qfalse					
//	DETAIL:
void tqfGenericDAMObj::dClearNativeError()
{
	mErrorInfo.clearError();
}

//	##################################################################
//	PURPOSE:	Obtain an error message and error code from the database
//	RETURN:		Status = qtrue/qfalse					
//	DETAIL:		setError() queries the database using its connection handle
eErrorState tqfGenericDAMObj::dGetNativeError(qlong &errorCode, EXTfldval &pErrorText)
{
	eErrorState errorState = kErrorOk;
	if(mErrorInfo.getErrorPending() == qtrue)	// get cached error
	{	
		errorCode = mErrorInfo.getErrorCode();
		mErrorInfo.getErrorText(pErrorText);
		errorState = mErrorInfo.setError();			// next error ?
	}
	else																			// set up error
	{
		errorState = mErrorInfo.setError();
		errorCode = mErrorInfo.getErrorCode();
		mErrorInfo.getErrorText(pErrorText);
		if(errorState == kErrorPending)
			errorState = mErrorInfo.setError();		// set up next error
	}
	return errorState;
}

//	##################################################################
//	PURPOSE:	Determine whether direct execution is supported
//	RETURN:		Status = qtrue/qfalse						
//	DETAIL:	  Set to qfalse to force a separate prepare() and execute()
qbool tqfGenericDAMObj::dAllowsDirectExec()
{
	return qtrue;
}

//	##################################################################
//	PURPOSE:	Manage implementation-specific method calls
//	RETURN:		Status = qtrue/qfalse
//
qbool	tqfGenericDAMObj::dMethodCall(EXTCompInfo* pEci, EXTfldval &rtnVal, qbool &hasRtnVal)
{
	qlong funcId = ECOgetId(pEci);
	qbool rtnStatus = qtrue, funcStatus = qfalse;
	hasRtnVal = qfalse; 

	debugMsg(3,"MethodCall with funcId %x\n",funcId);
	
	switch (funcId)
	{
		case cGenSessionMethod1: 
		{
			funcStatus = doMethod1(pEci); //call method implementation here
			break;
		}
		case cGenSessionMethod2:
		{
			funcStatus = doMethod2(pEci); //call method implementation here
			break;
		}
		default:
		{ //An invalid method id was passed
			rtnStatus = qfalse;
		}
	}
	
	hasRtnVal = qtrue;
	rtnVal.setLong(funcStatus);
	return rtnStatus;
}	

//	##################################################################
//	PURPOSE:	Property support for derived session object
//	RETURN:		Status = qtrue/qfalse
//	DETAIL:	  Allows the implementation to specify which of its properties are assignable
qbool	tqfGenericDAMObj::dPropertyCanAssign(WPARAM wParam, LPARAM lParam, EXTCompInfo* pEci)
{
	qbool rtnStatus = qfalse;
	switch(ECOgetId(pEci))
	{			
		case cGenSessionPropName1:		
		case cGenSessionPropName2:	
		{
			rtnStatus = qtrue;
			break;
		}
		default:			
			break;
	}
	return rtnStatus;
}

//	##################################################################
//	PURPOSE:	Property support for derived session object
//	RETURN:		Status = qtrue/qfalse
//	DETAIL:	  Called when Omnis wishes to set one of the derived session object's properties
qbool	tqfGenericDAMObj::dSetProperty(WPARAM wParam, LPARAM lParam, EXTCompInfo* pEci)
{
	qbool rtnStatus = qfalse;
	mErrorInfo.clearError();													
	// get the externals parameter
	EXTParamInfo* param = ECOfindParamNum( pEci, 1 );
	
	if ( param )
	{                             
		// get the fldval from the parameter.
		EXTfldval fval( (qfldval)param->mData );
		switch(ECOgetId(pEci))
		{
			case cGenSessionPropName1:
			{
				rtnStatus = qtrue;
				mProperty1 = fval.getChar();	
				break;
			}
			case cGenSessionPropName2:
			{
				rtnStatus = qtrue;
				mProperty2 = (fval.getBool() == preBoolTrue)? qtrue : qfalse;	
				break;
			}	
			default:
			{
				rtnStatus = qfalse;
			}	
		}
	}
	return rtnStatus;
}

//	##################################################################
//	PURPOSE:	Property support for derived session object
//	RETURN:		Status = qtrue/qfalse
//	DETAIL:	  Called when Omnis requires the value of a derived session object property
qbool	tqfGenericDAMObj::dGetProperty(WPARAM wParam, LPARAM lParam, EXTCompInfo* pEci, EXTfldval &pPropVal)
{
	qbool rtnStatus = qtrue;
	switch(ECOgetId(pEci))
	{
		case cGenSessionPropName1:
		{
			pPropVal.setChar(mProperty1);
			break;
		}
		case cGenSessionPropName2:	
		{
			pPropVal.setBool(mProperty2? preBoolTrue : preBoolFalse);
			break;
		}
		case cGenSessionPropName3:
		{
			pPropVal.setLong(mProperty3);
			break;
		}
		default:
		{
			rtnStatus = qfalse; 
			break;
		}
	}
	return rtnStatus;
}

//	##################################################################
//	PURPOSE:	Return the version (string) of the connected database
//	RETURN:		Status = qtrue/qfalse					
//	DETAIL:
qbool	tqfGenericDAMObj::dGetVersion(str255 &pVersion)
{
	pVersion = mServerVersion;
	return qtrue;
}

//	##################################################################
//	PURPOSE:	Return the client API version (Client libraries built against)
//	RETURN:		Status = qtrue/qfalse						
//	DETAIL:
qbool	tqfGenericDAMObj::dGetApiVersion(str255 &pApiVersion)
{
	pApiVersion = mClientVersion;
	return qtrue;
}

//	##################################################################
//	PURPOSE:	Implementation's error class constructor
//	RETURN:							
//	DETAIL:	  
GenericErrorInfo::GenericErrorInfo()
{
	mConnection = NULL;
	clearError();
}

//	##################################################################
//	PURPOSE:	Implementation's error class destructor
//	RETURN:								
//	DETAIL:	  
GenericErrorInfo::~GenericErrorInfo()
{
}

//	##################################################################
//	PURPOSE:	Set error class's connection handle
//	RETURN:							
//	DETAIL:	  
void GenericErrorInfo::setConnectionHandle(void *pHandle)
{
	mConnection = pHandle;
}

//	##################################################################
//	PURPOSE:	Clear error
//	RETURN:					
//	DETAIL:	  
void GenericErrorInfo::clearError()
{
	mErrorCode = 0;
	mErrorPending = qfalse;					
	mErrorText.setEmpty(fftCharacter, dpFcharacter);
}

//	##################################################################
//	PURPOSE:	Query for an error and store if available
//	RETURN:		Error state						
//	DETAIL:	  Optional pErrorText overrides error checking, if supplied
eErrorState GenericErrorInfo::setError(str255 *pErrorText)
{
	eErrorState errorState = kErrorOk;
	str255 errorText;
	RESloadString(gInstLib, cResDefNativeError, errorText);

	mErrorCode = 0;
	if (pErrorText != NULL)
	{	//an error message was supplied
		mErrorCode = -1;
		mErrorText.setChar(*pErrorText);
	}
	else 
	{	//query the client to get the error message
		if (mConnection != NULL) 
		{	
			//-Implementation obtains the error message and error code here-
			mErrorCode = -1; //Just use the default error message for now
			mErrorText.setChar(errorText);
		}
	}

	if (mErrorCode != 0)
	{
		mErrorPending = qtrue;
		errorState = kErrorPending;
	}

	return errorState;
}

//	##################################################################
//	PURPOSE:	Return the cached native error code
//	RETURN:		Status = qtrue/qfalse				
//	DETAIL:		This retrieves the next error if available
qlong	GenericErrorInfo::getErrorCode()
{
	return mErrorCode;
}

//	##################################################################
//	PURPOSE:	Return the cached native error text
//	RETURN:		Status = qtrue/qfalse				
//	DETAIL:		Retrieves the next error message
void	GenericErrorInfo::getErrorText(EXTfldval &pErrorText)
{
	pErrorText = mErrorText;
}

//	##################################################################
//	PURPOSE:	Return error-pending status of the object
//	RETURN:		Status = qtrue/qfalse				
//	DETAIL:		Returns qtrue if the an error has been cached
qbool	GenericErrorInfo::getErrorPending()
{
	return mErrorPending;
}

//	##################################################################
//	PURPOSE:	Set up implementation-specific type mappings
//	RETURN:		None
//	DETAIL:
GenericDAMTypeTable::GenericDAMTypeTable()
{
}

//	##################################################################
//	PURPOSE:	Clear implementation-specific type settings
//	RETURN:		None
//	DETAIL:
GenericDAMTypeTable::~GenericDAMTypeTable()
{
}

//	##################################################################
//	PURPOSE:	Convert server's data type to Omnis data type
//	RETURN:		Status - qtrue/qfalse
//	DETAIL:		This procedure derives the Omnis type,sub-type,column size and C-type 
//						from the supplied database type information
void tqfGenericDAMObj::mapImplToOmnis(int colType, int precision, int scale, int &pColSize, ffttype &bufferType, qshort &bufferSubType, eCType &omCType)
{																				 
	switch (colType)
	{
		case 1: //e.g. VARCHAR
		{
			bufferType = fftCharacter;
			bufferSubType = dpFcharacter;
			pColSize = precision;
			omCType = omChar;
			break;
		}

		default:
		{
			bufferType = fftBinary;
			bufferSubType = 0;
			omCType = omBinary;
			break;
		}
	}
}

//	##################################################################
//	PURPOSE:	Convert an Omnis datatype to the server's datatype
//	RETURN:		pDataType Type (for dColtext)
//	DETAIL:	
qbool tqfGenericDAMObj::mapOmnisToImpl(ffttype pfftType, qshort pSubType, qlong pLength, str255 &pDataType, int &pColType)
{
	str255 lengthStr; qlongToString(pLength, lengthStr);
	lengthStr.insert('(',1); lengthStr.concat((qchar)')');

	switch (pfftType)
	{
		case fftCharacter:
		{
			break;
		}
		case fftInteger:
		{
			break;
		}
		case fftDate:
		{
			break;
		}
		case fftNumber:
		{
			break;
		}
		case fftBoolean:
		{
			break;
		}
		case fftSequence:
		{
			break;
		}
		default:
		{
			pDataType = str255(QTEXT("bytea"));
			pColType = 0;
			break;
		}
	}

	pDataType.upps();
	return qtrue;
}

//	##################################################################
//	PURPOSE:	Return a SQL text desription for a table column based
//						on a description of the Omnis variable
//	RETURN:		SQL text
//	DETAIL:		
qbool tqfGenericDAMObj::dColtext(ffttype pfftType, qshort pSubType, qlong pLength, str255 &pRtnString)
{
	int colType; //not used
	mapOmnisToImpl(pfftType, pSubType, pLength, pRtnString, colType);
	
	return qtrue;
}

//	##################################################################
//	PURPOSE:	Standard call for any code necessary to start a transaction.
//						
//	RETURN:		Status = qtrue/qfalse
//						
//	DETAIL:		Only called when transaction mode is kTranManual or kTranAutomatic
qbool tqfGenericDAMObj::dBegin()
{
	if (mTransactionMode == kTranManual)
	{
			debugMsg(3,"Begin transaction\n"); 
	}

	return qtrue;
}

//	##################################################################
//	PURPOSE:	Default implementation for $method1()
//	DETAIL:
qbool tqfGenericDAMObj::doMethod1(EXTCompInfo* pEci)
{
	qbool rtnStatus = qfalse;
	eDAMError damError = kDAMNoError;

	do { //Default implementation
		rtnStatus = qtrue;
	} while (0);

	if (damError != kDAMNoError)
		setError(damError);

	return rtnStatus;
}

//	##################################################################
//	PURPOSE:	Default implementation for $method2()
//	DETAIL:
qbool tqfGenericDAMObj::doMethod2(EXTCompInfo* pEci)
{
	qbool rtnStatus = qfalse;
	ffttype paramType; qshort subType;
	eDAMError damError = kDAMNoError;

	do { //Default implementation- just check the parameter types and exit
		EXTParamInfo* param = ECOfindParamNum( pEci, 1 );
		if (param == NULL) {damError = kDAMParameterNumError; break; }
		
		EXTfldval fvalParam1( (qfldval)param->mData );
		fvalParam1.getType(paramType, &subType);	
		if (paramType != fftCharacter) { damError = kDAMParameterTypeError; break; }
	
		param = ECOfindParamNum( pEci, 2 );
		if (param == NULL) {damError = kDAMParameterNumError; break; }
		
		EXTfldval fvalParam2( (qfldval)param->mData );
		fvalParam2.getType(paramType, &subType);	
		if (paramType != fftInteger) { damError = kDAMParameterTypeError; break; }

		rtnStatus = qtrue;
	} while (0);

	if (damError != kDAMNoError)
		setError(damError);

	return rtnStatus;
}

//	##################################################################
//	PURPOSE:	Allows implementation to take action when unicode mode switches
//	DETAIL:		
void tqfGenericDAMObj::dUnicodeChanged()
{
	
}

//	############################# Worker #############################
//	PURPOSE:	Get count of properties for SQLite Worker object
//	DETAIL:		gra0846
qshort StatementWorker::propCount()
{
	return sizeof(StatementWorkerProps) / sizeof(StatementWorkerProps[0]);
}

//	############################# Worker #############################
//	PURPOSE:	Get count of methods for SQLite Worker object
//	DETAIL:		gra0846
qshort StatementWorker::methodCount()
{
	return sizeof(StatementWorkerFuncs) / sizeof(StatementWorkerFuncs[0]);
}

/* EOF */




