mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 22:43:03 +01:00
Improvement CORE-5921 : Provide information about Global Commit Number, Commit Number of currently used database snapshot (if any) and Commit Numbers assigned to the committed transactions.
This commit is contained in:
parent
f463db457b
commit
fded677e95
@ -733,6 +733,37 @@ Example:
|
|||||||
select * from x order by rand();
|
select * from x order by rand();
|
||||||
|
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
RDB$GET_TRANSACTION_CN
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
(FB4 extension)
|
||||||
|
Function:
|
||||||
|
Returns commit number of given transaction.
|
||||||
|
Note, engine internally uses unsigned 8-bit integer for commit numbers,
|
||||||
|
while SQL language have no unsigned integers, thus one should be ready
|
||||||
|
to see negative numbers here (it is possible only if engine commits more
|
||||||
|
than 2^32 transactions since last database start, as global commit number
|
||||||
|
is reset at each restart).
|
||||||
|
|
||||||
|
There are some "special" values used for non-committed transactions and
|
||||||
|
transactions, committed before database was started:
|
||||||
|
|
||||||
|
0 - transaction is active,
|
||||||
|
1 - transaction committed before database started
|
||||||
|
-2 - transaction is dead (rolled back)
|
||||||
|
-1 - transaction is in limbo
|
||||||
|
|
||||||
|
See also README.read_consistency.md
|
||||||
|
|
||||||
|
Format:
|
||||||
|
RDB$SYSTEM_PRIVILEGE( <number> )
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
select rdb$get_transaction_cn(current_transaction) from rdb$database;
|
||||||
|
select rdb$get_transaction_cn(123) from rdb$database;
|
||||||
|
|
||||||
|
|
||||||
--------------------
|
--------------------
|
||||||
RDB$SYSTEM_PRIVILEGE
|
RDB$SYSTEM_PRIVILEGE
|
||||||
--------------------
|
--------------------
|
||||||
|
@ -102,6 +102,13 @@ Usage:
|
|||||||
| same as of CURRENT_ROLE pseudo-variable
|
| same as of CURRENT_ROLE pseudo-variable
|
||||||
|
|
|
|
||||||
ENGINE_VERSION | Engine version number, e.g. "2.1.0" (since V2.1)
|
ENGINE_VERSION | Engine version number, e.g. "2.1.0" (since V2.1)
|
||||||
|
|
|
||||||
|
GLOBAL_CN | Most current value of global Commit Number counter
|
||||||
|
|
|
||||||
|
SNAPSHOT_CN | Value of Commit Number of currently database snapshot: either
|
||||||
|
| transaction level (for SNAPSHOT or CONSISTENCY transaction),
|
||||||
|
| or request level (for READ COMMITTED READ CONSISTENCY
|
||||||
|
| transaction). NULL, if snapshot is not exist.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
To prevent DoS attacks against Firebird Server you are not allowed to have
|
To prevent DoS attacks against Firebird Server you are not allowed to have
|
||||||
|
@ -630,6 +630,7 @@ using namespace Firebird;
|
|||||||
%token <metaNamePtr> VARBINARY
|
%token <metaNamePtr> VARBINARY
|
||||||
%token <metaNamePtr> WINDOW
|
%token <metaNamePtr> WINDOW
|
||||||
%token <metaNamePtr> CONSISTENCY
|
%token <metaNamePtr> CONSISTENCY
|
||||||
|
%token <metaNamePtr> RDB_GET_TRANSACTION_CN
|
||||||
|
|
||||||
// external connections pool management
|
// external connections pool management
|
||||||
%token <metaNamePtr> CONNECTIONS
|
%token <metaNamePtr> CONNECTIONS
|
||||||
@ -7787,6 +7788,7 @@ system_function_std_syntax
|
|||||||
| POWER
|
| POWER
|
||||||
| RAND
|
| RAND
|
||||||
| RDB_GET_CONTEXT
|
| RDB_GET_CONTEXT
|
||||||
|
| RDB_GET_TRANSACTION_CN
|
||||||
| RDB_ROLE_IN_USE
|
| RDB_ROLE_IN_USE
|
||||||
| RDB_SET_CONTEXT
|
| RDB_SET_CONTEXT
|
||||||
| REPLACE
|
| REPLACE
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include "../jrd/mov_proto.h"
|
#include "../jrd/mov_proto.h"
|
||||||
#include "../jrd/pag_proto.h"
|
#include "../jrd/pag_proto.h"
|
||||||
#include "../jrd/tra_proto.h"
|
#include "../jrd/tra_proto.h"
|
||||||
|
#include "../jrd/tpc_proto.h"
|
||||||
#include "../jrd/scl_proto.h"
|
#include "../jrd/scl_proto.h"
|
||||||
#include "../common/os/guid.h"
|
#include "../common/os/guid.h"
|
||||||
#include "../jrd/license.h"
|
#include "../jrd/license.h"
|
||||||
@ -169,6 +170,7 @@ void setParamsDblDec(DataTypeUtilBase* dataTypeUtil, const SysFunction* function
|
|||||||
void setParamsDecFloat(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
|
void setParamsDecFloat(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
|
||||||
void setParamsFromList(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
|
void setParamsFromList(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
|
||||||
void setParamsInteger(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
|
void setParamsInteger(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
|
||||||
|
void setParamsInt64(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
|
||||||
void setParamsSecondInteger(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
|
void setParamsSecondInteger(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
|
||||||
|
|
||||||
// specific setParams functions
|
// specific setParams functions
|
||||||
@ -235,6 +237,7 @@ dsc* evlFloor(thread_db* tdbb, const SysFunction* function, const NestValueArray
|
|||||||
dsc* evlGenUuid(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
dsc* evlGenUuid(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
||||||
dsc* evlGetContext(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
dsc* evlGetContext(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
||||||
dsc* evlSetContext(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
dsc* evlSetContext(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
||||||
|
dsc* evlGetTranCN(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
||||||
dsc* evlHash(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
dsc* evlHash(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
||||||
dsc* evlLeft(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
dsc* evlLeft(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
||||||
dsc* evlLnLog10(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
dsc* evlLnLog10(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
|
||||||
@ -276,6 +279,7 @@ const char
|
|||||||
// SYSTEM namespace: global and database wise items
|
// SYSTEM namespace: global and database wise items
|
||||||
ENGINE_VERSION[] = "ENGINE_VERSION",
|
ENGINE_VERSION[] = "ENGINE_VERSION",
|
||||||
DATABASE_NAME[] = "DB_NAME",
|
DATABASE_NAME[] = "DB_NAME",
|
||||||
|
GLOBAL_CN_NAME[] = "GLOBAL_CN",
|
||||||
EXT_CONN_POOL_SIZE[] = "EXT_CONN_POOL_SIZE",
|
EXT_CONN_POOL_SIZE[] = "EXT_CONN_POOL_SIZE",
|
||||||
EXT_CONN_POOL_IDLE[] = "EXT_CONN_POOL_IDLE_COUNT",
|
EXT_CONN_POOL_IDLE[] = "EXT_CONN_POOL_IDLE_COUNT",
|
||||||
EXT_CONN_POOL_ACTIVE[] = "EXT_CONN_POOL_ACTIVE_COUNT",
|
EXT_CONN_POOL_ACTIVE[] = "EXT_CONN_POOL_ACTIVE_COUNT",
|
||||||
@ -298,6 +302,7 @@ const char
|
|||||||
ISOLATION_LEVEL_NAME[] = "ISOLATION_LEVEL",
|
ISOLATION_LEVEL_NAME[] = "ISOLATION_LEVEL",
|
||||||
LOCK_TIMEOUT_NAME[] = "LOCK_TIMEOUT",
|
LOCK_TIMEOUT_NAME[] = "LOCK_TIMEOUT",
|
||||||
READ_ONLY_NAME[] = "READ_ONLY",
|
READ_ONLY_NAME[] = "READ_ONLY",
|
||||||
|
SNAPSHOT_CN_NAME[] = "SNAPSHOT_CN",
|
||||||
// DDL_TRIGGER namespace
|
// DDL_TRIGGER namespace
|
||||||
DDL_EVENT_NAME[] = "DDL_EVENT",
|
DDL_EVENT_NAME[] = "DDL_EVENT",
|
||||||
EVENT_TYPE_NAME[] = "EVENT_TYPE",
|
EVENT_TYPE_NAME[] = "EVENT_TYPE",
|
||||||
@ -473,6 +478,16 @@ void setParamsInteger(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc*
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setParamsInt64(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc** args)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < argsCount; ++i)
|
||||||
|
{
|
||||||
|
if (args[i]->isUnknown())
|
||||||
|
args[i]->makeInt64(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void setParamsSecondInteger(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc** args)
|
void setParamsSecondInteger(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc** args)
|
||||||
{
|
{
|
||||||
if (argsCount >= 2)
|
if (argsCount >= 2)
|
||||||
@ -2685,6 +2700,24 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar
|
|||||||
resultStr.printf("%" SLONGFORMAT, transaction->tra_lock_timeout);
|
resultStr.printf("%" SLONGFORMAT, transaction->tra_lock_timeout);
|
||||||
else if (nameStr == READ_ONLY_NAME)
|
else if (nameStr == READ_ONLY_NAME)
|
||||||
resultStr = (transaction->tra_flags & TRA_readonly) ? TRUE_VALUE : FALSE_VALUE;
|
resultStr = (transaction->tra_flags & TRA_readonly) ? TRUE_VALUE : FALSE_VALUE;
|
||||||
|
else if (nameStr == GLOBAL_CN_NAME)
|
||||||
|
resultStr.printf("%" SQUADFORMAT, dbb->dbb_tip_cache->getGlobalCommitNumber());
|
||||||
|
else if (nameStr == SNAPSHOT_CN_NAME)
|
||||||
|
{
|
||||||
|
if (!(transaction->tra_flags & TRA_read_committed))
|
||||||
|
resultStr.printf("%" SQUADFORMAT, transaction->tra_snapshot_number);
|
||||||
|
else if ((transaction->tra_flags & TRA_read_committed) &&
|
||||||
|
(transaction->tra_flags & TRA_read_consistency))
|
||||||
|
{
|
||||||
|
jrd_req* snapshot_req = request->req_snapshot.m_owner;
|
||||||
|
if (snapshot_req)
|
||||||
|
resultStr.printf("%" SQUADFORMAT, snapshot_req->req_snapshot.m_number);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
else if (nameStr == EXT_CONN_POOL_SIZE)
|
else if (nameStr == EXT_CONN_POOL_SIZE)
|
||||||
resultStr.printf("%d", EDS::Manager::getConnPool()->getMaxCount());
|
resultStr.printf("%d", EDS::Manager::getConnPool()->getMaxCount());
|
||||||
else if (nameStr == EXT_CONN_POOL_IDLE)
|
else if (nameStr == EXT_CONN_POOL_IDLE)
|
||||||
@ -2890,6 +2923,38 @@ dsc* evlSetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dsc* evlGetTranCN(thread_db* tdbb, const SysFunction* function, const NestValueArray& args,
|
||||||
|
impure_value* impure)
|
||||||
|
{
|
||||||
|
fb_assert(args.getCount() == 1);
|
||||||
|
|
||||||
|
Database* dbb = tdbb->getDatabase();
|
||||||
|
jrd_req* request = tdbb->getRequest();
|
||||||
|
|
||||||
|
request->req_flags &= ~req_null;
|
||||||
|
const dsc* value = EVL_expr(tdbb, request, args[0]);
|
||||||
|
if (request->req_flags & req_null)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
TraNumber traNum = MOV_get_int64(tdbb, value, 0);
|
||||||
|
if (traNum > dbb->dbb_next_transaction)
|
||||||
|
{
|
||||||
|
request->req_flags |= req_null;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommitNumber cn = dbb->dbb_tip_cache->snapshotState(tdbb, traNum);
|
||||||
|
|
||||||
|
dsc result;
|
||||||
|
result.makeInt64(0, (SINT64*)&cn);
|
||||||
|
|
||||||
|
EVL_make_value(tdbb, &result, impure);
|
||||||
|
|
||||||
|
request->req_flags &= ~req_null;
|
||||||
|
return &impure->vlu_desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
dsc* evlHash(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
|
dsc* evlHash(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
|
||||||
impure_value* impure)
|
impure_value* impure)
|
||||||
{
|
{
|
||||||
@ -4565,6 +4630,7 @@ const SysFunction SysFunction::functions[] =
|
|||||||
{"QUANTIZE", 2, 2, setParamsDecFloat, makeDecFloatResult, evlQuantize, NULL},
|
{"QUANTIZE", 2, 2, setParamsDecFloat, makeDecFloatResult, evlQuantize, NULL},
|
||||||
{"RAND", 0, 0, NULL, makeDoubleResult, evlRand, NULL},
|
{"RAND", 0, 0, NULL, makeDoubleResult, evlRand, NULL},
|
||||||
{RDB_GET_CONTEXT, 2, 2, setParamsGetSetContext, makeGetSetContext, evlGetContext, NULL},
|
{RDB_GET_CONTEXT, 2, 2, setParamsGetSetContext, makeGetSetContext, evlGetContext, NULL},
|
||||||
|
{"RDB$GET_TRANSACTION_CN", 1, 1, setParamsInt64, makeInt64Result, evlGetTranCN, NULL},
|
||||||
{"RDB$ROLE_IN_USE", 1, 1, setParamsAsciiVal, makeBooleanResult, evlRoleInUse, NULL},
|
{"RDB$ROLE_IN_USE", 1, 1, setParamsAsciiVal, makeBooleanResult, evlRoleInUse, NULL},
|
||||||
{RDB_SET_CONTEXT, 3, 3, setParamsGetSetContext, makeGetSetContext, evlSetContext, NULL},
|
{RDB_SET_CONTEXT, 3, 3, setParamsGetSetContext, makeGetSetContext, evlSetContext, NULL},
|
||||||
{"RDB$SYSTEM_PRIVILEGE", 1, 1, NULL, makeBooleanResult, evlSystemPrivilege, NULL},
|
{"RDB$SYSTEM_PRIVILEGE", 1, 1, NULL, makeBooleanResult, evlSystemPrivilege, NULL},
|
||||||
|
@ -140,6 +140,11 @@ public:
|
|||||||
//void assignLatestTransactionId(TraNumber number);
|
//void assignLatestTransactionId(TraNumber number);
|
||||||
void assignLatestAttachmentId(AttNumber number);
|
void assignLatestAttachmentId(AttNumber number);
|
||||||
|
|
||||||
|
CommitNumber getGlobalCommitNumber() const
|
||||||
|
{
|
||||||
|
return m_tpcHeader->getHeader()->latest_commit_number.load(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class GlobalTpcHeader : public Firebird::MemoryHeader
|
class GlobalTpcHeader : public Firebird::MemoryHeader
|
||||||
{
|
{
|
||||||
|
@ -355,6 +355,7 @@ static const TOK tokens[] =
|
|||||||
{TOK_DB_KEY, "RDB$DB_KEY", false},
|
{TOK_DB_KEY, "RDB$DB_KEY", false},
|
||||||
{TOK_RDB_ERROR, "RDB$ERROR", false},
|
{TOK_RDB_ERROR, "RDB$ERROR", false},
|
||||||
{TOK_RDB_GET_CONTEXT, "RDB$GET_CONTEXT", false},
|
{TOK_RDB_GET_CONTEXT, "RDB$GET_CONTEXT", false},
|
||||||
|
{TOK_RDB_GET_TRANSACTION_CN, "RDB$GET_TRANSACTION_CN", false},
|
||||||
{TOK_RDB_RECORD_VERSION, "RDB$RECORD_VERSION", false},
|
{TOK_RDB_RECORD_VERSION, "RDB$RECORD_VERSION", false},
|
||||||
{TOK_RDB_ROLE_IN_USE, "RDB$ROLE_IN_USE", false},
|
{TOK_RDB_ROLE_IN_USE, "RDB$ROLE_IN_USE", false},
|
||||||
{TOK_RDB_SET_CONTEXT, "RDB$SET_CONTEXT", false},
|
{TOK_RDB_SET_CONTEXT, "RDB$SET_CONTEXT", false},
|
||||||
|
Loading…
Reference in New Issue
Block a user