英文:
How can I retrieve all context variables of a Firebird database connection
问题
Firebird有许多上下文变量,可以使用RDB$GET_CONTEXT
函数访问,对于用户上下文,可以使用RDB$SET_CONTEXT
进行设置。
用户上下文变量可以在监控表MON$CONTEXT_VARIABLES
中找到(管理员可以看到所有连接的变量),但系统上下文的变量在此表中不存在。是否有一种方法可以列出所有上下文变量,包括来自系统上下文的变量?
英文:
Firebird has a number of context variables which are accessible with the RDB$GET_CONTEXT
function, and - for user contexts - can be set with RDB$SET_CONTEXT
.
The user context variables can be found in the monitoring table MON$CONTEXT_VARIABLES
(administrators can see them for all connections), but variables of the SYSTEM context are absent in this table. Is there a way to list all context variables, including the variables from the SYSTEM context?
答案1
得分: 0
现在无法查询所有SYSTEM上下文变量,也无法发现哪些SYSTEM上下文变量名称对于Firebird版本是有效的。我已经提出了一个改进请求以添加这方面的功能,https://github.com/FirebirdSQL/firebird/issues/7623。
作为一种解决方法,您可以使用已知的SYSTEM上下文变量名称列表,并检查所有这些变量(跳过版本不支持的变量)。下面的代码是一个EXECUTE BLOCK
,但这可以很容易地修改为可选择的存储过程。这段代码应该在Firebird 2.5及更高版本上运行。
execute block
returns (
CONTEXT_NAME varchar(20) character set ASCII,
CONTEXT_VAR_NAME varchar(80) character set NONE,
CONTEXT_VAR_VALUE varchar(32765) character set NONE)
as
declare CONTEXT_VAR_NAMES varchar(500) character set ASCII;
declare CONTEXT_VAR_NAMES_LENGTH integer;
declare SEPARATOR_POS integer = 0;
declare NAME_START integer = 1;
begin
CONTEXT_NAME = 'SYSTEM';
-- Firebird 5.0.0 beta-2快照的SYSTEM上下文名称
CONTEXT_VAR_NAMES = 'CLIENT_ADDRESS,CLIENT_HOST,CLIENT_PID,CLIENT_PROCESS,'
|| 'CURRENT_ROLE,CURRENT_USER,DB_FILE_ID,DB_GUID,DB_NAME,EFFECTIVE_USER,'
|| 'ENGINE_VERSION,EXT_CONN_POOL_ACTIVE_COUNT,EXT_CONN_POOL_IDLE_COUNT,'
|| 'EXT_CONN_POOL_LIFETIME,EXT_CONN_POOL_SIZE,GLOBAL_CN,ISOLATION_LEVEL,'
|| 'LOCK_TIMEOUT,NETWORK_PROTOCOL,READ_ONLY,REPLICA_MODE,'
|| 'REPLICATION_SEQUENCE,PARALLEL_WORKERS,SESSION_ID,SESSION_IDLE_TIMEOUT,'
|| 'SESSION_TIMEZONE,SNAPSHOT_NUMBER,STATEMENT_TIMEOUT,TRANSACTION_ID,'
|| 'WIRE_COMPRESSED,WIRE_CRYPT_PLUGIN,WIRE_ENCRYPTED';
CONTEXT_VAR_NAMES_LENGTH = char_length(CONTEXT_VAR_NAMES);
-- 提取单个上下文变量名称
while (SEPARATOR_POS < CONTEXT_VAR_NAMES_LENGTH) do
begin
-- 在列表中找到下一个逗号
SEPARATOR_POS = position(',', CONTEXT_VAR_NAMES, NAME_START);
if (SEPARATOR_POS = 0) then
begin
-- 未找到逗号,定位在字符串结束后
SEPARATOR_POS = CONTEXT_VAR_NAMES_LENGTH + 1;
end
CONTEXT_VAR_NAME = substring(CONTEXT_VAR_NAMES from NAME_START for SEPARATOR_POS - NAME_START);
-- 定位到下一个上下文变量名称的第一个字符(或字符串结束后)
NAME_START = SEPARATOR_POS + 1;
CONTEXT_VAR_VALUE = rdb$get_context('SYSTEM', CONTEXT_VAR_NAME);
suspend;
-- 当gdscode ctx_var_not_found时继续;/*在2.5上不起作用的继续*/
when gdscode ctx_var_not_found do
begin
end
end
-- 检索当前连接和事务的用户上下文变量
for select
case when MON$TRANSACTION_ID is null then 'USER_SESSION' else 'USER_TRANSACTION' end,
MON$VARIABLE_NAME,
MON$VARIABLE_VALUE
from MON$CONTEXT_VARIABLES
where MON$ATTACHMENT_ID = current_connection
and (MON$TRANSACTION_ID is null or MON$TRANSACTION_ID = current_transaction)
order by MON$TRANSACTION_ID nulls first, MON$VARIABLE_NAME
into CONTEXT_NAME, CONTEXT_VAR_NAME, CONTEXT_VAR_VALUE do
begin
suspend;
end
end
英文:
Right now there is no way to query all SYSTEM context variables, nor a way to discover which SYSTEM context variable names are valid for a Firebird version. I have filed an improvement request to add something for this, https://github.com/FirebirdSQL/firebird/issues/7623.
As a workaround, you can use a list of known SYSTEM context variable names and check all of them (skipping the ones which don't exist for a version). The code below is an EXECUTE BLOCK
, but this can easily be modified to a selectable stored procedure. The code should work on Firebird 2.5 and higher.
execute block
returns (
CONTEXT_NAME varchar(20) character set ASCII,
CONTEXT_VAR_NAME varchar(80) character set NONE,
CONTEXT_VAR_VALUE varchar(32765) character set NONE)
as
declare CONTEXT_VAR_NAMES varchar(500) character set ASCII;
declare CONTEXT_VAR_NAMES_LENGTH integer;
declare SEPARATOR_POS integer = 0;
declare NAME_START integer = 1;
begin
CONTEXT_NAME = 'SYSTEM';
-- SYSTEM context names as of Firebird 5.0.0 beta-2 snapshot
CONTEXT_VAR_NAMES = 'CLIENT_ADDRESS,CLIENT_HOST,CLIENT_PID,CLIENT_PROCESS,'
|| 'CURRENT_ROLE,CURRENT_USER,DB_FILE_ID,DB_GUID,DB_NAME,EFFECTIVE_USER,'
|| 'ENGINE_VERSION,EXT_CONN_POOL_ACTIVE_COUNT,EXT_CONN_POOL_IDLE_COUNT,'
|| 'EXT_CONN_POOL_LIFETIME,EXT_CONN_POOL_SIZE,GLOBAL_CN,ISOLATION_LEVEL,'
|| 'LOCK_TIMEOUT,NETWORK_PROTOCOL,READ_ONLY,REPLICA_MODE,'
|| 'REPLICATION_SEQUENCE,PARALLEL_WORKERS,SESSION_ID,SESSION_IDLE_TIMEOUT,'
|| 'SESSION_TIMEZONE,SNAPSHOT_NUMBER,STATEMENT_TIMEOUT,TRANSACTION_ID,'
|| 'WIRE_COMPRESSED,WIRE_CRYPT_PLUGIN,WIRE_ENCRYPTED';
CONTEXT_VAR_NAMES_LENGTH = char_length(CONTEXT_VAR_NAMES);
-- Extract individual context var names
while (SEPARATOR_POS < CONTEXT_VAR_NAMES_LENGTH) do
begin
-- find next comma in list
SEPARATOR_POS = position(',', CONTEXT_VAR_NAMES, NAME_START);
if (SEPARATOR_POS = 0) then
begin
-- comma not found, position after end of string
SEPARATOR_POS = CONTEXT_VAR_NAMES_LENGTH + 1;
end
CONTEXT_VAR_NAME = substring(CONTEXT_VAR_NAMES from NAME_START for SEPARATOR_POS - NAME_START);
-- Position at first character of next context var name (or beyond end of string)
NAME_START = SEPARATOR_POS + 1;
CONTEXT_VAR_VALUE = rdb$get_context('SYSTEM', CONTEXT_VAR_NAME);
suspend;
-- when gdscode ctx_var_not_found do continue; /* continue doesn't work on 2.5 */
when gdscode ctx_var_not_found do
begin
end
end
-- Retrieve user context variables for current connection and transaction
for select
case when MON$TRANSACTION_ID is null then 'USER_SESSION' else 'USER_TRANSACTION' end,
MON$VARIABLE_NAME,
MON$VARIABLE_VALUE
from MON$CONTEXT_VARIABLES
where MON$ATTACHMENT_ID = current_connection
and (MON$TRANSACTION_ID is null or MON$TRANSACTION_ID = current_transaction)
order by MON$TRANSACTION_ID nulls first, MON$VARIABLE_NAME
into CONTEXT_NAME, CONTEXT_VAR_NAME, CONTEXT_VAR_VALUE do
begin
suspend;
end
end
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论