Index: src/libchcore/TSQLiteSerializerRowData.cpp =================================================================== diff -u -N -r19925be73ffcadd9f345f10e03e55aadb3f0eeac -r5693271a6736f524997e3951fc7b7b6323bc6447 --- src/libchcore/TSQLiteSerializerRowData.cpp (.../TSQLiteSerializerRowData.cpp) (revision 19925be73ffcadd9f345f10e03e55aadb3f0eeac) +++ src/libchcore/TSQLiteSerializerRowData.cpp (.../TSQLiteSerializerRowData.cpp) (revision 5693271a6736f524997e3951fc7b7b6323bc6447) @@ -23,6 +23,7 @@ #include #include "TSerializerException.h" #include "ErrorCodes.h" +#include "SerializerTrace.h" BEGIN_CHCORE_NAMESPACE @@ -38,86 +39,136 @@ void operator()(bool value) const { - ATLTRACE(_T("- param(bool): %ld\n"), value ? 1l : 0l); + DBTRACE_D(_T("- param(bool): %ld\n"), value ? 1l : 0l); m_rStatement.BindValue(m_rColumn++, value); } void operator()(short value) const { - ATLTRACE(_T("- param(short): %d\n"), value); + DBTRACE_D(_T("- param(short): %d\n"), value); m_rStatement.BindValue(m_rColumn++, value); } void operator()(unsigned short value) const { - ATLTRACE(_T("- param(ushort): %u\n"), value); + DBTRACE_D(_T("- param(ushort): %u\n"), value); m_rStatement.BindValue(m_rColumn++, value); } void operator()(int value) const { - ATLTRACE(_T("- param(int): %ld\n"), value); + DBTRACE_D(_T("- param(int): %ld\n"), value); m_rStatement.BindValue(m_rColumn++, value); } void operator()(unsigned int value) const { - ATLTRACE(_T("- param(uint): %lu\n"), value); + DBTRACE_D(_T("- param(uint): %lu\n"), value); m_rStatement.BindValue(m_rColumn++, value); } void operator()(long value) const { - ATLTRACE(_T("- param(long): %ld\n"), value); + DBTRACE_D(_T("- param(long): %ld\n"), value); m_rStatement.BindValue(m_rColumn++, value); } void operator()(unsigned long value) const { - ATLTRACE(_T("- param(ulong): %lu\n"), value); + DBTRACE_D(_T("- param(ulong): %lu\n"), value); m_rStatement.BindValue(m_rColumn++, value); } void operator()(long long value) const { - ATLTRACE(_T("- param(longlong): %I64d\n"), value); + DBTRACE_D(_T("- param(longlong): %I64d\n"), value); m_rStatement.BindValue(m_rColumn++, value); } void operator()(unsigned long long value) const { - ATLTRACE(_T("- param(ulonglong): %I64u\n"), value); + DBTRACE_D(_T("- param(ulonglong): %I64u\n"), value); m_rStatement.BindValue(m_rColumn++, value); } void operator()(double value) const { - ATLTRACE(_T("- param(double): %f\n"), value); + DBTRACE_D(_T("- param(double): %f\n"), value); m_rStatement.BindValue(m_rColumn++, value); } void operator()(const TString& value) const { - ATLTRACE(_T("- param(string): '%s'\n"), (PCTSTR)value); + DBTRACE_D(_T("- param(string): '%s'\n"), (PCTSTR)value); m_rStatement.BindValue(m_rColumn++, value); } void operator()(const TSmartPath& value) const { - ATLTRACE(_T("- param(path): %s\n"), value.ToString()); + DBTRACE_D(_T("- param(path): %s\n"), value.ToString()); m_rStatement.BindValue(m_rColumn++, value); } int& m_rColumn; sqlite::TSQLiteStatement& m_rStatement; }; + } + +/////////////////////////////////////////////////////////////////////////// +TRowID::TRowID(const TSQLiteColumnDefinitionPtr& spColumnDefinition) : + m_bitset(spColumnDefinition->GetCount() + 1) // count of columns and a bit for add/modify +{ +} + +TRowID::~TRowID() +{ +} + +void TRowID::SetAddedBit(bool bAdded) +{ + m_bitset[0] = bAdded; +} + +void TRowID::SetColumnBit(size_t stIndex, bool bColumnExists) +{ + ++stIndex; + + if(stIndex >= m_bitset.size()) + THROW_SERIALIZER_EXCEPTION(eErr_BoundsExceeded, _T("Row identification info cannot be generated")); + + m_bitset[stIndex] = bColumnExists; +} + +bool TRowID::operator==(const TRowID rSrc) const +{ + return m_bitset == rSrc.m_bitset; +} + +bool TRowID::operator<(const TRowID rSrc) const +{ + return m_bitset < rSrc.m_bitset; +} + +void TRowID::Clear() +{ + m_bitset.reset(); +} + +bool TRowID::HasAny() const +{ + return m_bitset.any(); +} + +/////////////////////////////////////////////////////////////////////////// TSQLiteSerializerRowData::TSQLiteSerializerRowData(size_t stRowID, const TSQLiteColumnDefinitionPtr& spColumnDefinition, bool bAdded) : m_stRowID(stRowID), m_spColumns(spColumnDefinition), m_bAdded(bAdded) { + if(!spColumnDefinition) + THROW_SERIALIZER_EXCEPTION(eErr_InvalidArgument, _T("No column definition provided")); } TSQLiteSerializerRowData::~TSQLiteSerializerRowData() @@ -148,19 +199,49 @@ return *this; } -void TSQLiteSerializerRowData::Flush(const sqlite::TSQLiteDatabasePtr& spDatabase, const TString& strContainerName) +void TSQLiteSerializerRowData::BindParamsAndExec(sqlite::TSQLiteStatement& tStatement) { using namespace sqlite; - TSQLiteStatement tStatement(spDatabase); + if(m_bAdded) + { + // exec query + int iColumn = 1; + tStatement.BindValue(iColumn++, m_stRowID); + for(MapVariants::iterator iterVariant = m_mapValues.begin(); iterVariant != m_mapValues.end(); ++iterVariant) + { + boost::apply_visitor(SQLiteBindValueVisitor(tStatement, iColumn), iterVariant->second); + } + tStatement.Step(); + } + else if(!m_mapValues.empty()) + { + int iColumn = 1; + for(MapVariants::iterator iterVariant = m_mapValues.begin(); iterVariant != m_mapValues.end(); ++iterVariant) + { + boost::apply_visitor(SQLiteBindValueVisitor(tStatement, iColumn), iterVariant->second); + } + tStatement.BindValue(iColumn++, m_stRowID); + + tStatement.Step(); + + int iChanges = tStatement.Changes(); + _ASSERTE(iChanges == 1); + if(iChanges != 1) + THROW_SERIALIZER_EXCEPTION(eErr_InvalidData, _T("Update query did not update record in the database")); + } +} + +TString TSQLiteSerializerRowData::GetQuery(const TString& strContainerName) const +{ if(m_bAdded) { // prepare insert query TString strQuery = boost::str(boost::wformat(L"INSERT INTO %1%(id,") % strContainerName).c_str(); TString strParams; - for(MapVariants::iterator iterVariant = m_mapValues.begin(); iterVariant != m_mapValues.end(); ++iterVariant) + for(MapVariants::const_iterator iterVariant = m_mapValues.begin(); iterVariant != m_mapValues.end(); ++iterVariant) { strQuery += boost::str(boost::wformat(_T("%1%,")) % m_spColumns->GetColumnName(iterVariant->first)).c_str(); strParams += _T("?,"); @@ -173,48 +254,37 @@ strQuery += strParams; strQuery += _T(")"); - // exec query - int iColumn = 1; - tStatement.Prepare(strQuery); - tStatement.BindValue(iColumn++, m_stRowID); - for(MapVariants::iterator iterVariant = m_mapValues.begin(); iterVariant != m_mapValues.end(); ++iterVariant) - { - boost::apply_visitor(SQLiteBindValueVisitor(tStatement, iColumn), iterVariant->second); - } - - ATLTRACE(_T("Executing query: %s\n"), (PCTSTR)strQuery); - tStatement.Step(); + return strQuery; } else if(!m_mapValues.empty()) { // prepare update query TString strQuery = boost::str(boost::wformat(L"UPDATE %1% SET ") % strContainerName).c_str(); - for(MapVariants::iterator iterVariant = m_mapValues.begin(); iterVariant != m_mapValues.end(); ++iterVariant) + for(MapVariants::const_iterator iterVariant = m_mapValues.begin(); iterVariant != m_mapValues.end(); ++iterVariant) { strQuery += boost::str(boost::wformat(_T("%1%=?,")) % m_spColumns->GetColumnName(iterVariant->first)).c_str(); } strQuery.TrimRightSelf(_T(",")); strQuery += _T(" WHERE id=?"); - int iColumn = 1; + return strQuery; + } + else + return TString(); +} - ATLTRACE(_T("Executing query: %s\n"), (PCTSTR)strQuery); - tStatement.Prepare(strQuery); - for(MapVariants::iterator iterVariant = m_mapValues.begin(); iterVariant != m_mapValues.end(); ++iterVariant) - { - boost::apply_visitor(SQLiteBindValueVisitor(tStatement, iColumn), iterVariant->second); - } - tStatement.BindValue(iColumn++, m_stRowID); - - tStatement.Step(); - - int iChanges = tStatement.Changes(); - _ASSERTE(iChanges == 1); - if(iChanges != 1) - THROW_SERIALIZER_EXCEPTION(eErr_InvalidData, _T("Update query did not update record in the database")); +TRowID TSQLiteSerializerRowData::GetChangeIdentification() const +{ + TRowID rowID(m_spColumns); + rowID.SetAddedBit(m_bAdded); + for(MapVariants::const_iterator iterVariant = m_mapValues.begin(); iterVariant != m_mapValues.end(); ++iterVariant) + { + rowID.SetColumnBit(iterVariant->first, true); } + + return rowID; } END_CHCORE_NAMESPACE