如何解释RDB $ FORMATS查询结果

lex*_*eme 4 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'
Run Code Online (Sandbox Code Playgroud)

文档说明如下:

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
Run Code Online (Sandbox Code Playgroud)

该表总共有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;
Run Code Online (Sandbox Code Playgroud)

以下是结果:

结果

如您所见,我只有22列,无论位置还是ID都不能匹配上面日志中的24/28键.

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

怎么了?我怎么解释这个?

Ari*_*The 6

我无法理解数字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指南" - https://www.firebirdsql.org/en/reference-manuals/
  • "Firebird Internals(正在进行的工作)" - 与上述相同的链接
  • c:\Program Files\Firebird\Firebird_2_1\include\ibase.h - dtype_XXX和相关常量
  • 解析内存结构的FLOSS低级库,如C++中的IB ++或Pascal中的UIB.那些解析那些类型和子类型以有意义的方式解释原始的内存数据.

select CAST(SUBSTRING....

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

Type=16 Scale=0 Length=8 Subtype=0 Flags=0 Offset=8
Type=17 Scale=4 Length=8 Subtype=1 Flags=0 Offset=16
Run Code Online (Sandbox Code Playgroud)

而37是VARCHAR的代码.

再次,阅读源 - ibase.h

   #define blr_varying             (unsigned char)37
   #define blr_varying2            (unsigned char)38  
Run Code Online (Sandbox Code Playgroud)

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

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