如何解释 RDB$FORMATS 查询结果

How to interpret the RDB$FORMATS query result

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

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'

Documentation 声明如下:

RDB$DESCRIPTOR | BLOB FORMAT | Stores column names and data attributes as BLOB, as they were at the time the format record was created

查询结果如下:

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

table总共有 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;

结果如下:

如您所见,我只有 22 列,positionid 都无法匹配上面日志中的 24/28 键.

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

这是怎么回事?我该如何解释?

I can't understand the meaning behind the numbers 4, 8, 12, 16, 20, 24, 28

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

所有 Format=15 行都具有相同的 "length=4" 列。
这正是“4、8、12、16、20、24”之间的差异

在 Format=16 行中,长度为 4, 12, 4, 4, 4
那些匹配偏移量之间的间隙:4, 8, 20, 24, 28

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

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

  • "API Guide" - https://www.firebirdsql.org/en/reference-manuals/
  • "Firebird Internals (Work In Progress)" - 同上link
  • 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 值。您的日志在那里遗漏了一个参数,这对数字字段很重要。下面是某人 table.

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

whereas 37 is the VARCHAR's code.

再次阅读来源 - ibase.h

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

BLR 代表二进制语言表示 - 它是 Firebird 的内部字节码,它的私有半编译 "virtual machine"。我真的不认为你真的想深入了解底层实现细节。

更新:"whereas 37 is the VARCHAR's code" 实际上完全记录在相应的 table 描述中:
https://firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref-appx04-fields.html