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

Improve finding entity and field nodes #12

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Improve finding entity and field nodes #12

wants to merge 2 commits into from

Conversation

kungwangtotvs
Copy link

Here are changes that works for my gremlin implementation again our own database. Please help me review it. Thank you.

@twilmes
Copy link
Owner

twilmes commented Mar 15, 2017

Thanks for the PR Kung. I'll take a look.

@@ -37,7 +37,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>4.12</junit.version>
<tinkerpop.version>3.1.0-incubating</tinkerpop.version>
<calcite.version>1.5.0</calcite.version>
<calcite.version>1.6.0</calcite.version>
Copy link
Author

Choose a reason for hiding this comment

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

If upgrade to 1.8.0 and newer, there will be a JDBC error during planner's parse phase

@@ -95,6 +96,20 @@ private GremlinToEnumerableConverter getConverter(int fieldIndex, String field,
List<String> fieldNames = join.getRowType().getFieldNames();
final String chosenField = fieldNames.get(fieldIndex);
return fieldMap.get(join).get(chosenField);
} else if (node instanceof EnumerableCalc) {
Copy link
Author

@kungwangtotvs kungwangtotvs Mar 15, 2017

Choose a reason for hiding this comment

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

In my case, I always get this object as instance of EnumerableCalc instead of EnumerableJoin. By look deeper into the inputs, I will be able to get the converter out of these fields

@@ -121,7 +121,7 @@ public String explain(String sql) {
final FieldMapVisitor fieldMapper = new FieldMapVisitor();
new RelWalker(root, fieldMapper);
final TraversalVisitor traversalVisitor = new TraversalVisitor(graph.traversal(),
scanMap, fieldMapper.getFieldMap());
scanMap, fieldMapper.getFieldMap(), schemaConfig);
Copy link
Author

Choose a reason for hiding this comment

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

When doing 3 tables or more table joins, I see parser gives path that are joining two tables that has no relationship described in SchemaConfig, why? I think it should be problem is Calcite, here I was thinking of providing schema to checking in TraversalVisitor, but was not able to find left and right gremlin table in any of these nodes, so this will be a TODO item to check why it join two tables that has no relationship defined.

@@ -185,8 +186,8 @@ public JoinQueryExecutor(final RelNode node,
}
}
}
final Property<Object> property = result.get(tableId).
property(tableIdToTableDefMap.get(tableId).getColumn(simpleFieldName.toLowerCase()).getPropertyName());
TableColumn tableColumn = tableIdToTableDefMap.get(tableId).getColumn(simpleFieldName.toLowerCase());
Copy link
Author

Choose a reason for hiding this comment

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

Sometimes I got null tableColumns here, so original statement will throw NPE in this case.

@@ -82,15 +89,39 @@ public void visit(RelNode node) {
final String rightAliasedColumn = rightJoinFields.get(rightKeyId);

if(!(left instanceof GremlinToEnumerableConverter)) {
left = fieldMap.get(left).get(leftAliasedColumn);
if (fieldMap.get(left) != null && fieldMap.get(left).containsKey(leftAliasedColumn)) {
Copy link
Author

Choose a reason for hiding this comment

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

In my own Gremlin implementation, I found left is always null when doing this simple get(leftAliasedColumn), so I have to look deeper to its joins to see what was involved in join and register them in tableTraversalMap, otherwise, later when doing get tableId, null will return and throw bad reference exception.

} else {
List<RelNode> scan = scanMap.get(left);
GraphTraversal leftTraversal = TraversalBuilder.toTraversal(scan);
traversals.add(leftTraversal);
tableTraversalMap.put(getTableId((GremlinToEnumerableConverter) left), leftTraversal);
}
if(!(right instanceof GremlinToEnumerableConverter)) {
right = fieldMap.get(join).get(rightAliasedColumn);
if (fieldMap.get(join) != null && fieldMap.get(join).containsKey(rightAliasedColumn)) {
Copy link
Author

Choose a reason for hiding this comment

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

Same reason as above

@@ -50,8 +51,8 @@ public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
}

@Override
public RelOptCost computeSelfCost(RelOptPlanner planner) {
return super.computeSelfCost(planner).multiplyBy(.1);
public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq) {
Copy link
Author

Choose a reason for hiding this comment

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

implementation changes from Calcite 1.5.0 to 1.6.0

@@ -61,11 +61,23 @@ public static Object convertType(Object value, TableColumn column) {
case "string":
return value;
case "integer":
return ((Number) value).intValue();
try {
Copy link
Author

Choose a reason for hiding this comment

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

I wonder if this is correct way of converting these types, but it works for me so far, same to the rest of changes

@twilmes
Copy link
Owner

twilmes commented Mar 15, 2017

Would it be possible for you to provide the schema you're working with along with some queries?

@kungwangtotvs
Copy link
Author

There are there tables involve in this query:
mdmcustomer, mdmticket and mdmopportunity.

the relationship is defined as:
mdmcustomer.mdmcompanycode <= mdmticket.mdmcompanycode
mdmcustomer.mdmcompanycode <= mdmopportunity.mdmcompanycode

here is the SQL query:
select c.mdmcompanycode, count(i.mdmcompanycode), count(o.mdmcompanycode)
from mdmcustomer as c join mdmticket as i on c.mdmcompanycode = i.mdmcompanycode
join mdmopportunity as o on o.mdmcompanycode = c.mdmcompanycode
group by c.mdmcompanycode

Although I did see where I can see the gremlin generated, but I would imaging it should be something like this:

g.V().hasLabel("mdmcustomer").as("customers")
.match(
__.as("c").both("has Opportunity").count().as("opportunities"),
__.as("c").both("has_ticket").count().as("tickets"))
.select("customers", "opportunities", "tickets")

But after SQL had been parsed, and creating traversal tree, it traverses from mdmticket to mdmopportunity.

twilmes pushed a commit that referenced this pull request Nov 5, 2021
AN-822 Unit tests and checkstyle updates
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