ParserFactory 类

如果编写解析器,您还必须编写用于生成解析器实例的工厂。为此,请对 ParserFactory 类设置子类。

解析器工厂是单例。您的子类必须为无状态子类,没有包含数据的字段。子类还不得修改任何全局变量。

ParserFactory 类定义了以下方法。您的子类必须覆盖 prepare() 方法。可以覆盖其他方法。

设置

Vertica 将在启动程序节点上调用 plan() 一次,以执行下列任务:

  • 检查已从 COPY 语句中的函数调用传递的任何参数和错误消息(如果出现任何问题)。您通过从传递至 plan() 方法的 ServerInterface 的实例中获得 ParamReader 对象读取参数。

  • 存储各个主机解析数据所需的任何信息。例如,可以将参数存储在通过 planCtxt 参数传入的 PlanContext 实例中。plan() 方法仅在启动程序节点上运行,而 prepareUDSources() 方法则在每个读取数据源的主机上运行。因此,该对象是它们之间的唯一通信方式。

    您通过从 getWriter() 方法中获取 ParamWriter 对象在 PlanContext 中存储数据。然后,通过对 ParamWriter 调用方法(比如 setString)写入参数。

创建解析器

Vertica 将在每个节点上调用 prepare(),以使用由 plan() 方法存储的数据来创建并初始化解析器。

定义参数

实施 getParameterTypes() 可定义解析器所使用的参数的名称和类型。Vertica 使用此信息对调用人员发出有关未知或缺失参数的警告。Vertica 会忽略未知参数并为缺失参数使用默认值。当您需要为函数定义类型和参数时,您不需要覆盖此方法。

定义解析器输出

实施 getParserReturnType() 可定义解析器输出的表列的数据类型。如果适用,getParserReturnType() 还可以定义数据类型的大小、精度和小数位数。通常,此方法从 argTypeperColumnParamReader 参数读取输出表的数据类型,并验证是否能够输出相应的数据类型。如果 getParserReturnType() 已准备好输出数据类型,则它会对 returnType 参数中传递的 SizedColumnTypes 对象调用方法。除了输出列的数据类型之外,方法还应指定有关列的数据类型的任何附加信息:

  • 对于二进制和字符串数据类型(例如,CHAR、VARCHAR 和 LONG VARBINARY),请指定其最大长度。

  • 对于 NUMERIC 类型,请指定其精度和小数位数。

  • 对于 Time/Timestamp 类型(无论是否带有时区),请指定其精度(-1 表示未指定)。

  • 对于 ARRAY 类型,请指定元素的最大数量。

  • 对于所有其他类型,无需指定长度或精度。

支持协作解析

要支持协作解析,请实施 prepareChunker() 并返回 UDChunker 子类的实例。如果 isChunkerApportionable() 返回 true,则此方法返回 null 是错误的。

目前仅在 C++ API 中支持协作解析。

支持分摊加载

要支持分摊加载,解析器、块分割器或这两者都必须支持分摊。要指示解析器可以分摊加载,请实施 isParserApportionable() 并返回 true。要指示块分割器可以分摊加载,请实施 isChunkerApportionable() 并返回 true

isChunkerApportionable() 方法会将 ServerInterface 作为实参,因此您可以访问 COPY 语句中提供的参数。例如,如果用户可以指定记录分隔符,您可能需要此类信息。当且仅当工厂可以为此输入创建块分割器时,此方法将返回 true

API

ParserFactory API 提供了以下通过子类扩展的方法:

virtual void plan(ServerInterface &srvInterface, PerColumnParamReader &perColumnParamReader, PlanContext &planCtxt);

virtual UDParser * prepare(ServerInterface &srvInterface, PerColumnParamReader &perColumnParamReader,
            PlanContext &planCtxt, const SizedColumnTypes &returnType)=0;

virtual void getParameterType(ServerInterface &srvInterface, SizedColumnTypes &parameterTypes);

virtual void getParserReturnType(ServerInterface &srvInterface, PerColumnParamReader &perColumnParamReader,
            PlanContext &planCtxt, const SizedColumnTypes &argTypes,
            SizedColumnTypes &returnType);

virtual bool isParserApportionable();

// C++ API only:
virtual bool isChunkerApportionable(ServerInterface &srvInterface);

virtual UDChunker * prepareChunker(ServerInterface &srvInterface, PerColumnParamReader &perColumnParamReader,
            PlanContext &planCtxt, const SizedColumnTypes &returnType);

如果要使用 分摊加载 将单个输入拆分成多个加载流,请实施 isParserApportionable() 和/或 isChunkerApportionable() 并返回 true。即使这些方法返回 true,也不能保证 Vertica 分摊加载。然而,如果这两个方法均返回 false,则表示解析器不会尝试这么做。

如果要使用 协作解析,请实施 prepareChunker() 并返回 UDChunker 子类的实例。仅 C++ API 支持协作解析。

Vertica 将为非隔离功能调用 prepareChunker() 方法。在隔离模式下使用函数时,此方法不可用。

如果您希望块分割器可用于分摊加载,请实施 isChunkerApportionable() 并返回 true

创建 ParserFactory 之后,您必须将其注册到 RegisterFactory 宏。

ParserFactory API 提供了以下通过子类扩展的方法:

public void plan(ServerInterface srvInterface, PerColumnParamReader perColumnParamReader, PlanContext planCtxt)
    throws UdfException;

public abstract UDParser prepare(ServerInterface srvInterface, PerColumnParamReader perColumnParamReader,
                PlanContext planCtxt, SizedColumnTypes returnType)
    throws UdfException;

public void getParameterType(ServerInterface srvInterface, SizedColumnTypes parameterTypes);

public void getParserReturnType(ServerInterface srvInterface, PerColumnParamReader perColumnParamReader,
                PlanContext planCtxt, SizedColumnTypes argTypes, SizedColumnTypes returnType)
    throws UdfException;

ParserFactory API 提供了以下通过子类扩展的方法:

class PyParserFactory(vertica_sdk.SourceFactory):
    def __init__(self):
        pass
    def plan(self):
        pass
    def prepareUDSources(self, srvInterface):
        # User implement the function to create PyUDParser.
        pass