Skip to content

Commit

Permalink
added Cypher's CALL procedure support
Browse files Browse the repository at this point in the history
  • Loading branch information
vlowingkloude committed Dec 13, 2024
1 parent ba868f9 commit 8265d38
Show file tree
Hide file tree
Showing 22 changed files with 739 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2019-2024 The Polypheny Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.polypheny.db.adapter;

import org.polypheny.db.algebra.AlgNode;
import org.polypheny.db.plan.AlgCluster;
import org.polypheny.db.plan.AlgPlanner;
import org.polypheny.db.plan.AlgTraitSet;
import org.polypheny.db.plan.Convention;
import org.polypheny.db.plan.volcano.VolcanoPlanner;
import org.polypheny.db.type.entity.PolyValue;
import java.util.ArrayList;

public interface NeoProcedureProvider {
public Convention getConvention( AlgPlanner planner );
public AlgNode getCall( AlgCluster cluster, AlgTraitSet traits, ArrayList<String> namespace, String procedureName, ArrayList<PolyValue> arguments, boolean yieldAll, ArrayList<String> yieldItems);
public Adapter getStore();
}
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,12 @@ public enum Kind {
*/
PROCEDURE_CALL,

/**
* CypherProcedureCall
* We separate Cypher procedure calls and SQL procedure calls
*/
CYPHER_PROCEDURE_CALL,

/**
* NewSpecification
*/
Expand Down Expand Up @@ -1399,7 +1405,7 @@ public enum Kind {
DELETE,
UPDATE,
MERGE,
PROCEDURE_CALL );
PROCEDURE_CALL);

/**
* Category consisting of all DDL operators.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ enum NodeType {
VALUES,
AGGREGATE,
MERGE,
SORT
SORT,
CALL
}

}
85 changes: 85 additions & 0 deletions core/src/main/java/org/polypheny/db/algebra/core/lpg/LpgCall.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright 2019-2024 The Polypheny Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.polypheny.db.algebra.core.lpg;

import lombok.Getter;
import lombok.Setter;
import org.polypheny.db.adapter.Adapter;
import org.polypheny.db.algebra.AbstractAlgNode;
import org.polypheny.db.algebra.metadata.AlgMetadataQuery;
import org.polypheny.db.algebra.type.AlgDataType;
import org.polypheny.db.algebra.type.AlgDataTypeField;
import org.polypheny.db.algebra.type.AlgDataTypeFieldImpl;
import org.polypheny.db.algebra.type.AlgRecordType;
import org.polypheny.db.plan.AlgCluster;
import org.polypheny.db.plan.AlgOptCost;
import org.polypheny.db.plan.AlgPlanner;
import org.polypheny.db.plan.AlgTraitSet;
import org.polypheny.db.type.PolyType;
import org.polypheny.db.type.entity.PolyValue;
import java.util.ArrayList;

public abstract class LpgCall extends AbstractAlgNode implements LpgAlg {

@Getter
ArrayList<String> namespace;
@Getter
String procedureName;
@Getter
ArrayList<PolyValue> arguments;
@Setter
@Getter
Adapter procedureProvider; // will only be used when we reach a Neo4j store, so normally just pass a null to it

@Getter
boolean yieldAll;
@Getter
ArrayList<String> yieldItems;

public LpgCall( AlgCluster cluster, AlgTraitSet traits, ArrayList<String> namespace, String procedureName, ArrayList<PolyValue> arguments, Adapter procedureProvider, boolean yieldAll, ArrayList<String> yieldItems ) {
super( cluster, traits );
this.namespace = namespace;
this.procedureName = procedureName;
this.arguments = arguments;
this.procedureProvider = procedureProvider;
this.yieldAll = yieldAll;
this.yieldItems = yieldItems;
}

@Override
public String algCompareString() {
return getClass().getSimpleName().toString() + "$" + String.join( ".", namespace )
+ "." + procedureName + "$" + arguments.hashCode();
}


@Override
public NodeType getNodeType() {
return NodeType.CALL;
}

@Override
protected AlgDataType deriveRowType() {
if (!(procedureName.equals( "labels" ))) {
throw new UnsupportedOperationException("The called procedure is not supported");
}
ArrayList<AlgDataTypeField> fields = new ArrayList<>();
fields.add( new AlgDataTypeFieldImpl( -1L, "Labels", 0, getCluster().getTypeFactory().createPolyType( PolyType.VARCHAR ) ) );
return new AlgRecordType( fields );
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2019-2024 The Polypheny Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.polypheny.db.algebra.logical.lpg;

import org.polypheny.db.adapter.Adapter;
import org.polypheny.db.algebra.core.lpg.LpgCall;
import org.polypheny.db.plan.AlgCluster;
import org.polypheny.db.plan.AlgTraitSet;
import org.polypheny.db.type.entity.PolyValue;
import java.util.ArrayList;

public class LogicalLpgCall extends LpgCall {

public LogicalLpgCall( AlgCluster cluster, AlgTraitSet traits, ArrayList<String> namespace, String procedureName, ArrayList<PolyValue> arguments, Adapter procedureProvider, boolean yieldAll, ArrayList<String> yieldItems ) {
super( cluster, traits, namespace, procedureName, arguments, procedureProvider, yieldAll, yieldItems );
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2019-2024 The Polypheny Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.polypheny.db.algebra.rules;

import org.polypheny.db.adapter.Adapter;
import org.polypheny.db.adapter.AdapterManager;
import org.polypheny.db.adapter.NeoProcedureProvider;
import org.polypheny.db.algebra.AlgNode;
import org.polypheny.db.algebra.core.AlgFactories;
import org.polypheny.db.algebra.core.common.Modify;
import org.polypheny.db.algebra.core.lpg.LpgCall;
import org.polypheny.db.algebra.enumerable.EnumerableConvention;
import org.polypheny.db.algebra.logical.lpg.LogicalLpgCall;
import org.polypheny.db.plan.AlgOptRule;
import org.polypheny.db.plan.AlgOptRuleCall;
import org.polypheny.db.plan.Convention;

public class CypherCallLogicalToPhysicalRule extends AlgOptRule {

public static final CypherCallLogicalToPhysicalRule INSTANCE = new CypherCallLogicalToPhysicalRule( LogicalLpgCall.class );

public CypherCallLogicalToPhysicalRule( Class<? extends LpgCall> callAlg ) {
super( operand( callAlg, Convention.NONE, r -> true, any() ), AlgFactories.LOGICAL_BUILDER, callAlg.getSimpleName() + "ToPhysical" );
}

@Override
public void onMatch( AlgOptRuleCall call ) {
LpgCall oldAlg = call.alg( 0 );
Adapter neo = null;
for ( Adapter a : AdapterManager.getInstance().getStores().values() ) {
if ( a.adapterName.contains( "Neo" ) ) {
neo = a;
}
}
if ( neo == null ) {
throw new RuntimeException( "No neo adapter found" );
}
AlgNode newAlg = oldAlg;
newAlg.getTraitSet().replace( ((NeoProcedureProvider)neo).getConvention(call.getPlanner()) );
((LpgCall)newAlg).setProcedureProvider( ((NeoProcedureProvider)neo).getStore() );
//AlgNode newAlg = ((NeoProcedureProvider)neo).getCall( oldAlg.getCluster(), oldAlg.getTraitSet(), oldAlg.getNamespace(), oldAlg.getProcedureName(), oldAlg.getArguments() );
if ( newAlg != null ) {
call.transformTo( newAlg );
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public enum MonitoringType {
UPDATE,
MINUS,
INTERSECT,
UNION;
UNION,
CYPHER_PROCEDURE_CALL;


public static MonitoringType from( Kind kind ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
import org.polypheny.db.algebra.rules.AggregateProjectMergeRule;
import org.polypheny.db.algebra.rules.AggregateRemoveRule;
import org.polypheny.db.algebra.rules.CalcRemoveRule;
import org.polypheny.db.algebra.rules.CypherCallLogicalToPhysicalRule;
import org.polypheny.db.algebra.rules.FilterJoinRule;
import org.polypheny.db.algebra.rules.JoinAssociateRule;
import org.polypheny.db.algebra.rules.JoinCommuteRule;
Expand Down Expand Up @@ -835,6 +836,7 @@ public void registerModelRules() {
addRule( ModelSwitcherRule.MODEL_SWITCHER_RULE_REL_GRAPH );
addRule( ModelSwitcherRule.MODEL_SWITCHER_RULE_DOC_REL );
addRule( ModelSwitcherRule.MODEL_SWITCHER_RULE_DOC_GRAPH );
addRule( CypherCallLogicalToPhysicalRule.INSTANCE );
}


Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/org/polypheny/db/tools/Programs.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import org.polypheny.db.algebra.rules.AllocationToPhysicalModifyRule;
import org.polypheny.db.algebra.rules.AllocationToPhysicalScanRule;
import org.polypheny.db.algebra.rules.CalcMergeRule;
import org.polypheny.db.algebra.rules.CypherCallLogicalToPhysicalRule;
import org.polypheny.db.algebra.rules.FilterAggregateTransposeRule;
import org.polypheny.db.algebra.rules.FilterCalcMergeRule;
import org.polypheny.db.algebra.rules.FilterJoinRule;
Expand Down Expand Up @@ -172,6 +173,7 @@ public class Programs {
AllocationToPhysicalModifyRule.REL_INSTANCE,
AllocationToPhysicalModifyRule.DOC_INSTANCE,
AllocationToPhysicalModifyRule.GRAPH_INSTANCE,
CypherCallLogicalToPhysicalRule.INSTANCE,
RuntimeConfig.JOIN_COMMUTE.getBoolean()
? JoinAssociateRule.INSTANCE
: ProjectMergeRule.INSTANCE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.polypheny.db.algebra.rules.AggregateValuesRule;
import org.polypheny.db.algebra.rules.AllocationToPhysicalModifyRule;
import org.polypheny.db.algebra.rules.AllocationToPhysicalScanRule;
import org.polypheny.db.algebra.rules.CypherCallLogicalToPhysicalRule;
import org.polypheny.db.algebra.rules.FilterAggregateTransposeRule;
import org.polypheny.db.algebra.rules.FilterJoinRule;
import org.polypheny.db.algebra.rules.FilterProjectTransposeRule;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ public <T extends AlgNode & LpgAlg> AlgNode routeGraph( RoutedAlgBuilder builder
return alg;
} else if ( alg.getNodeType() == NodeType.VALUES ) {
return alg;
} else if ( alg.getNodeType() == NodeType.CALL ) {
// TODO: we currently still return LogicalLpgCall
return alg;
}
throw new UnsupportedOperationException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import java.util.List;
import lombok.Getter;
import org.polypheny.db.algebra.constant.Kind;
import org.polypheny.db.cypher.CypherCallResultItem;
import org.polypheny.db.cypher.expression.CypherExpression;
import org.polypheny.db.languages.ParserPos;
Expand Down Expand Up @@ -64,4 +65,9 @@ public CypherKind getCypherKind() {
return CypherKind.CALL;
}

@Override
public Kind getKind() {
return Kind.CYPHER_PROCEDURE_CALL;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.polypheny.db.algebra.constant.Kind;
import org.polypheny.db.algebra.core.AggregateCall;
import org.polypheny.db.algebra.core.common.Modify;
import org.polypheny.db.algebra.logical.lpg.LogicalLpgCall;
import org.polypheny.db.algebra.logical.lpg.LogicalLpgFilter;
import org.polypheny.db.algebra.logical.lpg.LogicalLpgMatch;
import org.polypheny.db.algebra.logical.lpg.LogicalLpgModify;
Expand All @@ -57,8 +58,10 @@
import org.polypheny.db.catalog.entity.logical.LogicalNamespace;
import org.polypheny.db.catalog.exceptions.GenericRuntimeException;
import org.polypheny.db.catalog.snapshot.Snapshot;
import org.polypheny.db.cypher.CypherCallResultItem;
import org.polypheny.db.cypher.CypherNode;
import org.polypheny.db.cypher.CypherNode.CypherFamily;
import org.polypheny.db.cypher.clause.CypherCall;
import org.polypheny.db.cypher.clause.CypherClause;
import org.polypheny.db.cypher.clause.CypherCreate;
import org.polypheny.db.cypher.clause.CypherDelete;
Expand All @@ -69,6 +72,7 @@
import org.polypheny.db.cypher.clause.CypherUnwind;
import org.polypheny.db.cypher.clause.CypherWhere;
import org.polypheny.db.cypher.clause.CypherWith;
import org.polypheny.db.cypher.expression.CypherExpression;
import org.polypheny.db.cypher.pattern.CypherPattern;
import org.polypheny.db.cypher.query.CypherSingleQuery;
import org.polypheny.db.languages.OperatorRegistry;
Expand All @@ -84,6 +88,7 @@
import org.polypheny.db.type.PolyType;
import org.polypheny.db.type.entity.PolyList;
import org.polypheny.db.type.entity.PolyString;
import org.polypheny.db.type.entity.PolyValue;
import org.polypheny.db.type.entity.graph.PolyDictionary;
import org.polypheny.db.type.entity.graph.PolyEdge;
import org.polypheny.db.type.entity.graph.PolyNode;
Expand Down Expand Up @@ -200,12 +205,39 @@ private void convertClauses( CypherClause clause, CypherContext context ) {
case REMOVE:
convertRemove( (CypherRemove) clause, context );
break;
case CALL:
convertCall( (CypherCall) clause, context );
break;
default:
throw new UnsupportedOperationException();
}

}

private void convertCall( CypherCall call, CypherContext context ) {
assert call.getNamespace() instanceof ArrayList;
context.kind = call.getKind();
ArrayList<String> namespace = (ArrayList<String>) call.getNamespace();
String procedureName = call.getName();
ArrayList<PolyValue> arguments = new ArrayList<>();
for ( CypherExpression argument : call.getArguments() ) {
// TODO: are we assuming that there will not be a function/procedure call inside this procedure call?
arguments.add( argument.getComparable() );
}
boolean yieldAll = true;
ArrayList<String> yieldItems = new ArrayList<>();
if ( call.getItems() != null ) {
yieldAll = false;
for ( CypherCallResultItem item : call.getItems() ) {
yieldItems.add( item.getExpression() );
}
} else {
yieldAll = true;
}
LogicalLpgCall procedureCall = new LogicalLpgCall(cluster, cluster.traitSet(), namespace, procedureName, arguments, null, yieldAll, yieldItems );
context.add( procedureCall );
}


private void convertRemove( CypherRemove clause, CypherContext context ) {
clause.getRemove( context );
Expand Down
Loading

0 comments on commit 8265d38

Please sign in to comment.