-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Add support for overloading to macros #13062
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
…ultiple macro overloads in default functions
Tishj
reviewed
Jul 18, 2024
github-actions bot
pushed a commit
to duckdb/duckdb-r
that referenced
this pull request
Jul 19, 2024
Merge pull request duckdb/duckdb#13062 from Mytherin/macrooverloads
Mytherin
added a commit
that referenced
this pull request
Sep 1, 2025
This PR implements (optional) types for macro parameters. #13062 Implemented macro overloads: ```sql CREATE MACRO m (a) AS a, (a, b) AS a + b, (a, b, c) AS a + b + c; SELECT m(40, 2); -- 42 ``` Allowing different behavior based on the supplied arguments. More recently, #18684 improved how arguments can be supplied to macro's: ```sql CREATE MACRO m(a, b := '2') AS a || b; SELECT m(a := '4'); -- 42 ``` Allowing parameters without a default to be used by name, and parameters with a default to be used by position. This PR implements typed macro parameters, allowing macro's with the same number of parameters to be overloaded by type: ```sql CREATE OR REPLACE MACRO m (a TINYINT) AS a + 1, (a SMALLINT) AS a + 2, (a INTEGER) AS a + 3, (a BIGINT) AS a + 4, (a HUGEINT) AS a + 5, (a) AS a + 10; SELECT m(39::INTEGER) i; -- 42 ``` The macro overload is selected similar to our regular functions, and typed parameters can be mixed with untyped parameters: ```sql CREATE MACRO m (a VARCHAR) AS a || '2', (a INTEGER, b) AS a + b, (a, b INTEGER) AS a - b; SELECT m(4); -- Macro m() does not support the supplied arguments. You might need to add explicit type casts. SELECT m(4::VARCHAR); -- 42 SELECT m(40, 2); -- Macro m() has multiple overloads that match the supplied arguments. SELECT m(40, 2::TINYINT); -- 42 SELECT m(44::TINYINT, 2); -- 42 ``` Explicit types can also be supplied for parameters with default values: ```sql CREATE MACRO m(a VARCHAR := 42) AS a; -- Default value '42' for parameter 'a' cannot be implicitly cast to 'VARCHAR'. Please add an explicit type cast. CREATE MACRO m(a VARCHAR := '42') AS a; SELECT m(); -- 42 SELECT m(42); -- Macro m() does not support the supplied arguments. You might need to add explicit type casts. ``` This is useful for when different types require different behaviour, or when you don't want to accidentally supply an argument with a certain type to a function (which happens to me all the time in Python!). I've also significantly improved the binding process of macro's in general, written more descriptive error messages, and unified a lot of the scalar macro binding code with table macro binding code. All of the tricks above should also work for table macro's. Note that this is only supported with in-memory databases, temporary macro's, or with v1.4.0 storage or later: ```sh # in-memory DB duckdb -c "CREATE MACRO m(a INTEGER) AS a;" # works # disk DB duckdb my.duckdb -c "CREATE MACRO m(a INTEGER) AS a;" # Typed macro parameters are only supported for storage versions v1.4.0 and higher. # temporary macro for disk DB duckdb my.duckdb -c "CREATE TEMPORARY MACRO m(a INTEGER) AS a;" # works # explicit v1.4.0 storage duckdb -c "ATTACH 'my.duckdb' AS my (STORAGE_VERSION 'v1.4.0'); USE my; CREATE MACRO m(a INTEGER) AS a;" # works ```
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR adds support for overloads to scalar and table macros. Since macro arguments are not typed, overloads are exclusively possible on the number of positional parameters, i.e. after this PR it is possible to create macros that accept a variable number of positional arguments through overloading.
It is currently only possible to define all overloads when creating a macro - i.e. there is no support for adding overloads to existing macros. Example syntax:
If an overload is not present, the error message prints all possible overloads:
Similarly, table functions support this behavior as well:
Serialization
In order to preserve backwards compatibility, serialization is done in two parts. The first function is serialized in the old manner (as a single
function
). Any extra overloads, if present, are serialized in a new fieldextra_functions
. As such, macros without overloads are fully backwards and forwards compatible. Macros with overloads cannot be deserialized by older versions of DuckDB and lead to a serialization error.Postgres Privilege Functions
The macro overloads are used to add support for Postgres privilege functions that we have as part of the Postgres compatibility layer.
array_ptr
This PR also adds the
array_ptr
class. Thearray_ptr
is a non-owning pointer to an array of objects with a count. It is by default bounds-checked, and can be iterated over similar to a vector. There is also anunsafe_array_ptr
that is not bounds checked. The idea is that this pointer class can be used instead of raw pointers to represent arrays in a safer manner throughout the system.