-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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: Adding support for new FieldMetadataType with Postgres enums #2674
Conversation
@@ -22,7 +22,7 @@ export const currencyObjectDefinition = { | |||
} satisfies FieldMetadataInterface, | |||
{ | |||
id: 'currencyCode', | |||
type: FieldMetadataType.TEXT, | |||
type: FieldMetadataType.VARCHAR, |
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.
Temporary workaround as composite type doesn't use the correct type in database, TEXT
should be text
not varchar
.
cc @Weiko
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.
Ok, we will need to migrate our DB though (to change the metadata). cc @charlesBochet
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.
If it's a temporary workaround, maybe we should actually use TEXT and run the migration to have the final result directly? (which is having text in the workspace schema I guess?). Except if we want to handle SHORT_TEXT type or something and use varchar
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.
Tbh, I'm pretty sure varchar is the same as text for postgres if you don't define a particular size
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 see here
The TEXT data type can store a string with unlimited length.
If you do not specify the n integer for the VARCHAR data type, it behaves like the TEXT datatype. The performance of the VARCHAR (without the size n) and TEXT are the same.
https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-char-varchar-text/
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.
Do we want to store currency in an enum in the future?
Plus: data is more robust
Minus: migration when geopolitics evolves :D
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.
Regarding varchar vs text, I don't think we should use both. I think varchar should be good, and agree we should avoid generating migrations if possible
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 not sure to understand the motivation behind this change
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.
@Weiko: Ok good point that Postgres handle varchar
without length in the same way as text
.
I'm ok with avoiding migrations, but I don't really like to have inconsistence between the metadata and what is actually stored in the database.
For better explanation @charlesBochet, instead of always redefining the composite types like Link
or Currency
, I've moved the composite types definitions that initially was in the schema-builder into the field-metadata.
That way we're using the same object to define them. But it involve creating the FieldMetadata
for the inner fields of composite types, and that was manually done before by manually putting the type varchar
.
But actually varchar
is not mapped in our FieldMetadataType
.
The first thing I does is putting the type FieldMetadataType.TEXT
for this fields, but this one is converted to a text
column type in Postgres not a varchar
.
It's why I've created a temporary type to avoid breaking changes, but from what @Weiko says, I can still put TEXT
, we'll just have some inconsistency but it should work the same.
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.
Do we want to store currency in an enum in the future? Plus: data is more robust Minus: migration when geopolitics evolves :D
It's something that we can consider
server/src/metadata/workspace-migration/factories/abstract.factory.ts
Outdated
Show resolved
Hide resolved
server/src/metadata/workspace-migration/factories/enum-column-action.factory.ts
Show resolved
Hide resolved
server/src/workspace/workspace-migration-runner/services/workspace-migration-enum.service.ts
Show resolved
Hide resolved
) { | ||
const enumValues = migrationColumn.enum; | ||
|
||
// TODO: Maybe we can do something better if we can recreate the old `TableColumn` object |
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.
Try to rely on TypeORM by recreating the old TableColumn
.
This is needed to support updating other properties at the same time.
In this PR we can't change the options of a FieldMetadata
with the defaultValue
at the same time.
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.
Could you elaborate more here? What happens if we do both at same time?
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.
If we currently do both at the same time, TypeORM
migrations will brakes enum migrations an drop the enum column before recreating it, so all the data will be lost
server/src/database/typeorm/metadata/migrations/1700663879152-addEnumOptions.ts
Show resolved
Hide resolved
@@ -22,7 +22,7 @@ export const currencyObjectDefinition = { | |||
} satisfies FieldMetadataInterface, | |||
{ | |||
id: 'currencyCode', | |||
type: FieldMetadataType.TEXT, | |||
type: FieldMetadataType.VARCHAR, |
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.
Ok, we will need to migrate our DB though (to change the metadata). cc @charlesBochet
@@ -22,7 +22,7 @@ export const currencyObjectDefinition = { | |||
} satisfies FieldMetadataInterface, | |||
{ | |||
id: 'currencyCode', | |||
type: FieldMetadataType.TEXT, | |||
type: FieldMetadataType.VARCHAR, |
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.
If it's a temporary workaround, maybe we should actually use TEXT and run the migration to have the final result directly? (which is having text in the workspace schema I guess?). Except if we want to handle SHORT_TEXT type or something and use varchar
@@ -22,7 +22,7 @@ export const currencyObjectDefinition = { | |||
} satisfies FieldMetadataInterface, | |||
{ | |||
id: 'currencyCode', | |||
type: FieldMetadataType.TEXT, | |||
type: FieldMetadataType.VARCHAR, |
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.
Tbh, I'm pretty sure varchar is the same as text for postgres if you don't define a particular size
@@ -22,7 +22,7 @@ export const currencyObjectDefinition = { | |||
} satisfies FieldMetadataInterface, | |||
{ | |||
id: 'currencyCode', | |||
type: FieldMetadataType.TEXT, | |||
type: FieldMetadataType.VARCHAR, |
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 see here
The TEXT data type can store a string with unlimited length.
If you do not specify the n integer for the VARCHAR data type, it behaves like the TEXT datatype. The performance of the VARCHAR (without the size n) and TEXT are the same.
https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-char-varchar-text/
@@ -22,7 +22,7 @@ export const currencyObjectDefinition = { | |||
} satisfies FieldMetadataInterface, | |||
{ | |||
id: 'currencyCode', | |||
type: FieldMetadataType.TEXT, | |||
type: FieldMetadataType.VARCHAR, |
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 instead maybe we can keep varchar, that would avoid unnecessary migrations @magrinj @charlesBochet
Ideally we should keep things consistent but looks like in this case it's fine
} from 'src/metadata/workspace-migration/workspace-migration.entity'; | ||
import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; | ||
|
||
export class AbstractFactory<T extends FieldMetadataType | 'default'> |
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.
Can we use a less generic name instead of AbstractFactory? WorkspaceMigrationFactory or something like that?
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.
@Weiko Yes we can, but actually AbstractFactory
should only be used inside this folder.
I'll rename it WorkspaceColumnActionAbstractFactory
import { WorkspaceMigrationColumnAlter } from 'src/metadata/workspace-migration/workspace-migration.entity'; | ||
|
||
@Injectable() | ||
export class WorkspaceMigrationEnumService { |
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.
Should we prefix custom enums with "_"? @charlesBochet
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 think it will because the name is based on: ${tableName}_${migrationColumn.columnName}
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.
You mean because of table name? What if we add a custom enum on a standard object? As for the column name then yes we just to make sure we put an _ there when creating the migration
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.
@Weiko Actually enum names are based on the field name, so if the field is _myField
the enum will be something like _myTable__myField_enum
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.
Another masterpiece!
@@ -3,7 +3,7 @@ ARG PG_MAIN_VERSION=14 | |||
FROM postgres:${PG_MAIN_VERSION} as postgres | |||
|
|||
ARG PG_MAIN_VERSION | |||
ARG PG_GRAPHQL_VERSION=1.3.0 | |||
ARG PG_GRAPHQL_VERSION=1.4.2 |
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 will also need to update our local install script
server/src/database/typeorm/metadata/migrations/1700663879152-addEnumOptions.ts
Show resolved
Hide resolved
@@ -22,7 +22,7 @@ export const currencyObjectDefinition = { | |||
} satisfies FieldMetadataInterface, | |||
{ | |||
id: 'currencyCode', | |||
type: FieldMetadataType.TEXT, | |||
type: FieldMetadataType.VARCHAR, |
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.
Do we want to store currency in an enum in the future?
Plus: data is more robust
Minus: migration when geopolitics evolves :D
@@ -22,7 +22,7 @@ export const currencyObjectDefinition = { | |||
} satisfies FieldMetadataInterface, | |||
{ | |||
id: 'currencyCode', | |||
type: FieldMetadataType.TEXT, | |||
type: FieldMetadataType.VARCHAR, |
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.
Regarding varchar vs text, I don't think we should use both. I think varchar should be good, and agree we should avoid generating migrations if possible
@@ -22,7 +22,7 @@ export const currencyObjectDefinition = { | |||
} satisfies FieldMetadataInterface, | |||
{ | |||
id: 'currencyCode', | |||
type: FieldMetadataType.TEXT, | |||
type: FieldMetadataType.VARCHAR, |
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 not sure to understand the motivation behind this change
const updatedFieldMetadata = await super.updateOne(id, record); | ||
|
||
if (record.options || record.defaultValue) { | ||
await this.workspaceMigrationService.createCustomMigration( |
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 am not sure about the createCustomMigration API long term. I feel that we should maybe provide something more restrictive: createColumn, udpateColumnType, updateEnumOptions...
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 can let it like this for now
import { WorkspaceMigrationColumnAlter } from 'src/metadata/workspace-migration/workspace-migration.entity'; | ||
|
||
@Injectable() | ||
export class WorkspaceMigrationEnumService { |
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 think it will because the name is based on: ${tableName}_${migrationColumn.columnName}
); | ||
|
||
// Update existing rows to handle missing values | ||
await this.handleMissingEnumValues( |
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 is the first migration that will touch the data. I am very curious to see how it behaves on production.
On a regular project I would avoid that, but as we are doing migration per workspace, it's actually great. It will help migrating between versions of twenty handling data migration too and we will be able to test it on test workspaces, tier 3 workspaces before trying it on more important workspaces or clients!
); | ||
} | ||
|
||
private async renameEnumType( |
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 much complexity, but all steps make sense to me
) { | ||
const enumValues = migrationColumn.enum; | ||
|
||
// TODO: Maybe we can do something better if we can recreate the old `TableColumn` object |
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.
Could you elaborate more here? What happens if we do both at same time?
feat: wip enum type feat: try to alter enum feat: wip enum feat: wip enum feat: schema-builder can handle enum fix: return default value in field metadata response
This reverts commit 3857539.
Description
This PR introduces support for a new
FieldMetadataType
, utilizing Postgres enums to enhance our data modeling capabilities. We have introduced three new types:RATING
,SELECT
, andMULTI_SELECT
.Key features
Creation and Update of FieldMetadata:
FieldMetadata
with additional options for these enum types. For instance, when creating a field with the typeMULTI_SELECT
, the options include properties likeposition
,color
,label
, andvalue
.FieldMetadata
:Options update
id
for each option within aFieldMetadata
type. Thisid
is crucial for theupdateOneField
mutation, ensuring a seamless transition between old and new enum values.Utilization in Document queries:
Frontend Integration:
FieldMetadata
options with the enum values. This mapping will deduce properties such ascolor
andposition
, facilitating the way enums are updated in all the views.Known issues
Filtering on multiple choices enum doesn't work, it's due to
pg_graphql
that is not handling them properly supabase/pg_graphql#458