mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16: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();
|
||||
|
||||
|
||||
--------------------
|
||||
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
|
||||
--------------------
|
||||
|
@ -102,6 +102,13 @@ Usage:
|
||||
| same as of CURRENT_ROLE pseudo-variable
|
||||
|
|
||||
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:
|
||||
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> WINDOW
|
||||
%token <metaNamePtr> CONSISTENCY
|
||||
%token <metaNamePtr> RDB_GET_TRANSACTION_CN
|
||||
|
||||
// external connections pool management
|
||||
%token <metaNamePtr> CONNECTIONS
|
||||
@ -7787,6 +7788,7 @@ system_function_std_syntax
|
||||
| POWER
|
||||
| RAND
|
||||
| RDB_GET_CONTEXT
|
||||
| RDB_GET_TRANSACTION_CN
|
||||
| RDB_ROLE_IN_USE
|
||||
| RDB_SET_CONTEXT
|
||||
| REPLACE
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "../jrd/mov_proto.h"
|
||||
#include "../jrd/pag_proto.h"
|
||||
#include "../jrd/tra_proto.h"
|
||||
#include "../jrd/tpc_proto.h"
|
||||
#include "../jrd/scl_proto.h"
|
||||
#include "../common/os/guid.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 setParamsFromList(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);
|
||||
|
||||
// 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* 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* 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* 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);
|
||||
@ -276,6 +279,7 @@ const char
|
||||
// SYSTEM namespace: global and database wise items
|
||||
ENGINE_VERSION[] = "ENGINE_VERSION",
|
||||
DATABASE_NAME[] = "DB_NAME",
|
||||
GLOBAL_CN_NAME[] = "GLOBAL_CN",
|
||||
EXT_CONN_POOL_SIZE[] = "EXT_CONN_POOL_SIZE",
|
||||
EXT_CONN_POOL_IDLE[] = "EXT_CONN_POOL_IDLE_COUNT",
|
||||
EXT_CONN_POOL_ACTIVE[] = "EXT_CONN_POOL_ACTIVE_COUNT",
|
||||
@ -298,6 +302,7 @@ const char
|
||||
ISOLATION_LEVEL_NAME[] = "ISOLATION_LEVEL",
|
||||
LOCK_TIMEOUT_NAME[] = "LOCK_TIMEOUT",
|
||||
READ_ONLY_NAME[] = "READ_ONLY",
|
||||
SNAPSHOT_CN_NAME[] = "SNAPSHOT_CN",
|
||||
// DDL_TRIGGER namespace
|
||||
DDL_EVENT_NAME[] = "DDL_EVENT",
|
||||
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)
|
||||
{
|
||||
if (argsCount >= 2)
|
||||
@ -2685,6 +2700,24 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar
|
||||
resultStr.printf("%" SLONGFORMAT, transaction->tra_lock_timeout);
|
||||
else if (nameStr == READ_ONLY_NAME)
|
||||
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)
|
||||
resultStr.printf("%d", EDS::Manager::getConnPool()->getMaxCount());
|
||||
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,
|
||||
impure_value* impure)
|
||||
{
|
||||
@ -4565,6 +4630,7 @@ const SysFunction SysFunction::functions[] =
|
||||
{"QUANTIZE", 2, 2, setParamsDecFloat, makeDecFloatResult, evlQuantize, NULL},
|
||||
{"RAND", 0, 0, NULL, makeDoubleResult, evlRand, 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_SET_CONTEXT, 3, 3, setParamsGetSetContext, makeGetSetContext, evlSetContext, NULL},
|
||||
{"RDB$SYSTEM_PRIVILEGE", 1, 1, NULL, makeBooleanResult, evlSystemPrivilege, NULL},
|
||||
|
@ -140,6 +140,11 @@ public:
|
||||
//void assignLatestTransactionId(TraNumber number);
|
||||
void assignLatestAttachmentId(AttNumber number);
|
||||
|
||||
CommitNumber getGlobalCommitNumber() const
|
||||
{
|
||||
return m_tpcHeader->getHeader()->latest_commit_number.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
private:
|
||||
class GlobalTpcHeader : public Firebird::MemoryHeader
|
||||
{
|
||||
|
@ -355,6 +355,7 @@ static const TOK tokens[] =
|
||||
{TOK_DB_KEY, "RDB$DB_KEY", false},
|
||||
{TOK_RDB_ERROR, "RDB$ERROR", 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_ROLE_IN_USE, "RDB$ROLE_IN_USE", false},
|
||||
{TOK_RDB_SET_CONTEXT, "RDB$SET_CONTEXT", false},
|
||||
|
Loading…
Reference in New Issue
Block a user