如何检索 Firebird 数据库连接的所有上下文变量

huangapple go评论75阅读模式
英文:

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 = &#39;SYSTEM&#39;;
  -- SYSTEM context names as of Firebird 5.0.0 beta-2 snapshot
  CONTEXT_VAR_NAMES = &#39;CLIENT_ADDRESS,CLIENT_HOST,CLIENT_PID,CLIENT_PROCESS,&#39;
    || &#39;CURRENT_ROLE,CURRENT_USER,DB_FILE_ID,DB_GUID,DB_NAME,EFFECTIVE_USER,&#39; 
    || &#39;ENGINE_VERSION,EXT_CONN_POOL_ACTIVE_COUNT,EXT_CONN_POOL_IDLE_COUNT,&#39; 
    || &#39;EXT_CONN_POOL_LIFETIME,EXT_CONN_POOL_SIZE,GLOBAL_CN,ISOLATION_LEVEL,&#39; 
    || &#39;LOCK_TIMEOUT,NETWORK_PROTOCOL,READ_ONLY,REPLICA_MODE,&#39; 
    || &#39;REPLICATION_SEQUENCE,PARALLEL_WORKERS,SESSION_ID,SESSION_IDLE_TIMEOUT,&#39; 
    || &#39;SESSION_TIMEZONE,SNAPSHOT_NUMBER,STATEMENT_TIMEOUT,TRANSACTION_ID,&#39; 
    || &#39;WIRE_COMPRESSED,WIRE_CRYPT_PLUGIN,WIRE_ENCRYPTED&#39;;
  CONTEXT_VAR_NAMES_LENGTH = char_length(CONTEXT_VAR_NAMES);
  -- Extract individual context var names
  while (SEPARATOR_POS &lt; CONTEXT_VAR_NAMES_LENGTH) do
  begin
	-- find next comma in list
  	SEPARATOR_POS = position(&#39;,&#39;, 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(&#39;SYSTEM&#39;, CONTEXT_VAR_NAME);
    suspend;
   
    -- when gdscode ctx_var_not_found do continue; /* continue doesn&#39;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 &#39;USER_SESSION&#39; else &#39;USER_TRANSACTION&#39; 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

huangapple
  • 本文由 发表于 2023年6月8日 23:52:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76433664.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定