FROM_PROTOBUF

功能概述

把 Protobuf 编码的二进制数据解析为 STRUCT,消息中的每个字段对应 STRUCT 的一个字段,嵌套消息、repeated 字段、map 字段分别转为嵌套 STRUCT、ARRAY、MAP。解析后可以像普通列一样按字段过滤、聚合,配合

LATERAL VIEW EXPLODE
LATERAL VIEW EXPLODE
展开 repeated 字段。

只需把消息整体转成 JSON 文本查看或转存时,用 PROTOBUF_TO_JSON。描述符的生成方法见 Protobuf 函数。

语法

FROM_PROTOBUF(<data>, <message_name>, <descriptor> [, <options>])

参数说明

  • <data>
    <data>
    :BINARY 类型,Protobuf 编码的消息数据。为 NULL 时返回 NULL;空的 BINARY 解析为所有字段都是 NULL 的 STRUCT。

  • <message_name>
    <message_name>
    :STRING 常量,消息类型名。可以写完整名(如
    'test.SimpleMsg'
    'test.SimpleMsg'
    ),也可以只写消息名(如
    'SimpleMsg'
    'SimpleMsg'
    )。

  • <descriptor>
    <descriptor>
    :BINARY 常量,
    protoc --descriptor_set_out
    protoc --descriptor_set_out
    生成的
    FileDescriptorSet
    FileDescriptorSet
    。

  • <options>
    <options>
    :可选,
    MAP<STRING, STRING>
    MAP<STRING, STRING>
    常量,key 不区分大小写:

选项默认值说明
mode
mode
PERMISSIVE
PERMISSIVE
PERMISSIVE
PERMISSIVE
:数据损坏时该行返回 NULL;
FAILFAST
FAILFAST
:数据损坏时查询报错
failed to parse protobuf message
failed to parse protobuf message
emit.default.values
emit.default.values
false
false
true
true
时未设置的字段返回 proto3 默认值(0、空串等),而不是 NULL
unwrap.well.known.types
unwrap.well.known.types
false
false
true
true
时把
google.protobuf.Int32Value
google.protobuf.Int32Value
等包装类型展开为对应的标量
max.descriptor.bytes
max.descriptor.bytes
1048576
1048576
描述符大小上限(字节)

类型映射:

Protobuf 类型Lakehouse 类型
int32、sint32、sfixed32、uint32、fixed32INT
int64、sint64、sfixed64、uint64、fixed64BIGINT
float / doubleFLOAT / DOUBLE
bool / string / bytesBOOLEAN / STRING / BINARY
enumSTRING(枚举名)
嵌套 message / repeated / mapSTRUCT / ARRAY / MAP
google.protobuf.Timestamp
google.protobuf.Timestamp
TIMESTAMP
google.protobuf.Duration
google.protobuf.Duration
INTERVAL DAY TO SECOND

使用示例

以下示例使用这个 proto 定义编译出的描述符:

syntax = "proto3"; package test; message SimpleMsg { int32 id = 1; string name = 2; double score = 3; bool active = 4; int64 ts = 5; float ratio = 6; bytes data = 7; }

解析一条消息:

SELECT from_protobuf( x'082a120568656c6c6f191f85eb51b81e094020012880d095ffbc3135000020403a03010203', 'test.SimpleMsg', x'0a89010a0a746573742e70726f746f120474657374226d0a0953696d706c654d7367120a0a026964180120012805120c0a046e616d65180220012809120d0a0573636f7265180320012801120e0a06616374697665180420012808120a0a027473180520012803120d0a05726174696f180620012802120c0a046461746118072001280c620670726f746f33' ) AS msg;

{"id":42,"name":"hello","score":3.14,"active":true,"ts":1700000000000,"ratio":2.5,"data":[01 02 03]}

取出单个字段:

SELECT msg.id, msg.name, msg.score FROM ( SELECT from_protobuf( x'082a120568656c6c6f191f85eb51b81e094020012880d095ffbc3135000020403a03010203', 'test.SimpleMsg', x'0a89010a0a746573742e70726f746f120474657374226d0a0953696d706c654d7367120a0a026964180120012805120c0a046e616d65180220012809120d0a0573636f7265180320012801120e0a06616374697665180420012808120a0a027473180520012803120d0a05726174696f180620012802120c0a046461746118072001280c620670726f746f33' ) AS msg );

idnamescore
42hello3.14

损坏的数据:默认

PERMISSIVE
PERMISSIVE
模式返回 NULL,
FAILFAST
FAILFAST
模式报错:

SELECT from_protobuf( x'12646162', 'test.SimpleMsg', x'0a89010a0a746573742e70726f746f120474657374226d0a0953696d706c654d7367120a0a026964180120012805120c0a046e616d65180220012809120d0a0573636f7265180320012801120e0a06616374697665180420012808120a0a027473180520012803120d0a05726174696f180620012802120c0a046461746118072001280c620670726f746f33', map('mode', 'PERMISSIVE') ) AS msg;

NULL

x'12646162'
x'12646162'
声明了长度为 100 的 string 字段,实际只有 2 个字节,属于截断数据。

注意事项

  • 消息类型名和描述符必须是常量。
  • 默认
    PERMISSIVE
    PERMISSIVE
    模式下,损坏的数据返回 NULL,不会中断查询。需要严格校验时用
    map('mode', 'FAILFAST')
    map('mode', 'FAILFAST')
    。
  • proto3 中未设置的字段默认返回 NULL,需要默认值时设置
    emit.default.values
    emit.default.values
    。

相关文档

联系我们
预约咨询
微信咨询
电话咨询
邮件咨询