Skip to content

feat: auto-increment for entity id#244

Open
0xTitan wants to merge 8 commits intosnapshot-labs:masterfrom
0xTitan:master
Open

feat: auto-increment for entity id#244
0xTitan wants to merge 8 commits intosnapshot-labs:masterfrom
0xTitan:master

Conversation

@0xTitan
Copy link
Copy Markdown

@0xTitan 0xTitan commented Jul 6, 2023

Hello.
Implementation done. Auto increment annotation can be added only once on entity definition. Only Int, BigInt and ID (for nested object) are managed.

Eg :
`scalar Text

type Post {
id: Int! @autoincrement
author: String!
content: Text!
tag: String
tx_hash: String!
created_at: Int!
created_at_block: Int!
poster: Poster
}

type Poster {
id: ID! @autoincrement
name: String!
}`

Unfortunately i'm struggling with knex implementation and the primaryKey definition. There is normally the possiblity to define if an autoIncrement field should be defined as primaryKey, this is not working when i'm setting it false. Due to that i can only managed one autoIncrement field per table. Maybe enought for now.

Eg :

Knex increment

knex.schema.createTable('users', function (table) { table.increments('id'); table.increments('other_id', { primaryKey: false }); });

I added two more tests :

  • should work with autoincrement
  • should work with autoincrement and nested objects

image

I put the constant needed under type.ts. Let me know if it's suitable.

The result under myssql for the schema above :
image

Copy link
Copy Markdown
Member

@Sekhmet Sekhmet left a comment

Choose a reason for hiding this comment

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

@autoincrement can be handled as native GraphQL directive, like @derivedFrom

@0xTitan
Copy link
Copy Markdown
Author

0xTitan commented Jul 10, 2023

Ok thx, will check that.

@0xTitan
Copy link
Copy Markdown
Author

0xTitan commented Jul 26, 2023

Update done. New directive @autoincrement added.

* @param schema
* @returns A map where key is table name and values a list of fields with annotation autoIncrement
*/
private extractAutoIncrementFields(schema: string) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This shouldn't be handled with regexes. Directive can be handled natively with GraphQL.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Hi, can you guide me to some example of what you want. From my understanding autoIncrement directive is not native in GraphQL so i need to implement the logic behind this new directive. Thank you.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

As we extended GraphQL with our custom directive here, we can then access that directive directly from our GraphQL tree.

This way you can look at the field (id field in this example, and check if it has @autoincrement directive, same as we do with @derivedFrom:
https://github.com/checkpoint-labs/checkpoint/blob/e6dd8b3580604d39de79f4c8c41fb2103582677c/src/graphql/resolvers.ts#L182-L186

That means we don't have to bother with writing our own dummy parser for GraphQL to extract autoIncrementFields, and just check for field.astNode.directives here:
https://github.com/checkpoint-labs/checkpoint/blob/23698a4587b4fe2b1160fe0224401e0d5d1bb90f/src/graphql/controller.ts#L223-L228

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

OK thx for the hint. I will check it and modify accordingly.

@Sekhmet
Copy link
Copy Markdown
Member

Sekhmet commented Oct 19, 2023

@0xTitan thank you for your contribution so far. Are you still expecting to work on this issue? If not I could push it across finish line.

@0xTitan
Copy link
Copy Markdown
Author

0xTitan commented Oct 19, 2023

Hello @Sekhmet, sorry i didn't had time to continue on this, i was involved in other starknet project. I would like to finish this task. But if it's easier for you can push it across finish line and i can create a new PR later with correct implementation.
Thank you.

@0xTitan
Copy link
Copy Markdown
Author

0xTitan commented Nov 4, 2023

Hi @Sekhmet, i pushed changes to remove regex and use directive. Huge thanks for your help and your patience !

Copy link
Copy Markdown
Member

@Sekhmet Sekhmet left a comment

Choose a reason for hiding this comment

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

Looks way cleaner thank you!

General thoughts:

  • can you revert any unrelated changes to the formatting? Most of it would be solved by running Prettier or yarn lint.
  • the comments added are a bit too much in my opinion as they explain pretty self-explanatory code, so they could be removed
  • we have added ORM since and it won't work well with it (as currently ORM requires you to create new instances of ORM models by passing ID to a constructor) - is this something you are also willing to take a look at? Otherwise we probably should at least prevent ORM models from being created for entities with autoincrement fields until it's implemented. If you don't want to work on that I could at this logic so we could get your PR merged.


it('should work', async () => {
const controller = new GqlEntityController(`
const schema = `
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'd use just a single test case to test everything (just put autoincrement and nested properties in here) or
use it.each to avoid duplication of code.

Comment on lines +227 to +235
//if there is no autoIncrement fields on current table, mark the id as primary
const tableHasAutoIncrement = this.getTypeFields(type).some(field => {
const directives = field.astNode?.directives ?? [];
const autoIncrementDirective = directives.find(dir => dir.name.value === 'autoIncrement');
return autoIncrementDirective;
})

if (!tableHasAutoIncrement)
t.primary(['id']);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This code duplicates quite a bit of logic from below.
I wonder if it wouldn't be cleaner to remove this initial lookup and instead use original forEach:

let tableHasAutoIncrement = false

// ...
this.getTypeFields(type).forEach(field => {
  // ...
  if (autoIncrementDirective) {
    tableHasAutoIncrement = true
    t.increments(field.name, { primaryKey: true });
  }
}

// ...
if (!tableHasAutoIncrement) {
  t.primary(['id'])
}

Copy link
Copy Markdown
Author

@0xTitan 0xTitan Nov 4, 2023

Choose a reason for hiding this comment

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

Thanks a lot for the review. I updated code based on your comments.
Regarding ORM, i could take a look ?

package.json Outdated
"src/**/*"
]
}
} No newline at end of file
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you revert this change?

const directives = field.astNode?.directives ?? [];
const autoIncrementDirective = directives.find(dir => dir.name.value === 'autoIncrement');

//Check if field is declared as autoincrement
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
//Check if field is declared as autoincrement

expect(createQuery).toMatchSnapshot();
});

it('should work with autoincrement and nested objects', async () => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I feel like it could just be the only test case in this file (it should work).

@0xTitan
Copy link
Copy Markdown
Author

0xTitan commented Nov 6, 2023

Thanks for your comments. Update done.

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.

2 participants