-
Notifications
You must be signed in to change notification settings - Fork 200
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
1601 default vals #1624
base: master
Are you sure you want to change the base?
1601 default vals #1624
Conversation
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.
Thanks 👍 Good job so far!
…to 1601-default-vals
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.
We're getting closer :)
defColumn = Column { | ||
name = "" | ||
, columnType = PUUID | ||
, defaultValue = Nothing | ||
, notNull = False | ||
, isUnique = False | ||
, generator = Nothing | ||
} | ||
|
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.
Typically IHP code is indentend a bit different, like this:
defColumn = Column { | |
name = "" | |
, columnType = PUUID | |
, defaultValue = Nothing | |
, notNull = False | |
, isUnique = False | |
, generator = Nothing | |
} | |
defColumn = | |
Column | |
{ name = "" | |
, columnType = PUUID | |
-- .... | |
} |
|
||
-} | ||
defCreateTable :: Text -> CreateTable | ||
defCreateTable t = CreateTable { |
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.
The variables here should be spelled out, e.g. tableName
instead of t
defCreateTable t = CreateTable { | |
defCreateTable tableName = CreateTable { |
|
||
-- | Takes a name for our table and a list of column and inserts the list | ||
-- into to our default table. | ||
defCreateTableWCol :: Text -> [Column] -> CreateTable |
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.
IMO this can be just done via defCreateTable
. When you have a table that has no columns, you could still pass an empty list like defCreateTable "myTableWithoutCols" []
.
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.
Yes, I agree now, especially now I see how often each pattern appears, it makes more sense to define this in these ways - will alter :)
setColumnDefaultVal :: Maybe Expression -> Column -> Column | ||
setColumnDefaultVal expression column = column {defaultValue = expression} | ||
|
||
|
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.
Functions below this lines are IMO not a good idea. By having these very specific functions outside of the test suites we actually make tests harder to change, because you now need to look at two files to understands what's going on. So it would be better to undo the changes below and just make use of defTable
and defColumn
inside the tests.
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.
So my thinking here was that if you had repeating units or tests, you can define them once, remember them and then use them as normal and so long as you know the definition of the table or column, you could:
- reuse it
- use it as a new base for a table/column
Perhaps it's not useful for whole tables but certainly default values/columns that may repeat and have complicated structures.
That said, I do see your point and there are several items that are superfluous; secondly, I'm sure if you needed to define repeatable units, you would define them as needed and perhaps on the test page like was done before.
Therefore, I will revert the tests to defintions of defColumn
etc and leave space for IHP to define its own monomers as required.
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.
I was also thinking that the writer would check the definition of the test by ctrl+clicking on the name and opening up the references window -> but I guess not everyone uses vscode for IDE which is understandable.
compileSql [statement] `shouldBe` sql | ||
|
||
it "should compile a CREATE TABLE statement with an array column" do | ||
let sql = cs [plain|CREATE TABLE array_tests (\n pay_by_quarter INT[]\n);\n|] | ||
let statement = StatementCreateTable CreateTable |
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.
Here's an example how I imagine this to be working after the PR is merged:
let statement = StatementCreateTable (
defCreateTable "array_tests"
[ defColumn "pay_by_quarter" (PArray PInt)
]
)
Okay should all now be complete :) |
@ | ||
-} | ||
compilerSpecTable :: CreateTable | ||
compilerSpecTable = defCreateTablePKID "users" ["id"] cols |
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.
As this is test related logic it shouldn't live here
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.
maybe we can move this into some test module instead
-- | Takes a name for our table and a list of column and inserts the list | ||
-- into to our empty table. | ||
defCreateTable :: Text -> [Column] -> CreateTable | ||
defCreateTable tablename columns = emptyTable { name = tablename |
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.
This function doesn't seem useful to me, why can't we just write emptyTable { name = .. , columns = .. }
directly?
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.
It's more for speed: it means you don't have to write the record parts over and over again especially if they're the only two values in emptyTable
being changed and you could quickly be certain that the only values changed were the name and the columns contained. If other values needed changing, then it's up to the writer to use emptyTable {..}
or (defCreateTable tablename columns){..})
-> both options are always available.
Since they were a recurring feature, it made sense to write them this way initially.
defCreateTableWSetCol :: Text -> Text -> PostgresType -> CreateTable | ||
defCreateTableWSetCol tablename columnname pgt = defCreateTable tablename (pure $ setColumn columnname pgt) | ||
|
||
{- | Same as its progenitor `defCreateTableWSetCol` except it uses `setColumnN` | ||
-} | ||
defCreateTableWSetColN :: Text -> Text -> PostgresType -> CreateTable | ||
defCreateTableWSetColN tablename columnname pgt = defCreateTable tablename (pure $ setColumnN columnname pgt) |
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.
Same with those functions, I think it's more clear to write:
emptyTable { name = "users", columns = [ colUUID ] }
instead of
defCreateTableWSetCol "users" "id" ...
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.
Same as before, for speed (not needing to write records) and composability (ability to easily use (.) and ($) to change values or combine them with other things). I do understand the concerns for clarity's sake though.
Since there were quite a few examples of where only certain values in certain fields are changed, if you know what the functions do, you can have a quick idea of what the table or column looks like or have a fast way of defining a more complex table as a base for another table by using base functions.
Again, the option the use the base tables and columns and record syntax is always there and would be functionally identical.
By using a specific function that encapsulates a pattern, I can quickly reason out the structure of the full table if I know what the function does UNLESS I modify it using ( )
and add more records with {..}
or putting another function ahead of it which modifies the table further.
It really depends on much you want to represent specific patterns/structures of tests with functions. Also a lot of these functions can end up being helper functions much larger structures; but these will be made when needed I imagine.
colText :: Text -> Column | ||
colText text = setColumnN text PText |
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.
I'd prefer to also just write emptyColumn { name, columnType = PText }
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.
It's written this way because setColumn
and setColumnN
use emptyColumn
as precursors and edits them according to their patterns.
By partially applying setColumn
/N
with PText, one can make the assumption that any str
called with colText
will always return a column with the name
of str
, a columnType
of PText
and notNull
value of True
-> so for all cases where one needs to generate a column that will look like so, they can do so with one parameter and not mess with records and be reasonably confident that it will create the desired column.
Once again, the option to write with emptyColumn
and records is also available.
Co-authored-by: Marc Scholten <[email protected]>
Co-authored-by: Marc Scholten <[email protected]>
…to 1601-default-vals
I've been a bit busy so haven't been able to rewrite the tests but I have time to do so tomorrow evening :) |
Great, thanks for the update! Happy to review again later today 👍 |
Is this ready for review again? :) |
Not yet, hopefully by the end of tonight! :) I must admit my motivation to rewrite to instances of |
I think, I'm done with this here: Rewriting instances of |
I've figured out the pull request:
I've got quite a few to go but hopefully the strategy I'm going for is apparent and is helpful to you.
If you have any thoughts on some other things or style comments then let me know and I'll try and incorporate them. I'll do the rest of these tomorrow