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

Implement predicate type conversion. #204

Merged
merged 1 commit into from
Nov 26, 2018
Merged

Implement predicate type conversion. #204

merged 1 commit into from
Nov 26, 2018

Conversation

Dragomir-Ivanov
Copy link
Contributor

Helps with querying for schema.Time and others. It also skips validation for schema.* types during predicate phase of query.
This is just a preview PR, I will fix the tests, when implementation is accepted.

schema/field.go Outdated Show resolved Hide resolved
Copy link
Collaborator

@smyrman smyrman left a comment

Choose a reason for hiding this comment

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

I think the overall approach looks sane -- could you point out the part that worries you @Dragomir-Ivanov?

schema/query/predicate.go Outdated Show resolved Hide resolved
schema/time.go Outdated Show resolved Hide resolved
schema/time.go Outdated Show resolved Hide resolved
schema/query/predicate_validator.go Outdated Show resolved Hide resolved
schema/query/predicate.go Outdated Show resolved Hide resolved
@Dragomir-Ivanov
Copy link
Contributor Author

Dragomir-Ivanov commented Oct 24, 2018

@smyrman My initial concern is:

  1. The name for the validation function ValidateOperator, is not quite right, since we are converting the current Expression and return a new one. So I guess more appropriate name is needed to reflect that.
  2. Predicate is defined as []Expression but we still need to comply with Expression interface, so ValidateOperator is just a noise for Predicate type, i.e. pass-though.

I do like however the way whole operator validation step is separate from other steps, and can be opted-out if needed.

@smyrman
Copy link
Collaborator

smyrman commented Oct 25, 2018

Why is ValidateOperator needed at the Expression andPredicate level? What does it do? Isn't it enough with the new FieldValidator method?

@smyrman
Copy link
Collaborator

smyrman commented Oct 25, 2018

It looks like it validates that the operator is allowed? Can't that be done as part of the normal Validate?

@Dragomir-Ivanov
Copy link
Contributor Author

It looks like it validates that the operator is allowed? Can't that be done as part of the normal Validate?

I am not sure I understand. You want FieldValidator Validate(value interface{}) (interface{}, error) to accept the op as well, and make the check on the spot? But I think Validate is used on other places apart from Query parsing.

@Dragomir-Ivanov
Copy link
Contributor Author

Dragomir-Ivanov commented Oct 25, 2018

Why is ValidateOperator needed at the Expression andPredicate level? What does it do? Isn't it enough with the new FieldValidator method?

I think your proposal was separate interface OperatorValidator and not adding new method to FieldValidator however I am all for the latter case, and will make the change if you say so.

Also I will try to remove ValidateOperator function from Expression interface and use a global function.

@Dragomir-Ivanov
Copy link
Contributor Author

@smyrman Are we calling interface functions, and struct functions method in Go? I thought method was for OOP principles?

@smyrman
Copy link
Collaborator

smyrman commented Oct 25, 2018

I am not sure I understand. You want FieldValidator Validate(value interface{}) (interface{}, error) to accept the op as well,

no. I mean why does the Predicate and Expression need a new method:

// ValidateOperator TODO
func (e Predicate) ValidateOperator(validator schema.Validator) (Expression, error) {
	return nil, validateOperatorExpressions(e, validator)
}

// Expression is a query or query component that can be matched against a payload.
type Expression interface {
	Match(payload map[string]interface{}) bool
	Validate(validator schema.Validator) error
	ValidateOperator(validator schema.Validator) (Expression, error)
	String() string
}

How does Expression.ValidateOperator differ from Expresssion.Validate? Why is it necessary to return a new expression?

I think your proposal was separate interface OperatorValidator and not adding new method to FieldValidator however I am all for the latter case, and will make the change if you say so.

yes, that was my proposal (to add it as a new interface for the schema package).

@smyrman
Copy link
Collaborator

smyrman commented Oct 25, 2018

@smyrman Are we calling interface functions, and struct functions method in Go? I thought method was for OOP principles?

The concept, in my mind, is the same regarding of language.

Quote: A method is a function with a special receiver argument.

Or, as they say all methods are functions, not all functions are methods.

schema/query/predicate.go Outdated Show resolved Hide resolved
@Dragomir-Ivanov
Copy link
Contributor Author

Hi @smyrman @rs , here is my design proposal for this PR.
Sindre, I didn't quite followed your design on Comparabe interface, but I think this will still be OK.

Lets define 2 new interfaces that can be implemented by schema.FieldValidator

type FieldComparator interface {
	Less(this interface{}, other interface{}) bool
}

type FieldPreparator interface {
        // This can be named Parse as well. I would like to go into schema.FieldValidator interface,
        // so it will be mandatory for all schema types.
	Prepare(value interface{}) (interface{}, error)
}

FieldComarator will be used in the Expression.Match method, and can give custom types rest-layer-mem support. Perfect candidates will be schema.Integer, schema.Float, schema.Time and possibly others.
FieldPreparator will be used in ParsePredicate in order to make sure all query types match the schema defined types. This will not do full type Validate but will only make sure the types are compatible. It will still put as Validate the type in the Expression expected by the DB/Storer.

In order to accomplish the above, I needed to refactor a little bit passed arguments of some functions involved in predicate parsing. I will not go into much details here, because code will explain better.
No change in the public API is made. Please when reviewing this PC, use the Files Changed tab in the GitHub, because last commit undoes much of the previous work.
Thanks for the help, guys!

@rs
Copy link
Owner

rs commented Nov 7, 2018

Looks good to me.

schema/dependency.go Outdated Show resolved Hide resolved
Copy link
Collaborator

@smyrman smyrman left a comment

Choose a reason for hiding this comment

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

I think the design looks good overall. I think Prepare on schema needs a better name, otherwise some small comments and advice here and there. God work.

schema/integer.go Outdated Show resolved Hide resolved
schema/integer.go Show resolved Hide resolved
schema/query/predicate.go Outdated Show resolved Hide resolved
schema/query/predicate.go Outdated Show resolved Hide resolved
schema/query/predicate.go Outdated Show resolved Hide resolved
schema/query/predicate_validator.go Outdated Show resolved Hide resolved
schema/query/predicate_validator.go Outdated Show resolved Hide resolved
@Dragomir-Ivanov
Copy link
Contributor Author

Dragomir-Ivanov commented Nov 11, 2018

@smyrman Committed with your suggestions. Didn't implemented Integer field with Float compare value. Lets leave that for later, when we clean things up.
Wanted to add ValidateQuery method to schema.FieldValidator however, schema.Schema also needs to implement method for FieldValidator, and I think that is wrong. We can discuss however.
I did some simple tests, it seems all to work, however when I refactor all broken tests we can have clear picture.

There will be patches for all rest-layer-* Storer implementers, accepting pointer to expressions.

@smyrman
Copy link
Collaborator

smyrman commented Nov 12, 2018

Think this approach looks good @Dragomir-Ivanov 👍 Looking forward to the result :-) I think it's fair not to add ValdateQuery to the FieldValidator interface for now.

@Dragomir-Ivanov
Copy link
Contributor Author

Thanks @smyrman , can you take quick look on the questions above?

@smyrman
Copy link
Collaborator

smyrman commented Nov 12, 2018

Thanks @smyrman , can you take quick look on the questions above?

Tried to answer the ones for unresolved (closed) conversations - Let me know if there are any more questions I have missed.

There will be patches for all rest-layer-* Storer implementers, accepting pointer to expressions.

Do you mean for the type switch?

https://github.com/rs/rest-layer-mongo/blob/8ed09d3750ca8f3efa5367f6c11c9674437d31e0/query.go#L70

Yes, I suppose so... I don't like adding struct pointers to slices (memory gets scattered), but it's fine. We already do slices of pointers for e.g. resource.Items. When I do an overhaul in #77 (eventually) I can have another look at the query design to see if there is anything we can/should do differently there as well.

@Dragomir-Ivanov
Copy link
Contributor Author

I actually made a couple of code comments above on the last commit, since I am not sure how to best Go approach.

@smyrman
Copy link
Collaborator

smyrman commented Nov 12, 2018

I actually made a couple of code comments above on the last commit, since I am not sure how to best Go approach.

Can't see any comments in neither Changed Files nor the last commit itself -- sure they are not with state pending? If they are you need to "submit a review" for me to see them.

Copy link
Contributor Author

@Dragomir-Ivanov Dragomir-Ivanov left a comment

Choose a reason for hiding this comment

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

Sorry @smyrman, didn't used review functionality before. I thought these are regular code comments. Will not happen again.

schema/dependency.go Outdated Show resolved Hide resolved
schema/query/predicate.go Outdated Show resolved Hide resolved
schema/query/predicate_validator.go Outdated Show resolved Hide resolved
schema/time.go Outdated Show resolved Hide resolved
Copy link
Collaborator

@smyrman smyrman left a comment

Choose a reason for hiding this comment

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

Looks quite good.

README.md Outdated Show resolved Hide resolved
schema/alloff.go Outdated Show resolved Hide resolved
schema/alloff.go Outdated Show resolved Hide resolved
schema/anyof.go Show resolved Hide resolved
schema/float_test.go Outdated Show resolved Hide resolved
schema/query/predicate_validator.go Show resolved Hide resolved
return fmt.Errorf("%s: invalid query expression `%#v': %v", field, v, err)
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

looks like indenting error -- If there is a way ti enable gofmt or goimports in your editor, it should fix this automatically on save.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am using VSCode, with the Golang plugin, so I have these enabled. Don't know what happened.

@smyrman
Copy link
Collaborator

smyrman commented Nov 20, 2018

PS! Can you please add a note to the "breaking changes" section of the README with a link to this PR?

Breaking changes is defined as anything that changes the public interface in a way that would cause old code to no longer compile.

@smyrman
Copy link
Collaborator

smyrman commented Nov 20, 2018

Before we do the final merge, please also do a final rebase and squah and write a nice commit message :-)

@Dragomir-Ivanov
Copy link
Contributor Author

Dragomir-Ivanov commented Nov 21, 2018

@smyrman This is what I recall for the breaking changes part. Do you recall something else?

- PR #204: 
	- Storage drivers need to accept pointer to `Expression` implementer in `query.Predicate`.
	- `filter` parameters in sub-query will be validated for type match.
	- `filter` parameters will be validated for type match only, instead of type & constrains.

@Dragomir-Ivanov
Copy link
Contributor Author

Dragomir-Ivanov commented Nov 21, 2018

@smyrman Pushed the squashed rebase. When you merge it, I will do additional PRs to fix the DB drivers.

EDIT: It seems that SQLite3 and Google Data Store drivers are rotten. They complain about missing schema.Lookup. Only rest-layer-es is eligible for quick fix.

@smyrman
Copy link
Collaborator

smyrman commented Nov 22, 2018

Yes. Third-party drivers seam out of date.

schema/alloff.go Outdated Show resolved Hide resolved
schema/alloff.go Outdated Show resolved Hide resolved
schema/array.go Outdated Show resolved Hide resolved
schema/array.go Outdated Show resolved Hide resolved
schema/array.go Show resolved Hide resolved
@smyrman
Copy link
Collaborator

smyrman commented Nov 22, 2018

Sorry for comming with even more comments now... I sort of look at this in between other things and haven't been able to really spot everything in my first pass through. Thanks a lot for your great work!

@Dragomir-Ivanov
Copy link
Contributor Author

No problem Sindre, I am learning a lot of things during these passes, so let it be as many as needed :)
I have made a new commit addressing your suggestions. Did separate commit so it will be easier for you to review. Then you can make q squash merge or I can squash the PR if you want.

smyrman
smyrman previously approved these changes Nov 22, 2018
Copy link
Collaborator

@smyrman smyrman left a comment

Choose a reason for hiding this comment

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

LGTM -- @rs, you want to have a final look to see if you can spot something?

@smyrman
Copy link
Collaborator

smyrman commented Nov 26, 2018

@Dragomir-Ivanov can you squash the last fixup commits as well? If there are no more comments, I think this is good for merging and we can deal with any fallout if there is anything we haven't spotted yet.

Checks query parameters if applicable to concrete schema resource types. Doesn't not check type constrains.
Checks sub-resource query parameters.
Adds suport for custom comparable types, and support for `rest-layer-mem`.
@Dragomir-Ivanov
Copy link
Contributor Author

@smyrman Done.

@smyrman smyrman merged commit 4e99227 into rs:master Nov 26, 2018
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