Skip to content
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

feat: select-query-parser-v2 #558

Merged
merged 124 commits into from
Oct 18, 2024
Merged

feat: select-query-parser-v2 #558

merged 124 commits into from
Oct 18, 2024

Conversation

avallete
Copy link
Member

@avallete avallete commented Sep 27, 2024

What kind of change does this PR introduce?

  • Introduces new, separate code for the parser and result types, each tested independently.
  • Adds corresponding type tests for each runtime test case.
  • Fixes several bugs related to type result inference.

What is the current behavior?

There are several result type mismatches referenced across multiple issues:

I have reproduced these issues in test cases with similar topologies to verify runtime behavior and ensure proper type inference.

What is the new behavior?

The rewrite should resolve all the related issues regarding select operations that I’ve encountered so far. However, I may have missed some cases, and there could be regressions in edge cases (despite passing all existing tests). Given the number of related issues, I’m unsure if the previous test coverage was sufficient. I recommend to deploy that out over an rc version first in coordination with supabase-js rc candidate so we can gather feedbacks about possibles regression before making the switch.

Additionally, we might need to evaluate how this performs on large databases with many tables and relations. The use of recursive types could potentially introduce performance concerns in such cases.

Additional context

I didn’t rewrite the original parser for fun. After spending a considerable amount of time trying to fix the existing one (I swear I tried see: #554 😓 ), it became clear that starting fresh with a cleaner, more testable, and debuggable version was necessary. I know it make for a big PR but I wasn't able to really reduce more than that the amount of changes, sorry 😅

alaister and others added 30 commits October 11, 2022 21:27
…sion

Chore/revert to old typedoc version
Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.0.4 to 3.1.2.
- [Release notes](https://github.com/isaacs/minimatch/releases)
- [Commits](isaacs/minimatch@v3.0.4...v3.1.2)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
This makes the doc comments show up for all the function signatures,
instead of just the first one.
Bumps [json5](https://github.com/json5/json5) from 2.2.1 to 2.2.3.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](json5/json5@v2.2.1...v2.2.3)

---
updated-dependencies:
- dependency-name: json5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
RPC return types aren't getting propagated properly. E.g. if a function
returns `boolean`, the `data` will be typed as `boolean[]`.

To fix this, we change PostgrestBuilder's type parameter to be the
actual type of `data`, instead of the element type of `data` (which
assumes `data` is always an array, which is incorrect).

In doing so we effectively remove all usage of `PostgrestResponse` and
`PostgrestMaybeSingleResponse`. We can stop exporting these on the next
major version.

This also fixes the behavior of `.returns<NewResult>()`, which was
inconsistent with the documentation (i.e. `data` was typed as
`NewResult[]` instead of `NewResult`).
* Prettify intersected types when selecting multiple columns

Resolves #398

* update type test

---------

Co-authored-by: Bobbie Soedirgo <[email protected]>
@avallete
Copy link
Member Author

avallete commented Oct 4, 2024

Alright !

I've been able to use this new version within the larger codebase without lint errors in worker/api/monitoring so I'm now more confident that there should be little regression with this new parser version.

Only change I had to make on the supabase-js side of things were for rpc calls and porting the relationships types to be 1-1 with postgrest-js:

diff --git a/src/SupabaseClient.ts b/src/SupabaseClient.ts
index 9f0a32c..3ca6f8e 100644
--- a/src/SupabaseClient.ts
+++ b/src/SupabaseClient.ts
@@ -221,7 +221,9 @@ export default class SupabaseClient<
         ? Fn['Returns'][number]
         : never
       : never,
-    Fn['Returns']
+    Fn['Returns'],
+    null,
+    null
   > {
     return this.rest.rpc(fn, args, options)
   }
diff --git a/src/lib/types.ts b/src/lib/types.ts
index 85531a0..0b8d329 100644
--- a/src/lib/types.ts
+++ b/src/lib/types.ts
@@ -80,16 +80,26 @@ export type SupabaseClientOptions<SchemaName> = {
   accessToken?: () => Promise<string>
 }
 
+export type GenericRelationship = {
+  foreignKeyName: string
+  columns: string[]
+  isOneToOne?: boolean
+  referencedRelation: string
+  referencedColumns: string[]
+}
+
 export type GenericTable = {
   Row: Record<string, unknown>
   Insert: Record<string, unknown>
   Update: Record<string, unknown>
+  Relationships: GenericRelationship[]
 }
 
 export type GenericUpdatableView = GenericTable
 
 export type GenericNonUpdatableView = {
   Row: Record<string, unknown>
+  Relationships: GenericRelationship[]
 }
 
 export type GenericView = GenericUpdatableView | GenericNonUpdatableView

So this is now ready for review whenever you have time for it @soedirgo 👍

@whollacsek
Copy link

Would this PR fix type error when using virtual columns (ie. calling postgres function as column)?

@avallete
Copy link
Member Author

avallete commented Oct 9, 2024

Would this PR fix type error when using virtual columns (ie. calling postgres function as column)?

Hey, I'm not sure what issue you're referring too I don't think so, from my understanding the only way to call functions in postgrest is via RPC (https://docs.postgrest.org/en/v12/references/api/functions.html).

The only way I think you could achieve to use them as columns would be via some kind of views maybe ?

Also note that this PR does not impact any runtime behavior, only make the result types inference match it better.

@whollacsek
Copy link

whollacsek commented Oct 9, 2024

What I was referring to does work (see: https://docs.postgrest.org/en/latest/references/api/computed_fields.html#computed-fields), my question is about fixing the generated type as the typescript error message is preventing builds of my next.js app to succeed. I've been forced to add ts-ignore everywhere since 2 years and I was thinking that this PR sounds like it would fix this issue

@avallete
Copy link
Member Author

avallete commented Oct 9, 2024

What I was referring to does work (see: https://docs.postgrest.org/en/latest/references/api/computed_fields.html#computed-fields), my question is about fixing the generated type as the typescript error message is preventing builds of my next.js app to succeed. I've been forced to add ts-ignore everywhere since 2 years and I was thinking that this PR sounds like it would fix this issue

Thank's for pointing out the case, I'll have a look, if it's correctly picked up as a column during introspection then it should work. Otherwise, if it's considered a function I don't think the current version will fix this issue. I'll make a test case to make sure of it tough.

@whollacsek
Copy link

I see in any case thank you for taking the time to improve this part of supabase SDK!

@avallete
Copy link
Member Author

avallete commented Oct 9, 2024

I'm locking the discussion to keep the focus on the PR review. Please open an issue or comment over a current one if you want to discuss details.

@supabase supabase locked as off-topic and limited conversation to collaborators Oct 9, 2024
soedirgo and others added 9 commits October 10, 2024 03:45
* move all parsing logic into one file to clearly delineate module
boundaries (parsing vs. result type resolution)
* collapse non-embedded resource parsing into one type
* make `!left` a no-op
* resolve all errors in parser.test-d.ts
@soedirgo soedirgo force-pushed the avallete/fix-select-query-parser branch from d52234f to c6c2795 Compare October 18, 2024 06:57
@soedirgo soedirgo changed the base branch from master to rc October 18, 2024 07:03
@soedirgo soedirgo merged commit 5a87c05 into rc Oct 18, 2024
1 check passed
@avallete avallete deleted the avallete/fix-select-query-parser branch October 23, 2024 09:37
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.