/* $Revision: 28 $ $Date: 23/03/05 11:49 $ Copyright © 2001-2006, FSL Technologies Limited. Contact "http://fost.3.felspar.com". */ #include "stdafx.h" #include using namespace std; using namespace FSLib; namespace { Revision c_revision( L"$Archive: /FOST.3/F3Util/assign.cpp $", __DATE__, L"$Revision: 28 $", L"$Date: 23/03/05 11:49 $" ); const Setting c_dsn( L"$Archive: /FOST.3/F3Util/assign.cpp $", L"ID", L"DSN", L"dsn=FostID", true ); const Setting c_method( L"$Archive: /FOST.3/F3Util/assign.cpp $", L"ID", L"Method", L"FostID", true ); const Setting c_table( L"$Archive: /FOST.3/F3Util/assign.cpp $", L"ID", L"Table", L"FSLib_Domain", true ); const Setting c_column( L"$Archive: /FOST.3/F3Util/assign.cpp $", L"ID", L"Column", L"nextID", true ); const wchar_t IDFaultMsg[]=L"Error in ID assignment."; Mutex g_dbc_mutex; inline DBConnection &g_dbConnectionRO() { Mutex::Lock lock( g_dbc_mutex ); static DBConnection dbc( Setting::value( L"ID", L"DSN" ) ); return dbc; } inline DBConnection &g_dbConnectionRW() { Mutex::Lock lock( g_dbc_mutex ); static DBConnection dbc( Setting::value( L"ID", L"DSN" ), Setting::value( L"ID", L"DSN" ) ); return dbc; } // Assignment methods ID fostID( const ID &domain ); ID exclusive( const ID &domain ); } /* Exceptions */ inline Exceptions::IDFault::IDFault( const FSLib::wstring &msg ) : Exception( msg ) { } inline const wchar_t * const Exceptions::IDFault::message() const { return IDFaultMsg; } /* Assignment */ inline ID FSLib::nextID( const ID &domain ) { FSLib::wstring method( Setting::value( L"ID", L"Method" ) ); if ( method == L"Exclusive" ) { return exclusive( domain ); } else if ( method == L"FostID" ) { return fostID( domain ); } else { throw Exceptions::IDFault( L"Method '" + method + L"' not recognised." ); } } inline ID FSLib::currentID( const ID &domain ) { try { Recordset rs( g_dbConnectionRO().execute( L"SELECT (" + c_column.value() + L" - 1) AS cur FROM " + c_table.value() + L" WHERE id=" + domain.asString() ) ); if ( rs.eof() ) throw FSLib::Exceptions::IDFault( L"No ID number found for domain" ); return field_cast< ID >( rs, L"cur" ); } catch ( FSLib::Exceptions::Exception &e ) { e.info() << L"Fetching current ID for domain " << domain << std::endl; throw; } } /* Methods */ namespace { // FostID ID fostID( const ID &domain ) { // Uses the read only API despite doing a write as the write connection doesn't return a recordset Recordset rs( g_dbConnectionRO().execute( L"BEGIN TRAN\n" L"SET NOCOUNT ON\n" L"UPDATE " + c_table.value() + L" SET " + c_column.value() + L"=" + c_column.value() + L"+1 WHERE id=" + domain.asString() + L"\n" L"SET NOCOUNT OFF\n" L"SELECT (" + c_column.value() + L" - 1) AS next FROM " + c_table.value() + L" WHERE id=" + domain.asString() + L"\n" L"COMMIT TRAN" ) ); return field_cast< ID >( rs, 0 ); } // Exclusive Mutex exclusive_mutex; ID exclusive_nextID; ID exclusive( const ID &domain ) { Mutex::Lock lock( exclusive_mutex ); if ( exclusive_nextID.isnull() ) { exclusive_nextID = field_cast< ID >( g_dbConnectionRW().execute( L"SELECT " + c_column.value() + L" AS next FROM " + c_table.value() + L" WHERE id=" + domain.asString() ), L"next" ); } ID ret( exclusive_nextID ); exclusive_nextID = _wtoi( exclusive_nextID.asString().c_str() ) + 1; g_dbConnectionRW().execute( e_writeCNX, L"UPDATE " + c_table.value() + L" SET " + c_column.value() + L"=" + exclusive_nextID.asString() + L" WHERE id=" + domain.asString() ); return ret; } }