-
-
Notifications
You must be signed in to change notification settings - Fork 151
feat(typegen): add functions setof type introspection #971
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
base: master
Are you sure you want to change the base?
Conversation
- Introspect the setof function fields for functions - Restore functions as unions of args + returns
317219e
to
64a1afc
Compare
Pull Request Test Coverage Report for Build 16782706401Details
💛 - Coveralls |
@@ -33,7 +33,7 @@ export default class PostgresMetaTypes { | |||
t.typrelid = 0 | |||
or ( | |||
select | |||
c.relkind ${includeTableTypes ? `in ('c', 'r')` : `= 'c'`} | |||
c.relkind ${includeTableTypes ? `in ('c', 'r', 'v')` : `= 'c'`} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment
Include functions that loops to a view for embedded functions.
select 1 from pg_class c | ||
where c.oid = rt.typrelid | ||
-- exclude custom types relation from what is considered a set of table | ||
and c.relkind in ('r', 'p', 'v', 'm', 'f') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment
All possible function embeding relations:
r | ordinary table
p | partitioned table
v | view
m | materialized view
f | foreign table
for (const column of columns) { | ||
if (column.table_id in columnsByTableId) { | ||
columnsByTableId[column.table_id].push(column) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment
Use traditional for loop to avoid the need to loop twice for filter then foreach/push.
for (const schema in introspectionBySchema) { | ||
introspectionBySchema[schema].tables.sort((a, b) => a.name.localeCompare(b.name)) | ||
introspectionBySchema[schema].views.sort((a, b) => a.name.localeCompare(b.name)) | ||
introspectionBySchema[schema].functions.sort((a, b) => a.fn.name.localeCompare(b.fn.name)) | ||
introspectionBySchema[schema].enums.sort((a, b) => a.name.localeCompare(b.name)) | ||
introspectionBySchema[schema].compositeTypes.sort((a, b) => a.name.localeCompare(b.name)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment
Group the place where we sort things for consistency to dedup the places where sorts are needed.
// OR if the function takes a table row but doesn't qualify as embedded (for error reporting) | ||
(inArgs[0].table_name && !func.return_table_name))) | ||
) { | ||
introspectionBySchema[func.schema].functions.push({ fn: func, inArgs }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment
We save the inArgs
along with the function definition as it'll be needed in many places when generating the function return types. Since it's already available keep it along for re-use.
if (conflictingFns.length > 0) { | ||
const conflictingFn = conflictingFns[0] | ||
const returnTypeName = typesById[conflictingFn.fn.return_type_id]?.name || 'unknown' | ||
return `Could not choose the best candidate function between: ${schema.name}.${fn.name}(), ${schema.name}.${fn.name}( => ${returnTypeName}). Try renaming the parameters or the function itself in the database so function overloading can be resolved` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment
This'll be used to warn the user at compile time that his function won't be available in postgrest due to conflicts.
} | ||
${ | ||
'is_updatable' in view && view.is_updatable | ||
view.is_updatable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment
Now we fill up the is_updatable
field with false if necessary: https://github.com/supabase/postgres-meta/pull/971/files#diff-c903ec71df16a8ae5f665c19c21b273f74c2f8eb02f5e8a3552ebe69d18be18fR76-R79
for (const fnName in schemaFunctionsGroupedByName) { | ||
schemaFunctionsGroupedByName[fnName].sort((a, b) => | ||
b.fn.definition.localeCompare(a.fn.definition) | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment
With functions having multiple definition overrides (same name) we sort them by definition text value. We might want to do another approach to have more stability 🤔
What kind of change does this PR introduce?
Add all the necessary informations for embeded functions type inferences to work in postgrest-js (see: feat(types): add embeded functions type inference postgrest-js#632 )
Canary tested that it's mostly retro-compatible by generating the types on the infrastructure codebase. The new type definition didn't raised much type errors but we don't use a lot of functions/
rpc
calls in it. So there is still a chance for this to break some codebases. Best approach might be to release this one as an-rc
release so it can be opt-in via local cliecho "vXX-rc" > supabase/.temp/postgres-meta-version && supabase gen types
That way with a canary release of the
postgrest-js
and thesupabase-js
we might release gradually with a way for people to opt-out if it causes issue.I'm open to suggestion about how to release this !
Closes: PGMETA-61