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

WIP: Schema support #1466

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open

WIP: Schema support #1466

wants to merge 6 commits into from

Conversation

arrowd
Copy link
Contributor

@arrowd arrowd commented Jan 17, 2023

This is a first take on #1454

It adds entitySchema field and teach sqlite backend to use it. I'm a bit worried that I had to import Internal modules, so I decided to ask for early feedback.

@arrowd arrowd force-pushed the schema branch 6 times, most recently from dbc038e to 166bdf9 Compare January 27, 2023 15:04
@arrowd
Copy link
Contributor Author

arrowd commented Feb 1, 2023

At this stage the schema support is added to Sqlite and PostgreSQL backend. There is a simple test that passes for these backends too.

@thanhvh2205
Copy link

@arrowd Currently, we have a hardcode doesTableExist function. I also need help creating a new table with the same name as the existing one but in a new schema. I think your PR can be added to the doesTableExist function. What do you think?

@arrowd
Copy link
Contributor Author

arrowd commented Feb 16, 2023

I'm not sure what function you're talking about. I did adapt doesTableExist for PostgreSQL: https://github.com/yesodweb/persistent/pull/1466/files#diff-3a6af517565f4d723a74260939388b56ca107830b6a9ae68db5a877ca084f520L598

@thanhvh2205
Copy link

@arrowd Sorry, you are right. Your PR will be able to solve my current problem. Can you tell me when the PR will be ready? I hope it can be merged soon.

@arrowd
Copy link
Contributor Author

arrowd commented Feb 18, 2023

At the moment this PR lacks 2 things:

  1. MySQL and MongoDB changes.
  2. A bit more tests

Once this is done a review from Persistent developers would be required, which may take some time.

Copy link
Collaborator

@parsonsmatt parsonsmatt left a comment

Choose a reason for hiding this comment

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

This is a fantastic start! Apologies for the delayed review.

With the current change set, this is a minor bump to persistent, which will require new lower bounds on persistent-sqlite and persistent-postgresql to take advantage of the feature.

Comment on lines +134 to +135
, entitySchema :: !(Maybe Text)
-- ^ The schema name of the database table.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's make another newtype SchemaNameDB for this - will make it easier to disambiguate what is and isn't a schema vs any other bit of text

@@ -34,6 +34,7 @@ data Column = Column
-- | This value specifies how a field references another table.
--
-- @since 2.11.0.0
-- TODO: what about schema name there?
Copy link
Collaborator

Choose a reason for hiding this comment

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

This does seem important to resolve. Unfortunately, the ColumnReference type is exposed, meaning that we will incur a major version bump if we modify it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Since ColumnReference isn't supported yet, this addition will fail for things that need to use it - which is specifying foreign key relationships in migrations. I suspect that a test that works on this schema would fail:

mkPersist sqlSettings [persistLowerCase|
  Foo schema=foo_schema
    name Int

  Bar 
    foo FooId 
|]

Comment on lines +1113 to +1122
let mbRefdef = find (\ent -> getEntityDBSchema ent == getEntityDBSchema edef
&& getEntityDBName ent == crTableName colRef)
defs
(schema, _) = schemaNamePair edef
in case mbRefdef of
Just refdef
| Just _oldName /= fmap fieldDB (getEntityIdField edef)
->
[AddReference
(crTableName colRef)
(schema, crTableName colRef)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh, nice, you handle this appropriately here. Well done.

@@ -731,6 +738,7 @@ mayDefault def = case def of
Just d -> " DEFAULT " <> d

type SafeToRemove = Bool
type SchemaEntityName = (Text, EntityNameDB)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd prefer to see a newtype or a data with named fields to make this more explicit

Comment on lines +692 to +697
schemaNamePair' :: Maybe Text -> EntityNameDB -> SchemaEntityName
schemaNamePair' mbSchema entName = case mbSchema of
Nothing -> ("", entName)
Just "main" -> ("", entName)
Just "temp" -> ("temp", entName)
Just schema -> ("", EntityNameDB $ (schema <> "_") <> unEntityNameDB entName)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Intriguing - so sqlite only has two schema, main and temp? And we mimic that by using schema_table_name? I'd be inclined to use __ (two underscore) to make the distinction more clear - that way you can see foo__bar_baz and know that foo is the supposed schema, rather than foo_bar_baz potentially being either BarBaz schema=foo or FooBarBaz (no schema).

Comment on lines +1364 to +1371
schemaNamePair :: EntityDef -> SchemaEntityName
schemaNamePair ent = schemaNamePair' (getEntityDBSchema ent) (getEntityDBName ent)

schemaNamePair' :: Maybe Text -> EntityNameDB -> SchemaEntityName
schemaNamePair' mbSchema entName = case mbSchema of
Nothing -> ("", entName)
Just "public" -> ("", entName)
Just schema -> (schema, entName)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Uses of this function case on "" and treat it differently - I think that's a good reason to keep this as a Maybe Text instead of a Text.

I'm also curious about treating "public" differently here - can you explain why we don't just keep the public prefix? Presumably, the user must have specified that - ie Foo schema=public - and I'm hesitant to override a user choice.

@arrowd
Copy link
Contributor Author

arrowd commented Jun 1, 2023

Thanks for the review. Currently I'm swamped with daily work, so I will not be able to address your comments and move this work forward. I'm hoping to get more free time in the second half of June.

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.

3 participants