Important
The SingleStore 9.1 release candidate (RC) gives you the opportunity to preview, evaluate, and provide feedback on new and upcoming features prior to their general availability. In the interim, SingleStore 9.0 is recommended for production workloads, which can later be upgraded to SingleStore 9.1.
Overloaded Functions and Stored Procedures
On this page
Note
This is a Preview feature.
User Defined Functions (UDFs) and Stored Procedures (SPs) can be overloaded.
Enable Function and Procedure Overloading
Enable function and procedure overloading by setting the engine variable enable_ to ON.OFF by default.
SET GLOBAL enable_overloaded_functions = ON;
Important
Once enable_ is set to ON, it cannot be turned OFF.
Introductory Example
Imagine creating a "pretty print" function for different types; the "pretty print" functions receive values and return a formatted string as a VARCHAR.
Without function overloading, each variant must have a unique name.
Without Overloading
CREATE OR REPLACE FUNCTION PrettyPrint_Int (value INT) RETURNS VARCHAR(100) ...CREATE OR REPLACE FUNCTION PrettyPrint_2Ints (value1 INT, value2 INT) RETURNS VARCHAR(100) ...CREATE OR REPLACE FUNCTION PrettyPrint_Varchar (value VARCHAR(100)) RETURNS VARCHAR(100) ...
With Overloading
CREATE OR REPLACE FUNCTION PrettyPrint (value INT) RETURNS VARCHAR(100) ...CREATE OR REPLACE FUNCTION PrettyPrint (value1 INT, value2 INT) RETURNS VARCHAR(100) ...CREATE OR REPLACE FUNCTION PrettyPrint (value VARCHAR(100)) RETURNS VARCHAR(100) ...
Supported Types
The following types are supported for function overloading:
-
Numeric types
-
INT,TINYINT,SMALLINT,MEDIUMINT,BIGINT -
BOOL -
FLOAT,DOUBLE,DECIMAL
-
-
String types
-
CHAR,VARCHAR -
BINARY,VARBINARY -
TEXT,TINYTEXT,MEDIUMTEXT,LONGTEXT -
BLOB,TINYBLOB,MEDIUMBLOB,LONGBLOB
-
Create an Overloaded Function or Procedure
Use the standard CREATE FUNCTION (UDF) or CREATE PROCEDURE syntax to create an overloaded function or procedure.
Note
Function overloading works the same for functions and procedures.
When function overloading is enabled and CREATE FUNCTION is called, the system creates an overloaded function if the following criteria are met.
-
All input types are in the list of supported types.
-
There is not a non-overloaded function with the same name as the new function.
-
Refer to Non-Overloaded Functions for more information.
-
-
There is no function, overloaded or not, with the same name and input types as the new function.
-
Overloading on type length is not supported.
Refer to Type Equality for more information. -
Overloading with types that are within certain groups of types is not supported (for example, types that differ only in length or charset).
Refer to Type Groups for more information.
-
If these function overloading criteria are not met, the following occurs:
-
If there is a non-overloaded function with the same name as the new function, an error is raised.
-
If there is a function, overloaded or not, with the same name and input types as the new function, an error is raised.
-
If one or more input type(s) are not in the list of supported types, a non-overloaded function is created.
When CREATE OR REPLACE FUNCTION is used:
-
If a non-overloaded function with the same name exists, that function is replaced with the new definition.
-
If an overloaded function with the same signature (name and arguments) exists, that function is replaced with the new definition.
-
Otherwise, a new function is created.
Important
When using CREATE OR REPLACE FUNCTION, if a non-overloaded function with the same name exists, that function is replaced with the new definition.
Non-Overloaded Functions
Functions created prior to enabling function overloading are non-overloaded functions and cannot be overloaded.
Attempting to overload a non-overloaded function returns an error.CREATE OR REPLACE to recreate the function.
Variant ID
Each overloaded function is assigned a unique variant ID which distinguishes that function from other functions with the same name.
Use SHOW FUNCTIONS to obtain an overloaded function's variant ID and its input argument types, as shown in the following example.
CREATE OR REPLACE FUNCTION x() ...CREATE OR REPLACE FUNCTION x(a int) ...CREATE OR REPLACE FUNCTION x(a int, b int) ...CREATE OR REPLACE FUNCTION x(a bigint) ...CREATE OR REPLACE FUNCTION y(a bigint) ...SHOW FUNCTIONS;
+-----------------+-----------+-----------------------+------------+---------+-------------+--------------+------+---------+
| Functions_in_db | Arguments | Function Type | Variant ID | Definer | Data Format | Runtime Type | Link | Options |
+-----------------+-----------+-----------------------+------------+---------+-------------+--------------+------+---------+
| x | | User Defined Function | 0 | root@% | | PSQL | | |
| x | BIGINT | User Defined Function | 3 | root@% | | PSQL | | |
| x | INT | User Defined Function | 1 | root@% | | PSQL | | |
| x | INT, INT | User Defined Function | 2 | root@% | | PSQL | | |
| y | BIGINT | User Defined Function | 0 | root@% | | PSQL | | |
+-----------------+-----------+-----------------------+------------+---------+-------------+--------------+------+---------+Type Equality
Function overloading treats the following types as equal:
-
Types that differ only in the length parameter (e.
g. , CHAR(10)andCHAR(20)). -
Types that are equivalent in SingleStore (e.
g. , BOOLandTINYINT).
If two function variants have the same number of arguments and all argument types are equivalent, the second CREATE FUNCTION returns an error.
The following commands attempt to create two variants of PrettyPrint that differ only in the length of the CHAR argument.
CREATE FUNCTION PrettyPrint (value CHAR(10)) RETURNS VARCHAR(100) ... -- succeeds
CREATE FUNCTION PrettyPrint (value1 CHAR(20)) RETURNS VARCHAR(100) ...
ERROR 3020 (HY000): Function `PrettyPrint` with same parameter types already exists.Type Groups
For function overloading, types within the following groups are considered equivalent.
-
TINYINTandSMALLINT. -
MEDIUMINTandINT. -
Fixed-size string:
CHAR(LENGTH)andBINARY(LENGTH)(differ only in charset). -
Variable-length string:
VARCHARandVARBINARY(differ only in charset). -
Blob and text types:
LONGBLOB,MEDIUMBLOB,BLOB,TINYBLOB,TEXT,LONGTEXT,MEDIUMTEXT, andTINYTEXT(differ only in length).
Any two types from any of these groups are considered equivalent.VARCHAR and VARBINARY are considered equivalent, LONGBLOB and TEXT are considered equivalent.
For a function variant to be valid, it must differ from existing variants in at least one of the following ways:
-
A different number of arguments.
-
At least one argument of a non-equivalent type.
The following commands attempt to create two variants of PrettyPrint, both with fixed-size string arguments.
CREATE FUNCTION PrettyPrint (value CHAR(10)) RETURNS VARCHAR(100) ...-- succeeds, creates function PrettyPrint with ID 0
CREATE FUNCTION PrettyPrint (value1 BINARY(10)) RETURNS VARCHAR(100) ...
ERROR 3021 (HY000): Cannot create function `db`.`PrettyPrint`: it is ambiguous with respect to a variant with ID 5. Creating such a function will result in ambiguous function calls. If you want to create function with the new definition, drop the existing function with 'DROP FUNCTION `db`.`PrettyPrint` WITH ID 5'."To resolve this error, either keep and use the first function definition, with the CHAR(10) argument, or drop that function and recreate the function with the BINARY(10) argument.
Drop an Overloaded Function or Procedure
Note
Function overloading works the same for functions and procedures.
If there is only one variant of the overloaded function, that is, there is only one function with that function name, drop the function using the existing DROP FUNCTION syntax.
To drop a function with multiple variants, obtain the variant ID from SHOW FUNCTIONS and use the following syntax.
DROP FUNCTION [IF EXISTS] { function_name | database_name.function_name } WITH ID variant_id;
Dropping an overloaded function with multiple variants without the WITH ID clause returns an error.
Overloaded Function and Procedure Resolution
Note
Function overloading works the same for functions and procedures.
When an overloaded function with multiple variants is called, the engine resolves which variant to run by finding the variant whose parameter types most closely match the types of the input arguments.
The engine defines argument type matches as follows:
-
Exact (strong) match: The argument type exactly matches the parameter type (for example,
INT-INT). -
Compatible (light) match: The argument can be converted to the parameter type (for example,
INT-BIGINT).-
If the parameter and argument types are both numeric types or both string types, that is considered a Compatible match.
-
-
No match: All other conversions are not considered a match (for example,
VARCHAR-INT).
The engine chooses the variant to run as follows:
-
Filter by number of arguments.
-
Exclude all variants with a different number of arguments than the number of parameters in the function call.
-
If there is exactly one variant remaining, select that variant.
If there are no variants remaining, return an error. If there are multiple variants remaining, proceed to Step 2.
-
-
Filter by argument type.
-
Exclude all variants where at least one parameter in the function call cannot be matched (exact or compatible) to an argument in the variant definition.
-
If there is exactly one variant remaining, select that variant.
If there are no variants remaining, return an error. If there are multiple variants remaining, proceed to Step 3.
-
-
Prefer the most specific match.
-
Among the remaining candidates, select the variant with the highest number of exact (strong) matches.
-
-
If multiple variants have the same number of exact (strong) matches, the function call is considered ambiguous and an error is returned.
-
Use explicit casts in the function call to avoid the ambiguity.
Refer to Example 2 - Use Explicit Casts to Resolve Ambiguous Function Resolution for an example of using explicit casts to avoid ambiguous function calls.
-
After the variant is selected, the engine typecasts the arguments in the function call to the corresponding types in the variant definition.
Usage of Overloaded Functions in UDAFs
Overloaded functions cannot be used in User-Defined Aggregate Functions (UDAFs).
-
Overloading a function that is already used in a UDAF is not supported.
-
Creating a UDAF using an overloaded function is not supported.
Examples
Example 1 - Create and Call an Overloaded Function
Create an overloaded function print_ with two variants.
DELIMITER //CREATE FUNCTION print_type(input INT) RETURNS TEXT ASBEGINRETURN "Integer";END //CREATE FUNCTION print_type(input BIGINT) RETURNS TEXT ASBEGINRETURN "Big Integer";END//DELIMITER ;
Display the overloaded functions and their variant IDs.
SHOW FUNCTIONS;
+-------------------+-----------+-----------------------+------------+---------+-------------+--------------+------+---------+
| Functions_in_test | Arguments | Function Type | Variant ID | Definer | Data Format | Runtime Type | Link | Options |
+-------------------+-----------+-----------------------+------------+---------+-------------+--------------+------+---------+
| print_type | BIGINT | User Defined Function | 1 | root@% | | PSQL | | |
| print_type | INT | User Defined Function | 0 | root@% | | PSQL | | |
+-------------------+-----------+-----------------------+------------+---------+-------------+--------------+------+---------+Create a table and insert data into that table.
CREATE TABLE t(i INT, b BIGINT, t TINYINT);INSERT INTO t VALUES (1,2,3);
It is possible to call function print_ for columns i and b without explicit casts, because function resolution can unambiguously choose the best candidate.
SELECT print_type(i)FROM t;
+---------------+
| print_type(i) |
+---------------+
| Integer |
+---------------+SELECT print_type(b)FROM t;
+---------------+
| print_type(b) |
+---------------+
| Big Integer |
+---------------+Example 2 - Use Explicit Casts to Resolve Ambiguous Function Resolution
This example uses the table t created in the preceding example.
CREATE TABLE t(i INT, b BIGINT, t TINYINT);INSERT INTO t VALUES (1,2,3);
Create two variants of the function format_.INT as input and the other takes a BIGINT as input.
DELIMITER //CREATE FUNCTION format_value(input INT) RETURNS TEXT ASBEGINRETURN FORMAT(input, 1);END //CREATE FUNCTION format_value(input BIGINT) RETURNS TEXT ASBEGINRETURN FORMAT(input, 1);END//DELIMITER ;
As in the preceding example, when format_ is called on the INT column i or the BIGINT column b, the engine can unambiguously choose which variant to call.
SELECT format_value(i)FROM t;
+-----------------+
| format_value(i) |
+-----------------+
| 1.0 |
+-----------------+However, if format_ is called on the TINYINT column t, the engine cannot determine which variant to call, as TINYINT is a Compatible match for both INT and BIGINT.
SELECT format_value(t)FROM t;
ERROR 3021 (HY000): Ambiguous function call: `format_value` has multiple overloads matching the provided arguments. Consider using explicit casts for one or more arguments to specify parameter types.Use an explicit cast to call format_ on the TINYINT column t.
SELECT format_value(t:>INT)FROM t;
+----------------------+
| format_value(t:>INT) |
+----------------------+
| 3.0 |
+----------------------+Example 3 - Overloading a Non-Overloaded Function (Error)
Attempting to overload a non-overloaded function returns an error, as shown in the following example.
Verify that function overloading is not enabled.
SELECT enable_overloaded_functions;
+-------------------------------+
| @@enable_overloaded_functions |
+-------------------------------+
| 0 |
+-------------------------------+Create a function f; f is created as a non-overloaded function.
DELIMITER //CREATE FUNCTION f(a INT) RETURNS TEXT ASBEGINRETURN "This is a non-overloaded function";END //DELIMITER ;
Turn on function overloading.
SET GLOBAL enable_overloaded_functions = ON;
+-------------------------------+
| @@enable_overloaded_functions |
+-------------------------------+
| 1 |
+-------------------------------+Try to overload function f.
DELIMITER //CREATE FUNCTION f(a BIGINT) RETURNS TEXT ASBEGINRETURN "Try to overload function f";END //DELIMITER ;
ERROR 3012 (HY000): Cannot create function `f` because it already exists. To overload this function, it must be upgraded first: drop the function and then recreate it.To resolve the error drop f, and recreate it.
Example 4 - Create and Call an Overloaded Procedure
Create an overloaded procedure output_ with two variants.
DELIMITER //CREATE PROCEDURE output_type(input INT) ASBEGINECHO SELECT "Integer";END //CREATE PROCEDURE output_type(input BIGINT) ASBEGINECHO SELECT "Big Integer";END//DELIMITER ;
Display the overloaded procedures and their variant IDs.
SHOW PROCEDURES;
+--------------------+-----------+------------------+------------+---------+
| Procedures_in_test | Arguments | Routine Lifetime | Variant ID | Definer |
+--------------------+-----------+------------------+------------+---------+
| output_type | BIGINT | Permanent | 1 | root@% |
| output_type | INT | Permanent | 0 | root@% |
+--------------------+-----------+------------------+------------+---------+Call the two variants.
CALL output_type(1:>INT);
+---------+
| Integer |
+---------+
| Integer |
+---------+CALL output_type(1:>BIGINT);
+-------------+
| Big Integer |
+-------------+
| Big Integer |
+-------------+Last modified: March 17, 2026