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

Adding support for Filter blocks to SQL backend #166

Merged
merged 5 commits into from Jan 25, 2019
Merged

Conversation

jmeulemans
Copy link
Collaborator

No description provided.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.006%) to 95.127% when pulling af6bcdc on add-sql-filters into 432ac3b on master.

@coveralls
Copy link

coveralls commented Jan 23, 2019

Coverage Status

Coverage decreased (-0.06%) to 95.075% when pulling ba0dd02 on add-sql-filters into 432ac3b on master.

u'has_substring': Operator(u'contains', Cardinality.UNARY),
}

UNSUPPORTED_OPERATOR_NAMES = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Any particular reason to specify this set in addition to SUPPORTED_OPERATORS? Seems kind of error-prone -- we'll always need to remember to add every new filtering operator to one of these constants here, or we'll get a random KeyError on line 205 of emit_sql.py. I'd suggest defining SUPPORTED_OPERATORS and then if the operator in the BinaryComposition isn't there then saying it's unsupported.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Nope, thanks fixed that.

graphql_compiler/compiler/ir_lowering_sql/constants.py Outdated Show resolved Hide resolved
graphql_compiler/compiler/ir_lowering_sql/constants.py Outdated Show resolved Hide resolved
graphql_compiler/compiler/ir_lowering_sql/constants.py Outdated Show resolved Hide resolved


SUPPORTED_OPERATORS = {
u'contains': Operator(u'in_', Cardinality.LIST_VALUED),
Copy link
Contributor

Choose a reason for hiding this comment

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

Are the specific names (Operator.name values) here important? Are they used to look up things in SQLAlchemy? A comment might be helpful to explain why the existing compiler operator names are being remapped to new names.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes they are important for the getattr calls. For example, if we are resolving column_name @filter(op_name: "=", value: ["$variable"])
The corresponding python ends up being getattr(Column(column_name), '__eq__')(BindParameter('variable_name') which programattically gets us to Column('column_name') == BindParameter('variable_name'). I'll add this to a comment.

Returns:
Expression, SQLAlchemy expression.
"""
variable_name = expression.variable_name
Copy link
Contributor

Choose a reason for hiding this comment

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

expression is meant to be of type Variable, no? If so, then line 260 should be an assertion -- variable names are required to start with $.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good to know, this is an assertion now.

left = _expression_to_sql(expression.left, node, context)
right = _expression_to_sql(expression.right, node, context)
if sql_operator.cardinality == constants.Cardinality.UNARY:
# ensure the operator is grabbed from the Column object
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like there should be an assertion here? The assumption appears to be that after this block, left is an instance of Column.

left, right = right, left
if not isinstance(right, BindParameter):
raise AssertionError(
u'List valued operator expects column as left side of expression')
Copy link
Contributor

Choose a reason for hiding this comment

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

Always include the value that caused the error in the error message. Imagine debugging this problem -- the error message tells you that something went wrong, but you don't know precisely in what way it went wrong since the exact value of right isn't returned. So the first step afterward is to change the error message to give you more info so that you can actually start looking into it. Let's just skip that first step and make the error message include the data we'd need to start diagnosing the problem.

How about List valued operator {} expects BindParameter as the right side of the expression, but instead got {} or something to that effect?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This should be fixed now, the check is the same for UNARY and LIST_VALUED things, so they both call the same method with a more detailed error now.

u'List valued operator expects column as left side of expression')
if not isinstance(left, Column):
raise AssertionError(
u'List valued operator expects bind parameter as right side of expression')
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the error messages and checks are backwards relative to each other. Also, let's refer to types by their actual names: BindParameter, Column, etc.

graphql_compiler/compiler/emit_sql.py Outdated Show resolved Hide resolved
Copy link
Contributor

@obi1kenobi obi1kenobi left a comment

Choose a reason for hiding this comment

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

Just a few nits, looks good overall.

right.expanding = True
clause = getattr(left, sql_operator.name)(right)
return clause
else:
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: At one point there was a subtle bug in the compiler where an if-elif tree like this one, where each branch was meant to return, actually had a code path that didn't return. With the raise AssertionError in the else branch, that meant that no error was raised (since the else wasn't taken, one of other the branches was taken but didn't return), and instead the function simply returned None to the caller ... which promptly exploded elsewhere.

So if all branches are meant to return, I'd pull the AssertionError out of the else, and make it say Unreachable state reached (+ as much contextual info as possible) instead of necessarily blaming the cardinality.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That makes sense. I remember that error, it is very hard to track down.

graphql_compiler/compiler/emit_sql.py Outdated Show resolved Hide resolved
graphql_compiler/compiler/ir_lowering_sql/__init__.py Outdated Show resolved Hide resolved
def compile_and_run_match_query(schema, graphql_query, parameters, graph_client):
"""Compiles and runs a MATCH query against the supplied graph client."""
compilation_result = graphql_to_match(schema, graphql_query, parameters)
# OrientDB expects decimals to be passed as their string representation
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: This is slightly misleading. The MATCH code the compiler emits expects Decimals to come in as strings, since they are wrapped in a statement that causes OrientDB to parse them into Decimal types before using them.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Corrected, thanks for the explanation.

Copy link
Contributor

@obi1kenobi obi1kenobi left a comment

Choose a reason for hiding this comment

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

Looks great, thank you!

@jmeulemans jmeulemans merged commit eebc64d into master Jan 25, 2019
@obi1kenobi obi1kenobi deleted the add-sql-filters branch October 16, 2019 14:54
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.

None yet

3 participants