如何解释RDB $ FORMATS查询结果

时间:2017-11-08 15:55:22

标签: database firebird firebird2.5

要获取表架构更改的历史记录,我运行了查询:

select CAST(SUBSTRING(f.rdb$descriptor FROM 1 FOR 32000) AS VARCHAR(32000)) log 
from rdb$formats f
join rdb$relations r on r.rdb$relation_id = f.rdb$relation_id
where r.rdb$relation_name = 'MY_TABLE_NAME'

godbolt demo声明如下:

  

RDB $ DESCRIPTOR | BLOB格式|将列名称和数据属性存储为BLOB,就像创建格式记录时一样

以下是查询结果:

LOG                                                  TABLE FORMAT ID
-------------------------------------------------    ----------------       
4: type=9 (LONG) length=4 sub_type=0 flags=0x0       15
8: type=9 (LONG) length=4 sub_type=0 flags=0x0   
12: type=14 (DATE) length=4 sub_type=0 flags=0x0 
16: type=9 (LONG) length=4 sub_type=0 flags=0x0  
20: type=9 (LONG) length=4 sub_type=0 flags=0x0  
24 <-- probably truncated?
-------------------------------------------------    ----------------
4: type=9 (LONG) length=4 sub_type=0 flags=0x0       16
8: type=3 (VARCHAR) length=12 sub_type=52 flags=0x0
20: type=14 (DATE) length=4 sub_type=0 flags=0x0
24: type=9 (LONG) length=4 sub_type=0 flags=0x0
28: type=9 (LONG) length=4 sub_type=0 flags=0x0

该表共有28行事件。但我无法理解数字4,8,12,16,20,24,28背后的含义。好的,让我们发出以下查询:

SELECT
    RF.RDB$FIELD_POSITION,
    RF.RDB$FIELD_ID,
    F.RDB$FIELD_TYPE,
    F.RDB$FIELD_SUB_TYPE
FROM RDB$RELATION_FIELDS RF
JOIN RDB$FIELDS F ON (F.RDB$FIELD_NAME = RF.RDB$FIELD_SOURCE)
WHERE RF.RDB$RELATION_NAME = 'MY_TABLE_NAME'
ORDER BY RF.RDB$FIELD_POSITION;

以下是结果:

Documentation

如您所见,我只有22列,位置 ID 都不能匹配上述日志中的24/28键。

另一个发现是日志中有type=3 (VARCHAR) sub_type=52,而37是VARCHAR的代码。

发生了什么事?我怎么解释这个?

1 个答案:

答案 0 :(得分:6)

  

我无法理解数字4,8,12,16,20,24,28背后的含义

这些是解压缩的内存缓冲区中的字节指针偏移量。

你所有的格式= 15行都有相同的&#34;长度= 4&#34;列。
而这正是&#34; 4,8,12,16,20,24和#34之间的差异;

在格式= 16行中,长度为4,12,4,4,4 这些是匹配偏移之间的差距:4,8,20,24,28

  • 指针1 +偏移1 =指针2
  • 指针2 +偏移2 =指针3
  • 等等

如果您需要进入低级别,请阅读低级文档:

  • &#34; API指南&#34; - https://www.firebirdsql.org/en/reference-manuals/
  • &#34; Firebird Internals(正在进行的工作)&#34; - 与上述相同的链接
  • c:\Program Files\Firebird\Firebird_2_1\include\ibase.h - dtype_XXX及相关常量
  • 解析内存结构的FLOSS低级库,如C ++中的IB ++或Pascal中的UIB。那些正在解析这些类型和子类型,以有意义的方式解释原始的内存数据。
  

select CAST(SUBSTRING....

由于您提到了 IBExpert ,我建议您使用内置的BLOB查看器查看RDB$Formats.rdb$descriptor值。您的日志错过了那里的一个参数,这对数字字段很重要。下面是一个表格中的转储。

Type=16 Scale=0 Length=8 Subtype=0 Flags=0 Offset=8
Type=17 Scale=4 Length=8 Subtype=1 Flags=0 Offset=16
  

而37是VARCHAR的代码。

再次阅读来源 - ibase.h

   #define blr_varying             (unsigned char)37
   #define blr_varying2            (unsigned char)38  

BLR代表二进制语言表示 - 它是内部Firebird的字节码,它是私有的半编译虚拟机&#34;。我真诚地认为你真的不想深入了解低级别的实施细节。

更新:&#34;而37是VARCHAR的代码&#34;实际上是完全记录在相应的表格描述中:
https://firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref-appx04-fields.html