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

Resolves domain base types #402

Closed

Conversation

andrew-w-ross
Copy link
Contributor

@andrew-w-ross andrew-w-ross commented Aug 2, 2023

Closes #399 and potentially #370.

Looks like citext type doesn't extend text this pr won't fix it.

I think the coding portion of this is done.
Still need to finish off the domain type tests and the domain array type tests.

Slight deviation is that array types resolve as [base_type] instead of [Opaque].

Edit: I knew that felt too easy, looks like mutation updates have some bugs but for some odd reason mutation insert works fine.

Edit: That was a lot harder then expected a lot of edge cases to deal with.

I'm going to mark this as ready for review but I think there might be potential tests for nullability in domain types.

E.g.

create domain not_null_int as int not null;

create table not_null_test (
    id serial primary key,
    field_int not_null_int
 );

Will resolve with a graphql type of:

type NotNullTest {
 id: Int!
 fieldInt: Int
}

Considering this is a bit of an anti pattern, check the notes section for create domain, it might not be worth dealing with.

sql/load_sql_context.sql Outdated Show resolved Hide resolved
sql/load_sql_context.sql Outdated Show resolved Hide resolved
test/expected/domain_field_types.out Outdated Show resolved Hide resolved
test/sql/domain_field_types.sql Show resolved Hide resolved
test/sql/domain_field_types.sql Show resolved Hide resolved
test/sql/domain_field_types.sql Show resolved Hide resolved
test/expected/domain_field_types.out Outdated Show resolved Hide resolved
Removes nightly from docker file for rust
Reverts docker file change
Improved configuration documentation
More domain type testing
@andrew-w-ross andrew-w-ross marked this pull request as ready for review August 17, 2023 04:19
@andrew-w-ross
Copy link
Contributor Author

@imor Should I update this pr or is there no hope in getting it in?

@imor
Copy link
Contributor

imor commented Sep 20, 2023

Hey @andrew-w-ross I thought this was still in progress. If this was ready, ideally I'd re-request review from the reviewers section at the top right of the PR. Anyways, I've just fixed a conflict and will review by tomorrow.

@andrew-w-ross
Copy link
Contributor Author

@imor Thanks, will do next time

Copy link
Contributor

@imor imor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @andrew-w-ross for this PR. Looking good. Just one question about functions below.

@olirice please take a quick look at this PR, if everything looks good we can merge.

src/sql_types.rs Show resolved Hide resolved
Copy link
Contributor

@olirice olirice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great stuff! thanks for putting so much thought into the tests

a few nits but conceptually I'd love to get this merged

Comment on lines +546 to +618
fn replace_array_element_base_type(mut context: Context) -> Context {
for (_, type_) in context.types.iter_mut() {
let array_element_type_oid = match type_.array_element_type_oid {
Some(oid) => oid,
None => continue,
};

let resolve_base_type = context
.schemas
.get(&type_.schema_oid)
.is_some_and(|s| s.directives.resolve_base_type);

if !resolve_base_type {
continue;
}

let array_element_type = match context.base_type_map.get(&array_element_type_oid) {
Some(oid) => *oid,
None => continue,
};

if let Some(type_) = Arc::get_mut(type_) {
type_.array_element_type_oid = Some(array_element_type);
}
}

context
}

fn replace_table_base_types(mut context: Context) -> Context {
for (_, table) in context.tables.iter_mut() {
let resolve_base_type = context
.schemas
.get(&table.schema_oid)
.is_some_and(|s| s.directives.resolve_base_type);

if !resolve_base_type {
continue;
}

let table = match Arc::get_mut(table) {
None => continue,
Some(table) => table,
};

for column in table.columns.iter_mut() {
let base_oid = match context.base_type_map.get(&column.type_oid) {
Some(oid) => *oid,
None => continue,
};

if let Some(column) = Arc::get_mut(column) {
column.type_oid = base_oid;
}
}

//Technically speaking, we should check the schema of the function to see if we should resolve the base type
//Problem is this might be counter-intuitive to the user as in this case the function is acting as a virtual column of the table
for function in table.functions.iter_mut() {
let base_oid = match context.base_type_map.get(&function.type_oid) {
Some(oid) => *oid,
None => continue,
};

if let Some(function) = Arc::get_mut(function) {
function.type_oid = base_oid;
}
}
}

context
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about extending TypeCategory and TypeDetails with a Domain variant and handling the resolution logic in to_graphql_type to keep it consistent with the existing type resolution stuff?

The context is the source of truth for the database' state and I'd like to be able to continue using it confidently for things like casting user input via the SQL layer during transpilation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@olirice Fair point I was trying to change as little as possible initially but that's been thrown out of the window at this point. It makes sense to include it as there is a decent amount more that can be done with that data. I'll get to it this weekend but if you don't mind just review this outline and correct me if I misunderstood something.

Change the base_type_map to domain instead and pull out all relevant, I'm thinking the oid, schema_oid, name, nullability, and possibly the element_oid. Might add the base_oid to that type to help with traversing the types later.

Change the types to include Domain in category type and adding it to the TypeCategory enum. Also create a Domain struct and add it to TypeDetails.

Revert the replace functions in load_sql_context. Mapping the domain type in the type details function.

Finally adding another match block to for Domain in the to_graphql_type function.

As for the tests, you're happy with them as is so if they pass we're good right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the base_type_map to domain instead and pull out all relevant, I'm thinking the oid, schema_oid, name, nullability, and possibly the element_oid. Might add the base_oid to that type to help with traversing the types later.

sorry I didn't understand what you're proposing here. Could you explain the goal at a higher level?

was that related to my comment "How about resolve_domains_as_base_type for clarity?"?
if so, I was only referring to the name of the comment directive. The name of the SQL CTE is okay as-is

Change the types to include Domain in category type and adding it to the TypeCategory enum. Also create a Domain struct and add it to TypeDetails.

yep

Revert the replace functions in load_sql_context. Mapping the domain type in the type details function.

yep

Finally adding another match block to for Domain in the to_graphql_type function.

yep

As for the tests, you're happy with them as is so if they pass we're good right?

they looked good on my first pass. I'll re-review when you're ready but if any need to be adjusted I'm happy to do it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was that related to my comment "How about resolve_domains_as_base_type for clarity?"?

Nope, just changing the config key.

sorry I didn't understand what you're proposing here. Could you explain the goal at a higher level?

Type category tends to map to a type off of the context query. Enum to enums, Composite to composites and Table to tables. I was just going to do the same for domain types. I can add the base_oid under table_oid. That's all the info I need to get this done for now. I was just thinking ahead for all the other data you might need for domains, like is it nullable or is it an array, etc.

sql/load_sql_context.sql Show resolved Hide resolved
docs/configuration.md Show resolved Hide resolved
} +
}
(1 row)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a tests that show what kind of error output we get if a user provides an invalid input value for a domain field?

For example, given a pos_int domain:

  • what happens if the user enters a negative number in a Filter
  • what happens if the user tries to insert a negative value

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do, Is this just for documenting behavior or is there a specific expected behavior other then returning:

 { 
     "data": null,
     "errors": [ 
         {
             "message": "Something bad happened."
         }
     ]
 }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just for documenting behavior, but if its too generic I might make a note to improve in the future

@olirice olirice marked this pull request as draft October 3, 2023 13:05
@olirice
Copy link
Contributor

olirice commented Oct 3, 2023

@andrew-w-ross I've converted this to a draft to keep the PRs clear. Please mark it "ready for review" once your ready

@olirice
Copy link
Contributor

olirice commented Oct 13, 2023

closing this for now. please re-open when you're ready

@olirice olirice closed this Oct 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Better domain type support
3 participants