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

refactor: Cleanup parsing logic #909

Merged
merged 27 commits into from
Oct 21, 2022

Conversation

AndrewSisley
Copy link
Contributor

@AndrewSisley AndrewSisley commented Oct 19, 2022

Relevant issue(s)

Part of #905, but does not yet resolve it

Description

Cleans up some of the parser code and types in preparation for decoupling mapper/planner/defra from gql. Moves the parser model out of the parser package, defining a public strongly typed model for interacting with defra.

There is still a little bit more to be done (mainly abstracting the schema stuff from away db.db), but I'm getting tired and these commits should be alright to review (it is also getting a bit large and will probs be easier for everyone to break this refactor into a couple of reviews).

Strongly suggest reviewing commit by commit, as there is a fair amount going on here now.

@AndrewSisley AndrewSisley added area/query Related to the query component area/parser Related to the parser components refactor This issue specific to or requires *notable* refactoring of existing codebases and components action/no-benchmark Skips the action that runs the benchmark. area/mapper Related to the mapper components labels Oct 19, 2022
@AndrewSisley AndrewSisley added this to the DefraDB v0.4 milestone Oct 19, 2022
@AndrewSisley AndrewSisley requested a review from a team October 19, 2022 20:18
@AndrewSisley AndrewSisley self-assigned this Oct 19, 2022
Name: field.Name.Value,
Alias: getFieldAlias(field),
}
}

type Aggregate struct {
Copy link
Contributor Author

@AndrewSisley AndrewSisley Oct 19, 2022

Choose a reason for hiding this comment

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

I'll document this (and AggregateTarget) a bit later (outside of this PR), along with all the other models in this package. It'll also probably be refactored a little further.

func parseAggregate(field *ast.Field, index int) (*Aggregate, error) {
targets := make([]*AggregateTarget, len(field.Arguments))

for i, argument := range field.Arguments {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This function is pretty much a straight-up cut-paste of the trimmed one in mapper

@codecov
Copy link

codecov bot commented Oct 19, 2022

Codecov Report

Merging #909 (29ef5f5) into develop (9490679) will increase coverage by 0.09%.
The diff coverage is 93.46%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop     #909      +/-   ##
===========================================
+ Coverage    59.79%   59.89%   +0.09%     
===========================================
  Files          156      159       +3     
  Lines        17415    17423       +8     
===========================================
+ Hits         10414    10436      +22     
+ Misses        6065     6053      -12     
+ Partials       936      934       -2     
Impacted Files Coverage Δ
db/collection_delete.go 29.41% <0.00%> (ø)
mapper/commitSelect.go 0.00% <ø> (ø)
mapper/targetable.go 75.00% <ø> (ø)
query/graphql/schema/descriptions.go 87.57% <50.00%> (ø)
db/collection_update.go 54.93% <75.00%> (ø)
planner/group.go 83.51% <75.00%> (ø)
query/graphql/parser/filter.go 62.71% <80.00%> (ø)
planner/planner.go 77.21% <87.50%> (ø)
query/graphql/parser/query.go 82.77% <90.11%> (-0.31%) ⬇️
planner/select.go 78.32% <91.66%> (ø)
... and 21 more

@AndrewSisley AndrewSisley force-pushed the sisley/refactor/I905-decouple-from-gql branch 2 times, most recently from 4b0084c to 18534ad Compare October 19, 2022 21:01
@@ -58,7 +58,7 @@ func (n *limitNode) Value() core.Doc { return n.plan.Value() }

func (n *limitNode) Next() (bool, error) {
// check if we're passed the limit
if n.limit != 0 && n.rowIndex-n.offset >= n.limit {
if n.limit != 0 && n.rowIndex >= n.limit+n.offset {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This had to be changed, as it actually overflows under normal conditions. A bit surprised Golang doesn't panic on overflows...

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm trying to undestand where this overfows. Can you point it out please. I'm curious.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

e.g if rowIndex is 0, and offset is greater than 0

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah yes I see cuz they are of type uint64. It should definitely panic on overflow. https://go.dev/play/p/bDfmcZbLKma

Copy link
Collaborator

Choose a reason for hiding this comment

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

No... my bad. It doesn't panic: https://go.dev/play/p/yHe5EyEu11I

Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is really strange behaviour that to me in your linked playgrounds, feels inconsistent to let the runtime pass, but compile fail.

DotNet panics too, and I think so does the JVM. There is a tiny runtime cost to checking, but given how runtime heavy Go can be anyway it seems odd not to do this. Maybe it is because the lang lacks the syntax to opt-out (allowing overflows can be really handy at times, for example during key generation)

@AndrewSisley AndrewSisley force-pushed the sisley/refactor/I905-decouple-from-gql branch 2 times, most recently from 1c17c39 to 7e13656 Compare October 20, 2022 21:19
Copy link
Collaborator

@fredcarle fredcarle left a comment

Choose a reason for hiding this comment

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

LGTM. This was quite easy to review. Lots of changes but not too much new stuff. Glad you've decided to create PRs as you change things and not wait for everything to be done.

@@ -8,65 +8,20 @@
// by the Apache License, Version 2.0, included in the file
Copy link
Member

Choose a reason for hiding this comment

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

question: is the purpose of the consts.go file different from the types file? I thought there was consensus to keep types under it's own namespace using types package ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

having a types file in directory full of other files with other types is not very helpful IMO. A types file made sense when there was only a sub set of the model in it (and even that was odd as is was super-arbitrary as to what was in it)

Copy link
Member

Choose a reason for hiding this comment

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

having a types file in directory full of other files with other types is not very helpful IMO. A types file made sense when there was only a sub set of the model in it (and even that was odd as is was super-arbitrary as to what was in it)

While I agree that it was odd, I am talking from the perspective of keeping things in harmony as the code base grows and having a convention that would be well understood by the team, for example, I am happy with storing constants in consts.go file as it is very self-evident to know what that file contains. Would like to see us use consistent patterns to store constants, variables etc. (for structs probably more useful names split under different files). I really enjoyed a popular convention in C++ that said no more than one class / struct per file (perhaps too strict for Go peepz haha).


// Filter contains the parsed condition map to be
// run by the Filter Evaluator.
// @todo: Cache filter structure for faster condition
Copy link
Member

Choose a reason for hiding this comment

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

todo: remove or add corresponding issue number.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

out of scope

// of a graphql query. It includes all the possible
// arguments and all
//
// @todo: Change name to ObjectMutation to indicate
Copy link
Member

Choose a reason for hiding this comment

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

todo: remove or add corresponding issue number.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

out of scope

Comment on lines -127 to -131
type OptionalDocKeys struct {
HasValue bool
Value []string
}

Copy link
Member

Choose a reason for hiding this comment

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

praise: Thanks for removal of this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

:)

@@ -292,7 +293,7 @@ func (n *selectNode) initFields(parsed *mapper.Select) ([]aggregateNode, error)
// of that Target version we are querying.
// So instead of a LatestCommit subquery, we need
// a OneCommit subquery, with the supplied parameters.
commitSlct.DocKey = parsed.DocKeys.Value[0] // @todo check length
commitSlct.DocKey = client.Some(parsed.DocKeys.Value()[0]) // @todo check length
Copy link
Member

Choose a reason for hiding this comment

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

todo: remove or add the corresponding issue number.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

out of scope

@AndrewSisley
Copy link
Contributor Author

Thanks Fred! And thanks for the quick review :)

@AndrewSisley AndrewSisley force-pushed the sisley/refactor/I905-decouple-from-gql branch from 7e13656 to b564448 Compare October 21, 2022 13:57
The parser models will shortly be exposed as part of the public interface, and it should not be on the users to have to always populate this property.  It also makes more sense IMO to do it this way regardless, as alias is optional, but render-keys are not.
Makes it far clearer that it is optional
Also flattens them, as the previous structure suggested if one was present then the other was mandatory. Also switches from int64 to uint64 as they should not be negative (and makes it more consitent with a few other similar props who use uint64).
No reason for this to exist, and will confuse anyone using it.
Now using proper consts, and defined in the same location as everything else.
Previous if was conceptually incorrect. None option added no value (select.Root now defaults to Object, which could be handy for users anyway).  Also types the enum.
Also breaks up types.go in preparation for the moving of the rest of the model.
As agreed as a team, commit does not seek to rename all variables referencing this - that can be done later to save drowning this large PR with minor changes
The parser package is now responisble for converting an gql-ast into a shared model.  Soon it will be responisble for converting a string into the shared model.  Mostly a copy-paste commit.
@AndrewSisley AndrewSisley force-pushed the sisley/refactor/I905-decouple-from-gql branch from b564448 to 29ef5f5 Compare October 21, 2022 14:15
@AndrewSisley AndrewSisley dismissed shahzadlone’s stale review October 21, 2022 14:30

todos are out of scope

@AndrewSisley AndrewSisley merged commit 6ccae7f into develop Oct 21, 2022
@AndrewSisley AndrewSisley deleted the sisley/refactor/I905-decouple-from-gql branch October 21, 2022 14:30
shahzadlone pushed a commit to shahzadlone/defradb that referenced this pull request Feb 23, 2024
* Remove unused QueryType prop

* Remove unused order.statement prop

* Replace optionalDocKeys with client.Option

Type was added before we had client.Option

* Remove legacy commit entry

Should have been removed in the PR that removed the commit query

* Remove unused statement property

* Remove unused func from interface

* Remove Root from Field

* Remove unused func

* Parse aggregates in parser package

* Remove statement from parser.Select

* Remove ast from OperationDefinition

* Remove unused Name from OperationDefinition

* Make parser.Alias optional

The parser models will shortly be exposed as part of the public interface, and it should not be on the users to have to always populate this property.  It also makes more sense IMO to do it this way regardless, as alias is optional, but render-keys are not.

* Make commit.DocKey option type

Makes it far clearer that it is optional

* Use option for parser.limit

Also flattens them, as the previous structure suggested if one was present then the other was mandatory. Also switches from int64 to uint64 as they should not be negative (and makes it more consitent with a few other similar props who use uint64).

* Use option for parser.order

* Remove '.'s from parser.order.fields

No reason for this to exist, and will confuse anyone using it.

* Use option for parser.GroupBy

* Use option for parser.Filter

* Cleanup commit-query branching

Now using proper consts, and defined in the same location as everything else.

* Remove unused param

* Remove unused commit.GetRoot func

* Remove unused mutation.GetRoot func

* Tidy up parser.Root references

Previous if was conceptually incorrect. None option added no value (select.Root now defaults to Object, which could be handy for users anyway).  Also types the enum.

* Move parser.types to client dir

Also breaks up types.go in preparation for the moving of the rest of the model.

* Rename parser.Query to parser.Request

As agreed as a team, commit does not seek to rename all variables referencing this - that can be done later to save drowning this large PR with minor changes

* Move request model out of parser package

The parser package is now responisble for converting an gql-ast into a shared model.  Soon it will be responisble for converting a string into the shared model.  Mostly a copy-paste commit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
action/no-benchmark Skips the action that runs the benchmark. area/mapper Related to the mapper components area/parser Related to the parser components area/query Related to the query component refactor This issue specific to or requires *notable* refactoring of existing codebases and components
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants