class UDAFRegistration extends Logging
Provides methods to register a UDAF (user-defined aggregate function) in the Snowflake database.
Session.udaf returns an object of this class.
To register a UDAF, you must:
- Define a UDAF class.
- Create an instance of that class, and register that instance as a UDAF.
The next sections describe these steps in more detail.
Defining the UDAF Class
Define a class that inherits from one of the UDAF[N] classes (e.g. UDAF1, UDAF2, etc.),
where n specifies the number of input arguments for your UDAF. For example, if your UDAF
passes in 2 input arguments, extend the UDAF2 class.
In your class, override the following methods:
initialize(), which returns the initial state of the aggregation.accumulate(), which updates the aggregation state with a new input row.merge(), which merges two aggregation states into one.terminate(), which produces the final output value from the aggregation state.outputType(), which returns a types.DataType object that describes the type of the returned value.
Supported Data Types
Snowflake supports the following data types for the input arguments and return value of a UDAF:
SQL Type | Scala Type | Java Type | Notes |
|---|---|---|---|
NUMBER | Short or Option[Short] | Short or java.lang.Short | Supported |
NUMBER | Int or Option[Int] | Integer | Supported |
NUMBER | Long or Option[Long] | Long or java.lang.Long | Supported |
FLOAT | Float or Option[Float] | Float or java.lang.Float | Supported |
DOUBLE | Double or Option[Double] | Double | Supported |
NUMBER | java.math.BigDecimal | java.math.BigDecimal | Supported |
VARCHAR | String or java.lang.String | java.lang.String | Supported |
BOOL | Boolean or Option[Boolean] | Boolean | Supported |
DATE | java.sql.Date | java.sql.Date | Supported |
TIME | java.sql.Time | java.sql.Time | Supported |
TIMESTAMP | java.sql.Timestamp | java.sql.Timestamp | Supported |
BINARY | Array[Byte] | byte[] | Supported |
ARRAY | Array[String] or Array[Variant] | String[] or Variant[] | Supported array of type Array[String] or Array[Variant] |
OBJECT | Map[String, String] or Map[String, Variant] | Map | For Scala, supported mutable map of type scala.collection.mutable.Map[String, String] or scala.collection.mutable.Map[String, Variant]. For Java, use inputSchema() to specify types. |
VARIANT | com.snowflake.snowpark.types.Variant | Variant | Supported |
Note: GEOGRAPHY and GEOMETRY types are not supported for UDAF input arguments or return values.
Note: Structured types (ARRAY, OBJECT, MAP with nested types) have limited support. For complex nested structures, consider using VARIANT type and performing conversion in your UDAF code.
Aggregation State Requirements
The aggregation state class must be serializable. To ensure compatibility with Kryo serialization:
- For best compatibility: The state class should implement
java.io.Serializableand have a public no-arg constructor. - For Scala case classes or classes without no-arg constructors: Kryo uses Objenesis to instantiate objects without calling constructors. This works when the server has Objenesis support enabled.
- For custom serialization: Implement
java.io.Externalizablefor fine-grained control over serialization.
Example of a UDAF Class
The following is an example of a UDAF class that computes the average of integers. The state is a custom class that holds the sum and count.
The UDAF passes in 1 argument, so the class extends UDAF1.
// State class must be Serializable with a no-arg constructor for Kryo deserialization class AvgState extends Serializable { var sum: Long = 0L var count: Long = 0L } class MyAvgUDAF extends UDAF1[AvgState, Double, Int] { override def initialize(): AvgState = new AvgState() override def accumulate(state: AvgState, input: Int): AvgState = { state.sum += input state.count += 1 state } override def merge(state1: AvgState, state2: AvgState): AvgState = { state1.sum += state2.sum state1.count += state2.count state1 } override def terminate(state: AvgState): Double = { if (state.count == 0) 0.0 else state.sum.toDouble / state.count } override def outputType(): DataType = DoubleType }
Registering the UDAF
Next, create an instance of the new class, and register the class by calling one of the UDAFRegistration methods. You can register a temporary or permanent UDAF by name.
Registering a Temporary UDAF By Name
To register a temporary UDAF by name, call registerTemporary, passing in a name for the UDAF
and an instance of the UDAF class. For example:
// Use the MyAvgUDAF defined in previous example. val myAvg = session.udaf.registerTemporary("my_avg", new MyAvgUDAF()) df.select(myAvg(col("a"))).show()
Registering a Permanent UDAF By Name
If you need to use the UDAF in subsequent sessions, register a permanent UDAF.
When registering a permanent UDAF, you must specify a stage where the registration method will upload the JAR files for the UDAF and its dependencies. For example:
val myAvg = session.udaf.registerPermanent("my_avg", new MyAvgUDAF(), "@myStage") df.select(myAvg(col("a"))).show()
- Since
1.19.0
- Alphabetic
- By Inheritance
- UDAFRegistration
- Logging
- AnyRef
- Any
- Hide All
- Show All
- Public
- Protected
Value Members
- final def !=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- final def ##: Int
- Definition Classes
- AnyRef → Any
- final def ==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- final def asInstanceOf[T0]: T0
- Definition Classes
- Any
- def clone(): AnyRef
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.CloneNotSupportedException]) @HotSpotIntrinsicCandidate() @native()
- final def eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- def equals(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef → Any
- final def getClass(): Class[_ <: AnyRef]
- Definition Classes
- AnyRef → Any
- Annotations
- @HotSpotIntrinsicCandidate() @native()
- def hashCode(): Int
- Definition Classes
- AnyRef → Any
- Annotations
- @HotSpotIntrinsicCandidate() @native()
- final def isInstanceOf[T0]: Boolean
- Definition Classes
- Any
- def log(): Logger
- Attributes
- protected[internal]
- Definition Classes
- Logging
- def logDebug(msg: String, throwable: Throwable): Unit
- Attributes
- protected[internal]
- Definition Classes
- Logging
- def logDebug(msg: String): Unit
- Attributes
- protected[internal]
- Definition Classes
- Logging
- def logError(msg: String, throwable: Throwable): Unit
- Attributes
- protected[internal]
- Definition Classes
- Logging
- def logError(msg: String): Unit
- Attributes
- protected[internal]
- Definition Classes
- Logging
- def logInfo(msg: String, throwable: Throwable): Unit
- Attributes
- protected[internal]
- Definition Classes
- Logging
- def logInfo(msg: String): Unit
- Attributes
- protected[internal]
- Definition Classes
- Logging
- def logTrace(msg: String, throwable: Throwable): Unit
- Attributes
- protected[internal]
- Definition Classes
- Logging
- def logTrace(msg: String): Unit
- Attributes
- protected[internal]
- Definition Classes
- Logging
- def logWarning(msg: String, throwable: Throwable): Unit
- Attributes
- protected[internal]
- Definition Classes
- Logging
- def logWarning(msg: String): Unit
- Attributes
- protected[internal]
- Definition Classes
- Logging
- final def ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- final def notify(): Unit
- Definition Classes
- AnyRef
- Annotations
- @HotSpotIntrinsicCandidate() @native()
- final def notifyAll(): Unit
- Definition Classes
- AnyRef
- Annotations
- @HotSpotIntrinsicCandidate() @native()
- def registerPermanent(funcName: String, udaf: JavaUDAF, stageLocation: String): AggregateFunction
Registers a Java UDAF instance as a permanent UDAF.
Registers a Java UDAF instance as a permanent UDAF.
- funcName
The name of the UDAF.
- udaf
The Java UDAF instance.
- stageLocation
The stage location to upload JARs.
- returns
An AggregateFunction representing the UDAF.
- Since
1.19.0
- def registerPermanent(funcName: String, udaf: UDAF, stageLocation: String): AggregateFunction
Registers a Scala UDAF instance as a permanent UDAF.
Registers a Scala UDAF instance as a permanent UDAF.
- funcName
The name of the UDAF.
- udaf
The Scala UDAF instance to be registered.
- stageLocation
The stage location to upload JARs.
- returns
An AggregateFunction representing the UDAF.
- Since
1.19.0
- def registerTemporary(funcName: String, udaf: JavaUDAF): AggregateFunction
Registers a Java UDAF instance as a temporary UDAF.
Registers a Java UDAF instance as a temporary UDAF.
- funcName
The name of the UDAF.
- udaf
The Java UDAF instance.
- returns
An AggregateFunction representing the UDAF.
- Since
1.19.0
- def registerTemporary(udaf: JavaUDAF): AggregateFunction
Registers a Java UDAF instance as a temporary anonymous UDAF that is scoped to this session.
Registers a Java UDAF instance as a temporary anonymous UDAF that is scoped to this session.
- udaf
The Java UDAF instance.
- returns
An AggregateFunction representing the UDAF.
- Since
1.19.0
- def registerTemporary(funcName: String, udaf: UDAF): AggregateFunction
Registers a Scala UDAF instance as a temporary UDAF.
Registers a Scala UDAF instance as a temporary UDAF.
- funcName
The name of the UDAF.
- udaf
The Scala UDAF instance to be registered.
- returns
An AggregateFunction representing the UDAF.
- Since
1.19.0
- def registerTemporary(udaf: UDAF): AggregateFunction
Registers a Scala UDAF instance as a temporary anonymous UDAF that is scoped to this session.
Registers a Scala UDAF instance as a temporary anonymous UDAF that is scoped to this session.
- udaf
The Scala UDAF instance to be registered.
- returns
An AggregateFunction representing the UDAF.
- Since
1.19.0
- final def synchronized[T0](arg0: => T0): T0
- Definition Classes
- AnyRef
- def toString(): String
- Definition Classes
- AnyRef → Any
- def udaf(funcName: String, execName: String = "", execFilePath: String = "")(func: => AggregateFunction): AggregateFunction
- Attributes
- protected
- Annotations
- @inline()
- final def wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException]) @native()
- final def wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
Deprecated Value Members
- def finalize(): Unit
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.Throwable]) @Deprecated
- Deprecated
(Since version 9)