⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbcore.cpp

📁 c语言编程软件vc6.0中文绿色版_vc6.0官方下载
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			// First addnew call, cache record values
			StoreFields();
		}
		else
		{
			// subsequent Edit/AddNew call.  Restore values, save them again
			LoadFields();
			StoreFields();
		}
	}

	SetFieldNull(NULL);
	SetFieldDirty(NULL, FALSE);

	m_nEditMode = addnew;
}

void CRecordset::Edit()
{
	ASSERT_VALID(this);
	ASSERT(m_hstmt != SQL_NULL_HSTMT);
	// we can't construct an UPDATE statement w/o any columns
	ASSERT(m_nFields != 0);

	if (!m_bUpdatable)
		ThrowDBException(AFX_SQL_ERROR_RECORDSET_READONLY);

	if (m_dwOptions & useMultiRowFetch)
	{
		// Can't use update methods on multi-row rowset
		ASSERT(FALSE);
		return;
	}

	if (m_bEOF || m_bBOF || m_bDeleted)
	{
		TRACE0("Error: Edit attempt failed - not on a record.\n");
		ThrowDBException(AFX_SQL_ERROR_NO_CURRENT_RECORD);
	}

	if ((m_nOpenType == dynaset || m_nOpenType == dynamic) &&
		m_nLockMode == pessimistic)
	{
		RETCODE nRetCode;
		AFX_ODBC_CALL(::SQLSetPos(m_hstmt, 1, SQL_POSITION,
			SQL_LCK_EXCLUSIVE));
		if (!Check(nRetCode))
		{
			TRACE0("Error: attempt to lock record failed during Edit function.\n");
			ThrowDBException(nRetCode);
		}
	}

	if (m_bCheckCacheForDirtyFields && m_nFields > 0)
	{
		if (m_nEditMode == noMode)
			// First edit call, cache record values
			StoreFields();
		else
		{
			// subsequent Edit/AddNew call.  Restore values, save them again
			LoadFields();
			StoreFields();
		}
	}

	m_nEditMode = edit;
}

BOOL CRecordset::Update()
{
	ASSERT_VALID(this);
	ASSERT(m_hstmt != SQL_NULL_HSTMT);

	if (m_dwOptions & useMultiRowFetch)
	{
		// Can't use update methods on multi-row rowset
		ASSERT(FALSE);
		return FALSE;
	}

	if (m_nEditMode != addnew && m_nEditMode != edit)
	{
		TRACE0("Error: must enter Edit or AddNew mode before updating.\n");
		ThrowDBException(AFX_SQL_ERROR_ILLEGAL_MODE);
	}
	return UpdateInsertDelete();
}

void CRecordset::Delete()
{
	ASSERT_VALID(this);
	ASSERT(m_hstmt != SQL_NULL_HSTMT);

	if (m_dwOptions & useMultiRowFetch)
	{
		// Can't use update methods on multi-row rowset
		ASSERT(FALSE);
		return;
	}

	if (m_nEditMode != noMode)
	{
		TRACE0("Error: attempted to delete while still in Edit or AddNew mode.\n");
		ThrowDBException(AFX_SQL_ERROR_ILLEGAL_MODE);
	}
	UpdateInsertDelete();   // This call can't fail in delete mode (noMode)
}

void CRecordset::CancelUpdate()
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());

	if (m_nEditMode == noMode)
		// Do nothing if not in edit mode
		return;
	else
		// Reset the edit mode
		m_nEditMode = noMode;

	// Restore cache if necessary
	if (m_bCheckCacheForDirtyFields && m_nFields > 0)
		LoadFields();
}

BOOL CRecordset::FlushResultSet() const
{
	RETCODE nRetCode;
	AFX_ODBC_CALL(::SQLMoreResults(m_hstmt));

	if (!Check(nRetCode))
	{
		TRACE0("Error: attempt FlushResultSet failed.\n");
		AfxThrowDBException(nRetCode, m_pDatabase, m_hstmt);
	}

	// Reset state of cursor
	((CRecordset*)this)->ResetCursor();

	return nRetCode != SQL_NO_DATA_FOUND;
}

void CRecordset::GetODBCFieldInfo(LPCTSTR lpszName,
	CODBCFieldInfo& fieldinfo)
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());
	ASSERT(lpszName != NULL);

	// No data or no column info fetched yet
	if (GetODBCFieldCount() <= 0)
	{
		ASSERT(FALSE);
		return;
	}

	// Get the index of the field corresponding to name
	short nField = GetFieldIndexByName(lpszName);

	GetODBCFieldInfo(nField, fieldinfo);
}

void CRecordset::GetODBCFieldInfo(short nIndex,
	CODBCFieldInfo& fieldinfo)
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());

	// No data or no column info fetched yet
	if (GetODBCFieldCount() <= 0)
	{
		ASSERT(FALSE);
		return;
	}

	// Just copy the data into the field info
	CODBCFieldInfo* pInfo = &m_rgODBCFieldInfos[nIndex];
	fieldinfo.m_strName = pInfo->m_strName;
	fieldinfo.m_nSQLType = pInfo->m_nSQLType;
	fieldinfo.m_nPrecision = pInfo->m_nPrecision;
	fieldinfo.m_nScale = pInfo->m_nScale;
	fieldinfo.m_nNullability = pInfo->m_nNullability;
}

void CRecordset::GetFieldValue(LPCTSTR lpszName,
	CDBVariant& varValue, short nFieldType)
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());
	ASSERT(lpszName != NULL);

	// No data or no column info fetched yet
	if (GetODBCFieldCount() <= 0)
	{
		ASSERT(FALSE);
		varValue.Clear();
		return;
	}

	// Get the index of the field corresponding to name
	short nField = GetFieldIndexByName(lpszName);

	GetFieldValue(nField, varValue, nFieldType);
}

void CRecordset::GetFieldValue(short nIndex,
	CDBVariant& varValue, short nFieldType)
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());

	// Clear the previous variant
	varValue.Clear();

	// No data or no column info fetched yet
	if (GetODBCFieldCount() <= 0)
	{
		ASSERT(FALSE);
		return;
	}

	// Convert index to 1-based and check range
	nIndex++;
	if (nIndex < 1 || nIndex > GetODBCFieldCount())
	{
		ThrowDBException(AFX_SQL_ERROR_FIELD_NOT_FOUND);
	}

	void* pvData = NULL;
	int nLen = 0;

	// Determine the default field type and get the data buffer
	if (nFieldType == DEFAULT_FIELD_TYPE)
	{
		nFieldType =
			GetDefaultFieldType(m_rgODBCFieldInfos[nIndex - 1].m_nSQLType);
	}
	pvData = GetDataBuffer(varValue, nFieldType, &nLen,
		m_rgODBCFieldInfos[nIndex - 1].m_nSQLType,
		m_rgODBCFieldInfos[nIndex - 1].m_nPrecision);

	// Now can actually get the data
	long nActualSize = GetData(m_pDatabase, m_hstmt, nIndex,
		nFieldType, pvData, nLen,
		m_rgODBCFieldInfos[nIndex - 1].m_nSQLType);

	// Handle NULL data separately
	if (nActualSize == SQL_NULL_DATA)
	{
		// Clear value and set the value NULL
		varValue.Clear();
	}
	else
	{
		// May need to cleanup and call SQLGetData again if LONG_VAR data
		if (nFieldType == SQL_C_CHAR)
		{
			GetLongCharDataAndCleanup(m_pDatabase, m_hstmt, nIndex,
				nActualSize, &pvData, nLen, *varValue.m_pstring,
				m_rgODBCFieldInfos[nIndex - 1].m_nSQLType);

#ifdef _UNICODE
			// Now must convert string to UNICODE
			LPCSTR lpszOld = (LPCSTR)varValue.m_pstring->GetBuffer(0);
			CString* pStringNew = new CString(lpszOld);
			delete varValue.m_pstring;
			varValue.m_pstring = pStringNew;
#endif // _UNICODE
		}
		else if (nFieldType == SQL_C_BINARY)
		{
			GetLongBinaryDataAndCleanup(m_pDatabase, m_hstmt, nIndex,
				nActualSize, &pvData, nLen, varValue,
				m_rgODBCFieldInfos[nIndex - 1].m_nSQLType);
		}
	}
}

void CRecordset::GetFieldValue(LPCTSTR lpszName, CString& strValue)
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());
	ASSERT(lpszName != NULL);

	// No data or no column info fetched yet
	if (GetODBCFieldCount() <= 0)
	{
		ASSERT(FALSE);
		return;
	}

	// Get the index of the field corresponding to name
	short nField = GetFieldIndexByName(lpszName);

	GetFieldValue(nField, strValue);
}

void CRecordset::GetFieldValue(short nIndex, CString& strValue)
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());

	// No data or no column info fetched yet
	if (GetODBCFieldCount() <= 0)
	{
		ASSERT(FALSE);
		return;
	}

	// Convert index to 1-based and check range
	nIndex++;
	if (nIndex < 1 || nIndex > GetODBCFieldCount())
	{
		ThrowDBException(AFX_SQL_ERROR_FIELD_NOT_FOUND);
	}

	int nLen = GetTextLen(m_rgODBCFieldInfos[nIndex - 1].m_nSQLType,
			m_rgODBCFieldInfos[nIndex - 1].m_nPrecision);

#ifndef _UNICODE
	CString& strData = strValue;
#else
	CString strProxy;
	CString& strData = strProxy;
#endif
	void* pvData = strData.GetBufferSetLength(nLen);

	// Now can actually get the data
	long nActualSize = GetData(m_pDatabase, m_hstmt, nIndex,
		SQL_C_CHAR, pvData, nLen,
		m_rgODBCFieldInfos[nIndex - 1].m_nSQLType);

	// Handle NULL data separately
	if (nActualSize == SQL_NULL_DATA)
	{
		// Clear value
		strValue.Empty();
	}
	else
	{
		// May need to cleanup and call SQLGetData again if necessary
		GetLongCharDataAndCleanup(m_pDatabase, m_hstmt, nIndex,
			nActualSize, &pvData, nLen, strData,
			m_rgODBCFieldInfos[nIndex - 1].m_nSQLType);

#ifdef _UNICODE
	// Now must convert string to UNICODE
	strValue = (LPCSTR)strData.GetBuffer(0);
#endif // _UNIOCDE
	}
}

void CRecordset::SetFieldDirty(void* pv, BOOL bDirty)
{
	ASSERT_VALID(this);

	int nIndex, nIndexEnd;

	// If not setting all NULL, check simple case
	if (pv != NULL)
	{
		// GetBoundFieldIndex returns 1-based index
		nIndex = GetBoundFieldIndex(pv) - 1;

		if (nIndex < 0)
		{
			// pv must be address of field member
			ASSERT(FALSE);
			return;
		}
		else
		{
			nIndexEnd = nIndex;
		}
	}
	else
	{
		nIndex = 0;
		nIndexEnd = m_nFields - 1;
	}

	while (nIndex <= nIndexEnd)
	{
		if (bDirty)
			SetDirtyFieldStatus((DWORD)nIndex);
		else
			ClearDirtyFieldStatus((DWORD)nIndex);

		nIndex++;
	}
}

void CRecordset::SetFieldNull(void* pv, BOOL bNull)
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());
	ASSERT(!(m_dwOptions & useMultiRowFetch));

	// If not setting all fields NULL, check simple case (param) first
	if (pv != NULL)
	{
		// Cached index is 1-based
		int nIndex = GetBoundParamIndex(pv) - 1;
		if (nIndex >= 0)
		{
			if (bNull)
				SetNullParamStatus(nIndex);
			else
				ClearNullParamStatus(nIndex);
			return;
		}
	}

	// Not a param, must be a field
	if (m_nFields <= 0)
	{
		ASSERT(FALSE);
		return;
	}

	// Need field exchange mechanism to set PSEUDO NULL values
	// and to reset data lengths (especially for RFX_LongBinary)
	CFieldExchange fx(CFieldExchange::SetFieldNull, this, pv);
	fx.m_nFieldFound = 0;
	fx.m_bField = bNull;
	DoFieldExchange(&fx);

	// If no field found, m_nFieldFound will still be zero
	ASSERT(fx.m_nFieldFound != 0);
}

void CRecordset::SetParamNull(int nIndex, BOOL bNull)
{
	ASSERT_VALID(this);
	ASSERT((DWORD)nIndex < m_nParams);

	// Can be called before Open, but need to alloc status arrays first
	if (!IsOpen())
		AllocStatusArrays();

	if (bNull)
		SetNullParamStatus(nIndex);
	else
		ClearNullParamStatus(nIndex);

	return;
}

void CRecordset::SetLockingMode(UINT nLockMode)
{
	if (nLockMode == pessimistic)
	{
		RETCODE nRetCode;
		UDWORD dwTypes;
		SWORD nResult;
		AFX_SQL_SYNC(::SQLGetInfo(m_pDatabase->m_hdbc, SQL_LOCK_TYPES,
			&dwTypes, sizeof(dwTypes), &nResult));
		if (!Check(nRetCode) || !(dwTypes & SQL_LCK_EXCLUSIVE))
			ThrowDBException(AFX_SQL_ERROR_LOCK_MODE_NOT_SUPPORTED);
	}
	m_nLockMode = nLockMode;
}

BOOL CRecordset::Requery()
{
	RETCODE nRetCode;

	ASSERT_VALID(this);
	ASSERT(IsOpen());

	// Can't requery if using direct execution
	if (m_dwOptions & executeDirect)
		return FALSE;

	TRY
	{
		// Detect changes to filter and sort
		if ((m_strFilter != m_strRequeryFilter) || (m_strSort != m_strRequerySort))
		{
			m_strRequeryFilter = m_strFilter;
			m_strRequerySort = m_strSort;
			Close();
			if (m_strRequerySQL.IsEmpty())
				return Open(m_nOpenType, NULL, m_dwOptions);
			else
				return Open(m_nOpenType, m_strRequerySQL, m_dwOptions);
		}
		else
		{
			// Shutdown current query, preserving buffers for performance
			AFX_SQL_SYNC(::SQLFreeStmt(m_hstmt, SQL_CLOSE));
			m_lOpen = AFX_RECORDSET_STATUS_CLOSED;

			// Rebind date/time parameters
			RebindParams(m_hstmt);

			// now attempt to re-execute the SQL Query
			AFX_ODBC_CALL(::SQLExecute(m_hstmt));
			if (!Check(nRetCode))
			{
				TRACE0("Error: Requery attempt failed.\n");
				ThrowDBException(nRetCode);
			}

			m_lOpen = AFX_RECORDSET_STATUS_OPEN;

			// Reset some cursor properties and fetch first record
			ResetCursor();
			MoveNext();

			// If EOF, then result set empty, so set BOF as well
			m_bBOF = m_bEOF;
		}
	}
	CATCH_ALL(e)
	{
		Close();
		THROW_LAST();
	}
	END_CATCH_ALL

	return TRUE;    // all set
}

// Shutdown any pending query for CRecordset's hstmt's
void CRecordset::Cancel()
{
	ASSERT_VALID(this);
	ASSERT(m_hstmt != SQL_NULL_HSTMT);

	::SQLCancel(m_hstmt);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -