v0.14 to v1 Function Migration

If there are inaccuracies discovered with this documentation, please submit a GitHub issue.

This guide is intended to cover the differences between the function interfaces used in partiql-lang-kotlin v0.14 and partiql-lang-kotlin v1.

Background on v0.14’s PartiQLFunction

PartiQLFunction was introduced in partiql-lang-kotlin v0.13-alpha to provide scalar and aggregation function capabilities. The interface-based design served its initial purpose but revealed several limitations as the function system evolved. By the time v0.14.9 was released, the PartiQL team identified significant issues with the function modeling approach.

1. Interface-based architecture was hard to extend

PartiQLFunction used interfaces extensively, which made it difficult to add new functionality without breaking existing APIs. Abstract classes provide better extensibility and reduce boilerplate code for implementers.

2. Manual parameter validation and type safety

In v0.14, function implementers had to manually handle null checking, type validation, and parameter extraction. Functions received PartiQLValue arrays without compile-time type guarantees, requiring manual type checking and casting. This was error-prone and led to repetitive boilerplate code in every function implementation.

3. Fragmented signature system

Function signatures were split between FunctionSignature.Scalar and FunctionSignature.Aggregation, creating unnecessary API surface area since both had significant overlap. This complicated generic contexts where the function type wasn’t known in advance.

4. Complex overload management

Function overloading required manual creation of multiple function classes with different signatures. For functions with many possible type combinations, this could result in n² separate implementations with no built-in overload resolution mechanism.

Background on Function System in v1

The function system in PLK v1 was redesigned to address the prior pain points of PartiQLFunction. It provides abstract classes (Fn, Agg) and overload classes (FnOverload, AggOverload) with builder patterns for better extensibility and developer experience. The new architecture includes unified signatures (RoutineSignature), overload signatures (RoutineOverloadSignature), type-safe parameters (Parameter), and automatic validation to reduce boilerplate code.

To use the new function system, we’ve provided more examples within the partiql-lang-kotlin library’s migration guide

Included in the code examples are how to

Other Differences

  • v1 uses unified RoutineSignature for both scalar and aggregation functions, reducing API surface area and simplifying generic contexts. v0.14 uses separate FunctionSignature.Scalar and FunctionSignature.Aggregation classes.

  • v1 function system is consolidated into partiql-spi. v0.14 PartiQLFunction components are pulled in from partiql-types and partiql-spi. We made this change since all function components are interrelated and maintaining separate packages created unnecessary complexity.

  • v1 introduces builder patterns (Fn.Builder, FnOverload.Builder) for cleaner construction with validation and defaults, especially beneficial for Java users working with objects that have many parameters and arguments.

  • v1 provides isNullCall() and isMissingCall() flags to control routine behavior when arguments are NULL or MISSING, allowing functions to specify their null/missing call semantics declaratively.

  • v1 introduces RoutineOverloadSignature for efficient overload matching without requiring full signature information during overload resolution.

  • v1 provides two approaches for function implementation. Use Fn when implementing a function for a single, well-defined type signature. Use FnOverload when a function name needs to support multiple parameter type combinations, as it can manage several type-specific implementations under one function name. This design prevents the exponential growth of individual function classes that would otherwise be needed for polymorphic operations.