Repository navigation
[Pg] Add PostGreSQL function support - #6467
FirstTimeGaming wants to merge 32 commits into
Conversation
Scaffolds PgFunction and builds out the helper classes such as PgFunctionBuilder and pgFunction
Add function type generics so we pass through specific types instead of widened types
Add infer helperrs for pg funtion returns and args
Add setof, tableReturn, void, record, trigger, helpers, udate type inferencing to be more explicit
Add type testing for all basic and custom cases for function arguments and return types
Update to beta stream, use AnyPgColumnBuilder, ResolvePgColumnConfig, InferSelectModel over previous alpha versions
Add callback function inside the builder to allow users to reference the defined function parameters, used exclusively for arguments for now
Add schema support to pgFunctions and add PgSchema.function() to mimic table style declarations
Mark pgFunctionWithSchema helper as internal with reference to public functions
Move function imports to the barrel import for functions add in a39b057
Explicitly omit parenthesis in PgFunctionArgument
Add runutime tests to confirm: * configuration * as(body) parsing * argument references
|
Thanks for picking this up! We run Postgres functions in production on Drizzle today through a userland workaround: TS definitions that a script turns into I wrote up an RFC that pulls the existing work together (this PR, #4753, #4844, #5373 and the v1 prototype from #5891) into one design for the v1 kit. It covers overload-aware identity, which changes need Happy to contribute test cases from our production use, or help with the drizzle-kit side on top of this PR, whichever is most useful to the maintainers. |
|
This information is amazing. My design choices align with the document you sent, and I'll be sure to follow that so that contributors stay aligned. My biggest issue right now is the edge cases I may not be thinking about. If there's any specific issues you have ran into regarding functions and trigger definition behavior as DDL that would be great information when writing test cases for the kit side. If you have any more questions feel free to comment on this PR or send me an email |
3663e7c to
d208a61
Compare
Add fromExports entry for functions, define DDL schema for functions
d208a61 to
162ac55
Compare
Normalize config values from string, giving api a small subset of types casted to strings
Map orm PgFunction state to serializable kit Function state
Remove unnecessary whitespace in `functionFrom`
Sort configuration so that we keep a consistent ordering to make diffs consistent even when users might change order
Use inline params in body so that we don't get parameterized values since we handle that conversion in kit
Create a consistent helper function for the SQL name of a function arg
Use argument name helper in kit from orm so naming stays consistent across changes
Get proper sql types through helpers so kit doesn't lose information on conversion
Use function table helper to get fully qualified escaped function name
Unwrap column to capture schema for an enum before returning it to builder
|
Thanks, great to hear the designs line up! Here are the edge cases that shaped our setup, roughly in the order I'd turn them into kit tests:
Happy to answer more here, or review the kit side when it's up. |
Serialize function arg defaults from AnyPgColumnBuilder
f6e5b08 to
3795c67
Compare
|
Hello, I have two design questions that weren't answered by the RFC 1. Argument naming and prefixingMy design prefixes arguments with
2. Declare conventionsPostGreSQL requires you to define variables you're going to use in a CREATE OR REPLACE FUNCTION public.get_active_users()
RETURNS uuid[]
LANGUAGE plpgsql
SECURITY INVOKER
AS $function$
DECLARE
users_list uuid[];
active_cutoff timestamptz := NOW() - INTERVAL '365 days';
BEGIN
SELECT COALESCE(ARRAY_AGG(user_id), ARRAY[]::uuid[])
INTO users_list
FROM public.users
WHERE last_activity > active_cutoff;
RETURN users_list;
END;
$function$;In the current API users would have to define this declare block manually in the as section Example const getActiveUsers = pgFunction('getActiveUsers', {
args: {},
returns: uuid().array(),
}).as(sql`
DECLARE
users_list uuid[];
active_cutoff timestamptz := NOW() - INTERVAL '365 days';
BEGIN
SELECT COALESCE(ARRAY_AGG(${users.userId}), ARRAY[]::uuid[])
INTO users_list
FROM ${users}
WHERE ${users.lastActivity} > active_cutoff;
RETURN users_list;
END;
`);But if we allowed users to define their variables in the declare block we could do two things
Example const getActiveUsers = pgFunction('getActiveUsers', {
args: {},
returns: uuid().array(),
declare: {
usersList: uuid().array(),
activeCutoff: date().default(sql`NOW() - INTERVAL '365 days'`)
}
}).as((f) => {
return sql`
SELECT COALESCE(ARRAY_AGG(${users.userId}), ARRAY[]::uuid[])
INTO ${f.declare.userList}
FROM ${users}
WHERE ${users.lastActivity} > ${f.declare.activeCutoff};
RETURN ${f.declare.userList}${f.declare.userList};
`
});Now this would come with the same issue as 1. where we may need to restrict this namespace with a prefix such as Please let me know if you have any questions. |
|
Thanks! On 1, I'd skip the On 2, a typed |
Convert functions from InterimSchema to DDL using arg overloads and marking duplicate signatures
Override the diff checker `getCompositeKey` when `entityType === 'functions'` so we can properly compare without losing overloads
Discover functions in diff, convert to json, push to json in order
Add support for `RETURNS NULL ON NULL INPUT` null input type
Add declare handler, tests, and kit discovery
Add basic function to sql convertors, ignoring arg and return type cases on funtion alterations
Allow arg and return type changes by dropping the function before creating it
Note: This is a draft to get feedback, full drizzle-kit implementation is not finished yet, future implementation will support full migration compatibility
Description
Adds first-class PostgreSQL function support to Drizzle ORM
Functions can be declared using
pgFunction()or through a PostgreSQL schema usingpgSchema(...).function().ORM
PgFunctionandPgFunctionBuilderSETOF,void,record, andtriggerreturnsExample:
Tests
Scope
This PR introduces the ORM PostgreSQL function api intended for code-first schema generation through Drizzle Kit.
Included:
drizzle-ormdeclaration APINot included:
PgTable,PgFunction, and behavior constructorOUT,INOUT, orVARIADICarguments