mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16:43:03 +01:00
Fix #8185 - SIGSEGV with WHERE CURRENT OF statement with statement cache turned on.
This commit is contained in:
parent
5b6533ccd2
commit
83c97a2060
@ -23,7 +23,7 @@
|
|||||||
#include "../dsql/DsqlRequests.h"
|
#include "../dsql/DsqlRequests.h"
|
||||||
#include "../dsql/dsql.h"
|
#include "../dsql/dsql.h"
|
||||||
#include "../dsql/DsqlBatch.h"
|
#include "../dsql/DsqlBatch.h"
|
||||||
///#include "../dsql/DsqlStatementCache.h"
|
#include "../dsql/DsqlStatementCache.h"
|
||||||
#include "../dsql/Nodes.h"
|
#include "../dsql/Nodes.h"
|
||||||
#include "../jrd/Statement.h"
|
#include "../jrd/Statement.h"
|
||||||
#include "../jrd/req.h"
|
#include "../jrd/req.h"
|
||||||
@ -177,6 +177,9 @@ void DsqlRequest::destroy(thread_db* tdbb, DsqlRequest* dsqlRequest)
|
|||||||
{
|
{
|
||||||
childStatement->addFlags(DsqlStatement::FLAG_ORPHAN);
|
childStatement->addFlags(DsqlStatement::FLAG_ORPHAN);
|
||||||
childStatement->setParentRequest(nullptr);
|
childStatement->setParentRequest(nullptr);
|
||||||
|
childStatement->setParentDbKey(nullptr);
|
||||||
|
childStatement->setParentRecVersion(nullptr);
|
||||||
|
dsqlRequest->req_dbb->dbb_statement_cache->removeStatement(tdbb, childStatement);
|
||||||
|
|
||||||
// hvlad: lines below is commented out as
|
// hvlad: lines below is commented out as
|
||||||
// - child is already unlinked from its parent request
|
// - child is already unlinked from its parent request
|
||||||
|
@ -156,20 +156,44 @@ void DsqlStatementCache::putStatement(thread_db* tdbb, const string& text, USHOR
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DsqlStatementCache::removeStatement(thread_db* tdbb, DsqlStatement* statement)
|
||||||
|
{
|
||||||
|
if (const auto cacheKey = statement->getCacheKey())
|
||||||
|
{
|
||||||
|
if (const auto entryPtr = map.get(cacheKey))
|
||||||
|
{
|
||||||
|
const auto entry = *entryPtr;
|
||||||
|
|
||||||
|
entry->dsqlStatement->resetCacheKey();
|
||||||
|
|
||||||
|
if (entry->active)
|
||||||
|
{
|
||||||
|
entry->dsqlStatement->addRef();
|
||||||
|
activeStatementList.erase(entry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inactiveStatementList.erase(entry);
|
||||||
|
cacheSize -= entry->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
map.remove(entry->key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DsqlStatementCache::statementGoingInactive(Firebird::RefStrPtr& key)
|
void DsqlStatementCache::statementGoingInactive(Firebird::RefStrPtr& key)
|
||||||
{
|
{
|
||||||
const auto entryPtr = map.get(key);
|
const auto entryPtr = map.get(key);
|
||||||
|
|
||||||
if (!entryPtr)
|
if (!entryPtr)
|
||||||
{
|
|
||||||
fb_assert(false);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
const auto entry = *entryPtr;
|
const auto entry = *entryPtr;
|
||||||
|
|
||||||
fb_assert(entry->active);
|
fb_assert(entry->active);
|
||||||
entry->active = false;
|
entry->active = false;
|
||||||
|
entry->dsqlStatement->addRef();
|
||||||
entry->size = entry->dsqlStatement->getSize(); // update size
|
entry->size = entry->dsqlStatement->getSize(); // update size
|
||||||
|
|
||||||
inactiveStatementList.splice(inactiveStatementList.end(), activeStatementList, entry);
|
inactiveStatementList.splice(inactiveStatementList.end(), activeStatementList, entry);
|
||||||
@ -192,6 +216,9 @@ void DsqlStatementCache::purge(thread_db* tdbb, bool releaseLock)
|
|||||||
entry.dsqlStatement->resetCacheKey();
|
entry.dsqlStatement->resetCacheKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto& entry : inactiveStatementList)
|
||||||
|
entry.dsqlStatement->resetCacheKey();
|
||||||
|
|
||||||
map.clear();
|
map.clear();
|
||||||
activeStatementList.clear();
|
activeStatementList.clear();
|
||||||
inactiveStatementList.clear();
|
inactiveStatementList.clear();
|
||||||
@ -273,6 +300,7 @@ void DsqlStatementCache::shrink()
|
|||||||
while (cacheSize > maxCacheSize && !inactiveStatementList.isEmpty())
|
while (cacheSize > maxCacheSize && !inactiveStatementList.isEmpty())
|
||||||
{
|
{
|
||||||
const auto& front = inactiveStatementList.front();
|
const auto& front = inactiveStatementList.front();
|
||||||
|
front.dsqlStatement->resetCacheKey();
|
||||||
map.remove(front.key);
|
map.remove(front.key);
|
||||||
cacheSize -= front.size;
|
cacheSize -= front.size;
|
||||||
inactiveStatementList.erase(inactiveStatementList.begin());
|
inactiveStatementList.erase(inactiveStatementList.begin());
|
||||||
|
@ -106,6 +106,7 @@ public:
|
|||||||
void putStatement(thread_db* tdbb, const Firebird::string& text, USHORT clientDialect, bool isInternalRequest,
|
void putStatement(thread_db* tdbb, const Firebird::string& text, USHORT clientDialect, bool isInternalRequest,
|
||||||
Firebird::RefPtr<DsqlStatement> dsqlStatement);
|
Firebird::RefPtr<DsqlStatement> dsqlStatement);
|
||||||
|
|
||||||
|
void removeStatement(thread_db* tdbb, DsqlStatement* statement);
|
||||||
void statementGoingInactive(Firebird::RefStrPtr& key);
|
void statementGoingInactive(Firebird::RefStrPtr& key);
|
||||||
|
|
||||||
void purge(thread_db* tdbb, bool releaseLock);
|
void purge(thread_db* tdbb, bool releaseLock);
|
||||||
|
@ -65,10 +65,8 @@ int DsqlStatement::release()
|
|||||||
{
|
{
|
||||||
if (cacheKey)
|
if (cacheKey)
|
||||||
{
|
{
|
||||||
refCnt = ++refCounter;
|
dsqlAttachment->dbb_statement_cache->statementGoingInactive(cacheKey);
|
||||||
auto key = cacheKey;
|
refCnt = refCounter;
|
||||||
cacheKey = nullptr;
|
|
||||||
dsqlAttachment->dbb_statement_cache->statementGoingInactive(key);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -135,6 +135,7 @@ public:
|
|||||||
const dsql_par* getEof() const { return eof; }
|
const dsql_par* getEof() const { return eof; }
|
||||||
void setEof(dsql_par* value) { eof = value; }
|
void setEof(dsql_par* value) { eof = value; }
|
||||||
|
|
||||||
|
Firebird::RefStrPtr getCacheKey() { return cacheKey; }
|
||||||
void setCacheKey(Firebird::RefStrPtr& value) { cacheKey = value; }
|
void setCacheKey(Firebird::RefStrPtr& value) { cacheKey = value; }
|
||||||
void resetCacheKey() { cacheKey = nullptr; }
|
void resetCacheKey() { cacheKey = nullptr; }
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user