From 8b2dc004cf64966a5498118a362a94d61fe52631 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Mon, 18 Mar 2024 11:53:51 +0100 Subject: [PATCH 001/132] Add ability to serialize AlgNodes to PolyAlg strings for some LogicalRel operators --- .../polypheny/db/algebra/AbstractAlgNode.java | 49 +++++ .../org/polypheny/db/algebra/AlgNode.java | 29 +++ .../db/algebra/core/relational/RelScan.java | 18 ++ .../relational/LogicalRelAggregate.java | 29 +++ .../logical/relational/LogicalRelFilter.java | 21 ++ .../logical/relational/LogicalRelMinus.java | 11 ++ .../logical/relational/LogicalRelProject.java | 16 ++ .../logical/relational/LogicalRelSort.java | 19 ++ .../algebra/polyalg/PolyAlgDeclaration.java | 181 ++++++++++++++++++ .../db/algebra/polyalg/PolyAlgUtils.java | 107 +++++++++++ .../db/algebra/polyalg/arguments/AggArg.java | 56 ++++++ .../db/algebra/polyalg/arguments/AnyArg.java | 44 +++++ .../algebra/polyalg/arguments/BooleanArg.java | 42 ++++ .../polyalg/arguments/CollationArg.java | 71 +++++++ .../algebra/polyalg/arguments/EntityArg.java | 44 +++++ .../algebra/polyalg/arguments/FieldArg.java | 40 ++++ .../db/algebra/polyalg/arguments/IntArg.java | 42 ++++ .../db/algebra/polyalg/arguments/ListArg.java | 71 +++++++ .../algebra/polyalg/arguments/PolyAlgArg.java | 27 +++ .../polyalg/arguments/PolyAlgRegistry.java | 84 ++++++++ .../db/algebra/polyalg/arguments/RexArg.java | 56 ++++++ .../org/polypheny/db/plan/AlgOptUtil.java | 8 + 22 files changed, 1065 insertions(+) create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AnyArg.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/BooleanArg.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CollationArg.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EntityArg.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/IntArg.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArg.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgRegistry.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java diff --git a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java index 9aa8f1e040..897c44ad32 100644 --- a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java +++ b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java @@ -41,6 +41,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import lombok.Getter; @@ -52,6 +53,10 @@ import org.polypheny.db.algebra.metadata.AlgMetadataQuery; import org.polypheny.db.algebra.metadata.Metadata; import org.polypheny.db.algebra.metadata.MetadataFactory; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgRegistry; import org.polypheny.db.algebra.type.AlgDataType; import org.polypheny.db.catalog.entity.Entity; import org.polypheny.db.plan.AlgCluster; @@ -346,6 +351,50 @@ public AlgWriter explainTerms( AlgWriter pw ) { } + @Override + public void buildPolyAlgebra( StringBuilder sb ) { + PolyAlgDeclaration decl = getPolyAlgDeclaration(); + sb.append( decl.opName ); + sb.append( decl.serializeArguments( prepareAttributes() ) ); + + int size = getInputs().size(); + if ( size == 0 ) { + return; // skip parentheses for leaves + } + + sb.append( "(\n" ); + for ( AlgNode child : getInputs() ) { + child.buildPolyAlgebra( sb ); + + size--; + if ( size > 0 ) { + sb.append( ", " ); + } + } + sb.append( "\n)" ); + } + + + /** + * If a declaration should be shared by multiple implementations, + * this method must be redefined. + * Otherwise, this implementation should cover most cases. + * + * @return The declaration associated with the runtime class of the instance. + */ + @Override + public PolyAlgDeclaration getPolyAlgDeclaration() { + return PolyAlgRegistry.getDeclaration( getClass(), getInputs().size() ); + } + + + @Override + public Map prepareAttributes() { + // TODO: Move implementation from abstract class into child classes + return Collections.emptyMap(); + } + + @Override public AlgNode onRegister( AlgPlanner planner ) { List oldInputs = getInputs(); diff --git a/core/src/main/java/org/polypheny/db/algebra/AlgNode.java b/core/src/main/java/org/polypheny/db/algebra/AlgNode.java index 08293b170c..dd74299b53 100644 --- a/core/src/main/java/org/polypheny/db/algebra/AlgNode.java +++ b/core/src/main/java/org/polypheny/db/algebra/AlgNode.java @@ -35,6 +35,7 @@ import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; import org.jetbrains.annotations.Nullable; @@ -43,6 +44,9 @@ import org.polypheny.db.algebra.externalize.AlgWriterImpl; import org.polypheny.db.algebra.metadata.AlgMetadataQuery; import org.polypheny.db.algebra.metadata.Metadata; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; import org.polypheny.db.algebra.type.AlgDataType; import org.polypheny.db.catalog.entity.Entity; import org.polypheny.db.catalog.logistic.DataModel; @@ -236,6 +240,31 @@ public interface AlgNode extends AlgOptNode, Cloneable { */ void explain( AlgWriter pw ); + /** + * Recursively constructs a string representation of the tree rooted at this AlgNode using the provided StringBuilder. + * The basic structure of PolyAlgebra is {@code OPERATOR[attributes](children)}. + * + * @param sb StringBuilder for building the representation + */ + void buildPolyAlgebra( StringBuilder sb ); + + /** + * Retrieves the PolyAlgDeclaration for this AlgNode implementation. + * This method should be static. + * @return PolyAlgDeclaration for this AlgNode implementation + */ + PolyAlgDeclaration getPolyAlgDeclaration(); + + /** + * Serializes the attributes of this instance for the purpose of creating the PolyAlgebra representation for this AlgNode. + * Each value in the returned map represents one serialized attribute of this AlgNode instance. + * The key is the corresponding parameter in the {@link org.polypheny.db.algebra.polyalg.PolyAlgDeclaration}. + * If no attributes exist, an empty map is returned. + * + * @return A map that maps parameters to serialized attributes of this AlgNode instance + */ + Map prepareAttributes(); + /** * Receives notification that this expression is about to be registered. The implementation of this method must at least register all child expressions. * diff --git a/core/src/main/java/org/polypheny/db/algebra/core/relational/RelScan.java b/core/src/main/java/org/polypheny/db/algebra/core/relational/RelScan.java index d297554189..c51d1e17e0 100644 --- a/core/src/main/java/org/polypheny/db/algebra/core/relational/RelScan.java +++ b/core/src/main/java/org/polypheny/db/algebra/core/relational/RelScan.java @@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -30,6 +31,11 @@ import org.polypheny.db.algebra.core.Project; import org.polypheny.db.algebra.core.common.Scan; import org.polypheny.db.algebra.metadata.AlgMetadataQuery; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; +import org.polypheny.db.algebra.polyalg.arguments.EntityArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgRegistry; import org.polypheny.db.algebra.type.AlgDataType; import org.polypheny.db.algebra.type.AlgDataTypeField; import org.polypheny.db.algebra.type.DocumentType; @@ -164,4 +170,16 @@ public boolean isCrossModel() { return entity.dataModel != DataModel.RELATIONAL; } + + @Override + public PolyAlgDeclaration getPolyAlgDeclaration() { + return PolyAlgRegistry.getDeclaration( RelScan.class ); + } + + + @Override + public Map prepareAttributes() { + return Map.of( getPolyAlgDeclaration().getPos( 0 ), new EntityArg( entity ) ); + } + } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java index 9637281b81..c5fe627de9 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java @@ -34,12 +34,20 @@ package org.polypheny.db.algebra.logical.relational; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.AlgShuttle; import org.polypheny.db.algebra.core.Aggregate; import org.polypheny.db.algebra.core.AggregateCall; import org.polypheny.db.algebra.core.relational.RelAlg; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; +import org.polypheny.db.algebra.polyalg.arguments.AggArg; +import org.polypheny.db.algebra.polyalg.arguments.FieldArg; +import org.polypheny.db.algebra.polyalg.arguments.ListArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; import org.polypheny.db.algebra.rules.AggregateProjectPullUpConstantsRule; import org.polypheny.db.algebra.rules.AggregateReduceFunctionsRule; import org.polypheny.db.plan.AlgCluster; @@ -111,5 +119,26 @@ public AlgNode accept( AlgShuttle shuttle ) { } + @Override + public Map prepareAttributes() { + PolyAlgDeclaration decl = getPolyAlgDeclaration(); + Map attributes = new HashMap<>(); + + PolyAlgArg groupArg = new ListArg<>( groupSet.asList().stream().map( FieldArg::new ).toList() ); + PolyAlgArg aggsArg = new ListArg<>( aggCalls.stream().map( AggArg::new ).toList(), this ); + + attributes.put( decl.getPos( 0 ), groupArg ); + attributes.put( decl.getPos( 1 ), aggsArg ); + if ( getGroupType() != Group.SIMPLE ) { + PolyAlgArg groupSetArg = new ListArg<>( groupSets.stream().map( set -> + new ListArg<>( set.asList().stream().map( FieldArg::new ).toList() ) + ).toList() ); + + attributes.put( decl.getParam( "groups" ), groupSetArg ); + } + + return attributes; + } + } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java index 3d6b1e821e..4f1121dd74 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java @@ -35,6 +35,8 @@ import com.google.common.collect.ImmutableSet; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; import lombok.Getter; import org.polypheny.db.algebra.AlgCollationTraitDef; @@ -48,6 +50,12 @@ import org.polypheny.db.algebra.metadata.AlgMdCollation; import org.polypheny.db.algebra.metadata.AlgMdDistribution; import org.polypheny.db.algebra.metadata.AlgMetadataQuery; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; +import org.polypheny.db.algebra.polyalg.arguments.AnyArg; +import org.polypheny.db.algebra.polyalg.arguments.ListArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.RexArg; import org.polypheny.db.plan.AlgCluster; import org.polypheny.db.plan.AlgTraitSet; import org.polypheny.db.plan.Convention; @@ -120,4 +128,17 @@ public AlgWriter explainTerms( AlgWriter pw ) { return super.explainTerms( pw ); } + + @Override + public Map prepareAttributes() { + PolyAlgDeclaration decl = getPolyAlgDeclaration(); + Map attributes = new HashMap<>(); + PolyAlgArg varArg = new ListArg<>( variablesSet.stream().map( AnyArg::new ).toList() ); + + attributes.put( decl.getPos( 0 ), new RexArg( condition, this ) ); + attributes.put( decl.getParam( "variables" ), varArg ); + + return attributes; + } + } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelMinus.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelMinus.java index fe4de0f77f..00f5f2ef55 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelMinus.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelMinus.java @@ -34,12 +34,17 @@ package org.polypheny.db.algebra.logical.relational; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.polypheny.db.algebra.AlgInput; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.AlgShuttle; import org.polypheny.db.algebra.core.Minus; import org.polypheny.db.algebra.core.relational.RelAlg; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; +import org.polypheny.db.algebra.polyalg.arguments.BooleanArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; import org.polypheny.db.plan.AlgCluster; import org.polypheny.db.plan.AlgTraitSet; import org.polypheny.db.plan.Convention; @@ -90,5 +95,11 @@ public AlgNode accept( AlgShuttle shuttle ) { return shuttle.visit( this ); } + + @Override + public Map prepareAttributes() { + return Map.of(getPolyAlgDeclaration().getParam( "all" ), new BooleanArg( all ) ); + } + } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java index 7e08007f8b..b48e2548e4 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java @@ -33,7 +33,9 @@ package org.polypheny.db.algebra.logical.relational; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import java.util.stream.IntStream; import org.polypheny.db.algebra.AlgCollationTraitDef; @@ -43,6 +45,10 @@ import org.polypheny.db.algebra.core.relational.RelAlg; import org.polypheny.db.algebra.metadata.AlgMdCollation; import org.polypheny.db.algebra.metadata.AlgMetadataQuery; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; +import org.polypheny.db.algebra.polyalg.arguments.ListArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.RexArg; import org.polypheny.db.algebra.type.AlgDataType; import org.polypheny.db.plan.AlgCluster; import org.polypheny.db.plan.AlgTraitSet; @@ -124,5 +130,15 @@ public AlgNode accept( AlgShuttle shuttle ) { return shuttle.visit( this ); } + + @Override + public Map prepareAttributes() { + PolyAlgArg projectsArg = new ListArg<>( exps.stream().map( RexArg::new ).toList(), rowType.getFieldNames(), this ); + + Map attributes = new HashMap<>(); + attributes.put( getPolyAlgDeclaration().getPos( 0 ), projectsArg ); + return attributes; + } + } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java index cbc6be8842..e4dc50f1e8 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java @@ -34,7 +34,9 @@ package org.polypheny.db.algebra.logical.relational; import com.google.common.collect.ImmutableList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.jetbrains.annotations.Nullable; import org.polypheny.db.algebra.AlgCollation; import org.polypheny.db.algebra.AlgCollationTraitDef; @@ -42,6 +44,11 @@ import org.polypheny.db.algebra.AlgShuttle; import org.polypheny.db.algebra.core.Sort; import org.polypheny.db.algebra.core.relational.RelAlg; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; +import org.polypheny.db.algebra.polyalg.arguments.CollationArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.RexArg; import org.polypheny.db.plan.AlgCluster; import org.polypheny.db.plan.AlgTraitSet; import org.polypheny.db.plan.Convention; @@ -93,5 +100,17 @@ public AlgNode accept( AlgShuttle shuttle ) { return shuttle.visit( this ); } + + @Override + public Map prepareAttributes() { + PolyAlgDeclaration decl = getPolyAlgDeclaration(); + Map attributes = new HashMap<>(); + + attributes.put( decl.getPos( 0 ), new CollationArg( collation, this ) ); + attributes.put( decl.getParam( "fetch" ), new RexArg( fetch ) ); + attributes.put( decl.getParam( "offset" ), new RexArg( offset ) ); + return attributes; + } + } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java new file mode 100644 index 0000000000..941ae4ad72 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java @@ -0,0 +1,181 @@ +/* + * 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.polyalg; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import java.util.StringJoiner; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; + + +public class PolyAlgDeclaration { + + public final String opName; + public final ImmutableList opAliases; + public final int numInputs; // -1 if arbitrary amount is allowed + + public final ImmutableList posParams; + public final ImmutableList kwParams; + private final ImmutableMap paramLookup; + + + public PolyAlgDeclaration( String opName, ImmutableList opAliases, int numInputs, ImmutableList params ) { + this.opName = opName; + this.opAliases = opAliases; + this.numInputs = numInputs; + + ImmutableMap.Builder bMap = ImmutableMap.builder(); + ImmutableList.Builder bPos = ImmutableList.builder(); + ImmutableList.Builder bKey = ImmutableList.builder(); + for ( Parameter p : params ) { + bMap.put( p.name, p ); + if ( p.isPositional() ) { + bPos.add( p ); + } else { + bKey.add( p ); + } + } + this.posParams = bPos.build(); + this.kwParams = bKey.build(); + this.paramLookup = bMap.build(); + } + + + public PolyAlgDeclaration( String opName, int numInputs, ImmutableList params ) { + this( opName, ImmutableList.of(), numInputs, params ); + } + + + public PolyAlgDeclaration( String opName, int numInputs ) { + this( opName, ImmutableList.of(), numInputs, ImmutableList.of() ); + } + + + public PolyAlgDeclaration( String opName, int numInputs, Parameter param ) { + this( opName, ImmutableList.of(), numInputs, ImmutableList.of( param ) ); + } + + + public String serializeArguments( Map preparedAttributes ) { + StringJoiner joiner = new StringJoiner( ", ", "[", "]" ); + + for ( Parameter p : posParams ) { + assert preparedAttributes.containsKey( p ); + joiner.add( preparedAttributes.get( p ).toPolyAlg() ); + } + for ( Parameter p : kwParams ) { + if ( preparedAttributes.containsKey( p ) ) { + String attribute = preparedAttributes.get( p ).toPolyAlg(); + if ( !p.defaultValue.equals( attribute ) ) { + joiner.add( p.name + "=" + attribute ); + } + } + } + return joiner.toString(); + } + + + public Parameter getPos( int i ) { + return posParams.get( i ); + } + + + public Parameter getParam( String name ) { + return paramLookup.get( name ); + } + + + /** + * Depending on whether a defaultValue is specified, a Parameter can result in two types of corresponding arguments: + *
    + *
  • Positional arguments: + * An argument for a positional Parameter always has to be included in the proper position. It does not have a default value
  • + *
  • Keyword arguments: Arguments are preceded by the name of the parameter. Keyword arguments can be omitted, in which case the defaultValue is used.
  • + *
+ * + * @param name The name of this Parameter + * @param type The type of this Parameter + * @param isMultiValued Boolean indicating whether an argument consisting of multiple values can be specified + * @param defaultValue The default value for this Parameter or null if it has no default value (if it should have a default value of null, use an empty string instead) + */ + public record Parameter(String name, ParamType type, boolean isMultiValued, String defaultValue) { + + public Parameter( String name ) { + this( name, ParamType.ANY ); + } + + + public Parameter( String name, ParamType type ) { + this( name, type, false, null ); + } + + + public Parameter( String name, ParamType type, boolean isMultiValued ) { + this( name, type, isMultiValued, null ); + } + + + public boolean isPositional() { + return defaultValue == null; + } + + } + + + public enum ParamType { + /** + * The default type. Should only be used if no other type fits better. + */ + ANY, + INTEGER, + STRING, + + /** + * A boolean flag, either "true" or "false". + */ + BOOLEAN, + + /** + * A serialized RexNode + */ + SIMPLE_REX, + AGGREGATE, + + /** + * A REX that evaluates to a boolean. + */ + BOOLEAN_REX, + ENTITY, + + /** + * A specific field (= column in the relational data model). + */ + FIELD, + + /** + * A list with no elements. + */ + EMPTY_LIST, + + /** + * + */ + COLLATION + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java new file mode 100644 index 0000000000..833799e4e4 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java @@ -0,0 +1,107 @@ +/* + * 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.polyalg; + +import java.util.ArrayList; +import java.util.List; +import org.polypheny.db.algebra.AlgNode; +import org.polypheny.db.algebra.type.AlgDataTypeField; +import org.polypheny.db.rex.RexNode; + +public class PolyAlgUtils { + + public static String replaceWithFieldNames( AlgNode alg, String str ) { + if ( str.contains( "$" ) ) { + int offset = 0; + for ( AlgNode input : alg.getInputs() ) { + for ( AlgDataTypeField field : input.getTupleType().getFields() ) { + String searchStr = "$" + (offset + field.getIndex()); + int position = str.indexOf( searchStr ); + if ( position >= 0 && (str.length() >= position + searchStr.length()) ) { + str = str.replace( searchStr, field.getName() ); + } + } + offset = input.getTupleType().getFields().size(); + } + } + return str; + } + + public static String getFieldNameFromIndex(AlgNode alg, int idx) { + for ( AlgNode input : alg.getInputs() ) { + List fields = input.getTupleType().getFields(); + if (idx < fields.size()) { + return fields.get( idx ).getName(); + } + idx += fields.size(); + } + return Integer.toString( idx ); + } + + + public static List replaceWithFieldNames( AlgNode alg, List exps ) { + return exps.stream() + .map( exp -> replaceWithFieldNames( alg, exp.toString() ) ) + .toList(); + } + + public static String appendAlias(String exp, String alias) { + if ( !alias.equals( exp ) ) { + exp += " AS " + alias; + } + return exp; + } + + + /** + * Each element in exps is compared with the corresponding element in aliases. + * If they differ, the alias is appended to the element, separated by the keyword {@code AS}. + * For example {@code AVG(age) AS average}. + * + * @param exps List of strings to be assigned an alias + * @param aliases List with each element being the alias for the corresponding value in exps + * @return Copy of the list exps with aliases appended where values differ + */ + public static List appendAliases( List exps, List aliases ) { + assert exps.size() == aliases.size(); + List list = new ArrayList<>(); + for ( int i = 0; i < exps.size(); i++ ) { + list.add( appendAlias(exps.get( i ), aliases.get( i )) ); + } + return list; + } + + + /** + * Joins the values for a multivalued attribute into a single string. + * If values contains more than one element, the returned string is surrounded with brackets to represent a list. + * + * @param values the values to be joined + * @return a string either representing a list containing or values or a single value if values is of size 1. + */ + public static String joinMultiValued( List values ) { + if ( values.isEmpty() ) { + return ""; + } + if ( values.size() == 1 ) { + return values.get( 0 ); + } + + return "[" + String.join( ", ", values ) + "]"; + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java new file mode 100644 index 0000000000..f70b1c8e4e --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java @@ -0,0 +1,56 @@ +/* + * 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.polyalg.arguments; + +import org.polypheny.db.algebra.AlgNode; +import org.polypheny.db.algebra.core.AggregateCall; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; +import org.polypheny.db.algebra.polyalg.PolyAlgUtils; + +public class AggArg implements PolyAlgArg { + + private final AggregateCall agg; + private final AlgNode algNode; + + + public AggArg( AggregateCall agg ) { + this( agg, null ); + } + + + public AggArg( AggregateCall agg, AlgNode fieldNameProvider ) { + this.agg = agg; + this.algNode = fieldNameProvider; + } + + + @Override + public ParamType getType() { + return ParamType.AGGREGATE; + } + + + @Override + public String toPolyAlg() { + String str = PolyAlgUtils.appendAlias( agg.toString(), agg.getName() ); + if ( algNode == null ) { + return str; + } + return PolyAlgUtils.replaceWithFieldNames( algNode, str ); + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AnyArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AnyArg.java new file mode 100644 index 0000000000..888a621455 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AnyArg.java @@ -0,0 +1,44 @@ +/* + * 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.polyalg.arguments; + +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; + +/** + * PolyAlgArgument implementation for the case where no other ParamType fits better. + * toPolyAlg() returns the default string representation of the object. + */ +public class AnyArg implements PolyAlgArg { + + private final Object arg; + + public AnyArg(Object arg) { + this.arg = arg; + } + + @Override + public ParamType getType() { + return ParamType.ANY; + } + + + @Override + public String toPolyAlg() { + return arg.toString(); + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/BooleanArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/BooleanArg.java new file mode 100644 index 0000000000..1e84790255 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/BooleanArg.java @@ -0,0 +1,42 @@ +/* + * 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.polyalg.arguments; + +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; + +public class BooleanArg implements PolyAlgArg { + + private final boolean arg; + + + public BooleanArg( boolean arg ) { + this.arg = arg; + } + + + @Override + public ParamType getType() { + return ParamType.BOOLEAN; + } + + + @Override + public String toPolyAlg() { + return Boolean.toString( arg ).toUpperCase(); + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CollationArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CollationArg.java new file mode 100644 index 0000000000..067cd80508 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CollationArg.java @@ -0,0 +1,71 @@ +/* + * 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.polyalg.arguments; + +import java.util.Iterator; +import java.util.List; +import java.util.StringJoiner; +import org.polypheny.db.algebra.AlgCollation; +import org.polypheny.db.algebra.AlgFieldCollation; +import org.polypheny.db.algebra.AlgNode; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; +import org.polypheny.db.algebra.polyalg.PolyAlgUtils; + +public class CollationArg implements PolyAlgArg { + + private final AlgCollation arg; + private final AlgNode algNode; + + + public CollationArg( AlgCollation arg, AlgNode fieldNameProvider ) { + this.arg = arg; + this.algNode = fieldNameProvider; + } + + + @Override + public ParamType getType() { + return ParamType.COLLATION; + } + + + @Override + public String toPolyAlg() { + List colls = arg.getFieldCollations(); + if ( colls.isEmpty() ) { + return ""; + } + + StringJoiner joiner; + if ( colls.size() == 1 ) { + joiner = new StringJoiner( "" ); + } else { + joiner = new StringJoiner( ", ", "[", "]" ); + } + + for ( AlgFieldCollation coll : colls ) { + String str = PolyAlgUtils.getFieldNameFromIndex( algNode, coll.getFieldIndex() ); + if ( coll.direction != AlgFieldCollation.Direction.ASCENDING || coll.nullDirection != coll.direction.defaultNullDirection() ) { + str += " " + coll.shortString(); + } + joiner.add( str ); + } + + return joiner.toString(); + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EntityArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EntityArg.java new file mode 100644 index 0000000000..b335a30110 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EntityArg.java @@ -0,0 +1,44 @@ +/* + * 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.polyalg.arguments; + +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; +import org.polypheny.db.catalog.entity.Entity; + +public class EntityArg implements PolyAlgArg { + + private final Entity e; + + + public EntityArg( Entity e ) { + this.e = e; + } + + + @Override + public ParamType getType() { + return ParamType.ENTITY; + } + + + @Override + public String toPolyAlg() { + return e.getNamespaceName() + "." + e.name; + } + + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java new file mode 100644 index 0000000000..f087c5c248 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java @@ -0,0 +1,40 @@ +/* + * 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.polyalg.arguments; + +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; + +public class FieldArg implements PolyAlgArg { + + private final int field; + + public FieldArg( int field ) { + this.field = field; + } + + @Override + public ParamType getType() { + return ParamType.FIELD; + } + + + @Override + public String toPolyAlg() { + return Integer.toString( field ); + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/IntArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/IntArg.java new file mode 100644 index 0000000000..d7a0d063fb --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/IntArg.java @@ -0,0 +1,42 @@ +/* + * 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.polyalg.arguments; + +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; + +public class IntArg implements PolyAlgArg { + + private final int arg; + + + public IntArg( int arg ) { + this.arg = arg; + } + + + @Override + public ParamType getType() { + return ParamType.INTEGER; + } + + + @Override + public String toPolyAlg() { + return Integer.toString( arg ); + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java new file mode 100644 index 0000000000..33fcc83788 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java @@ -0,0 +1,71 @@ +/* + * 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.polyalg.arguments; + +import java.util.List; +import org.polypheny.db.algebra.AlgNode; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; +import org.polypheny.db.algebra.polyalg.PolyAlgUtils; + +public class ListArg implements PolyAlgArg { + + private final List args; + private final List aliases; + private final AlgNode algNode; + + + public ListArg( List args ) { + this( args, null, null ); + } + + public ListArg( List args, List aliases ) { + this(args, aliases, null); + } + + public ListArg( List args, AlgNode fieldNameProvider ) { + this(args, null, fieldNameProvider); + } + + public ListArg( List args, List aliases, AlgNode fieldNameProvider ) { + this.args = args; + this.aliases = aliases; + this.algNode = fieldNameProvider; + } + + + @Override + public ParamType getType() { + if ( args.isEmpty() ) { + return ParamType.EMPTY_LIST; + } + return args.get( 0 ).getType(); + } + + + @Override + public String toPolyAlg() { + List strArgs = args.stream().map( PolyAlgArg::toPolyAlg ).toList(); + if (algNode != null) { + strArgs = PolyAlgUtils.replaceWithFieldNames( algNode, strArgs ); + } + if ( aliases != null ) { + strArgs = PolyAlgUtils.appendAliases( strArgs, aliases ); + } + return PolyAlgUtils.joinMultiValued( strArgs ); + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArg.java new file mode 100644 index 0000000000..01b0d93067 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArg.java @@ -0,0 +1,27 @@ +/* + * 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.polyalg.arguments; + +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; + +public interface PolyAlgArg { + + ParamType getType(); + + String toPolyAlg(); + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgRegistry.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgRegistry.java new file mode 100644 index 0000000000..248dd1f10c --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgRegistry.java @@ -0,0 +1,84 @@ +/* + * 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.polyalg.arguments; + +import com.google.common.collect.ImmutableList; +import java.util.HashMap; +import java.util.Map; +import org.polypheny.db.algebra.AlgNode; +import org.polypheny.db.algebra.core.relational.RelScan; +import org.polypheny.db.algebra.logical.relational.LogicalRelAggregate; +import org.polypheny.db.algebra.logical.relational.LogicalRelFilter; +import org.polypheny.db.algebra.logical.relational.LogicalRelMinus; +import org.polypheny.db.algebra.logical.relational.LogicalRelProject; +import org.polypheny.db.algebra.logical.relational.LogicalRelSort; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; + +public class PolyAlgRegistry { + + private static final Map, PolyAlgDeclaration> declarations = new HashMap<>(); + + + static { + declarations.put( LogicalRelProject.class, new PolyAlgDeclaration( "PROJECT", 1, + new Parameter( "projects", ParamType.SIMPLE_REX, true ) ) ); + + declarations.put( RelScan.class, new PolyAlgDeclaration( "SCAN", 0, + new Parameter( "entity", ParamType.ENTITY ) ) ); + + declarations.put( LogicalRelFilter.class, new PolyAlgDeclaration( "FILTER", 1, ImmutableList.of( + new Parameter( "condition", ParamType.SIMPLE_REX, false ), + new Parameter( "variables", ParamType.ANY, true, "" ) ) ) ); + + declarations.put( LogicalRelAggregate.class, new PolyAlgDeclaration( "AGG", 1, ImmutableList.of( + new Parameter( "group", ParamType.FIELD, true ), + new Parameter( "groups", ParamType.ANY, true, "" ), + new Parameter( "aggs", ParamType.AGGREGATE, true ) ) ) ); + + declarations.put( LogicalRelMinus.class, new PolyAlgDeclaration( "MINUS", 2, ImmutableList.of( + new Parameter( "all", ParamType.BOOLEAN, false, "false" ) ) ) ); + + declarations.put( LogicalRelSort.class, new PolyAlgDeclaration( "SORT", 1, ImmutableList.of( + new Parameter( "collation", ParamType.COLLATION, false ), + new Parameter( "fetch", ParamType.SIMPLE_REX, false, "" ), + new Parameter( "offset", ParamType.SIMPLE_REX, false, "" ) ) ) ); + } + + + public static PolyAlgDeclaration getDeclaration( Class clazz ) { + return getDeclaration( clazz, 0 ); + } + + + /** + * Retrieves the PolyAlgDeclaration associated with the specified class from a map of declarations, + * or returns a default PolyAlgDeclaration if none is found. + * + * @param clazz The class for which the PolyAlgDeclaration is being retrieved + * @param numInputs The number of inputs associated with the PolyAlgDeclaration if a new one is created. + * @return The PolyAlgDeclaration associated with the specified class if found in the map, + * or a new PolyAlgDeclaration initialized with the class name and the specified number of inputs. + */ + public static PolyAlgDeclaration getDeclaration( Class clazz, int numInputs ) { + return declarations.getOrDefault( + clazz, + new PolyAlgDeclaration( clazz.getSimpleName(), numInputs ) ); + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java new file mode 100644 index 0000000000..7b984e2d4b --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java @@ -0,0 +1,56 @@ +/* + * 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.polyalg.arguments; + +import org.polypheny.db.algebra.AlgNode; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; +import org.polypheny.db.algebra.polyalg.PolyAlgUtils; +import org.polypheny.db.rex.RexNode; + +public class RexArg implements PolyAlgArg { + + private final RexNode node; + private final AlgNode algNode; + + + public RexArg( RexNode node ) { + this( node, null ); + } + + + public RexArg( RexNode node, AlgNode fieldNameProvider ) { + this.node = node; + this.algNode = fieldNameProvider; + } + + + @Override + public ParamType getType() { + return ParamType.SIMPLE_REX; + } + + + @Override + public String toPolyAlg() { + String str = node == null ? "" : node.toString(); + if ( algNode == null ) { + return str; + } + return PolyAlgUtils.replaceWithFieldNames( algNode, str ); + } + +} diff --git a/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java b/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java index 6e7dac3fd5..d6b38a0706 100644 --- a/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java +++ b/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java @@ -1360,6 +1360,14 @@ public static void registerAbstractAlgs( AlgPlanner planner ) { * @return Plan */ public static String dumpPlan( String header, AlgNode alg, ExplainFormat format, ExplainLevel detailLevel ) { + //TODO: Delete lines for testing PolyAlg serialization + StringBuilder sb = new StringBuilder(); + alg.buildPolyAlgebra( sb ); + System.out.println(header); + System.out.println(sb); + System.out.println(); + + StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter( sw ); if ( !header.isEmpty() ) { From 54d127e0d7429f2cc9d8fd7f54645434f056ef76 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Tue, 19 Mar 2024 11:16:37 +0100 Subject: [PATCH 002/132] Move mapping to PolyAlgArg for ListArg into constructors --- .../relational/LogicalRelAggregate.java | 8 ++--- .../logical/relational/LogicalRelFilter.java | 2 +- .../logical/relational/LogicalRelSort.java | 5 ++- .../db/algebra/polyalg/PolyAlgUtils.java | 18 ++++++++--- .../db/algebra/polyalg/arguments/AggArg.java | 8 ++--- .../polyalg/arguments/CollationArg.java | 32 ++++--------------- .../db/algebra/polyalg/arguments/ListArg.java | 31 +++++++++++------- 7 files changed, 52 insertions(+), 52 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java index c5fe627de9..54fe1372e0 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java @@ -124,15 +124,13 @@ public Map prepareAttributes() { PolyAlgDeclaration decl = getPolyAlgDeclaration(); Map attributes = new HashMap<>(); - PolyAlgArg groupArg = new ListArg<>( groupSet.asList().stream().map( FieldArg::new ).toList() ); - PolyAlgArg aggsArg = new ListArg<>( aggCalls.stream().map( AggArg::new ).toList(), this ); + PolyAlgArg groupArg = new ListArg<>( groupSet.asList(), FieldArg::new ); + PolyAlgArg aggsArg = new ListArg<>( aggCalls, a -> new AggArg( a, this ) ); attributes.put( decl.getPos( 0 ), groupArg ); attributes.put( decl.getPos( 1 ), aggsArg ); if ( getGroupType() != Group.SIMPLE ) { - PolyAlgArg groupSetArg = new ListArg<>( groupSets.stream().map( set -> - new ListArg<>( set.asList().stream().map( FieldArg::new ).toList() ) - ).toList() ); + PolyAlgArg groupSetArg = new ListArg<>( groupSets, set -> new ListArg<>( set.asList(), FieldArg::new ) ); attributes.put( decl.getParam( "groups" ), groupSetArg ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java index 4f1121dd74..39ad6ffd0d 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java @@ -133,7 +133,7 @@ public AlgWriter explainTerms( AlgWriter pw ) { public Map prepareAttributes() { PolyAlgDeclaration decl = getPolyAlgDeclaration(); Map attributes = new HashMap<>(); - PolyAlgArg varArg = new ListArg<>( variablesSet.stream().map( AnyArg::new ).toList() ); + PolyAlgArg varArg = new ListArg<>( variablesSet.asList(), AnyArg::new ); attributes.put( decl.getPos( 0 ), new RexArg( condition, this ) ); attributes.put( decl.getParam( "variables" ), varArg ); diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java index e4dc50f1e8..c2f54332aa 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java @@ -47,6 +47,7 @@ import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; import org.polypheny.db.algebra.polyalg.arguments.CollationArg; +import org.polypheny.db.algebra.polyalg.arguments.ListArg; import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; import org.polypheny.db.algebra.polyalg.arguments.RexArg; import org.polypheny.db.plan.AlgCluster; @@ -106,7 +107,9 @@ public Map prepareAttributes() { PolyAlgDeclaration decl = getPolyAlgDeclaration(); Map attributes = new HashMap<>(); - attributes.put( decl.getPos( 0 ), new CollationArg( collation, this ) ); + PolyAlgArg collArg = new ListArg<>( collation.getFieldCollations(), c -> new CollationArg( c, this ) ); + + attributes.put( decl.getPos( 0 ), collArg ); attributes.put( decl.getParam( "fetch" ), new RexArg( fetch ) ); attributes.put( decl.getParam( "offset" ), new RexArg( offset ) ); return attributes; diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java index 833799e4e4..5474a58399 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java @@ -24,6 +24,14 @@ public class PolyAlgUtils { + /** + * Replaces all occurrences of '$' followed by some number corresponding to a field in the inputs of alg + * with the name of that field. + * + * @param alg the AlgNode whose inputs contain the field names + * @param str String whose occurrences of '$' + field number should be replaced + * @return str with field numbers replaced with their names. + */ public static String replaceWithFieldNames( AlgNode alg, String str ) { if ( str.contains( "$" ) ) { int offset = 0; @@ -41,10 +49,11 @@ public static String replaceWithFieldNames( AlgNode alg, String str ) { return str; } - public static String getFieldNameFromIndex(AlgNode alg, int idx) { + + public static String getFieldNameFromIndex( AlgNode alg, int idx ) { for ( AlgNode input : alg.getInputs() ) { List fields = input.getTupleType().getFields(); - if (idx < fields.size()) { + if ( idx < fields.size() ) { return fields.get( idx ).getName(); } idx += fields.size(); @@ -59,7 +68,8 @@ public static List replaceWithFieldNames( AlgNode alg, List exps ) { .toList(); } - public static String appendAlias(String exp, String alias) { + + public static String appendAlias( String exp, String alias ) { if ( !alias.equals( exp ) ) { exp += " AS " + alias; } @@ -80,7 +90,7 @@ public static List appendAliases( List exps, List aliase assert exps.size() == aliases.size(); List list = new ArrayList<>(); for ( int i = 0; i < exps.size(); i++ ) { - list.add( appendAlias(exps.get( i ), aliases.get( i )) ); + list.add( appendAlias( exps.get( i ), aliases.get( i ) ) ); } return list; } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java index f70b1c8e4e..52253067b0 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java @@ -46,11 +46,11 @@ public ParamType getType() { @Override public String toPolyAlg() { - String str = PolyAlgUtils.appendAlias( agg.toString(), agg.getName() ); - if ( algNode == null ) { - return str; + String str = agg.toString(); + if ( algNode != null ) { + str = PolyAlgUtils.replaceWithFieldNames( algNode, str ); } - return PolyAlgUtils.replaceWithFieldNames( algNode, str ); + return PolyAlgUtils.appendAlias( str, agg.getName() ); } } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CollationArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CollationArg.java index 067cd80508..588dac7381 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CollationArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CollationArg.java @@ -16,10 +16,6 @@ package org.polypheny.db.algebra.polyalg.arguments; -import java.util.Iterator; -import java.util.List; -import java.util.StringJoiner; -import org.polypheny.db.algebra.AlgCollation; import org.polypheny.db.algebra.AlgFieldCollation; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; @@ -27,11 +23,11 @@ public class CollationArg implements PolyAlgArg { - private final AlgCollation arg; + private final AlgFieldCollation arg; private final AlgNode algNode; - public CollationArg( AlgCollation arg, AlgNode fieldNameProvider ) { + public CollationArg( AlgFieldCollation arg, AlgNode fieldNameProvider ) { this.arg = arg; this.algNode = fieldNameProvider; } @@ -45,27 +41,11 @@ public ParamType getType() { @Override public String toPolyAlg() { - List colls = arg.getFieldCollations(); - if ( colls.isEmpty() ) { - return ""; + String str = PolyAlgUtils.getFieldNameFromIndex( algNode, arg.getFieldIndex() ); + if ( arg.direction != AlgFieldCollation.Direction.ASCENDING || arg.nullDirection != arg.direction.defaultNullDirection() ) { + str += " " + arg.shortString(); } - - StringJoiner joiner; - if ( colls.size() == 1 ) { - joiner = new StringJoiner( "" ); - } else { - joiner = new StringJoiner( ", ", "[", "]" ); - } - - for ( AlgFieldCollation coll : colls ) { - String str = PolyAlgUtils.getFieldNameFromIndex( algNode, coll.getFieldIndex() ); - if ( coll.direction != AlgFieldCollation.Direction.ASCENDING || coll.nullDirection != coll.direction.defaultNullDirection() ) { - str += " " + coll.shortString(); - } - joiner.add( str ); - } - - return joiner.toString(); + return str; } } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java index 33fcc83788..6307f9f5ed 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java @@ -17,6 +17,7 @@ package org.polypheny.db.algebra.polyalg.arguments; import java.util.List; +import java.util.function.Function; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; import org.polypheny.db.algebra.polyalg.PolyAlgUtils; @@ -28,22 +29,30 @@ public class ListArg implements PolyAlgArg { private final AlgNode algNode; - public ListArg( List args ) { - this( args, null, null ); + public ListArg( List args, List aliases, AlgNode fieldNameProvider ) { + this.args = args; + this.aliases = aliases; + this.algNode = fieldNameProvider; } - public ListArg( List args, List aliases ) { - this(args, aliases, null); + + public ListArg( List rawArgs, Function converter ) { + this( rawArgs, converter, null, null ); } - public ListArg( List args, AlgNode fieldNameProvider ) { - this(args, null, fieldNameProvider); + + public ListArg( List rawArgs, Function converter, AlgNode fieldNameProvider ) { + this( rawArgs, converter, null, fieldNameProvider ); } - public ListArg( List args, List aliases, AlgNode fieldNameProvider ) { - this.args = args; - this.aliases = aliases; - this.algNode = fieldNameProvider; + + public ListArg( List rawArgs, Function converter, List aliases ) { + this( rawArgs, converter, aliases, null ); + } + + + public ListArg( List rawArgs, Function converter, List aliases, AlgNode fieldNameProvider ) { + this( rawArgs.stream().map( converter ).toList(), aliases, fieldNameProvider ); } @@ -59,7 +68,7 @@ public ParamType getType() { @Override public String toPolyAlg() { List strArgs = args.stream().map( PolyAlgArg::toPolyAlg ).toList(); - if (algNode != null) { + if ( algNode != null ) { strArgs = PolyAlgUtils.replaceWithFieldNames( algNode, strArgs ); } if ( aliases != null ) { From cc1f9ae8f0081e26a2a252e9ec51a0e6e1418123 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Tue, 19 Mar 2024 15:12:11 +0100 Subject: [PATCH 003/132] Add PolyAlg representation for LogicalRelJoin --- .../polypheny/db/algebra/AbstractAlgNode.java | 2 +- .../db/algebra/core/relational/RelScan.java | 2 +- .../relational/LogicalRelAggregate.java | 10 ++-- .../logical/relational/LogicalRelJoin.java | 54 ++++++++++++++++--- .../logical/relational/LogicalRelProject.java | 2 +- .../algebra/polyalg/PolyAlgDeclaration.java | 7 ++- .../{arguments => }/PolyAlgRegistry.java | 18 ++++--- .../db/algebra/polyalg/PolyAlgUtils.java | 20 +++++-- .../polyalg/arguments/CorrelationArg.java | 43 +++++++++++++++ .../algebra/polyalg/arguments/FieldArg.java | 9 +++- 10 files changed, 139 insertions(+), 28 deletions(-) rename core/src/main/java/org/polypheny/db/algebra/polyalg/{arguments => }/PolyAlgRegistry.java (85%) create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CorrelationArg.java diff --git a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java index 897c44ad32..3a56b8146e 100644 --- a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java +++ b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java @@ -56,7 +56,7 @@ import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; -import org.polypheny.db.algebra.polyalg.arguments.PolyAlgRegistry; +import org.polypheny.db.algebra.polyalg.PolyAlgRegistry; import org.polypheny.db.algebra.type.AlgDataType; import org.polypheny.db.catalog.entity.Entity; import org.polypheny.db.plan.AlgCluster; diff --git a/core/src/main/java/org/polypheny/db/algebra/core/relational/RelScan.java b/core/src/main/java/org/polypheny/db/algebra/core/relational/RelScan.java index c51d1e17e0..31df77f9b1 100644 --- a/core/src/main/java/org/polypheny/db/algebra/core/relational/RelScan.java +++ b/core/src/main/java/org/polypheny/db/algebra/core/relational/RelScan.java @@ -35,7 +35,7 @@ import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; import org.polypheny.db.algebra.polyalg.arguments.EntityArg; import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; -import org.polypheny.db.algebra.polyalg.arguments.PolyAlgRegistry; +import org.polypheny.db.algebra.polyalg.PolyAlgRegistry; import org.polypheny.db.algebra.type.AlgDataType; import org.polypheny.db.algebra.type.AlgDataTypeField; import org.polypheny.db.algebra.type.DocumentType; diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java index 54fe1372e0..e6630f61ea 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java @@ -124,13 +124,17 @@ public Map prepareAttributes() { PolyAlgDeclaration decl = getPolyAlgDeclaration(); Map attributes = new HashMap<>(); - PolyAlgArg groupArg = new ListArg<>( groupSet.asList(), FieldArg::new ); + PolyAlgArg groupArg = new ListArg<>( groupSet.asList(), f -> new FieldArg( f, this ) ); PolyAlgArg aggsArg = new ListArg<>( aggCalls, a -> new AggArg( a, this ) ); attributes.put( decl.getPos( 0 ), groupArg ); - attributes.put( decl.getPos( 1 ), aggsArg ); + attributes.put( decl.getParam( "aggs" ), aggsArg ); if ( getGroupType() != Group.SIMPLE ) { - PolyAlgArg groupSetArg = new ListArg<>( groupSets, set -> new ListArg<>( set.asList(), FieldArg::new ) ); + PolyAlgArg groupSetArg = new ListArg<>( + groupSets, + set -> new ListArg( + set.asList(), + f -> new FieldArg( f, this ) ) ); attributes.put( decl.getParam( "groups" ), groupSetArg ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java index 7982b873e7..e6c491e9f2 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java @@ -34,6 +34,11 @@ package org.polypheny.db.algebra.logical.relational; +import com.google.common.collect.ImmutableList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.Set; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.AlgShuttle; @@ -42,6 +47,14 @@ import org.polypheny.db.algebra.core.Join; import org.polypheny.db.algebra.core.JoinAlgType; import org.polypheny.db.algebra.core.relational.RelAlg; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; +import org.polypheny.db.algebra.polyalg.arguments.AnyArg; +import org.polypheny.db.algebra.polyalg.arguments.BooleanArg; +import org.polypheny.db.algebra.polyalg.arguments.CorrelationArg; +import org.polypheny.db.algebra.polyalg.arguments.ListArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.RexArg; +import org.polypheny.db.algebra.type.AlgDataTypeField; import org.polypheny.db.plan.AlgCluster; import org.polypheny.db.plan.AlgTraitSet; import org.polypheny.db.plan.Convention; @@ -64,6 +77,8 @@ public final class LogicalRelJoin extends Join implements RelAlg { // NOTE jvs 14-Mar-2006: Normally we don't use state like this to control rule firing, but due to the non-local nature of semijoin optimizations, it's pretty much required. private final boolean semiJoinDone; + private final ImmutableList systemFieldList; + /** * Creates a LogicalJoin. @@ -78,27 +93,29 @@ public final class LogicalRelJoin extends Join implements RelAlg { * @param joinType Join type * @param variablesSet Set of variables that are set by the LHS and used by the RHS and are not available to nodes above this LogicalJoin in the tree * @param semiJoinDone Whether this join has been translated to a semi-join + * @param systemFieldList List of system fields that will be prefixed to output row type; typically empty but must not be null * @see #isSemiJoinDone() */ - public LogicalRelJoin( AlgCluster cluster, AlgTraitSet traitSet, AlgNode left, AlgNode right, RexNode condition, Set variablesSet, JoinAlgType joinType, boolean semiJoinDone ) { + public LogicalRelJoin( AlgCluster cluster, AlgTraitSet traitSet, AlgNode left, AlgNode right, RexNode condition, Set variablesSet, JoinAlgType joinType, boolean semiJoinDone, ImmutableList systemFieldList ) { super( cluster, traitSet.replace( ModelTrait.RELATIONAL ), left, right, condition, variablesSet, joinType ); this.semiJoinDone = semiJoinDone; + this.systemFieldList = Objects.requireNonNull( systemFieldList ); } /** * Creates a LogicalJoin, flagged with whether it has been translated to a semi-join. */ - public static LogicalRelJoin create( AlgNode left, AlgNode right, RexNode condition, Set variablesSet, JoinAlgType joinType, boolean semiJoinDone ) { + public static LogicalRelJoin create( AlgNode left, AlgNode right, RexNode condition, Set variablesSet, JoinAlgType joinType, boolean semiJoinDone, ImmutableList systemFieldList ) { final AlgCluster cluster = left.getCluster(); final AlgTraitSet traitSet = cluster.traitSetOf( Convention.NONE ); - return new LogicalRelJoin( cluster, traitSet, left, right, condition, variablesSet, joinType, semiJoinDone ); + return new LogicalRelJoin( cluster, traitSet, left, right, condition, variablesSet, joinType, semiJoinDone, systemFieldList ); } @Deprecated // to be removed before 2.0 - public static LogicalRelJoin create( AlgNode left, AlgNode right, RexNode condition, JoinAlgType joinType, Set variablesStopped, boolean semiJoinDone ) { - return create( left, right, condition, CorrelationId.setOf( variablesStopped ), joinType, semiJoinDone ); + public static LogicalRelJoin create( AlgNode left, AlgNode right, RexNode condition, JoinAlgType joinType, Set variablesStopped, boolean semiJoinDone, ImmutableList systemFieldList ) { + return create( left, right, condition, CorrelationId.setOf( variablesStopped ), joinType, semiJoinDone, systemFieldList ); } @@ -106,20 +123,20 @@ public static LogicalRelJoin create( AlgNode left, AlgNode right, RexNode condit * Creates a LogicalJoin. */ public static LogicalRelJoin create( AlgNode left, AlgNode right, RexNode condition, Set variablesSet, JoinAlgType joinType ) { - return create( left, right, condition, variablesSet, joinType, false ); + return create( left, right, condition, variablesSet, joinType, false, ImmutableList.of() ); } @Deprecated // to be removed before 2.0 public static LogicalRelJoin create( AlgNode left, AlgNode right, RexNode condition, JoinAlgType joinType, Set variablesStopped ) { - return create( left, right, condition, CorrelationId.setOf( variablesStopped ), joinType, false ); + return create( left, right, condition, CorrelationId.setOf( variablesStopped ), joinType, false, ImmutableList.of() ); } @Override public LogicalRelJoin copy( AlgTraitSet traitSet, RexNode conditionExpr, AlgNode left, AlgNode right, JoinAlgType joinType, boolean semiJoinDone ) { assert traitSet.containsIfApplicable( Convention.NONE ); - return new LogicalRelJoin( getCluster(), getCluster().traitSetOf( Convention.NONE ).replace( ModelTrait.RELATIONAL ), left, right, conditionExpr, variablesSet, joinType, semiJoinDone ); + return new LogicalRelJoin( getCluster(), getCluster().traitSetOf( Convention.NONE ).replace( ModelTrait.RELATIONAL ), left, right, conditionExpr, variablesSet, joinType, semiJoinDone, systemFieldList ); } @@ -142,4 +159,25 @@ public boolean isSemiJoinDone() { } + @Override + public List getSystemFieldList() { + return systemFieldList; + } + + + @Override + public Map prepareAttributes() { + Map attributes = new HashMap<>(); + PolyAlgArg varsArg = new ListArg<>( variablesSet.asList(), CorrelationArg::new ); + PolyAlgArg sysFieldsArg = new ListArg<>( systemFieldList, AnyArg::new ); + + attributes.put( getPolyAlgDeclaration().getPos( 0 ), new RexArg( condition, this ) ); + attributes.put( getPolyAlgDeclaration().getParam( "type" ), new AnyArg( joinType.name() ) ); + attributes.put( getPolyAlgDeclaration().getParam( "variables" ), varsArg ); + attributes.put( getPolyAlgDeclaration().getParam( "semiJoinDone" ), new BooleanArg( semiJoinDone ) ); + attributes.put( getPolyAlgDeclaration().getParam( "sysFields" ), sysFieldsArg ); + return attributes; + } + } + diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java index b48e2548e4..045beecf9f 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java @@ -133,7 +133,7 @@ public AlgNode accept( AlgShuttle shuttle ) { @Override public Map prepareAttributes() { - PolyAlgArg projectsArg = new ListArg<>( exps.stream().map( RexArg::new ).toList(), rowType.getFieldNames(), this ); + PolyAlgArg projectsArg = new ListArg<>( exps, RexArg::new, rowType.getFieldNames(), this ); Map attributes = new HashMap<>(); attributes.put( getPolyAlgDeclaration().getPos( 0 ), projectsArg ); diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java index 941ae4ad72..705a4105d1 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java @@ -175,7 +175,12 @@ public enum ParamType { /** * */ - COLLATION + COLLATION, + + /** + * Correlation ID + */ + CORR_ID } } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgRegistry.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java similarity index 85% rename from core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgRegistry.java rename to core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java index 248dd1f10c..32638468af 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgRegistry.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java @@ -14,19 +14,14 @@ * limitations under the License. */ -package org.polypheny.db.algebra.polyalg.arguments; +package org.polypheny.db.algebra.polyalg; import com.google.common.collect.ImmutableList; import java.util.HashMap; import java.util.Map; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.core.relational.RelScan; -import org.polypheny.db.algebra.logical.relational.LogicalRelAggregate; -import org.polypheny.db.algebra.logical.relational.LogicalRelFilter; -import org.polypheny.db.algebra.logical.relational.LogicalRelMinus; -import org.polypheny.db.algebra.logical.relational.LogicalRelProject; -import org.polypheny.db.algebra.logical.relational.LogicalRelSort; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; +import org.polypheny.db.algebra.logical.relational.*; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; @@ -49,7 +44,7 @@ public class PolyAlgRegistry { declarations.put( LogicalRelAggregate.class, new PolyAlgDeclaration( "AGG", 1, ImmutableList.of( new Parameter( "group", ParamType.FIELD, true ), new Parameter( "groups", ParamType.ANY, true, "" ), - new Parameter( "aggs", ParamType.AGGREGATE, true ) ) ) ); + new Parameter( "aggs", ParamType.AGGREGATE, true, "" ) ) ) ); declarations.put( LogicalRelMinus.class, new PolyAlgDeclaration( "MINUS", 2, ImmutableList.of( new Parameter( "all", ParamType.BOOLEAN, false, "false" ) ) ) ); @@ -58,6 +53,13 @@ public class PolyAlgRegistry { new Parameter( "collation", ParamType.COLLATION, false ), new Parameter( "fetch", ParamType.SIMPLE_REX, false, "" ), new Parameter( "offset", ParamType.SIMPLE_REX, false, "" ) ) ) ); + + declarations.put( LogicalRelJoin.class, new PolyAlgDeclaration( "JOIN", 2, ImmutableList.of( + new Parameter( "condition", ParamType.SIMPLE_REX, false ), + new Parameter( "type", ParamType.ANY, false, "INNER" ), + new Parameter( "variables", ParamType.CORR_ID, true, "" ), + new Parameter( "semiJoinDone", ParamType.BOOLEAN, false, "FALSE" ), + new Parameter( "sysFields", ParamType.ANY, true, "" ) ) ) ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java index 5474a58399..867cd74162 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.List; +import org.polypheny.db.algebra.AlgInput; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.type.AlgDataTypeField; import org.polypheny.db.rex.RexNode; @@ -35,15 +36,26 @@ public class PolyAlgUtils { public static String replaceWithFieldNames( AlgNode alg, String str ) { if ( str.contains( "$" ) ) { int offset = 0; - for ( AlgNode input : alg.getInputs() ) { - for ( AlgDataTypeField field : input.getTupleType().getFields() ) { + for (AlgNode input : alg.getInputs()) { + offset += input.getTupleType().getFields().size(); + } + // iterate in reverse order to make sure "$13" is replaced before $1 + for ( int i = alg.getInputs().size() - 1; i >= 0; i-- ) { + AlgNode input = alg.getInputs().get( i ); + List fields = input.getTupleType().getFields(); + offset -= fields.size(); + for ( int j = fields.size() - 1; j >= 0; j-- ) { + AlgDataTypeField field = fields.get( j ); String searchStr = "$" + (offset + field.getIndex()); int position = str.indexOf( searchStr ); - if ( position >= 0 && (str.length() >= position + searchStr.length()) ) { + int nextCharPosition = position + searchStr.length(); + if ( nextCharPosition < str.length() && Character.isDigit( str.charAt( nextCharPosition ) ) ) { + continue; + } + if ( position >= 0 && str.length() >= position + searchStr.length() ) { str = str.replace( searchStr, field.getName() ); } } - offset = input.getTupleType().getFields().size(); } } return str; diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CorrelationArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CorrelationArg.java new file mode 100644 index 0000000000..02cba39ff7 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CorrelationArg.java @@ -0,0 +1,43 @@ +/* + * 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.polyalg.arguments; + +import org.polypheny.db.algebra.core.CorrelationId; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; + +public class CorrelationArg implements PolyAlgArg{ + + private final CorrelationId arg; + + + public CorrelationArg( CorrelationId arg ) { + this.arg = arg; + } + + + @Override + public ParamType getType() { + return ParamType.CORR_ID; + } + + + @Override + public String toPolyAlg() { + return arg.toString(); + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java index f087c5c248..deb1878dd5 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java @@ -16,14 +16,18 @@ package org.polypheny.db.algebra.polyalg.arguments; +import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; +import org.polypheny.db.algebra.polyalg.PolyAlgUtils; public class FieldArg implements PolyAlgArg { private final int field; + private final AlgNode algNode; - public FieldArg( int field ) { + public FieldArg( int field, AlgNode fieldNameProvider ) { this.field = field; + this.algNode = fieldNameProvider; } @Override @@ -34,6 +38,9 @@ public ParamType getType() { @Override public String toPolyAlg() { + if ( algNode != null ) { + return PolyAlgUtils.getFieldNameFromIndex( algNode, field ); + } return Integer.toString( field ); } From 2dcf39575c41ca594720d8b0b1d3c819d941dccd Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Tue, 19 Mar 2024 19:31:55 +0100 Subject: [PATCH 004/132] Add PolyAlg support to more AlgNodes --- .../polypheny/db/algebra/AbstractAlgNode.java | 4 +- .../logical/relational/LogicalCalc.java | 21 +++++++++ .../relational/LogicalRelIntersect.java | 10 +++++ .../logical/relational/LogicalRelJoin.java | 4 +- .../logical/relational/LogicalRelUnion.java | 10 +++++ .../algebra/polyalg/PolyAlgDeclaration.java | 34 +++++++++++--- .../db/algebra/polyalg/PolyAlgRegistry.java | 18 ++++++-- .../db/algebra/polyalg/arguments/EnumArg.java | 44 +++++++++++++++++++ 8 files changed, 134 insertions(+), 11 deletions(-) create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EnumArg.java diff --git a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java index 3a56b8146e..5375e59b62 100644 --- a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java +++ b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java @@ -368,10 +368,10 @@ public void buildPolyAlgebra( StringBuilder sb ) { size--; if ( size > 0 ) { - sb.append( ", " ); + sb.append( ", \n" ); } } - sb.append( "\n)" ); + sb.append( ")" ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalCalc.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalCalc.java index 784c6c0eaf..0cb6ccc91b 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalCalc.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalCalc.java @@ -34,6 +34,8 @@ package org.polypheny.db.algebra.logical.relational; +import java.util.HashMap; +import java.util.Map; import java.util.Set; import org.polypheny.db.algebra.AlgCollationTraitDef; import org.polypheny.db.algebra.AlgDistributionTraitDef; @@ -44,6 +46,11 @@ import org.polypheny.db.algebra.metadata.AlgMdCollation; import org.polypheny.db.algebra.metadata.AlgMdDistribution; import org.polypheny.db.algebra.metadata.AlgMetadataQuery; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; +import org.polypheny.db.algebra.polyalg.arguments.ListArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.RexArg; import org.polypheny.db.algebra.rules.FilterCalcMergeRule; import org.polypheny.db.algebra.rules.FilterToCalcRule; import org.polypheny.db.algebra.rules.ProjectToCalcRule; @@ -109,4 +116,18 @@ public void collectVariablesUsed( Set variableSet ) { variableSet.addAll( vuv.variables ); } + + @Override + public Map prepareAttributes() { + PolyAlgDeclaration decl = getPolyAlgDeclaration(); + PolyAlgArg expsArg = new ListArg<>( program.getExprList(), RexArg::new, this ); + PolyAlgArg projectsArg = new ListArg<>( program.getProjectList(), RexArg::new, rowType.getFieldNames(), this ); + + Map attributes = new HashMap<>(); + attributes.put( decl.getPos( 0 ), expsArg ); + attributes.put( decl.getPos( 1 ), projectsArg ); + attributes.put( decl.getParam( "condition" ), new RexArg( program.getCondition(), this ) ); + return attributes; + } + } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelIntersect.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelIntersect.java index 08eebcc0a8..185ab104c9 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelIntersect.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelIntersect.java @@ -35,10 +35,14 @@ import java.util.List; +import java.util.Map; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.AlgShuttle; import org.polypheny.db.algebra.core.Intersect; import org.polypheny.db.algebra.core.relational.RelAlg; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; +import org.polypheny.db.algebra.polyalg.arguments.BooleanArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; import org.polypheny.db.plan.AlgCluster; import org.polypheny.db.plan.AlgTraitSet; import org.polypheny.db.plan.Convention; @@ -80,4 +84,10 @@ public AlgNode accept( AlgShuttle shuttle ) { return shuttle.visit( this ); } + + @Override + public Map prepareAttributes() { + return Map.of( getPolyAlgDeclaration().getParam( "all" ), new BooleanArg( all ) ); + } + } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java index e6c491e9f2..c3ea1885ff 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java @@ -47,10 +47,12 @@ import org.polypheny.db.algebra.core.Join; import org.polypheny.db.algebra.core.JoinAlgType; import org.polypheny.db.algebra.core.relational.RelAlg; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; import org.polypheny.db.algebra.polyalg.arguments.AnyArg; import org.polypheny.db.algebra.polyalg.arguments.BooleanArg; import org.polypheny.db.algebra.polyalg.arguments.CorrelationArg; +import org.polypheny.db.algebra.polyalg.arguments.EnumArg; import org.polypheny.db.algebra.polyalg.arguments.ListArg; import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; import org.polypheny.db.algebra.polyalg.arguments.RexArg; @@ -172,7 +174,7 @@ public Map prepareAttributes() { PolyAlgArg sysFieldsArg = new ListArg<>( systemFieldList, AnyArg::new ); attributes.put( getPolyAlgDeclaration().getPos( 0 ), new RexArg( condition, this ) ); - attributes.put( getPolyAlgDeclaration().getParam( "type" ), new AnyArg( joinType.name() ) ); + attributes.put( getPolyAlgDeclaration().getParam( "type" ), new EnumArg<>( joinType, ParamType.JOIN_TYPE_ENUM ) ); attributes.put( getPolyAlgDeclaration().getParam( "variables" ), varsArg ); attributes.put( getPolyAlgDeclaration().getParam( "semiJoinDone" ), new BooleanArg( semiJoinDone ) ); attributes.put( getPolyAlgDeclaration().getParam( "sysFields" ), sysFieldsArg ); diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelUnion.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelUnion.java index a488be758e..51503b11c1 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelUnion.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelUnion.java @@ -35,11 +35,15 @@ import java.util.List; +import java.util.Map; import org.polypheny.db.algebra.AlgInput; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.AlgShuttle; import org.polypheny.db.algebra.core.Union; import org.polypheny.db.algebra.core.relational.RelAlg; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; +import org.polypheny.db.algebra.polyalg.arguments.BooleanArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; import org.polypheny.db.plan.AlgCluster; import org.polypheny.db.plan.AlgTraitSet; import org.polypheny.db.plan.Convention; @@ -90,5 +94,11 @@ public AlgNode accept( AlgShuttle shuttle ) { return shuttle.visit( this ); } + + @Override + public Map prepareAttributes() { + return Map.of( getPolyAlgDeclaration().getParam( "all" ), new BooleanArg( all ) ); + } + } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java index 705a4105d1..78ffaaa642 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java @@ -76,13 +76,17 @@ public String serializeArguments( Map preparedAttributes for ( Parameter p : posParams ) { assert preparedAttributes.containsKey( p ); - joiner.add( preparedAttributes.get( p ).toPolyAlg() ); + PolyAlgArg arg = preparedAttributes.get( p ); + assert arg.getType() == p.type; + joiner.add( arg.toPolyAlg() ); } for ( Parameter p : kwParams ) { if ( preparedAttributes.containsKey( p ) ) { - String attribute = preparedAttributes.get( p ).toPolyAlg(); - if ( !p.defaultValue.equals( attribute ) ) { - joiner.add( p.name + "=" + attribute ); + PolyAlgArg arg = preparedAttributes.get( p ); + assert arg.getType() == p.type; + String value = arg.toPolyAlg(); + if ( !p.defaultValue.equals( value ) ) { + joiner.add( p.name + "=" + value ); } } } @@ -162,6 +166,8 @@ public enum ParamType { BOOLEAN_REX, ENTITY, + JOIN_TYPE_ENUM( true ), + /** * A specific field (= column in the relational data model). */ @@ -180,7 +186,25 @@ public enum ParamType { /** * Correlation ID */ - CORR_ID + CORR_ID; + + private final boolean isEnum; + + + ParamType() { + this.isEnum = false; + } + + + ParamType( boolean isEnum ) { + this.isEnum = isEnum; + } + + + public boolean isEnum() { + return isEnum; + } + } } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java index 32638468af..9ba01fed27 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java @@ -20,6 +20,7 @@ import java.util.HashMap; import java.util.Map; import org.polypheny.db.algebra.AlgNode; +import org.polypheny.db.algebra.core.JoinAlgType; import org.polypheny.db.algebra.core.relational.RelScan; import org.polypheny.db.algebra.logical.relational.*; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; @@ -46,8 +47,14 @@ public class PolyAlgRegistry { new Parameter( "groups", ParamType.ANY, true, "" ), new Parameter( "aggs", ParamType.AGGREGATE, true, "" ) ) ) ); - declarations.put( LogicalRelMinus.class, new PolyAlgDeclaration( "MINUS", 2, ImmutableList.of( - new Parameter( "all", ParamType.BOOLEAN, false, "false" ) ) ) ); + declarations.put( LogicalRelMinus.class, new PolyAlgDeclaration( "MINUS", 2, + new Parameter( "all", ParamType.BOOLEAN, false, "FALSE" ) ) ); + + declarations.put( LogicalRelUnion.class, new PolyAlgDeclaration( "UNION", 2, + new Parameter( "all", ParamType.BOOLEAN, false, "FALSE" ) ) ); + + declarations.put( LogicalRelIntersect.class, new PolyAlgDeclaration( "INTERSECT", 2, + new Parameter( "all", ParamType.BOOLEAN, false, "FALSE" ) ) ); declarations.put( LogicalRelSort.class, new PolyAlgDeclaration( "SORT", 1, ImmutableList.of( new Parameter( "collation", ParamType.COLLATION, false ), @@ -56,10 +63,15 @@ public class PolyAlgRegistry { declarations.put( LogicalRelJoin.class, new PolyAlgDeclaration( "JOIN", 2, ImmutableList.of( new Parameter( "condition", ParamType.SIMPLE_REX, false ), - new Parameter( "type", ParamType.ANY, false, "INNER" ), + new Parameter( "type", ParamType.JOIN_TYPE_ENUM, false, JoinAlgType.INNER.name() ), new Parameter( "variables", ParamType.CORR_ID, true, "" ), new Parameter( "semiJoinDone", ParamType.BOOLEAN, false, "FALSE" ), new Parameter( "sysFields", ParamType.ANY, true, "" ) ) ) ); + + declarations.put( LogicalCalc.class, new PolyAlgDeclaration( "CALC", 1, ImmutableList.of( + new Parameter( "exps", ParamType.SIMPLE_REX, true ), + new Parameter( "projects", ParamType.SIMPLE_REX, true ), + new Parameter( "condition", ParamType.SIMPLE_REX, false, "" ) ) ) ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EnumArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EnumArg.java new file mode 100644 index 0000000000..83bfe36796 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EnumArg.java @@ -0,0 +1,44 @@ +/* + * 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.polyalg.arguments; + +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; + +public class EnumArg> implements PolyAlgArg{ + + private final E arg; + private final ParamType type; + + public EnumArg( E arg, ParamType enumType ) { + assert enumType.isEnum(); + + this.arg = arg; + this.type = enumType; + } + + @Override + public ParamType getType() { + return type; + } + + + @Override + public String toPolyAlg() { + return arg.name(); + } + +} From 27993d427798a117c526628ca51d65a95fffec54 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Wed, 20 Mar 2024 16:28:10 +0100 Subject: [PATCH 005/132] Introduce PolyAlgArgs to facilitate collection of AlgNode attributes --- .../polypheny/db/algebra/AbstractAlgNode.java | 10 +- .../org/polypheny/db/algebra/AlgNode.java | 17 ++- .../db/algebra/core/relational/RelScan.java | 9 +- .../logical/relational/LogicalCalc.java | 18 ++- .../relational/LogicalRelAggregate.java | 18 ++- .../logical/relational/LogicalRelFilter.java | 17 +-- .../relational/LogicalRelIntersect.java | 9 +- .../logical/relational/LogicalRelJoin.java | 20 ++-- .../logical/relational/LogicalRelMinus.java | 10 +- .../logical/relational/LogicalRelProject.java | 12 +- .../logical/relational/LogicalRelSort.java | 18 ++- .../logical/relational/LogicalRelUnion.java | 9 +- .../algebra/polyalg/PolyAlgDeclaration.java | 26 ---- .../db/algebra/polyalg/PolyAlgRegistry.java | 42 +++++++ .../polyalg/arguments/PolyAlgArgs.java | 113 ++++++++++++++++++ 15 files changed, 224 insertions(+), 124 deletions(-) create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java diff --git a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java index 5375e59b62..ce5bd766c9 100644 --- a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java +++ b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java @@ -41,7 +41,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import lombok.Getter; @@ -54,9 +53,8 @@ import org.polypheny.db.algebra.metadata.Metadata; import org.polypheny.db.algebra.metadata.MetadataFactory; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; -import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; import org.polypheny.db.algebra.polyalg.PolyAlgRegistry; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.algebra.type.AlgDataType; import org.polypheny.db.catalog.entity.Entity; import org.polypheny.db.plan.AlgCluster; @@ -355,7 +353,7 @@ public AlgWriter explainTerms( AlgWriter pw ) { public void buildPolyAlgebra( StringBuilder sb ) { PolyAlgDeclaration decl = getPolyAlgDeclaration(); sb.append( decl.opName ); - sb.append( decl.serializeArguments( prepareAttributes() ) ); + sb.append( collectAttributes().serializeArguments() ); int size = getInputs().size(); if ( size == 0 ) { @@ -389,9 +387,9 @@ public PolyAlgDeclaration getPolyAlgDeclaration() { @Override - public Map prepareAttributes() { + public PolyAlgArgs collectAttributes() { // TODO: Move implementation from abstract class into child classes - return Collections.emptyMap(); + return new PolyAlgArgs( getPolyAlgDeclaration() ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/AlgNode.java b/core/src/main/java/org/polypheny/db/algebra/AlgNode.java index dd74299b53..ca0ff73fa5 100644 --- a/core/src/main/java/org/polypheny/db/algebra/AlgNode.java +++ b/core/src/main/java/org/polypheny/db/algebra/AlgNode.java @@ -35,7 +35,6 @@ import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Set; import org.jetbrains.annotations.Nullable; @@ -45,8 +44,7 @@ import org.polypheny.db.algebra.metadata.AlgMetadataQuery; import org.polypheny.db.algebra.metadata.Metadata; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; -import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.algebra.type.AlgDataType; import org.polypheny.db.catalog.entity.Entity; import org.polypheny.db.catalog.logistic.DataModel; @@ -251,19 +249,20 @@ public interface AlgNode extends AlgOptNode, Cloneable { /** * Retrieves the PolyAlgDeclaration for this AlgNode implementation. * This method should be static. + * * @return PolyAlgDeclaration for this AlgNode implementation */ PolyAlgDeclaration getPolyAlgDeclaration(); /** - * Serializes the attributes of this instance for the purpose of creating the PolyAlgebra representation for this AlgNode. - * Each value in the returned map represents one serialized attribute of this AlgNode instance. - * The key is the corresponding parameter in the {@link org.polypheny.db.algebra.polyalg.PolyAlgDeclaration}. - * If no attributes exist, an empty map is returned. + * Collects the attributes characterizing this instance for the purpose of creating the PolyAlgebra representation. + * The returned PolyAlgArgs contains every {@link org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg} relevant for this AlgNode instance. + * The corresponding {@link org.polypheny.db.algebra.polyalg.PolyAlgDeclaration} must be identical to {@code getPolyAlgDeclaration()}. + * Its parameters can be used to retrieve corresponding argument values. * - * @return A map that maps parameters to serialized attributes of this AlgNode instance + * @return PolyAlgArgs that maps parameters of the declaration to {@link org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg} that wraps the corresponding attribute */ - Map prepareAttributes(); + PolyAlgArgs collectAttributes(); /** * Receives notification that this expression is about to be registered. The implementation of this method must at least register all child expressions. diff --git a/core/src/main/java/org/polypheny/db/algebra/core/relational/RelScan.java b/core/src/main/java/org/polypheny/db/algebra/core/relational/RelScan.java index 31df77f9b1..29959235d9 100644 --- a/core/src/main/java/org/polypheny/db/algebra/core/relational/RelScan.java +++ b/core/src/main/java/org/polypheny/db/algebra/core/relational/RelScan.java @@ -20,7 +20,6 @@ import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -32,10 +31,9 @@ import org.polypheny.db.algebra.core.common.Scan; import org.polypheny.db.algebra.metadata.AlgMetadataQuery; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; import org.polypheny.db.algebra.polyalg.arguments.EntityArg; -import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; import org.polypheny.db.algebra.polyalg.PolyAlgRegistry; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.algebra.type.AlgDataType; import org.polypheny.db.algebra.type.AlgDataTypeField; import org.polypheny.db.algebra.type.DocumentType; @@ -178,8 +176,9 @@ public PolyAlgDeclaration getPolyAlgDeclaration() { @Override - public Map prepareAttributes() { - return Map.of( getPolyAlgDeclaration().getPos( 0 ), new EntityArg( entity ) ); + public PolyAlgArgs collectAttributes() { + PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); + return args.put( 0, new EntityArg( entity ) ); } } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalCalc.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalCalc.java index 0cb6ccc91b..42df0a4313 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalCalc.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalCalc.java @@ -34,8 +34,6 @@ package org.polypheny.db.algebra.logical.relational; -import java.util.HashMap; -import java.util.Map; import java.util.Set; import org.polypheny.db.algebra.AlgCollationTraitDef; import org.polypheny.db.algebra.AlgDistributionTraitDef; @@ -46,10 +44,9 @@ import org.polypheny.db.algebra.metadata.AlgMdCollation; import org.polypheny.db.algebra.metadata.AlgMdDistribution; import org.polypheny.db.algebra.metadata.AlgMetadataQuery; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; import org.polypheny.db.algebra.polyalg.arguments.ListArg; import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.algebra.polyalg.arguments.RexArg; import org.polypheny.db.algebra.rules.FilterCalcMergeRule; import org.polypheny.db.algebra.rules.FilterToCalcRule; @@ -118,16 +115,15 @@ public void collectVariablesUsed( Set variableSet ) { @Override - public Map prepareAttributes() { - PolyAlgDeclaration decl = getPolyAlgDeclaration(); + public PolyAlgArgs collectAttributes() { + PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); PolyAlgArg expsArg = new ListArg<>( program.getExprList(), RexArg::new, this ); PolyAlgArg projectsArg = new ListArg<>( program.getProjectList(), RexArg::new, rowType.getFieldNames(), this ); - Map attributes = new HashMap<>(); - attributes.put( decl.getPos( 0 ), expsArg ); - attributes.put( decl.getPos( 1 ), projectsArg ); - attributes.put( decl.getParam( "condition" ), new RexArg( program.getCondition(), this ) ); - return attributes; + args.put( 0, expsArg ); + args.put( 1, projectsArg ); + args.put( "condition", new RexArg( program.getCondition(), this ) ); + return args; } } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java index e6630f61ea..5dc306b3e2 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java @@ -34,20 +34,17 @@ package org.polypheny.db.algebra.logical.relational; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.AlgShuttle; import org.polypheny.db.algebra.core.Aggregate; import org.polypheny.db.algebra.core.AggregateCall; import org.polypheny.db.algebra.core.relational.RelAlg; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; import org.polypheny.db.algebra.polyalg.arguments.AggArg; import org.polypheny.db.algebra.polyalg.arguments.FieldArg; import org.polypheny.db.algebra.polyalg.arguments.ListArg; import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.algebra.rules.AggregateProjectPullUpConstantsRule; import org.polypheny.db.algebra.rules.AggregateReduceFunctionsRule; import org.polypheny.db.plan.AlgCluster; @@ -120,15 +117,14 @@ public AlgNode accept( AlgShuttle shuttle ) { @Override - public Map prepareAttributes() { - PolyAlgDeclaration decl = getPolyAlgDeclaration(); - Map attributes = new HashMap<>(); + public PolyAlgArgs collectAttributes() { + PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); PolyAlgArg groupArg = new ListArg<>( groupSet.asList(), f -> new FieldArg( f, this ) ); PolyAlgArg aggsArg = new ListArg<>( aggCalls, a -> new AggArg( a, this ) ); - attributes.put( decl.getPos( 0 ), groupArg ); - attributes.put( decl.getParam( "aggs" ), aggsArg ); + args.put( 0, groupArg ); + args.put( "aggs", aggsArg ); if ( getGroupType() != Group.SIMPLE ) { PolyAlgArg groupSetArg = new ListArg<>( groupSets, @@ -136,10 +132,10 @@ public Map prepareAttributes() { set.asList(), f -> new FieldArg( f, this ) ) ); - attributes.put( decl.getParam( "groups" ), groupSetArg ); + args.put( "groups", groupSetArg ); } - return attributes; + return args; } } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java index 39ad6ffd0d..2a32192a10 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java @@ -35,8 +35,6 @@ import com.google.common.collect.ImmutableSet; -import java.util.HashMap; -import java.util.Map; import java.util.Objects; import lombok.Getter; import org.polypheny.db.algebra.AlgCollationTraitDef; @@ -50,11 +48,10 @@ import org.polypheny.db.algebra.metadata.AlgMdCollation; import org.polypheny.db.algebra.metadata.AlgMdDistribution; import org.polypheny.db.algebra.metadata.AlgMetadataQuery; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; import org.polypheny.db.algebra.polyalg.arguments.AnyArg; import org.polypheny.db.algebra.polyalg.arguments.ListArg; import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.algebra.polyalg.arguments.RexArg; import org.polypheny.db.plan.AlgCluster; import org.polypheny.db.plan.AlgTraitSet; @@ -130,15 +127,13 @@ public AlgWriter explainTerms( AlgWriter pw ) { @Override - public Map prepareAttributes() { - PolyAlgDeclaration decl = getPolyAlgDeclaration(); - Map attributes = new HashMap<>(); + public PolyAlgArgs collectAttributes() { + PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); PolyAlgArg varArg = new ListArg<>( variablesSet.asList(), AnyArg::new ); - attributes.put( decl.getPos( 0 ), new RexArg( condition, this ) ); - attributes.put( decl.getParam( "variables" ), varArg ); - - return attributes; + args.put( 0, new RexArg( condition, this ) ); + args.put( "variables", varArg ); + return args; } } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelIntersect.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelIntersect.java index 185ab104c9..eba2016986 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelIntersect.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelIntersect.java @@ -35,14 +35,12 @@ import java.util.List; -import java.util.Map; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.AlgShuttle; import org.polypheny.db.algebra.core.Intersect; import org.polypheny.db.algebra.core.relational.RelAlg; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; import org.polypheny.db.algebra.polyalg.arguments.BooleanArg; -import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.plan.AlgCluster; import org.polypheny.db.plan.AlgTraitSet; import org.polypheny.db.plan.Convention; @@ -86,8 +84,9 @@ public AlgNode accept( AlgShuttle shuttle ) { @Override - public Map prepareAttributes() { - return Map.of( getPolyAlgDeclaration().getParam( "all" ), new BooleanArg( all ) ); + public PolyAlgArgs collectAttributes() { + PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); + return args.put( "all", new BooleanArg( all ) ); } } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java index c3ea1885ff..a56684a312 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java @@ -35,9 +35,7 @@ import com.google.common.collect.ImmutableList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Set; import org.polypheny.db.algebra.AlgNode; @@ -48,13 +46,13 @@ import org.polypheny.db.algebra.core.JoinAlgType; import org.polypheny.db.algebra.core.relational.RelAlg; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; import org.polypheny.db.algebra.polyalg.arguments.AnyArg; import org.polypheny.db.algebra.polyalg.arguments.BooleanArg; import org.polypheny.db.algebra.polyalg.arguments.CorrelationArg; import org.polypheny.db.algebra.polyalg.arguments.EnumArg; import org.polypheny.db.algebra.polyalg.arguments.ListArg; import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.algebra.polyalg.arguments.RexArg; import org.polypheny.db.algebra.type.AlgDataTypeField; import org.polypheny.db.plan.AlgCluster; @@ -168,17 +166,17 @@ public List getSystemFieldList() { @Override - public Map prepareAttributes() { - Map attributes = new HashMap<>(); + public PolyAlgArgs collectAttributes() { + PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); PolyAlgArg varsArg = new ListArg<>( variablesSet.asList(), CorrelationArg::new ); PolyAlgArg sysFieldsArg = new ListArg<>( systemFieldList, AnyArg::new ); - attributes.put( getPolyAlgDeclaration().getPos( 0 ), new RexArg( condition, this ) ); - attributes.put( getPolyAlgDeclaration().getParam( "type" ), new EnumArg<>( joinType, ParamType.JOIN_TYPE_ENUM ) ); - attributes.put( getPolyAlgDeclaration().getParam( "variables" ), varsArg ); - attributes.put( getPolyAlgDeclaration().getParam( "semiJoinDone" ), new BooleanArg( semiJoinDone ) ); - attributes.put( getPolyAlgDeclaration().getParam( "sysFields" ), sysFieldsArg ); - return attributes; + args.put( 0, new RexArg( condition, this ) ) + .put( "type", new EnumArg<>( joinType, ParamType.JOIN_TYPE_ENUM ) ) + .put( "variables", varsArg ) + .put( "semiJoinDone", new BooleanArg( semiJoinDone ) ) + .put( "sysFields", sysFieldsArg ); + return args; } } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelMinus.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelMinus.java index 00f5f2ef55..657d1d9bc8 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelMinus.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelMinus.java @@ -34,17 +34,14 @@ package org.polypheny.db.algebra.logical.relational; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.polypheny.db.algebra.AlgInput; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.AlgShuttle; import org.polypheny.db.algebra.core.Minus; import org.polypheny.db.algebra.core.relational.RelAlg; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; import org.polypheny.db.algebra.polyalg.arguments.BooleanArg; -import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.plan.AlgCluster; import org.polypheny.db.plan.AlgTraitSet; import org.polypheny.db.plan.Convention; @@ -97,8 +94,9 @@ public AlgNode accept( AlgShuttle shuttle ) { @Override - public Map prepareAttributes() { - return Map.of(getPolyAlgDeclaration().getParam( "all" ), new BooleanArg( all ) ); + public PolyAlgArgs collectAttributes() { + PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); + return args.put( "all", new BooleanArg( all ) ); } } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java index 045beecf9f..a31208fabd 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java @@ -33,9 +33,7 @@ package org.polypheny.db.algebra.logical.relational; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; import java.util.stream.IntStream; import org.polypheny.db.algebra.AlgCollationTraitDef; @@ -45,9 +43,9 @@ import org.polypheny.db.algebra.core.relational.RelAlg; import org.polypheny.db.algebra.metadata.AlgMdCollation; import org.polypheny.db.algebra.metadata.AlgMetadataQuery; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; import org.polypheny.db.algebra.polyalg.arguments.ListArg; import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.algebra.polyalg.arguments.RexArg; import org.polypheny.db.algebra.type.AlgDataType; import org.polypheny.db.plan.AlgCluster; @@ -132,12 +130,12 @@ public AlgNode accept( AlgShuttle shuttle ) { @Override - public Map prepareAttributes() { + public PolyAlgArgs collectAttributes() { + PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); PolyAlgArg projectsArg = new ListArg<>( exps, RexArg::new, rowType.getFieldNames(), this ); - Map attributes = new HashMap<>(); - attributes.put( getPolyAlgDeclaration().getPos( 0 ), projectsArg ); - return attributes; + args.put( 0, projectsArg ); + return args; } } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java index c2f54332aa..783637e9f4 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java @@ -34,9 +34,7 @@ package org.polypheny.db.algebra.logical.relational; import com.google.common.collect.ImmutableList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.jetbrains.annotations.Nullable; import org.polypheny.db.algebra.AlgCollation; import org.polypheny.db.algebra.AlgCollationTraitDef; @@ -44,11 +42,10 @@ import org.polypheny.db.algebra.AlgShuttle; import org.polypheny.db.algebra.core.Sort; import org.polypheny.db.algebra.core.relational.RelAlg; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; import org.polypheny.db.algebra.polyalg.arguments.CollationArg; import org.polypheny.db.algebra.polyalg.arguments.ListArg; import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.algebra.polyalg.arguments.RexArg; import org.polypheny.db.plan.AlgCluster; import org.polypheny.db.plan.AlgTraitSet; @@ -103,16 +100,15 @@ public AlgNode accept( AlgShuttle shuttle ) { @Override - public Map prepareAttributes() { - PolyAlgDeclaration decl = getPolyAlgDeclaration(); - Map attributes = new HashMap<>(); + public PolyAlgArgs collectAttributes() { + PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); PolyAlgArg collArg = new ListArg<>( collation.getFieldCollations(), c -> new CollationArg( c, this ) ); - attributes.put( decl.getPos( 0 ), collArg ); - attributes.put( decl.getParam( "fetch" ), new RexArg( fetch ) ); - attributes.put( decl.getParam( "offset" ), new RexArg( offset ) ); - return attributes; + args.put( 0, collArg ) + .put( "fetch", new RexArg( fetch ) ) + .put( "offset", new RexArg( offset ) ); + return args; } } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelUnion.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelUnion.java index 51503b11c1..773269b445 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelUnion.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelUnion.java @@ -35,15 +35,13 @@ import java.util.List; -import java.util.Map; import org.polypheny.db.algebra.AlgInput; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.AlgShuttle; import org.polypheny.db.algebra.core.Union; import org.polypheny.db.algebra.core.relational.RelAlg; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; import org.polypheny.db.algebra.polyalg.arguments.BooleanArg; -import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.plan.AlgCluster; import org.polypheny.db.plan.AlgTraitSet; import org.polypheny.db.plan.Convention; @@ -96,8 +94,9 @@ public AlgNode accept( AlgShuttle shuttle ) { @Override - public Map prepareAttributes() { - return Map.of( getPolyAlgDeclaration().getParam( "all" ), new BooleanArg( all ) ); + public PolyAlgArgs collectAttributes() { + PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); + return args.put( "all", new BooleanArg( all ) ); } } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java index 78ffaaa642..5b5a6d78e0 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java @@ -18,9 +18,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import java.util.Map; -import java.util.StringJoiner; -import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; public class PolyAlgDeclaration { @@ -71,29 +68,6 @@ public PolyAlgDeclaration( String opName, int numInputs, Parameter param ) { } - public String serializeArguments( Map preparedAttributes ) { - StringJoiner joiner = new StringJoiner( ", ", "[", "]" ); - - for ( Parameter p : posParams ) { - assert preparedAttributes.containsKey( p ); - PolyAlgArg arg = preparedAttributes.get( p ); - assert arg.getType() == p.type; - joiner.add( arg.toPolyAlg() ); - } - for ( Parameter p : kwParams ) { - if ( preparedAttributes.containsKey( p ) ) { - PolyAlgArg arg = preparedAttributes.get( p ); - assert arg.getType() == p.type; - String value = arg.toPolyAlg(); - if ( !p.defaultValue.equals( value ) ) { - joiner.add( p.name + "=" + value ); - } - } - } - return joiner.toString(); - } - - public Parameter getPos( int i ) { return posParams.get( i ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java index 9ba01fed27..942243b7bb 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java @@ -29,9 +29,16 @@ public class PolyAlgRegistry { private static final Map, PolyAlgDeclaration> declarations = new HashMap<>(); + private static final Map> classes = new HashMap<>(); static { + populateDeclarationsMap(); + populateClassesMap(); + } + + + private static void populateDeclarationsMap() { declarations.put( LogicalRelProject.class, new PolyAlgDeclaration( "PROJECT", 1, new Parameter( "projects", ParamType.SIMPLE_REX, true ) ) ); @@ -72,6 +79,22 @@ public class PolyAlgRegistry { new Parameter( "exps", ParamType.SIMPLE_REX, true ), new Parameter( "projects", ParamType.SIMPLE_REX, true ), new Parameter( "condition", ParamType.SIMPLE_REX, false, "" ) ) ) ); + + } + + + private static void populateClassesMap() { + for ( Map.Entry, PolyAlgDeclaration> entry : declarations.entrySet() ) { + Class clazz = entry.getKey(); + PolyAlgDeclaration declaration = entry.getValue(); + + assert !classes.containsKey( declaration.opName ); + classes.put( declaration.opName, clazz ); + for ( String alias : declaration.opAliases ) { + assert !classes.containsKey( alias ); + classes.put( alias, clazz ); + } + } } @@ -95,4 +118,23 @@ public static PolyAlgDeclaration getDeclaration( Class clazz, new PolyAlgDeclaration( clazz.getSimpleName(), numInputs ) ); } + + public static Class getClass( String opName ) { + return classes.get( opName ); + } + + + /** + * Retrieves the PolyAlgDeclaration associated with the specified operator + * or returns null if the operator is not known. + * It is also possible to use an alias for the operator name. + * + * @param opName The name of the operator or one of its aliases + * @return The PolyAlgDeclaration associated with the opName if it exists, + * or null otherwise. + */ + public static PolyAlgDeclaration getDeclaration( String opName ) { + return declarations.get( getClass( opName ) ); + } + } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java new file mode 100644 index 0000000000..6b26033694 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java @@ -0,0 +1,113 @@ +/* + * 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.polyalg.arguments; + +import java.util.HashMap; +import java.util.Map; +import java.util.StringJoiner; +import lombok.Getter; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; + +/** + * Represents the parameters with corresponding values (PolyAlgArg) for an AlgNode instance. + * It is used as an intermediary representation when serializing or parsing between AlgNodes and PolyAlgebra. + */ +public class PolyAlgArgs { + + @Getter + private final PolyAlgDeclaration decl; + private final Map args = new HashMap<>(); + + + public PolyAlgArgs( PolyAlgDeclaration declaration ) { + this.decl = declaration; + } + + + public String serializeArguments() { + StringJoiner joiner = new StringJoiner( ", ", "[", "]" ); + + for ( Parameter p : decl.posParams ) { + assert args.containsKey( p ); + PolyAlgArg arg = getArg( p ); + joiner.add( arg.toPolyAlg() ); + } + for ( Parameter p : decl.kwParams ) { + if ( args.containsKey( p ) ) { + PolyAlgArg arg = getArg( p ); + String value = arg.toPolyAlg(); + if ( !p.defaultValue().equals( value ) ) { + joiner.add( p.name() + "=" + value ); + } + } + } + return joiner.toString(); + } + + + public PolyAlgArgs put( String name, PolyAlgArg arg ) { + return put( decl.getParam( name ), arg ); + } + + + public PolyAlgArgs put( int pos, PolyAlgArg arg ) { + return put( decl.getPos( pos ), arg ); + } + + + private PolyAlgArgs put( Parameter p, PolyAlgArg arg ) { + assert p.type() == arg.getType(); + + args.put( p, arg ); + return this; + } + + + private PolyAlgArg getArg( Parameter p ) { + return args.get( p ); + } + + + public PolyAlgArg getArg( String name ) { + return getArg( decl.getParam( name ) ); + } + + + public PolyAlgArg getArg( int pos ) { + return getArg( decl.getPos( pos ) ); + } + + + public T getArg( String name, Class type ) { + return getArg( decl.getParam( name ), type ); + } + + + public T getArg( int pos, Class type ) { + return getArg( decl.getPos( pos ), type ); + } + + + private T getArg( Parameter p, Class type ) { + PolyAlgArg arg = getArg( p ); + assert type.isInstance( arg ); + return type.cast( arg ); + } + + +} From 024d3ca460e3b3c8f01d224da35164233566015b Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Thu, 21 Mar 2024 11:24:23 +0100 Subject: [PATCH 006/132] Make "collation" in SORT optional for LIMIT to work correctly --- .../polypheny/db/algebra/logical/relational/LogicalRelSort.java | 2 +- .../java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java index 783637e9f4..ed903d2ff6 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java @@ -105,7 +105,7 @@ public PolyAlgArgs collectAttributes() { PolyAlgArg collArg = new ListArg<>( collation.getFieldCollations(), c -> new CollationArg( c, this ) ); - args.put( 0, collArg ) + args.put( "collation", collArg ) .put( "fetch", new RexArg( fetch ) ) .put( "offset", new RexArg( offset ) ); return args; diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java index 942243b7bb..4b4bd5a0ed 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java @@ -64,7 +64,7 @@ private static void populateDeclarationsMap() { new Parameter( "all", ParamType.BOOLEAN, false, "FALSE" ) ) ); declarations.put( LogicalRelSort.class, new PolyAlgDeclaration( "SORT", 1, ImmutableList.of( - new Parameter( "collation", ParamType.COLLATION, false ), + new Parameter( "collation", ParamType.COLLATION, false, "" ), new Parameter( "fetch", ParamType.SIMPLE_REX, false, "" ), new Parameter( "offset", ParamType.SIMPLE_REX, false, "" ) ) ) ); From 103b0f22993f88c5a6064b4ea5fcda6608d8677a Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Thu, 21 Mar 2024 18:08:16 +0100 Subject: [PATCH 007/132] Add tags to operators / params --- .../logical/relational/LogicalRelFilter.java | 2 - .../logical/relational/LogicalRelJoin.java | 6 +- .../algebra/polyalg/PolyAlgDeclaration.java | 95 +++++++++------ .../db/algebra/polyalg/PolyAlgRegistry.java | 110 +++++++++++------- 4 files changed, 132 insertions(+), 81 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java index 2a32192a10..c00de25e9e 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java @@ -129,10 +129,8 @@ public AlgWriter explainTerms( AlgWriter pw ) { @Override public PolyAlgArgs collectAttributes() { PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); - PolyAlgArg varArg = new ListArg<>( variablesSet.asList(), AnyArg::new ); args.put( 0, new RexArg( condition, this ) ); - args.put( "variables", varArg ); return args; } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java index a56684a312..f74751d0c6 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java @@ -168,14 +168,10 @@ public List getSystemFieldList() { @Override public PolyAlgArgs collectAttributes() { PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); - PolyAlgArg varsArg = new ListArg<>( variablesSet.asList(), CorrelationArg::new ); - PolyAlgArg sysFieldsArg = new ListArg<>( systemFieldList, AnyArg::new ); args.put( 0, new RexArg( condition, this ) ) .put( "type", new EnumArg<>( joinType, ParamType.JOIN_TYPE_ENUM ) ) - .put( "variables", varsArg ) - .put( "semiJoinDone", new BooleanArg( semiJoinDone ) ) - .put( "sysFields", sysFieldsArg ); + .put( "semiJoinDone", new BooleanArg( semiJoinDone ) ); return args; } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java index 5b5a6d78e0..4f7b90a73e 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java @@ -18,6 +18,12 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; +import lombok.Builder; +import lombok.NonNull; +import lombok.Singular; public class PolyAlgDeclaration { @@ -25,22 +31,30 @@ public class PolyAlgDeclaration { public final String opName; public final ImmutableList opAliases; public final int numInputs; // -1 if arbitrary amount is allowed + public final ImmutableList opTags; public final ImmutableList posParams; public final ImmutableList kwParams; private final ImmutableMap paramLookup; - public PolyAlgDeclaration( String opName, ImmutableList opAliases, int numInputs, ImmutableList params ) { + @Builder + public PolyAlgDeclaration( @NonNull String opName, @Singular ImmutableList opAliases, @Singular ImmutableList opTags, int numInputs, @Singular ImmutableList params ) { this.opName = opName; - this.opAliases = opAliases; + this.opAliases = (opAliases != null) ? opAliases : ImmutableList.of(); this.numInputs = numInputs; + this.opTags = (opTags != null) ? opTags : ImmutableList.of(); + params = (params != null) ? params : ImmutableList.of(); + + assert PolyAlgDeclaration.hasUniqueNames( params ); ImmutableMap.Builder bMap = ImmutableMap.builder(); ImmutableList.Builder bPos = ImmutableList.builder(); ImmutableList.Builder bKey = ImmutableList.builder(); for ( Parameter p : params ) { bMap.put( p.name, p ); + bMap.putAll( p.aliases.stream().collect( Collectors.toMap( a -> a, a -> p ) ) ); + if ( p.isPositional() ) { bPos.add( p ); } else { @@ -53,21 +67,6 @@ public PolyAlgDeclaration( String opName, ImmutableList opAliases, int n } - public PolyAlgDeclaration( String opName, int numInputs, ImmutableList params ) { - this( opName, ImmutableList.of(), numInputs, params ); - } - - - public PolyAlgDeclaration( String opName, int numInputs ) { - this( opName, ImmutableList.of(), numInputs, ImmutableList.of() ); - } - - - public PolyAlgDeclaration( String opName, int numInputs, Parameter param ) { - this( opName, ImmutableList.of(), numInputs, ImmutableList.of( param ) ); - } - - public Parameter getPos( int i ) { return posParams.get( i ); } @@ -78,6 +77,24 @@ public Parameter getParam( String name ) { } + private static boolean hasUniqueNames( ImmutableList params ) { + Set names = new HashSet<>(); + for ( Parameter p : params ) { + if ( names.contains( p.name ) ) { + return false; + } + names.add( p.name ); + for ( String alias : p.aliases ) { + if ( names.contains( alias ) ) { + return false; + } + names.add( alias ); + } + } + return true; + } + + /** * Depending on whether a defaultValue is specified, a Parameter can result in two types of corresponding arguments: *
    @@ -87,26 +104,14 @@ public Parameter getParam( String name ) { *
* * @param name The name of this Parameter + * @param aliases List of alias names that can additionally be used to identify this parameter. + * @param tags List of ParameterTags associated with this Parameter * @param type The type of this Parameter * @param isMultiValued Boolean indicating whether an argument consisting of multiple values can be specified * @param defaultValue The default value for this Parameter or null if it has no default value (if it should have a default value of null, use an empty string instead) */ - public record Parameter(String name, ParamType type, boolean isMultiValued, String defaultValue) { - - public Parameter( String name ) { - this( name, ParamType.ANY ); - } - - - public Parameter( String name, ParamType type ) { - this( name, type, false, null ); - } - - - public Parameter( String name, ParamType type, boolean isMultiValued ) { - this( name, type, isMultiValued, null ); - } - + @Builder + public record Parameter(@NonNull String name, @Singular ImmutableList aliases, @Singular ImmutableList tags, @NonNull ParamType type, boolean isMultiValued, String defaultValue) { public boolean isPositional() { return defaultValue == null; @@ -181,4 +186,28 @@ public boolean isEnum() { } + + public enum OperatorTag { + REL, + DOC, + LPG, + LOGICAL, + PHYSICAL, + ALLOCATION, + + /** + * Operator is irrelevant for the average user. + */ + ADVANCED + } + + + public enum ParameterTag { + + /** + * Only show parameter in advanced mode. + */ + ADVANCED + } + } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java index 4b4bd5a0ed..a928971764 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java @@ -18,11 +18,13 @@ import com.google.common.collect.ImmutableList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.core.JoinAlgType; import org.polypheny.db.algebra.core.relational.RelScan; import org.polypheny.db.algebra.logical.relational.*; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.OperatorTag; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; @@ -39,46 +41,72 @@ public class PolyAlgRegistry { private static void populateDeclarationsMap() { - declarations.put( LogicalRelProject.class, new PolyAlgDeclaration( "PROJECT", 1, - new Parameter( "projects", ParamType.SIMPLE_REX, true ) ) ); - - declarations.put( RelScan.class, new PolyAlgDeclaration( "SCAN", 0, - new Parameter( "entity", ParamType.ENTITY ) ) ); - - declarations.put( LogicalRelFilter.class, new PolyAlgDeclaration( "FILTER", 1, ImmutableList.of( - new Parameter( "condition", ParamType.SIMPLE_REX, false ), - new Parameter( "variables", ParamType.ANY, true, "" ) ) ) ); - - declarations.put( LogicalRelAggregate.class, new PolyAlgDeclaration( "AGG", 1, ImmutableList.of( - new Parameter( "group", ParamType.FIELD, true ), - new Parameter( "groups", ParamType.ANY, true, "" ), - new Parameter( "aggs", ParamType.AGGREGATE, true, "" ) ) ) ); - - declarations.put( LogicalRelMinus.class, new PolyAlgDeclaration( "MINUS", 2, - new Parameter( "all", ParamType.BOOLEAN, false, "FALSE" ) ) ); - - declarations.put( LogicalRelUnion.class, new PolyAlgDeclaration( "UNION", 2, - new Parameter( "all", ParamType.BOOLEAN, false, "FALSE" ) ) ); - - declarations.put( LogicalRelIntersect.class, new PolyAlgDeclaration( "INTERSECT", 2, - new Parameter( "all", ParamType.BOOLEAN, false, "FALSE" ) ) ); - - declarations.put( LogicalRelSort.class, new PolyAlgDeclaration( "SORT", 1, ImmutableList.of( - new Parameter( "collation", ParamType.COLLATION, false, "" ), - new Parameter( "fetch", ParamType.SIMPLE_REX, false, "" ), - new Parameter( "offset", ParamType.SIMPLE_REX, false, "" ) ) ) ); - - declarations.put( LogicalRelJoin.class, new PolyAlgDeclaration( "JOIN", 2, ImmutableList.of( - new Parameter( "condition", ParamType.SIMPLE_REX, false ), - new Parameter( "type", ParamType.JOIN_TYPE_ENUM, false, JoinAlgType.INNER.name() ), - new Parameter( "variables", ParamType.CORR_ID, true, "" ), - new Parameter( "semiJoinDone", ParamType.BOOLEAN, false, "FALSE" ), - new Parameter( "sysFields", ParamType.ANY, true, "" ) ) ) ); - - declarations.put( LogicalCalc.class, new PolyAlgDeclaration( "CALC", 1, ImmutableList.of( - new Parameter( "exps", ParamType.SIMPLE_REX, true ), - new Parameter( "projects", ParamType.SIMPLE_REX, true ), - new Parameter( "condition", ParamType.SIMPLE_REX, false, "" ) ) ) ); + ImmutableList logRelTags = ImmutableList.of( OperatorTag.LOGICAL, OperatorTag.REL ); + + declarations.put( LogicalRelProject.class, PolyAlgDeclaration.builder() + .opName( "PROJECT" ).opAlias( "P" ).numInputs( 1 ).opTags( logRelTags ) + .param( Parameter.builder().name( "projects" ).isMultiValued( true ).type( ParamType.SIMPLE_REX ).build() ) + .build() ); + + declarations.put( RelScan.class, PolyAlgDeclaration.builder() + .opName( "SCAN" ).numInputs( 0 ).opTags( logRelTags ) + .param( Parameter.builder().name( "entity" ).type( ParamType.SIMPLE_REX ).build() ) + .build() ); + + declarations.put( LogicalRelFilter.class, PolyAlgDeclaration.builder() + .opName( "FILTER" ).numInputs( 1 ).opTags( logRelTags ) + .param( Parameter.builder().name( "condition" ).type( ParamType.SIMPLE_REX ).build() ) + .build() ); + + declarations.put( LogicalRelAggregate.class, PolyAlgDeclaration.builder() + .opName( "AGG" ).numInputs( 1 ).opTags( logRelTags ) + .param( Parameter.builder().name( "group" ).type( ParamType.FIELD ).isMultiValued( true ).build() ) + .param( Parameter.builder().name( "groups" ).type( ParamType.ANY ).isMultiValued( true ).defaultValue( "" ).build() ) + .param( Parameter.builder().name( "aggs" ).type( ParamType.AGGREGATE ).isMultiValued( true ).defaultValue( "" ).build() ) + .build() ); + + declarations.put( LogicalRelMinus.class, PolyAlgDeclaration.builder() + .opName( "MINUS" ).numInputs( 2 ).opTags( logRelTags ) + .param( Parameter.builder().name( "all" ).type( ParamType.BOOLEAN ).defaultValue( "FALSE" ).build() ) + .build() ); + + declarations.put( LogicalRelUnion.class, PolyAlgDeclaration.builder() + .opName( "UNION" ).numInputs( 2 ).opTags( logRelTags ) + .param( Parameter.builder().name( "all" ).type( ParamType.BOOLEAN ).defaultValue( "FALSE" ).build() ) + .build() ); + + declarations.put( LogicalRelIntersect.class, PolyAlgDeclaration.builder() + .opName( "INTERSECT" ).numInputs( 2 ).opTags( logRelTags ) + .param( Parameter.builder().name( "all" ).type( ParamType.BOOLEAN ).defaultValue( "FALSE" ).build() ) + .build() ); + + declarations.put( LogicalRelSort.class, PolyAlgDeclaration.builder() + .opName( "SORT" ).numInputs( 1 ).opTags( logRelTags ) + .param( Parameter.builder().name( "sort" ).aliases( List.of( "collation", "order" ) ).type( ParamType.COLLATION ).defaultValue( "" ).build() ) + .param( Parameter.builder().name( "limit" ).alias( "fetch" ).type( ParamType.SIMPLE_REX ).defaultValue( "" ).build() ) + .param( Parameter.builder().name( "offset" ).type( ParamType.SIMPLE_REX ).defaultValue( "" ).build() ) + .build() ); + + declarations.put( LogicalRelJoin.class, PolyAlgDeclaration.builder() + .opName( "JOIN" ).numInputs( 2 ).opTags( logRelTags ) + .param( Parameter.builder().name( "condition" ).type( ParamType.SIMPLE_REX ).build() ) + .param( Parameter.builder().name( "type" ).type( ParamType.JOIN_TYPE_ENUM ).defaultValue( JoinAlgType.INNER.name() ).build() ) + .param( Parameter.builder().name( "semiJoinDone" ).type( ParamType.BOOLEAN ).defaultValue( "FALSE" ).build() ) + .build() ); + + declarations.put( LogicalCalc.class, PolyAlgDeclaration.builder() + .opName( "CALC" ).numInputs( 1 ).opTags( logRelTags ) + .param( Parameter.builder().name( "exps" ).type( ParamType.SIMPLE_REX ).isMultiValued( true ).build() ) + .param( Parameter.builder().name( "projects" ).type( ParamType.SIMPLE_REX ).isMultiValued( true ).build() ) + .param( Parameter.builder().name( "condition" ).type( ParamType.SIMPLE_REX ).defaultValue( "" ).build() ) + .build() ); + + /* + declarations.put( .class, PolyAlgDeclaration.builder() + .opName( "" ).numInputs( ).opTags( logRelTags ) + .param( Parameter.builder().name( "" ).type( ParamType. ).build() ) + .build() ); + */ } @@ -115,7 +143,7 @@ public static PolyAlgDeclaration getDeclaration( Class clazz public static PolyAlgDeclaration getDeclaration( Class clazz, int numInputs ) { return declarations.getOrDefault( clazz, - new PolyAlgDeclaration( clazz.getSimpleName(), numInputs ) ); + PolyAlgDeclaration.builder().opName( clazz.getSimpleName() ).numInputs( numInputs ).build() ); } From 57ff77d03917a9708c42588b1ad3669e259c2b66 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Thu, 21 Mar 2024 18:49:23 +0100 Subject: [PATCH 008/132] Add ability to unpack the arguments of ListArgs --- .../relational/LogicalRelAggregate.java | 2 +- .../logical/relational/LogicalRelProject.java | 2 +- .../logical/relational/LogicalRelSort.java | 9 ++++-- .../algebra/polyalg/PolyAlgDeclaration.java | 12 +++++++ .../db/algebra/polyalg/PolyAlgUtils.java | 19 ++++-------- .../db/algebra/polyalg/arguments/ListArg.java | 31 ++++++++++++++----- 6 files changed, 50 insertions(+), 25 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java index 5dc306b3e2..30b1f8d69a 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java @@ -120,7 +120,7 @@ public AlgNode accept( AlgShuttle shuttle ) { public PolyAlgArgs collectAttributes() { PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); - PolyAlgArg groupArg = new ListArg<>( groupSet.asList(), f -> new FieldArg( f, this ) ); + PolyAlgArg groupArg = new ListArg<>( groupSet.asList(), f -> new FieldArg( f, this ), args.getDecl().canUnpackValues() ); PolyAlgArg aggsArg = new ListArg<>( aggCalls, a -> new AggArg( a, this ) ); args.put( 0, groupArg ); diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java index a31208fabd..08b0b38f3e 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java @@ -132,7 +132,7 @@ public AlgNode accept( AlgShuttle shuttle ) { @Override public PolyAlgArgs collectAttributes() { PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); - PolyAlgArg projectsArg = new ListArg<>( exps, RexArg::new, rowType.getFieldNames(), this ); + PolyAlgArg projectsArg = new ListArg<>( exps, RexArg::new, rowType.getFieldNames(), this, args.getDecl().canUnpackValues() ); args.put( 0, projectsArg ); return args; diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java index ed903d2ff6..cbd0365e39 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java @@ -103,10 +103,13 @@ public AlgNode accept( AlgShuttle shuttle ) { public PolyAlgArgs collectAttributes() { PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); - PolyAlgArg collArg = new ListArg<>( collation.getFieldCollations(), c -> new CollationArg( c, this ) ); + PolyAlgArg collArg = new ListArg<>( + collation.getFieldCollations(), + c -> new CollationArg( c, this ), + args.getDecl().canUnpackValues() ); - args.put( "collation", collArg ) - .put( "fetch", new RexArg( fetch ) ) + args.put( "sort", collArg ) + .put( "limit", new RexArg( fetch ) ) .put( "offset", new RexArg( offset ) ); return args; } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java index 4f7b90a73e..ce26e54188 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java @@ -95,6 +95,18 @@ private static boolean hasUniqueNames( ImmutableList params ) { } + /** + * Checks whether this operator has exactly one positional parameter, which in addition must be multiValued. + * If this is the case, it is safe for the multiValued parameter to omit the brackets, as it is possible to + * infer that any positional argument must belong to the multiValued argument. + * + * @return whether it is safe to unpack the values of the (only) positional argument + */ + public boolean canUnpackValues() { + return posParams.size() == 1 && getPos( 0 ).isMultiValued; + } + + /** * Depending on whether a defaultValue is specified, a Parameter can result in two types of corresponding arguments: *
    diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java index 867cd74162..53d3993fa5 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java @@ -18,10 +18,8 @@ import java.util.ArrayList; import java.util.List; -import org.polypheny.db.algebra.AlgInput; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.type.AlgDataTypeField; -import org.polypheny.db.rex.RexNode; public class PolyAlgUtils { @@ -36,7 +34,7 @@ public class PolyAlgUtils { public static String replaceWithFieldNames( AlgNode alg, String str ) { if ( str.contains( "$" ) ) { int offset = 0; - for (AlgNode input : alg.getInputs()) { + for ( AlgNode input : alg.getInputs() ) { offset += input.getTupleType().getFields().size(); } // iterate in reverse order to make sure "$13" is replaced before $1 @@ -113,17 +111,12 @@ public static List appendAliases( List exps, List aliase * If values contains more than one element, the returned string is surrounded with brackets to represent a list. * * @param values the values to be joined - * @return a string either representing a list containing or values or a single value if values is of size 1. + * @param omitBrackets whether the surrounding brackets in the case of multiple values should be omitted + * @return a string either representing a list containing all entries of values or a single value if values is of size 1 */ - public static String joinMultiValued( List values ) { - if ( values.isEmpty() ) { - return ""; - } - if ( values.size() == 1 ) { - return values.get( 0 ); - } - - return "[" + String.join( ", ", values ) + "]"; + public static String joinMultiValued( List values, boolean omitBrackets ) { + String str = String.join( ", ", values ); + return (omitBrackets || values.size() <= 1) ? str : "[" + str + "]"; } } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java index 6307f9f5ed..ce3bd322da 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java @@ -27,32 +27,49 @@ public class ListArg implements PolyAlgArg { private final List args; private final List aliases; private final AlgNode algNode; + private final boolean unpackValues; - public ListArg( List args, List aliases, AlgNode fieldNameProvider ) { + public ListArg( List args, List aliases, AlgNode fieldNameProvider, boolean unpackValues ) { this.args = args; this.aliases = aliases; this.algNode = fieldNameProvider; + this.unpackValues = unpackValues; } public ListArg( List rawArgs, Function converter ) { - this( rawArgs, converter, null, null ); + this( rawArgs, converter, null, null, false ); + } + + + public ListArg( List rawArgs, Function converter, boolean unpackValues ) { + this( rawArgs, converter, null, null, unpackValues ); } public ListArg( List rawArgs, Function converter, AlgNode fieldNameProvider ) { - this( rawArgs, converter, null, fieldNameProvider ); + this( rawArgs, converter, null, fieldNameProvider, false ); } - public ListArg( List rawArgs, Function converter, List aliases ) { - this( rawArgs, converter, aliases, null ); + public ListArg( List rawArgs, Function converter, AlgNode fieldNameProvider, boolean unpackValues ) { + this( rawArgs, converter, null, fieldNameProvider, unpackValues ); + } + + + public ListArg( List rawArgs, Function converter, List aliases, boolean unpackValues ) { + this( rawArgs, converter, aliases, null, unpackValues ); } public ListArg( List rawArgs, Function converter, List aliases, AlgNode fieldNameProvider ) { - this( rawArgs.stream().map( converter ).toList(), aliases, fieldNameProvider ); + this( rawArgs.stream().map( converter ).toList(), aliases, fieldNameProvider, false ); + } + + + public ListArg( List rawArgs, Function converter, List aliases, AlgNode fieldNameProvider, boolean unpackValues ) { + this( rawArgs.stream().map( converter ).toList(), aliases, fieldNameProvider, unpackValues ); } @@ -74,7 +91,7 @@ public String toPolyAlg() { if ( aliases != null ) { strArgs = PolyAlgUtils.appendAliases( strArgs, aliases ); } - return PolyAlgUtils.joinMultiValued( strArgs ); + return PolyAlgUtils.joinMultiValued( strArgs, unpackValues ); } } From db4dd13c5f1de1febcee1f5f6000aa822f0f8a5b Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Fri, 22 Mar 2024 14:00:51 +0100 Subject: [PATCH 009/132] Begin implementing RexVisitor for replacing field ids with names --- .../logical/relational/LogicalRelProject.java | 2 +- .../db/algebra/polyalg/PolyAlgUtils.java | 122 ++++++++++++++++++ .../db/algebra/polyalg/arguments/RexArg.java | 3 +- .../java/org/polypheny/db/rex/RexCall.java | 35 ++++- 4 files changed, 158 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java index 08b0b38f3e..8c94b07143 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java @@ -132,7 +132,7 @@ public AlgNode accept( AlgShuttle shuttle ) { @Override public PolyAlgArgs collectAttributes() { PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); - PolyAlgArg projectsArg = new ListArg<>( exps, RexArg::new, rowType.getFieldNames(), this, args.getDecl().canUnpackValues() ); + PolyAlgArg projectsArg = new ListArg<>( exps, e -> new RexArg( e, this ), rowType.getFieldNames(), args.getDecl().canUnpackValues() ); args.put( 0, projectsArg ); return args; diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java index 53d3993fa5..97626e3252 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java @@ -16,10 +16,27 @@ package org.polypheny.db.algebra.polyalg; + import java.util.ArrayList; import java.util.List; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.type.AlgDataTypeField; +import org.polypheny.db.rex.RexCall; +import org.polypheny.db.rex.RexCorrelVariable; +import org.polypheny.db.rex.RexDynamicParam; +import org.polypheny.db.rex.RexElementRef; +import org.polypheny.db.rex.RexFieldAccess; +import org.polypheny.db.rex.RexIndexRef; +import org.polypheny.db.rex.RexLiteral; +import org.polypheny.db.rex.RexLocalRef; +import org.polypheny.db.rex.RexNameRef; +import org.polypheny.db.rex.RexNode; +import org.polypheny.db.rex.RexOver; +import org.polypheny.db.rex.RexPatternFieldRef; +import org.polypheny.db.rex.RexRangeRef; +import org.polypheny.db.rex.RexSubQuery; +import org.polypheny.db.rex.RexTableIndexRef; +import org.polypheny.db.rex.RexVisitor; public class PolyAlgUtils { @@ -119,4 +136,109 @@ public static String joinMultiValued( List values, boolean omitBrackets return (omitBrackets || values.size() <= 1) ? str : "[" + str + "]"; } + + public static String digestWithNames( RexNode expr, AlgNode context ) { + List fieldNames = context.getInputs().stream() + .flatMap( node -> node.getTupleType().getFields().stream() ) + .map( AlgDataTypeField::getName ) + .toList(); + return expr.accept( new NameReplacer( fieldNames ) ); + } + + + public static class NameReplacer implements RexVisitor { + + private final List names; + + + public NameReplacer( List names ) { + this.names = names; + } + + + @Override + public String visitIndexRef( RexIndexRef inputRef ) { + return names.get( inputRef.getIndex() ); + } + + + @Override + public String visitLocalRef( RexLocalRef localRef ) { + return "LocalRef: " + localRef; + } + + + @Override + public String visitLiteral( RexLiteral literal ) { + return literal.toString(); + } + + + @Override + public String visitCall( RexCall call ) { + return call.toString( this ); + } + + + @Override + public String visitOver( RexOver over ) { + return "over: " + over; + } + + + @Override + public String visitCorrelVariable( RexCorrelVariable correlVariable ) { + return "correlVariable: " + correlVariable; + } + + + @Override + public String visitDynamicParam( RexDynamicParam dynamicParam ) { + return "dynamicParam: " + dynamicParam; + } + + + @Override + public String visitRangeRef( RexRangeRef rangeRef ) { + return "rangeRef: " + rangeRef; + } + + + @Override + public String visitFieldAccess( RexFieldAccess fieldAccess ) { + return "fieldAccess: " + fieldAccess; + } + + + @Override + public String visitSubQuery( RexSubQuery subQuery ) { + return "subQuery: " + subQuery; + } + + + @Override + public String visitTableInputRef( RexTableIndexRef fieldRef ) { + return "tableInputRef: " + fieldRef; + } + + + @Override + public String visitPatternFieldRef( RexPatternFieldRef fieldRef ) { + return "patternFieldRef: " + fieldRef; + } + + + @Override + public String visitNameRef( RexNameRef nameRef ) { + return "nameRef: " + nameRef; + } + + + @Override + public String visitElementRef( RexElementRef rexElementRef ) { + return "elementRef: " + rexElementRef; + } + + } + } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java index 7b984e2d4b..81183c4592 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java @@ -17,6 +17,7 @@ package org.polypheny.db.algebra.polyalg.arguments; import org.polypheny.db.algebra.AlgNode; +import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; import org.polypheny.db.algebra.polyalg.PolyAlgUtils; import org.polypheny.db.rex.RexNode; @@ -50,7 +51,7 @@ public String toPolyAlg() { if ( algNode == null ) { return str; } - return PolyAlgUtils.replaceWithFieldNames( algNode, str ); + return PolyAlgUtils.replaceWithFieldNames( algNode, str ) + " { " + PolyAlgUtils.digestWithNames( node, algNode ) + " } "; } } diff --git a/core/src/main/java/org/polypheny/db/rex/RexCall.java b/core/src/main/java/org/polypheny/db/rex/RexCall.java index aa1caf7195..6c72f3979d 100644 --- a/core/src/main/java/org/polypheny/db/rex/RexCall.java +++ b/core/src/main/java/org/polypheny/db/rex/RexCall.java @@ -83,6 +83,7 @@ public RexCall( AlgDataType type, Operator op, RexNode... operands ) { this( type, op, ImmutableList.copyOf( operands ) ); } + public RexCall( AlgDataType type, Operator op, List operands ) { this.type = Objects.requireNonNull( type ); this.op = Objects.requireNonNull( op ); @@ -101,13 +102,26 @@ public RexCall( AlgDataType type, Operator op, List operands * @see RexLiteral#computeDigest(RexDigestIncludeType) */ protected final StringBuilder appendOperands( StringBuilder sb ) { + return appendOperands( sb, null ); + } + + + /** + * Like appendOperands( StringBuilder sb), but additionally takes a visitor for generating the + * string representation of any operands that are not RexLiterals. + * + * @param sb destination + * @param visitor RexVisitor which visits any non-literal operand for generating the string representation. + * @return original StringBuilder for fluent API + */ + protected final StringBuilder appendOperands( StringBuilder sb, RexVisitor visitor ) { for ( int i = 0; i < operands.size(); i++ ) { if ( i > 0 ) { sb.append( ", " ); } RexNode operand = operands.get( i ); if ( !(operand instanceof RexLiteral) ) { - sb.append( operand ); + sb.append( visitor == null ? operand : operand.accept( visitor ) ); continue; } // Type information might be omitted in certain cases to improve readability @@ -151,12 +165,17 @@ private static boolean equalSansNullability( AlgDataType a, AlgDataType b ) { protected @Nonnull String computeDigest( boolean withType ) { + return computeDigest( withType, null ); + } + + + protected @Nonnull String computeDigest( boolean withType, RexVisitor visitor ) { final StringBuilder sb = new StringBuilder( op.getName() ); if ( (operands.isEmpty()) && (op.getSyntax() == Syntax.FUNCTION_ID) ) { // Don't print params for empty arg list. For example, we want "SYSTEM_USER", not "SYSTEM_USER()". } else { sb.append( "(" ); - appendOperands( sb ); + appendOperands( sb, visitor ); sb.append( ")" ); } if ( withType ) { @@ -180,6 +199,18 @@ private static boolean equalSansNullability( AlgDataType a, AlgDataType b ) { } + /** + * Computes a string representation where the given visitor is used for generating + * the string of each operand. + * + * @param visitor RexVisitor that visits every operand for generating the string representation used + * @return String representation of this call, where operands are customized by the visitor. + */ + public final @Nonnull String toString( RexVisitor visitor ) { + return Objects.requireNonNull( computeDigest( isA( Kind.CAST ) || isA( Kind.NEW_SPECIFICATION ), visitor ) ); + } + + @Override public R accept( RexVisitor visitor ) { return visitor.visitCall( this ); From 33ba26a91c50756f29a62578b8be85211ef03559 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Fri, 22 Mar 2024 17:41:26 +0100 Subject: [PATCH 010/132] Allow for RexNode digests to use field names --- .../polypheny/db/algebra/AbstractAlgNode.java | 2 +- .../db/algebra/core/AggregateCall.java | 20 +++++- .../logical/relational/LogicalCalc.java | 6 +- .../relational/LogicalRelAggregate.java | 8 +-- .../logical/relational/LogicalRelFilter.java | 5 +- .../logical/relational/LogicalRelJoin.java | 6 +- .../logical/relational/LogicalRelProject.java | 2 +- .../db/algebra/polyalg/PolyAlgUtils.java | 68 +++++-------------- .../db/algebra/polyalg/arguments/AggArg.java | 29 +++++--- .../algebra/polyalg/arguments/FieldArg.java | 14 ++-- .../db/algebra/polyalg/arguments/ListArg.java | 41 ++++------- .../algebra/polyalg/arguments/PolyAlgArg.java | 5 ++ .../polyalg/arguments/PolyAlgArgs.java | 9 ++- .../db/algebra/polyalg/arguments/RexArg.java | 18 +++-- .../polypheny/db/rex/RexFieldCollation.java | 7 +- .../java/org/polypheny/db/rex/RexOver.java | 10 ++- .../org/polypheny/db/rex/RexSubQuery.java | 9 ++- .../java/org/polypheny/db/rex/RexWindow.java | 24 +++++-- .../org/polypheny/db/rex/RexWindowBound.java | 21 ++++++ 19 files changed, 168 insertions(+), 136 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java index ce5bd766c9..d8b03b0517 100644 --- a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java +++ b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java @@ -353,7 +353,7 @@ public AlgWriter explainTerms( AlgWriter pw ) { public void buildPolyAlgebra( StringBuilder sb ) { PolyAlgDeclaration decl = getPolyAlgDeclaration(); sb.append( decl.opName ); - sb.append( collectAttributes().serializeArguments() ); + sb.append( collectAttributes().serializeArguments( this ) ); int size = getInputs().size(); if ( size == 0 ) { diff --git a/core/src/main/java/org/polypheny/db/algebra/core/AggregateCall.java b/core/src/main/java/org/polypheny/db/algebra/core/AggregateCall.java index add0896e10..9253adc4e9 100644 --- a/core/src/main/java/org/polypheny/db/algebra/core/AggregateCall.java +++ b/core/src/main/java/org/polypheny/db/algebra/core/AggregateCall.java @@ -215,6 +215,18 @@ public AggregateCall rename( String name ) { public String toString() { + return toString( null ); + } + + + /** + * If fieldNames is null, args are serialized to "$" + arg. + * Otherwise, the value in fieldNames at index arg is used. + * + * @param fieldNames list containing the field names referenced by argList. + * @return string representation of this instance. + */ + public String toString( List fieldNames ) { StringBuilder buf = new StringBuilder( aggFunction.toString() ); buf.append( "(" ); if ( distinct ) { @@ -225,8 +237,12 @@ public String toString() { if ( ++i > 0 ) { buf.append( ", " ); } - buf.append( "$" ); - buf.append( arg ); + if ( fieldNames == null ) { + buf.append( "$" ); + buf.append( arg ); + } else { + buf.append( fieldNames.get( arg ) ); + } } buf.append( ")" ); if ( !collation.equals( AlgCollations.EMPTY ) ) { diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalCalc.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalCalc.java index 42df0a4313..3bdace4a6e 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalCalc.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalCalc.java @@ -117,12 +117,12 @@ public void collectVariablesUsed( Set variableSet ) { @Override public PolyAlgArgs collectAttributes() { PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); - PolyAlgArg expsArg = new ListArg<>( program.getExprList(), RexArg::new, this ); - PolyAlgArg projectsArg = new ListArg<>( program.getProjectList(), RexArg::new, rowType.getFieldNames(), this ); + PolyAlgArg expsArg = new ListArg<>( program.getExprList(), RexArg::new ); + PolyAlgArg projectsArg = new ListArg<>( program.getProjectList(), RexArg::new, rowType.getFieldNames() ); args.put( 0, expsArg ); args.put( 1, projectsArg ); - args.put( "condition", new RexArg( program.getCondition(), this ) ); + args.put( "condition", new RexArg( program.getCondition() ) ); return args; } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java index 30b1f8d69a..0b3d6e66b1 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java @@ -120,17 +120,15 @@ public AlgNode accept( AlgShuttle shuttle ) { public PolyAlgArgs collectAttributes() { PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); - PolyAlgArg groupArg = new ListArg<>( groupSet.asList(), f -> new FieldArg( f, this ), args.getDecl().canUnpackValues() ); - PolyAlgArg aggsArg = new ListArg<>( aggCalls, a -> new AggArg( a, this ) ); + PolyAlgArg groupArg = new ListArg<>( groupSet.asList(), FieldArg::new, args.getDecl().canUnpackValues() ); + PolyAlgArg aggsArg = new ListArg<>( aggCalls, AggArg::new ); args.put( 0, groupArg ); args.put( "aggs", aggsArg ); if ( getGroupType() != Group.SIMPLE ) { PolyAlgArg groupSetArg = new ListArg<>( groupSets, - set -> new ListArg( - set.asList(), - f -> new FieldArg( f, this ) ) ); + set -> new ListArg<>( set.asList(), FieldArg::new ) ); args.put( "groups", groupSetArg ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java index c00de25e9e..3798c63159 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java @@ -48,9 +48,6 @@ import org.polypheny.db.algebra.metadata.AlgMdCollation; import org.polypheny.db.algebra.metadata.AlgMdDistribution; import org.polypheny.db.algebra.metadata.AlgMetadataQuery; -import org.polypheny.db.algebra.polyalg.arguments.AnyArg; -import org.polypheny.db.algebra.polyalg.arguments.ListArg; -import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.algebra.polyalg.arguments.RexArg; import org.polypheny.db.plan.AlgCluster; @@ -130,7 +127,7 @@ public AlgWriter explainTerms( AlgWriter pw ) { public PolyAlgArgs collectAttributes() { PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); - args.put( 0, new RexArg( condition, this ) ); + args.put( 0, new RexArg( condition ) ); return args; } diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java index f74751d0c6..3ef2a9f0a3 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java @@ -46,12 +46,8 @@ import org.polypheny.db.algebra.core.JoinAlgType; import org.polypheny.db.algebra.core.relational.RelAlg; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; -import org.polypheny.db.algebra.polyalg.arguments.AnyArg; import org.polypheny.db.algebra.polyalg.arguments.BooleanArg; -import org.polypheny.db.algebra.polyalg.arguments.CorrelationArg; import org.polypheny.db.algebra.polyalg.arguments.EnumArg; -import org.polypheny.db.algebra.polyalg.arguments.ListArg; -import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.algebra.polyalg.arguments.RexArg; import org.polypheny.db.algebra.type.AlgDataTypeField; @@ -169,7 +165,7 @@ public List getSystemFieldList() { public PolyAlgArgs collectAttributes() { PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); - args.put( 0, new RexArg( condition, this ) ) + args.put( 0, new RexArg( condition ) ) .put( "type", new EnumArg<>( joinType, ParamType.JOIN_TYPE_ENUM ) ) .put( "semiJoinDone", new BooleanArg( semiJoinDone ) ); return args; diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java index 8c94b07143..79c157daa5 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java @@ -132,7 +132,7 @@ public AlgNode accept( AlgShuttle shuttle ) { @Override public PolyAlgArgs collectAttributes() { PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); - PolyAlgArg projectsArg = new ListArg<>( exps, e -> new RexArg( e, this ), rowType.getFieldNames(), args.getDecl().canUnpackValues() ); + PolyAlgArg projectsArg = new ListArg<>( exps, RexArg::new, rowType.getFieldNames(), args.getDecl().canUnpackValues() ); args.put( 0, projectsArg ); return args; diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java index 97626e3252..58fa2aa9c5 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java @@ -40,42 +40,6 @@ public class PolyAlgUtils { - /** - * Replaces all occurrences of '$' followed by some number corresponding to a field in the inputs of alg - * with the name of that field. - * - * @param alg the AlgNode whose inputs contain the field names - * @param str String whose occurrences of '$' + field number should be replaced - * @return str with field numbers replaced with their names. - */ - public static String replaceWithFieldNames( AlgNode alg, String str ) { - if ( str.contains( "$" ) ) { - int offset = 0; - for ( AlgNode input : alg.getInputs() ) { - offset += input.getTupleType().getFields().size(); - } - // iterate in reverse order to make sure "$13" is replaced before $1 - for ( int i = alg.getInputs().size() - 1; i >= 0; i-- ) { - AlgNode input = alg.getInputs().get( i ); - List fields = input.getTupleType().getFields(); - offset -= fields.size(); - for ( int j = fields.size() - 1; j >= 0; j-- ) { - AlgDataTypeField field = fields.get( j ); - String searchStr = "$" + (offset + field.getIndex()); - int position = str.indexOf( searchStr ); - int nextCharPosition = position + searchStr.length(); - if ( nextCharPosition < str.length() && Character.isDigit( str.charAt( nextCharPosition ) ) ) { - continue; - } - if ( position >= 0 && str.length() >= position + searchStr.length() ) { - str = str.replace( searchStr, field.getName() ); - } - } - } - } - return str; - } - public static String getFieldNameFromIndex( AlgNode alg, int idx ) { for ( AlgNode input : alg.getInputs() ) { @@ -89,18 +53,11 @@ public static String getFieldNameFromIndex( AlgNode alg, int idx ) { } - public static List replaceWithFieldNames( AlgNode alg, List exps ) { - return exps.stream() - .map( exp -> replaceWithFieldNames( alg, exp.toString() ) ) - .toList(); - } - - public static String appendAlias( String exp, String alias ) { - if ( !alias.equals( exp ) ) { - exp += " AS " + alias; + if ( alias == null || alias.equals( exp ) ) { + return exp; } - return exp; + return exp + " AS " + alias; } @@ -137,12 +94,19 @@ public static String joinMultiValued( List values, boolean omitBrackets } - public static String digestWithNames( RexNode expr, AlgNode context ) { - List fieldNames = context.getInputs().stream() + public static List getFieldNames( AlgNode context ) { + if ( context == null ) { + return List.of(); + } + return context.getInputs().stream() .flatMap( node -> node.getTupleType().getFields().stream() ) .map( AlgDataTypeField::getName ) .toList(); - return expr.accept( new NameReplacer( fieldNames ) ); + } + + + public static String digestWithNames( RexNode expr, AlgNode context ) { + return expr.accept( new NameReplacer( getFieldNames( context ) ) ); } @@ -182,7 +146,7 @@ public String visitCall( RexCall call ) { @Override public String visitOver( RexOver over ) { - return "over: " + over; + return over.toString( this ); } @@ -212,6 +176,10 @@ public String visitFieldAccess( RexFieldAccess fieldAccess ) { @Override public String visitSubQuery( RexSubQuery subQuery ) { + /* TODO: handling subquery when constructing PolyAlg representation + in method computeDigest( boolean withType, RexVisitor visitor ), + sb.append( AlgOptUtil.toString( alg ) ); + */ return "subQuery: " + subQuery; } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java index 52253067b0..52878fc69d 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java @@ -17,6 +17,7 @@ package org.polypheny.db.algebra.polyalg.arguments; import org.polypheny.db.algebra.AlgNode; +import org.polypheny.db.algebra.core.Aggregate; import org.polypheny.db.algebra.core.AggregateCall; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; import org.polypheny.db.algebra.polyalg.PolyAlgUtils; @@ -24,17 +25,10 @@ public class AggArg implements PolyAlgArg { private final AggregateCall agg; - private final AlgNode algNode; public AggArg( AggregateCall agg ) { - this( agg, null ); - } - - - public AggArg( AggregateCall agg, AlgNode fieldNameProvider ) { this.agg = agg; - this.algNode = fieldNameProvider; } @@ -46,11 +40,24 @@ public ParamType getType() { @Override public String toPolyAlg() { - String str = agg.toString(); - if ( algNode != null ) { - str = PolyAlgUtils.replaceWithFieldNames( algNode, str ); + return toPolyAlg( null ); + } + + + @Override + public String toPolyAlg( AlgNode context ) { + String str = agg.toString( PolyAlgUtils.getFieldNames( context ) ); + String name = agg.getName(); + if ( name == null ) { + // TODO: make sure agg.getName() is never null + Aggregate instance = (Aggregate) context; + int i = instance.getAggCallList().indexOf( agg ); + if ( i != -1 ) { + i += instance.getGroupSet().asList().size(); + } + name = "$f" + i; } - return PolyAlgUtils.appendAlias( str, agg.getName() ); + return PolyAlgUtils.appendAlias( str, name ); } } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java index deb1878dd5..214615c57b 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java @@ -23,11 +23,9 @@ public class FieldArg implements PolyAlgArg { private final int field; - private final AlgNode algNode; - public FieldArg( int field, AlgNode fieldNameProvider ) { + public FieldArg( int field ) { this.field = field; - this.algNode = fieldNameProvider; } @Override @@ -38,8 +36,14 @@ public ParamType getType() { @Override public String toPolyAlg() { - if ( algNode != null ) { - return PolyAlgUtils.getFieldNameFromIndex( algNode, field ); + return toPolyAlg(null); + } + + + @Override + public String toPolyAlg( AlgNode context ) { + if ( context != null ) { + return PolyAlgUtils.getFieldNameFromIndex( context, field ); } return Integer.toString( field ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java index ce3bd322da..b2798b5658 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java @@ -26,50 +26,33 @@ public class ListArg implements PolyAlgArg { private final List args; private final List aliases; - private final AlgNode algNode; private final boolean unpackValues; - public ListArg( List args, List aliases, AlgNode fieldNameProvider, boolean unpackValues ) { + public ListArg( List args, List aliases, boolean unpackValues ) { this.args = args; this.aliases = aliases; - this.algNode = fieldNameProvider; this.unpackValues = unpackValues; } public ListArg( List rawArgs, Function converter ) { - this( rawArgs, converter, null, null, false ); + this( rawArgs, converter, null, false ); } public ListArg( List rawArgs, Function converter, boolean unpackValues ) { - this( rawArgs, converter, null, null, unpackValues ); + this( rawArgs, converter, null, unpackValues ); } - public ListArg( List rawArgs, Function converter, AlgNode fieldNameProvider ) { - this( rawArgs, converter, null, fieldNameProvider, false ); - } - - - public ListArg( List rawArgs, Function converter, AlgNode fieldNameProvider, boolean unpackValues ) { - this( rawArgs, converter, null, fieldNameProvider, unpackValues ); + public ListArg( List rawArgs, Function converter, List aliases ) { + this( rawArgs.stream().map( converter ).toList(), aliases, false ); } public ListArg( List rawArgs, Function converter, List aliases, boolean unpackValues ) { - this( rawArgs, converter, aliases, null, unpackValues ); - } - - - public ListArg( List rawArgs, Function converter, List aliases, AlgNode fieldNameProvider ) { - this( rawArgs.stream().map( converter ).toList(), aliases, fieldNameProvider, false ); - } - - - public ListArg( List rawArgs, Function converter, List aliases, AlgNode fieldNameProvider, boolean unpackValues ) { - this( rawArgs.stream().map( converter ).toList(), aliases, fieldNameProvider, unpackValues ); + this( rawArgs.stream().map( converter ).toList(), aliases, unpackValues ); } @@ -84,10 +67,14 @@ public ParamType getType() { @Override public String toPolyAlg() { - List strArgs = args.stream().map( PolyAlgArg::toPolyAlg ).toList(); - if ( algNode != null ) { - strArgs = PolyAlgUtils.replaceWithFieldNames( algNode, strArgs ); - } + return toPolyAlg( null ); + } + + + @Override + public String toPolyAlg( AlgNode context ) { + List strArgs = args.stream().map( a -> a.toPolyAlg( context ) ).toList(); + if ( aliases != null ) { strArgs = PolyAlgUtils.appendAliases( strArgs, aliases ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArg.java index 01b0d93067..2e8c8e3b41 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArg.java @@ -16,6 +16,7 @@ package org.polypheny.db.algebra.polyalg.arguments; +import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; public interface PolyAlgArg { @@ -24,4 +25,8 @@ public interface PolyAlgArg { String toPolyAlg(); + default String toPolyAlg( AlgNode context ) { + return toPolyAlg(); + } + } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java index 6b26033694..26867507ce 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java @@ -20,8 +20,10 @@ import java.util.Map; import java.util.StringJoiner; import lombok.Getter; +import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; +import org.polypheny.db.algebra.polyalg.PolyAlgUtils; /** * Represents the parameters with corresponding values (PolyAlgArg) for an AlgNode instance. @@ -39,18 +41,19 @@ public PolyAlgArgs( PolyAlgDeclaration declaration ) { } - public String serializeArguments() { + public String serializeArguments( AlgNode context ) { + System.out.println( "\t" + decl.opName + ": " + PolyAlgUtils.getFieldNames( context ) ); StringJoiner joiner = new StringJoiner( ", ", "[", "]" ); for ( Parameter p : decl.posParams ) { assert args.containsKey( p ); PolyAlgArg arg = getArg( p ); - joiner.add( arg.toPolyAlg() ); + joiner.add( arg.toPolyAlg( context ) ); } for ( Parameter p : decl.kwParams ) { if ( args.containsKey( p ) ) { PolyAlgArg arg = getArg( p ); - String value = arg.toPolyAlg(); + String value = arg.toPolyAlg( context ); if ( !p.defaultValue().equals( value ) ) { joiner.add( p.name() + "=" + value ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java index 81183c4592..4cbde2c5b4 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java @@ -17,7 +17,6 @@ package org.polypheny.db.algebra.polyalg.arguments; import org.polypheny.db.algebra.AlgNode; -import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; import org.polypheny.db.algebra.polyalg.PolyAlgUtils; import org.polypheny.db.rex.RexNode; @@ -25,17 +24,10 @@ public class RexArg implements PolyAlgArg { private final RexNode node; - private final AlgNode algNode; public RexArg( RexNode node ) { - this( node, null ); - } - - - public RexArg( RexNode node, AlgNode fieldNameProvider ) { this.node = node; - this.algNode = fieldNameProvider; } @@ -47,11 +39,17 @@ public ParamType getType() { @Override public String toPolyAlg() { + return toPolyAlg( null ); + } + + + @Override + public String toPolyAlg( AlgNode context ) { String str = node == null ? "" : node.toString(); - if ( algNode == null ) { + if ( context == null || node == null ) { return str; } - return PolyAlgUtils.replaceWithFieldNames( algNode, str ) + " { " + PolyAlgUtils.digestWithNames( node, algNode ) + " } "; + return PolyAlgUtils.digestWithNames( node, context ); } } diff --git a/core/src/main/java/org/polypheny/db/rex/RexFieldCollation.java b/core/src/main/java/org/polypheny/db/rex/RexFieldCollation.java index dc0ffe1f29..fbadf6de47 100644 --- a/core/src/main/java/org/polypheny/db/rex/RexFieldCollation.java +++ b/core/src/main/java/org/polypheny/db/rex/RexFieldCollation.java @@ -71,7 +71,12 @@ public RexFieldCollation( RexNode left, Set right ) { @Override public String toString() { - final String s = left.toString(); + return toString( null ); + } + + + public String toString( RexVisitor visitor ) { + final String s = visitor == null ? left.toString() : left.accept( visitor ); if ( right.isEmpty() ) { return s; } diff --git a/core/src/main/java/org/polypheny/db/rex/RexOver.java b/core/src/main/java/org/polypheny/db/rex/RexOver.java index 721969ae6d..d7a912a996 100644 --- a/core/src/main/java/org/polypheny/db/rex/RexOver.java +++ b/core/src/main/java/org/polypheny/db/rex/RexOver.java @@ -102,19 +102,25 @@ public boolean isDistinct() { @Override protected @Nonnull String computeDigest( boolean withType ) { + return computeDigest( withType, null ); + } + + + @Override + protected @Nonnull String computeDigest( boolean withType, RexVisitor visitor ) { final StringBuilder sb = new StringBuilder( op.getName() ); sb.append( "(" ); if ( distinct ) { sb.append( "DISTINCT " ); } - appendOperands( sb ); + appendOperands( sb, visitor ); sb.append( ")" ); if ( withType ) { sb.append( ":" ); sb.append( type.getFullTypeString() ); } sb.append( " OVER (" ) - .append( window ) + .append( window.toString( visitor ) ) .append( ")" ); return sb.toString(); } diff --git a/core/src/main/java/org/polypheny/db/rex/RexSubQuery.java b/core/src/main/java/org/polypheny/db/rex/RexSubQuery.java index 8c37a5e11e..174d63dbcd 100644 --- a/core/src/main/java/org/polypheny/db/rex/RexSubQuery.java +++ b/core/src/main/java/org/polypheny/db/rex/RexSubQuery.java @@ -142,10 +142,17 @@ public R accept( RexBiVisitor visitor, P arg ) { @Override protected @Nonnull String computeDigest( boolean withType ) { + return computeDigest( withType, null ); + } + + + @Override + protected @Nonnull + String computeDigest( boolean withType, RexVisitor visitor ) { final StringBuilder sb = new StringBuilder( op.getName() ); sb.append( "(" ); for ( RexNode operand : operands ) { - sb.append( operand ); + sb.append( visitor == null ? operand : operand.accept( visitor ) ); sb.append( ", " ); } sb.append( "{\n" ); diff --git a/core/src/main/java/org/polypheny/db/rex/RexWindow.java b/core/src/main/java/org/polypheny/db/rex/RexWindow.java index 01715b0a2a..88a5103be3 100644 --- a/core/src/main/java/org/polypheny/db/rex/RexWindow.java +++ b/core/src/main/java/org/polypheny/db/rex/RexWindow.java @@ -77,6 +77,14 @@ public String toString() { } + public String toString( RexVisitor visitor ) { + if ( visitor == null ) { + return toString(); + } + return computeDigest( visitor ); + } + + public int hashCode() { return digest.hashCode(); } @@ -92,6 +100,11 @@ public boolean equals( Object that ) { private String computeDigest() { + return computeDigest( null ); + } + + + private String computeDigest( RexVisitor visitor ) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter( sw ); int clauseCount = 0; @@ -105,7 +118,7 @@ private String computeDigest() { pw.print( ", " ); } RexNode partitionKey = partitionKeys.get( i ); - pw.print( partitionKey.toString() ); + pw.print( visitor == null ? partitionKey.toString() : partitionKey.accept( visitor ) ); } } if ( orderKeys.size() > 0 ) { @@ -118,7 +131,7 @@ private String computeDigest() { pw.print( ", " ); } RexFieldCollation orderKey = orderKeys.get( i ); - pw.print( orderKey.toString() ); + pw.print( orderKey.toString( visitor ) ); } } if ( lowerBound == null ) { @@ -132,7 +145,7 @@ private String computeDigest() { } else { pw.print( "RANGE " ); } - pw.print( lowerBound.toString() ); + pw.print( lowerBound.toString( visitor ) ); } else { if ( clauseCount++ > 0 ) { pw.print( ' ' ); @@ -142,9 +155,9 @@ private String computeDigest() { } else { pw.print( "RANGE BETWEEN " ); } - pw.print( lowerBound.toString() ); + pw.print( lowerBound.toString( visitor ) ); pw.print( " AND " ); - pw.print( upperBound.toString() ); + pw.print( upperBound.toString( visitor ) ); } return sw.toString(); } @@ -163,5 +176,6 @@ public RexWindowBound getUpperBound() { public boolean isRows() { return isRows; } + } diff --git a/core/src/main/java/org/polypheny/db/rex/RexWindowBound.java b/core/src/main/java/org/polypheny/db/rex/RexWindowBound.java index c7f0a2c5c7..f68d27980d 100644 --- a/core/src/main/java/org/polypheny/db/rex/RexWindowBound.java +++ b/core/src/main/java/org/polypheny/db/rex/RexWindowBound.java @@ -136,6 +136,18 @@ public RexWindowBound accept( RexVisitor visitor ) { } + /** + * Returns a string representation of the bound using the given visitor to transform + * any RexNode in the process to a string. + * + * @param visitor the RexVisitor used to transform RexNodes into strings + * @return String representation of this bound + */ + public String toString( RexVisitor visitor ) { + return toString(); + } + + /** * Implements UNBOUNDED PRECEDING/FOLLOWING bound. */ @@ -301,6 +313,15 @@ public String toString() { } + @Override + public String toString( RexVisitor visitor ) { + if ( visitor == null ) { + return toString(); + } + return offset.accept( visitor ) + " " + kind.toString(); + } + + @Override public boolean equals( Object o ) { if ( this == o ) { From 3f9d4d766268b70e2c782e4d5e71805ca049ba68 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Fri, 22 Mar 2024 18:40:11 +0100 Subject: [PATCH 011/132] Introduce virtual projects when necessary --- .../polypheny/db/algebra/AbstractAlgNode.java | 24 ++++++++++++++++++- .../relational/LogicalRelAggregate.java | 2 +- .../logical/relational/LogicalRelJoin.java | 2 +- .../db/algebra/polyalg/PolyAlgRegistry.java | 10 ++++---- .../db/algebra/polyalg/PolyAlgUtils.java | 20 ++++++++++++++++ .../algebra/polyalg/arguments/BooleanArg.java | 2 +- .../polyalg/arguments/PolyAlgArgs.java | 1 - .../db/algebra/polyalg/arguments/RexArg.java | 9 +++++++ 8 files changed, 60 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java index d8b03b0517..d91f4da2d5 100644 --- a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java +++ b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java @@ -40,22 +40,29 @@ import java.io.StringWriter; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import lombok.Getter; import lombok.Setter; import lombok.experimental.SuperBuilder; +import org.checkerframework.checker.units.qual.A; import org.polypheny.db.algebra.constant.ExplainLevel; import org.polypheny.db.algebra.core.CorrelationId; import org.polypheny.db.algebra.externalize.AlgWriterImpl; +import org.polypheny.db.algebra.logical.relational.LogicalRelProject; import org.polypheny.db.algebra.metadata.AlgMetadataQuery; import org.polypheny.db.algebra.metadata.Metadata; import org.polypheny.db.algebra.metadata.MetadataFactory; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; import org.polypheny.db.algebra.polyalg.PolyAlgRegistry; +import org.polypheny.db.algebra.polyalg.PolyAlgUtils; import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.algebra.type.AlgDataType; +import org.polypheny.db.algebra.type.AlgDataTypeField; import org.polypheny.db.catalog.entity.Entity; import org.polypheny.db.plan.AlgCluster; import org.polypheny.db.plan.AlgOptCost; @@ -361,8 +368,23 @@ public void buildPolyAlgebra( StringBuilder sb ) { } sb.append( "(\n" ); + Set fieldNames = new HashSet<>(); for ( AlgNode child : getInputs() ) { - child.buildPolyAlgebra( sb ); + + List projections = PolyAlgUtils.getAuxProjections( child, fieldNames ); + + StringBuilder csb = new StringBuilder(); + if ( projections.isEmpty() ) { + child.buildPolyAlgebra( csb ); + } else { + csb.append( PolyAlgRegistry.getDeclaration( LogicalRelProject.class ).opName ) + .append( "*[" ) + .append( PolyAlgUtils.joinMultiValued( projections, true ) ) + .append( "](\n" ); + child.buildPolyAlgebra( csb ); + csb.append( ")" ); + } + sb.append( csb ); size--; if ( size > 0 ) { diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java index 0b3d6e66b1..621ef75dce 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelAggregate.java @@ -123,7 +123,7 @@ public PolyAlgArgs collectAttributes() { PolyAlgArg groupArg = new ListArg<>( groupSet.asList(), FieldArg::new, args.getDecl().canUnpackValues() ); PolyAlgArg aggsArg = new ListArg<>( aggCalls, AggArg::new ); - args.put( 0, groupArg ); + args.put( "group", groupArg ); args.put( "aggs", aggsArg ); if ( getGroupType() != Group.SIMPLE ) { PolyAlgArg groupSetArg = new ListArg<>( diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java index 3ef2a9f0a3..c6e1ef943c 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java @@ -165,7 +165,7 @@ public List getSystemFieldList() { public PolyAlgArgs collectAttributes() { PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); - args.put( 0, new RexArg( condition ) ) + args.put( 0, new RexArg( condition, true ) ) .put( "type", new EnumArg<>( joinType, ParamType.JOIN_TYPE_ENUM ) ) .put( "semiJoinDone", new BooleanArg( semiJoinDone ) ); return args; diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java index a928971764..950c12790a 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java @@ -60,24 +60,24 @@ private static void populateDeclarationsMap() { declarations.put( LogicalRelAggregate.class, PolyAlgDeclaration.builder() .opName( "AGG" ).numInputs( 1 ).opTags( logRelTags ) - .param( Parameter.builder().name( "group" ).type( ParamType.FIELD ).isMultiValued( true ).build() ) + .param( Parameter.builder().name( "group" ).type( ParamType.FIELD ).isMultiValued( true ).defaultValue( "" ).build() ) // select count(*) has no group .param( Parameter.builder().name( "groups" ).type( ParamType.ANY ).isMultiValued( true ).defaultValue( "" ).build() ) .param( Parameter.builder().name( "aggs" ).type( ParamType.AGGREGATE ).isMultiValued( true ).defaultValue( "" ).build() ) .build() ); declarations.put( LogicalRelMinus.class, PolyAlgDeclaration.builder() .opName( "MINUS" ).numInputs( 2 ).opTags( logRelTags ) - .param( Parameter.builder().name( "all" ).type( ParamType.BOOLEAN ).defaultValue( "FALSE" ).build() ) + .param( Parameter.builder().name( "all" ).type( ParamType.BOOLEAN ).defaultValue( "false" ).build() ) .build() ); declarations.put( LogicalRelUnion.class, PolyAlgDeclaration.builder() .opName( "UNION" ).numInputs( 2 ).opTags( logRelTags ) - .param( Parameter.builder().name( "all" ).type( ParamType.BOOLEAN ).defaultValue( "FALSE" ).build() ) + .param( Parameter.builder().name( "all" ).type( ParamType.BOOLEAN ).defaultValue( "false" ).build() ) .build() ); declarations.put( LogicalRelIntersect.class, PolyAlgDeclaration.builder() .opName( "INTERSECT" ).numInputs( 2 ).opTags( logRelTags ) - .param( Parameter.builder().name( "all" ).type( ParamType.BOOLEAN ).defaultValue( "FALSE" ).build() ) + .param( Parameter.builder().name( "all" ).type( ParamType.BOOLEAN ).defaultValue( "false" ).build() ) .build() ); declarations.put( LogicalRelSort.class, PolyAlgDeclaration.builder() @@ -91,7 +91,7 @@ private static void populateDeclarationsMap() { .opName( "JOIN" ).numInputs( 2 ).opTags( logRelTags ) .param( Parameter.builder().name( "condition" ).type( ParamType.SIMPLE_REX ).build() ) .param( Parameter.builder().name( "type" ).type( ParamType.JOIN_TYPE_ENUM ).defaultValue( JoinAlgType.INNER.name() ).build() ) - .param( Parameter.builder().name( "semiJoinDone" ).type( ParamType.BOOLEAN ).defaultValue( "FALSE" ).build() ) + .param( Parameter.builder().name( "semiJoinDone" ).type( ParamType.BOOLEAN ).defaultValue( "false" ).build() ) .build() ); declarations.put( LogicalCalc.class, PolyAlgDeclaration.builder() diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java index 58fa2aa9c5..da75958d7e 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Set; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.type.AlgDataTypeField; import org.polypheny.db.rex.RexCall; @@ -94,6 +95,25 @@ public static String joinMultiValued( List values, boolean omitBrackets } + public static List getAuxProjections( AlgNode child, Set fieldNames) { + List projections = new ArrayList<>(); + for ( AlgDataTypeField field : child.getTupleType().getFields() ) { + String name = field.getName(); + if ( fieldNames.contains( name ) ) { + int i = 0; + String prefix = name; + do { + name = prefix + i; + i++; + } while ( fieldNames.contains( name ) ); + projections.add( prefix + " AS " + name ); + } + fieldNames.add( name ); + } + return projections; + } + + public static List getFieldNames( AlgNode context ) { if ( context == null ) { return List.of(); diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/BooleanArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/BooleanArg.java index 1e84790255..c7c9c6a165 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/BooleanArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/BooleanArg.java @@ -36,7 +36,7 @@ public ParamType getType() { @Override public String toPolyAlg() { - return Boolean.toString( arg ).toUpperCase(); + return Boolean.toString( arg ); } } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java index 26867507ce..2265a48f3a 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java @@ -42,7 +42,6 @@ public PolyAlgArgs( PolyAlgDeclaration declaration ) { public String serializeArguments( AlgNode context ) { - System.out.println( "\t" + decl.opName + ": " + PolyAlgUtils.getFieldNames( context ) ); StringJoiner joiner = new StringJoiner( ", ", "[", "]" ); for ( Parameter p : decl.posParams ) { diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java index 4cbde2c5b4..486e3966c1 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java @@ -24,12 +24,18 @@ public class RexArg implements PolyAlgArg { private final RexNode node; + private boolean omitTrue = false; public RexArg( RexNode node ) { this.node = node; } + public RexArg( RexNode node, boolean omitTrue ) { + this(node); + this.omitTrue = omitTrue; + } + @Override public ParamType getType() { @@ -46,6 +52,9 @@ public String toPolyAlg() { @Override public String toPolyAlg( AlgNode context ) { String str = node == null ? "" : node.toString(); + if (omitTrue && str.equals( "true" )) { + return ""; + } if ( context == null || node == null ) { return str; } From 38c9a5896077d447b87d809e75935af8333fd605 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Mon, 25 Mar 2024 12:00:33 +0100 Subject: [PATCH 012/132] Fix javadoc generation error --- .../algebra/polyalg/PolyAlgDeclaration.java | 23 +++++++++++++------ .../polyalg/arguments/PolyAlgArgs.java | 7 +++--- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java index ce26e54188..142e4e185e 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java @@ -22,6 +22,7 @@ import java.util.Set; import java.util.stream.Collectors; import lombok.Builder; +import lombok.Data; import lombok.NonNull; import lombok.Singular; @@ -115,15 +116,23 @@ public boolean canUnpackValues() { *
  • Keyword arguments: Arguments are preceded by the name of the parameter. Keyword arguments can be omitted, in which case the defaultValue is used.
  • *
* - * @param name The name of this Parameter - * @param aliases List of alias names that can additionally be used to identify this parameter. - * @param tags List of ParameterTags associated with this Parameter - * @param type The type of this Parameter - * @param isMultiValued Boolean indicating whether an argument consisting of multiple values can be specified - * @param defaultValue The default value for this Parameter or null if it has no default value (if it should have a default value of null, use an empty string instead) + * The boolean isMultiValued indicates whether an argument can consist of a list of values of the specified type. */ @Builder - public record Parameter(@NonNull String name, @Singular ImmutableList aliases, @Singular ImmutableList tags, @NonNull ParamType type, boolean isMultiValued, String defaultValue) { + @Data + public static class Parameter { + + @NonNull + private final String name; + @Singular + private final ImmutableList aliases; + @Singular + private final ImmutableList tags; + @NonNull + private final ParamType type; + private final boolean isMultiValued; + private final String defaultValue; + public boolean isPositional() { return defaultValue == null; diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java index 2265a48f3a..135b63f9a4 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java @@ -23,7 +23,6 @@ import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.Parameter; -import org.polypheny.db.algebra.polyalg.PolyAlgUtils; /** * Represents the parameters with corresponding values (PolyAlgArg) for an AlgNode instance. @@ -53,8 +52,8 @@ public String serializeArguments( AlgNode context ) { if ( args.containsKey( p ) ) { PolyAlgArg arg = getArg( p ); String value = arg.toPolyAlg( context ); - if ( !p.defaultValue().equals( value ) ) { - joiner.add( p.name() + "=" + value ); + if ( !p.getDefaultValue().equals( value ) ) { + joiner.add( p.getName() + "=" + value ); } } } @@ -73,7 +72,7 @@ public PolyAlgArgs put( int pos, PolyAlgArg arg ) { private PolyAlgArgs put( Parameter p, PolyAlgArg arg ) { - assert p.type() == arg.getType(); + assert p.getType() == arg.getType(); args.put( p, arg ); return this; From b6bda1413565bd1c0453aab3d89f8bdc710323e2 Mon Sep 17 00:00:00 2001 From: datomo Date: Thu, 21 Mar 2024 11:29:20 +0100 Subject: [PATCH 013/132] removed unused fields from joins --- .../logical/relational/LogicalRelFilter.java | 2 ++ .../logical/relational/LogicalRelJoin.java | 31 +++++-------------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java index 3798c63159..0418e551df 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelFilter.java @@ -104,6 +104,7 @@ public static LogicalRelFilter create( final AlgNode input, RexNode condition, I } + @Override public LogicalRelFilter copy( AlgTraitSet traitSet, AlgNode input, RexNode condition ) { assert traitSet.containsIfApplicable( Convention.NONE ); @@ -132,3 +133,4 @@ public PolyAlgArgs collectAttributes() { } } + diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java index c6e1ef943c..837a0a52ce 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelJoin.java @@ -34,9 +34,6 @@ package org.polypheny.db.algebra.logical.relational; -import com.google.common.collect.ImmutableList; -import java.util.List; -import java.util.Objects; import java.util.Set; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.AlgShuttle; @@ -50,7 +47,6 @@ import org.polypheny.db.algebra.polyalg.arguments.EnumArg; import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; import org.polypheny.db.algebra.polyalg.arguments.RexArg; -import org.polypheny.db.algebra.type.AlgDataTypeField; import org.polypheny.db.plan.AlgCluster; import org.polypheny.db.plan.AlgTraitSet; import org.polypheny.db.plan.Convention; @@ -73,7 +69,6 @@ public final class LogicalRelJoin extends Join implements RelAlg { // NOTE jvs 14-Mar-2006: Normally we don't use state like this to control rule firing, but due to the non-local nature of semijoin optimizations, it's pretty much required. private final boolean semiJoinDone; - private final ImmutableList systemFieldList; /** @@ -89,29 +84,27 @@ public final class LogicalRelJoin extends Join implements RelAlg { * @param joinType Join type * @param variablesSet Set of variables that are set by the LHS and used by the RHS and are not available to nodes above this LogicalJoin in the tree * @param semiJoinDone Whether this join has been translated to a semi-join - * @param systemFieldList List of system fields that will be prefixed to output row type; typically empty but must not be null * @see #isSemiJoinDone() */ - public LogicalRelJoin( AlgCluster cluster, AlgTraitSet traitSet, AlgNode left, AlgNode right, RexNode condition, Set variablesSet, JoinAlgType joinType, boolean semiJoinDone, ImmutableList systemFieldList ) { + public LogicalRelJoin( AlgCluster cluster, AlgTraitSet traitSet, AlgNode left, AlgNode right, RexNode condition, Set variablesSet, JoinAlgType joinType, boolean semiJoinDone ) { super( cluster, traitSet.replace( ModelTrait.RELATIONAL ), left, right, condition, variablesSet, joinType ); this.semiJoinDone = semiJoinDone; - this.systemFieldList = Objects.requireNonNull( systemFieldList ); } /** * Creates a LogicalJoin, flagged with whether it has been translated to a semi-join. */ - public static LogicalRelJoin create( AlgNode left, AlgNode right, RexNode condition, Set variablesSet, JoinAlgType joinType, boolean semiJoinDone, ImmutableList systemFieldList ) { + public static LogicalRelJoin create( AlgNode left, AlgNode right, RexNode condition, Set variablesSet, JoinAlgType joinType, boolean semiJoinDone ) { final AlgCluster cluster = left.getCluster(); final AlgTraitSet traitSet = cluster.traitSetOf( Convention.NONE ); - return new LogicalRelJoin( cluster, traitSet, left, right, condition, variablesSet, joinType, semiJoinDone, systemFieldList ); + return new LogicalRelJoin( cluster, traitSet, left, right, condition, variablesSet, joinType, semiJoinDone ); } @Deprecated // to be removed before 2.0 - public static LogicalRelJoin create( AlgNode left, AlgNode right, RexNode condition, JoinAlgType joinType, Set variablesStopped, boolean semiJoinDone, ImmutableList systemFieldList ) { - return create( left, right, condition, CorrelationId.setOf( variablesStopped ), joinType, semiJoinDone, systemFieldList ); + public static LogicalRelJoin create( AlgNode left, AlgNode right, RexNode condition, JoinAlgType joinType, Set variablesStopped, boolean semiJoinDone ) { + return create( left, right, condition, CorrelationId.setOf( variablesStopped ), joinType, semiJoinDone ); } @@ -119,20 +112,20 @@ public static LogicalRelJoin create( AlgNode left, AlgNode right, RexNode condit * Creates a LogicalJoin. */ public static LogicalRelJoin create( AlgNode left, AlgNode right, RexNode condition, Set variablesSet, JoinAlgType joinType ) { - return create( left, right, condition, variablesSet, joinType, false, ImmutableList.of() ); + return create( left, right, condition, variablesSet, joinType, false ); } @Deprecated // to be removed before 2.0 public static LogicalRelJoin create( AlgNode left, AlgNode right, RexNode condition, JoinAlgType joinType, Set variablesStopped ) { - return create( left, right, condition, CorrelationId.setOf( variablesStopped ), joinType, false, ImmutableList.of() ); + return create( left, right, condition, CorrelationId.setOf( variablesStopped ), joinType, false ); } @Override public LogicalRelJoin copy( AlgTraitSet traitSet, RexNode conditionExpr, AlgNode left, AlgNode right, JoinAlgType joinType, boolean semiJoinDone ) { assert traitSet.containsIfApplicable( Convention.NONE ); - return new LogicalRelJoin( getCluster(), getCluster().traitSetOf( Convention.NONE ).replace( ModelTrait.RELATIONAL ), left, right, conditionExpr, variablesSet, joinType, semiJoinDone, systemFieldList ); + return new LogicalRelJoin( getCluster(), getCluster().traitSetOf( Convention.NONE ).replace( ModelTrait.RELATIONAL ), left, right, conditionExpr, variablesSet, joinType, semiJoinDone ); } @@ -154,13 +147,6 @@ public boolean isSemiJoinDone() { return semiJoinDone; } - - @Override - public List getSystemFieldList() { - return systemFieldList; - } - - @Override public PolyAlgArgs collectAttributes() { PolyAlgArgs args = new PolyAlgArgs( getPolyAlgDeclaration() ); @@ -170,6 +156,5 @@ public PolyAlgArgs collectAttributes() { .put( "semiJoinDone", new BooleanArg( semiJoinDone ) ); return args; } - } From 66338278026031c4cd5863dc5c7861e1529aea8f Mon Sep 17 00:00:00 2001 From: datomo Date: Thu, 21 Mar 2024 16:54:48 +0100 Subject: [PATCH 014/132] Fix type of entity param --- .../java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java index 950c12790a..3de9a1b8ae 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgRegistry.java @@ -50,7 +50,7 @@ private static void populateDeclarationsMap() { declarations.put( RelScan.class, PolyAlgDeclaration.builder() .opName( "SCAN" ).numInputs( 0 ).opTags( logRelTags ) - .param( Parameter.builder().name( "entity" ).type( ParamType.SIMPLE_REX ).build() ) + .param( Parameter.builder().name( "entity" ).type( ParamType.ENTITY ).build() ) .build() ); declarations.put( LogicalRelFilter.class, PolyAlgDeclaration.builder() From 328be2d7eacfaead9f40da155455feb633384e6b Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Tue, 26 Mar 2024 14:38:22 +0100 Subject: [PATCH 015/132] Add initial version of a PolyAlgParser --- core/build.gradle | 18 +- core/src/main/codegen/PolyAlgParser.jj | 193 ++++++++++++++++++ .../org/polypheny/db/plan/AlgOptUtil.java | 8 +- 3 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 core/src/main/codegen/PolyAlgParser.jj diff --git a/core/build.gradle b/core/build.gradle index 292b2be677..331a9e9d4d 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,3 +1,5 @@ +import org.javacc.plugin.gradle.javacc.CompileJavaccTask + buildscript { dependencies { // Protobuf @@ -5,6 +7,10 @@ buildscript { } } +plugins { + id "org.javacc.javacc" version "$javacc_plugin_version" +} + group "org.polypheny" @@ -63,6 +69,8 @@ dependencies { api group: "io.activej", name: "activej-serializer", version: activej_serializer_version + javacc group: "net.java.dev.javacc", name: "javacc", version: javacc_version // BSD 2-clause + // --- Test Compile --- testRuntimeOnly(group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: junit_jupiter_version) testImplementation group: "org.hamcrest", name: "hamcrest-core", version: hamcrest_core_version // BSD 3-clause @@ -75,11 +83,18 @@ protobuf { } } +tasks.register('generateParser', CompileJavaccTask) { + getConventionMapping().map("classpath", { configurations.javacc }) + arguments = [static: "false"] + inputDirectory = file("src/main/codegen") + outputDirectory = file(project.buildDir.absolutePath + "/generated-sources/org/polypheny/db/algebra/polyalg/parser") +} + sourceSets { main { java { - srcDirs = ["src/main/java", "build/generated/source/proto/main/java"] // "build/generated/sources/annotationProcessor" + srcDirs = ["src/main/java", "build/generated/source/proto/main/java", files("${buildDir}/generated-sources").builtBy(generateParser)] // "build/generated/sources/annotationProcessor" } resources { srcDirs = ["src/main/resources"] @@ -109,6 +124,7 @@ tasks.register('generateVersionProperties', Copy) { compileJava { dependsOn("generateVersionProperties") + dependsOn("generateParser") dependsOn(":config:processResources") dependsOn(":information:processResources") dependsOn("generateProto") diff --git a/core/src/main/codegen/PolyAlgParser.jj b/core/src/main/codegen/PolyAlgParser.jj new file mode 100644 index 0000000000..3fbdb21340 --- /dev/null +++ b/core/src/main/codegen/PolyAlgParser.jj @@ -0,0 +1,193 @@ + +options { + STATIC = false; + IGNORE_CASE = true; + UNICODE_INPUT = true; +} + +PARSER_BEGIN(PolyAlgParser) + +package org.polypheny.db.algebra.polyalg.parser; + +import java.io.StringReader; + +/** + * Parses Poly Algebra. + */ +public class PolyAlgParser { + + /** Main entry point. */ + public static void parse(String str) { + PolyAlgParser parser = new PolyAlgParser(new StringReader(str)); + + + try { + parser.Input(); + System.out.println("Successfully parsed input!"); + } catch (Exception e) { + System.out.println("Could not parse input correctly:"); + System.out.println(e.getMessage()); + e.printStackTrace(); + } + } + +} + +PARSER_END(PolyAlgParser) + +SKIP : +{ + " " +| "\t" +| "\n" +| "\r" +| "\f" +} + +TOKEN : +{ + +| +| +| +| +| +| +| +| | ) ( | | )+> +| )+ (".")? ()*> +| <#LETTER: ["_","a"-"z","A"-"Z","ö", "Ö", "ä", "Ä", "ü", "Ü", "à", "À", "ç","Ç", "á", "Á", "è", "È","í","Í", "î", "Î","ó","Ó","ò", "ô", "Ô", "Ò" , "í", "Í", "ë", "Ë", "â", "Â", "ï", "Ï", "é", "É", "ñ", "Ñ", "ß"] > +| <#DIGIT: ["0"-"9"]> +| <#IDENTIFIER_SYMBOL: ["#", "@", "$", "."]> +| +} + +/** Root production. */ +void Input() : +{} +{ + Operator() +} + + +void Operator() : +{} +{ + OpName() [Arguments()] [ [ChildOperators()] ] +} + +void ChildOperators() : +{} +{ + Operator() ( Operator())* +} + +void Arguments() : +{} +{ + NamedArgument() ( NamedArgument())* +} + +void NamedArgument() : +{} +{ + [LOOKAHEAD(2) ParamName() ] AliasedArgument() +} + + +void AliasedArgument() : +{} +{ + Argument() [ AliasName() ] +} + +void Argument() : +{} +{ + OuterExpression() + | + ListArgument() +} + +void ListArgument() : +{} +{ + AliasedArgument() ( AliasedArgument())* +} + +void OuterExpression() : +{} +{ + ( + InnerExpression() + | + InnerExpression() + | + Literal() + ) [OuterExpression()] // outer expressions cannot contain separators, as they could not always be differentiated from a ListArgument +} + +void InnerExpression() : // An expression which appears within parentheses +{} +{ + ( + InnerExpression() + | + InnerExpression() + | + Literal() + | + // inner expressions can contain , since we know it cannot be an alias for an argument + ) ()* [InnerExpression()] // inner expressions can contain separators! +} + +void Literal() : +{} +{ + + | + + | + + | + + | + +} + +void OpName() : +{} +{ + + | + +} + +void AliasName() : +{} +{ + OpName() +} + +void ParamName() : +{} +{ + OpName() +} \ No newline at end of file diff --git a/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java b/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java index d6b38a0706..d8f3e4fd58 100644 --- a/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java +++ b/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java @@ -84,6 +84,7 @@ import org.polypheny.db.algebra.logical.relational.LogicalRelProject; import org.polypheny.db.algebra.metadata.AlgMetadataQuery; import org.polypheny.db.algebra.operators.OperatorName; +import org.polypheny.db.algebra.polyalg.parser.PolyAlgParser; import org.polypheny.db.algebra.rules.AggregateProjectPullUpConstantsRule; import org.polypheny.db.algebra.rules.DateRangeRules; import org.polypheny.db.algebra.rules.FilterMergeRule; @@ -1363,11 +1364,12 @@ public static String dumpPlan( String header, AlgNode alg, ExplainFormat format, //TODO: Delete lines for testing PolyAlg serialization StringBuilder sb = new StringBuilder(); alg.buildPolyAlgebra( sb ); - System.out.println(header); - System.out.println(sb); + System.out.println( "===== " + header + " =====" ); + System.out.println( sb ); + System.out.print( "----> " ); + PolyAlgParser.parse( sb.toString() ); System.out.println(); - StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter( sw ); if ( !header.isEmpty() ) { From e6c72b761da54de309d17f079e93370d1e1bccb6 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Tue, 26 Mar 2024 15:20:35 +0100 Subject: [PATCH 016/132] Add mechanism to create AlgNode instances from PolyAlgArgs --- .../org/polypheny/db/algebra/AlgNode.java | 24 ++++++++++++++++++- .../logical/relational/LogicalRelProject.java | 9 +++++++ .../db/algebra/polyalg/arguments/ListArg.java | 3 +++ .../db/algebra/polyalg/arguments/RexArg.java | 7 ++++-- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/AlgNode.java b/core/src/main/java/org/polypheny/db/algebra/AlgNode.java index ca0ff73fa5..da09c8110c 100644 --- a/core/src/main/java/org/polypheny/db/algebra/AlgNode.java +++ b/core/src/main/java/org/polypheny/db/algebra/AlgNode.java @@ -34,6 +34,8 @@ package org.polypheny.db.algebra; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.List; import java.util.Objects; import java.util.Set; @@ -248,7 +250,7 @@ public interface AlgNode extends AlgOptNode, Cloneable { /** * Retrieves the PolyAlgDeclaration for this AlgNode implementation. - * This method should be static. + * This declaration is read only and can thus be a static object. * * @return PolyAlgDeclaration for this AlgNode implementation */ @@ -264,6 +266,26 @@ public interface AlgNode extends AlgOptNode, Cloneable { */ PolyAlgArgs collectAttributes(); + /** + * Creates an instance of {@code AlgNode} using reflection, based on the provided class, arguments, and children. + * Implementations of this interface should implement {@code public static AlgNode create(PolyAlgArgs args, List children)}. + * Otherwise, it will result in a NoSuchMethodException. + * + * @param clazz The class representing the implementation of {@code AlgNode}. + * @param args The arguments required for instantiation, whose {@code PolyAlgDeclaration} must correspond to the provided class. + * @param children The list of child nodes or an empty list if this node has no children + * @return A new instance of the provided class + * @throws RuntimeException If there is no method with the specified signature or an error occurred during instance creation + */ + static AlgNode create( Class clazz, PolyAlgArgs args, List children ) { + try { + Method method = clazz.getMethod( "create", PolyAlgArgs.class, List.class ); + return (AlgNode) method.invoke( null, args, children ); + } catch ( NoSuchMethodException | IllegalAccessException | InvocationTargetException e ) { + throw new RuntimeException( e ); + } + } + /** * Receives notification that this expression is about to be registered. The implementation of this method must at least register all child expressions. * diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java index 79c157daa5..2f2a7b6827 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelProject.java @@ -104,6 +104,15 @@ public static LogicalRelProject create( final AlgNode input, final List children) { + System.out.println("Creating AlgNode from LogicalRelProject"); + ListArg projects= args.getArg( 0, ListArg.class ); + + + return create( children.get( 0 ), projects.getArgs().stream().map( RexArg::getNode ).toList(), projects.getAliases() ); + } + + public static LogicalRelProject identity( final AlgNode input ) { return create( input, diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java index b2798b5658..f0c8d00da5 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java @@ -18,13 +18,16 @@ import java.util.List; import java.util.function.Function; +import lombok.Getter; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; import org.polypheny.db.algebra.polyalg.PolyAlgUtils; public class ListArg implements PolyAlgArg { + @Getter private final List args; + @Getter private final List aliases; private final boolean unpackValues; diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java index 486e3966c1..b10a3c017f 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java @@ -16,6 +16,7 @@ package org.polypheny.db.algebra.polyalg.arguments; +import lombok.Getter; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; import org.polypheny.db.algebra.polyalg.PolyAlgUtils; @@ -23,6 +24,7 @@ public class RexArg implements PolyAlgArg { + @Getter private final RexNode node; private boolean omitTrue = false; @@ -31,8 +33,9 @@ public RexArg( RexNode node ) { this.node = node; } + public RexArg( RexNode node, boolean omitTrue ) { - this(node); + this( node ); this.omitTrue = omitTrue; } @@ -52,7 +55,7 @@ public String toPolyAlg() { @Override public String toPolyAlg( AlgNode context ) { String str = node == null ? "" : node.toString(); - if (omitTrue && str.equals( "true" )) { + if ( omitTrue && str.equals( "true" ) ) { return ""; } if ( context == null || node == null ) { From 4690638f2e2df5287029eb80e50df3f21d0aee6c Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Wed, 3 Apr 2024 11:05:02 +0200 Subject: [PATCH 017/132] Change debug symbol for auxiliary projections --- .../src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java index d91f4da2d5..63b3a1c93c 100644 --- a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java +++ b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java @@ -378,7 +378,7 @@ public void buildPolyAlgebra( StringBuilder sb ) { child.buildPolyAlgebra( csb ); } else { csb.append( PolyAlgRegistry.getDeclaration( LogicalRelProject.class ).opName ) - .append( "*[" ) + .append( "#[" ) .append( PolyAlgUtils.joinMultiValued( projections, true ) ) .append( "](\n" ); child.buildPolyAlgebra( csb ); From 1af8ec79ece54df8c476ad7453b5c39aa778a74b Mon Sep 17 00:00:00 2001 From: datomo Date: Sun, 17 Mar 2024 16:08:42 +0100 Subject: [PATCH 018/132] mini adjustement to document webui component, some refactoring --- .../org/polypheny/db/adapter/ethereum/EthereumPlugin.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/ethereum-adapter/src/main/java/org/polypheny/db/adapter/ethereum/EthereumPlugin.java b/plugins/ethereum-adapter/src/main/java/org/polypheny/db/adapter/ethereum/EthereumPlugin.java index 5f355f985f..ffa83ae4fe 100644 --- a/plugins/ethereum-adapter/src/main/java/org/polypheny/db/adapter/ethereum/EthereumPlugin.java +++ b/plugins/ethereum-adapter/src/main/java/org/polypheny/db/adapter/ethereum/EthereumPlugin.java @@ -294,6 +294,10 @@ public void renameLogicalColumn( long id, String newColumnName ) { } + + + + @SuppressWarnings("unused") private interface Excludes { From 36bcd6811672d48f8f559b68684f362077300c69 Mon Sep 17 00:00:00 2001 From: datomo Date: Mon, 18 Mar 2024 23:37:49 +0100 Subject: [PATCH 019/132] some performance testing for serialization, while preserving functionality --- .../main/java/org/polypheny/db/type/entity/PolyValue.java | 2 +- .../java/org/polypheny/db/languages/MongoLanguagePlugin.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/polypheny/db/type/entity/PolyValue.java b/core/src/main/java/org/polypheny/db/type/entity/PolyValue.java index 61aaaea312..e4b941ac83 100644 --- a/core/src/main/java/org/polypheny/db/type/entity/PolyValue.java +++ b/core/src/main/java/org/polypheny/db/type/entity/PolyValue.java @@ -322,7 +322,7 @@ public static AlgDataType deriveType( PolyValue value, AlgDataTypeFactory typeFa public String toTypedJson() { try { return JSON_WRAPPER.writeValueAsString( this ); - } catch ( JsonProcessingException e ) { + } catch ( Exception e ) { log.warn( "Error on serializing typed JSON." ); return PolyNull.NULL.toTypedJson(); } diff --git a/plugins/mql-language/src/main/java/org/polypheny/db/languages/MongoLanguagePlugin.java b/plugins/mql-language/src/main/java/org/polypheny/db/languages/MongoLanguagePlugin.java index 56db38b764..e9d8282647 100644 --- a/plugins/mql-language/src/main/java/org/polypheny/db/languages/MongoLanguagePlugin.java +++ b/plugins/mql-language/src/main/java/org/polypheny/db/languages/MongoLanguagePlugin.java @@ -138,6 +138,11 @@ private static List anyQuerySplitter( QueryContext context ) } + public String preprocessing( String query, QueryContext context ) { + return query; + } + + public static void registerOperators() { if ( isInit ) { throw new GenericRuntimeException( "Mql operators were already registered." ); From 2f93a18abe10748b8b4b21c214456050d61634bf Mon Sep 17 00:00:00 2001 From: datomo Date: Tue, 19 Mar 2024 15:01:27 +0100 Subject: [PATCH 020/132] enabled namespace.collection.command( syntax for mql, switched to binary substitution for documents to improve performance --- .../java/org/polypheny/db/functions/RefactorFunctions.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/functions/RefactorFunctions.java b/core/src/main/java/org/polypheny/db/functions/RefactorFunctions.java index 588ed2f359..3de99f0982 100644 --- a/core/src/main/java/org/polypheny/db/functions/RefactorFunctions.java +++ b/core/src/main/java/org/polypheny/db/functions/RefactorFunctions.java @@ -47,13 +47,13 @@ public static PolyValue[] toObjectArray( PolyValue... obj ) { @SuppressWarnings("unused") public static PolyString fromDocument( PolyValue doc ) { - return PolyString.of( doc.toTypedJson() ); + return PolyString.of( doc.serialize() ); } @SuppressWarnings("unused") public static PolyValue toDocument( PolyString json ) { - return PolyValue.fromTypedJson( json.value, PolyValue.class ); + return PolyValue.deserialize( json.value ); } From 4f9a679a2d6887859e3c81c8fd8d82fa566f9fd7 Mon Sep 17 00:00:00 2001 From: datomo Date: Tue, 19 Mar 2024 21:53:55 +0100 Subject: [PATCH 021/132] adjustment to typed json deserializer to improve caching --- .../java/org/polypheny/db/functions/RefactorFunctions.java | 4 ++-- .../src/main/java/org/polypheny/db/type/entity/PolyValue.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/functions/RefactorFunctions.java b/core/src/main/java/org/polypheny/db/functions/RefactorFunctions.java index 3de99f0982..588ed2f359 100644 --- a/core/src/main/java/org/polypheny/db/functions/RefactorFunctions.java +++ b/core/src/main/java/org/polypheny/db/functions/RefactorFunctions.java @@ -47,13 +47,13 @@ public static PolyValue[] toObjectArray( PolyValue... obj ) { @SuppressWarnings("unused") public static PolyString fromDocument( PolyValue doc ) { - return PolyString.of( doc.serialize() ); + return PolyString.of( doc.toTypedJson() ); } @SuppressWarnings("unused") public static PolyValue toDocument( PolyString json ) { - return PolyValue.deserialize( json.value ); + return PolyValue.fromTypedJson( json.value, PolyValue.class ); } diff --git a/core/src/main/java/org/polypheny/db/type/entity/PolyValue.java b/core/src/main/java/org/polypheny/db/type/entity/PolyValue.java index e4b941ac83..61aaaea312 100644 --- a/core/src/main/java/org/polypheny/db/type/entity/PolyValue.java +++ b/core/src/main/java/org/polypheny/db/type/entity/PolyValue.java @@ -322,7 +322,7 @@ public static AlgDataType deriveType( PolyValue value, AlgDataTypeFactory typeFa public String toTypedJson() { try { return JSON_WRAPPER.writeValueAsString( this ); - } catch ( Exception e ) { + } catch ( JsonProcessingException e ) { log.warn( "Error on serializing typed JSON." ); return PolyNull.NULL.toTypedJson(); } From e6509f68ad01a96bdc2d91c50d372bd787871db1 Mon Sep 17 00:00:00 2001 From: datomo Date: Tue, 2 Apr 2024 11:46:25 +0200 Subject: [PATCH 022/132] added default namespace to adapters and removed hardcoded namespace from ddlManager and catalog methods --- core/src/main/java/org/polypheny/db/catalog/Catalog.java | 3 ++- .../org/polypheny/db/catalog/entity/LogicalAdapter.java | 6 +++++- .../java/org/polypheny/db/catalog/impl/PolyCatalog.java | 4 ++-- .../src/test/java/org/polypheny/db/catalog/MockCatalog.java | 2 +- .../org/polypheny/db/adapter/ethereum/EthereumPlugin.java | 4 ---- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/catalog/Catalog.java b/core/src/main/java/org/polypheny/db/catalog/Catalog.java index abf3d18016..98060c59ac 100644 --- a/core/src/main/java/org/polypheny/db/catalog/Catalog.java +++ b/core/src/main/java/org/polypheny/db/catalog/Catalog.java @@ -199,12 +199,13 @@ public void removeObserver( PropertyChangeListener listener ) { * * @param uniqueName The unique name of the adapter * @param clazz The class name of the adapter + * @param defaultNamespace The default namespace of the adapter * @param type The type of adapter * @param settings The configuration of the adapter * @param mode The deploy mode of the adapter * @return The id of the newly added adapter */ - public abstract long createAdapter( String uniqueName, String clazz, AdapterType type, Map settings, DeployMode mode ); + public abstract long createAdapter( String uniqueName, String clazz, long defaultNamespace, AdapterType type, Map settings, DeployMode mode ); /** * Update settings of an adapter diff --git a/core/src/main/java/org/polypheny/db/catalog/entity/LogicalAdapter.java b/core/src/main/java/org/polypheny/db/catalog/entity/LogicalAdapter.java index fc5f4da189..5c4627c877 100644 --- a/core/src/main/java/org/polypheny/db/catalog/entity/LogicalAdapter.java +++ b/core/src/main/java/org/polypheny/db/catalog/entity/LogicalAdapter.java @@ -53,6 +53,8 @@ public class LogicalAdapter implements PolyObject { public String adapterTypeName; @Serialize public DeployMode mode; + @Serialize + public long defaultNamespace; public enum AdapterType {STORE, SOURCE} @@ -64,7 +66,8 @@ public LogicalAdapter( @Deserialize("adapterName") @NonNull final String adapterName, @Deserialize("type") @NonNull final AdapterType adapterType, @Deserialize("mode") @NotNull final DeployMode mode, - @Deserialize("settings") @NonNull final Map settings ) { + @Deserialize("settings") @NonNull final Map settings, + @Deserialize("defaultNamespace") final long defaultNamespace ) { this.id = id; this.uniqueName = uniqueName; this.adapterName = adapterName; @@ -72,6 +75,7 @@ public LogicalAdapter( this.settings = new HashMap<>( settings ); this.adapterTypeName = getAdapterName(); this.mode = mode; + this.defaultNamespace = defaultNamespace; } diff --git a/core/src/main/java/org/polypheny/db/catalog/impl/PolyCatalog.java b/core/src/main/java/org/polypheny/db/catalog/impl/PolyCatalog.java index ba0cfeaa92..67082efb7e 100644 --- a/core/src/main/java/org/polypheny/db/catalog/impl/PolyCatalog.java +++ b/core/src/main/java/org/polypheny/db/catalog/impl/PolyCatalog.java @@ -406,9 +406,9 @@ public void dropNamespace( long id ) { @Override - public long createAdapter( String uniqueName, String clazz, AdapterType type, Map settings, DeployMode mode ) { + public long createAdapter( String uniqueName, String clazz, long defaultNamespace, AdapterType type, Map settings, DeployMode mode ) { long id = idBuilder.getNewAdapterId(); - adapters.put( id, new LogicalAdapter( id, uniqueName, clazz, type, mode, settings ) ); + adapters.put( id, new LogicalAdapter( id, uniqueName, clazz, type, mode, settings, defaultNamespace ) ); change(); return id; } diff --git a/core/src/test/java/org/polypheny/db/catalog/MockCatalog.java b/core/src/test/java/org/polypheny/db/catalog/MockCatalog.java index 7a3f583fa3..c04a51cf02 100644 --- a/core/src/test/java/org/polypheny/db/catalog/MockCatalog.java +++ b/core/src/test/java/org/polypheny/db/catalog/MockCatalog.java @@ -172,7 +172,7 @@ public void dropNamespace( long id ) { @Override - public long createAdapter( String uniqueName, String clazz, AdapterType type, Map settings, DeployMode mode ) { + public long createAdapter( String uniqueName, String clazz, long defaultNamespace, AdapterType type, Map settings, DeployMode mode ) { throw new NotImplementedException(); } diff --git a/plugins/ethereum-adapter/src/main/java/org/polypheny/db/adapter/ethereum/EthereumPlugin.java b/plugins/ethereum-adapter/src/main/java/org/polypheny/db/adapter/ethereum/EthereumPlugin.java index ffa83ae4fe..5f355f985f 100644 --- a/plugins/ethereum-adapter/src/main/java/org/polypheny/db/adapter/ethereum/EthereumPlugin.java +++ b/plugins/ethereum-adapter/src/main/java/org/polypheny/db/adapter/ethereum/EthereumPlugin.java @@ -294,10 +294,6 @@ public void renameLogicalColumn( long id, String newColumnName ) { } - - - - @SuppressWarnings("unused") private interface Excludes { From 9941c0148f06d76a824b89e003a9a7e8bb261e5a Mon Sep 17 00:00:00 2001 From: datomo Date: Tue, 2 Apr 2024 14:08:55 +0200 Subject: [PATCH 023/132] separated create source and store, adjusted some PolyValues --- core/src/main/java/org/polypheny/db/catalog/Catalog.java | 3 +-- .../org/polypheny/db/catalog/entity/LogicalAdapter.java | 6 +----- .../java/org/polypheny/db/catalog/impl/PolyCatalog.java | 4 ++-- .../src/test/java/org/polypheny/db/catalog/MockCatalog.java | 2 +- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/catalog/Catalog.java b/core/src/main/java/org/polypheny/db/catalog/Catalog.java index 98060c59ac..abf3d18016 100644 --- a/core/src/main/java/org/polypheny/db/catalog/Catalog.java +++ b/core/src/main/java/org/polypheny/db/catalog/Catalog.java @@ -199,13 +199,12 @@ public void removeObserver( PropertyChangeListener listener ) { * * @param uniqueName The unique name of the adapter * @param clazz The class name of the adapter - * @param defaultNamespace The default namespace of the adapter * @param type The type of adapter * @param settings The configuration of the adapter * @param mode The deploy mode of the adapter * @return The id of the newly added adapter */ - public abstract long createAdapter( String uniqueName, String clazz, long defaultNamespace, AdapterType type, Map settings, DeployMode mode ); + public abstract long createAdapter( String uniqueName, String clazz, AdapterType type, Map settings, DeployMode mode ); /** * Update settings of an adapter diff --git a/core/src/main/java/org/polypheny/db/catalog/entity/LogicalAdapter.java b/core/src/main/java/org/polypheny/db/catalog/entity/LogicalAdapter.java index 5c4627c877..fc5f4da189 100644 --- a/core/src/main/java/org/polypheny/db/catalog/entity/LogicalAdapter.java +++ b/core/src/main/java/org/polypheny/db/catalog/entity/LogicalAdapter.java @@ -53,8 +53,6 @@ public class LogicalAdapter implements PolyObject { public String adapterTypeName; @Serialize public DeployMode mode; - @Serialize - public long defaultNamespace; public enum AdapterType {STORE, SOURCE} @@ -66,8 +64,7 @@ public LogicalAdapter( @Deserialize("adapterName") @NonNull final String adapterName, @Deserialize("type") @NonNull final AdapterType adapterType, @Deserialize("mode") @NotNull final DeployMode mode, - @Deserialize("settings") @NonNull final Map settings, - @Deserialize("defaultNamespace") final long defaultNamespace ) { + @Deserialize("settings") @NonNull final Map settings ) { this.id = id; this.uniqueName = uniqueName; this.adapterName = adapterName; @@ -75,7 +72,6 @@ public LogicalAdapter( this.settings = new HashMap<>( settings ); this.adapterTypeName = getAdapterName(); this.mode = mode; - this.defaultNamespace = defaultNamespace; } diff --git a/core/src/main/java/org/polypheny/db/catalog/impl/PolyCatalog.java b/core/src/main/java/org/polypheny/db/catalog/impl/PolyCatalog.java index 67082efb7e..ba0cfeaa92 100644 --- a/core/src/main/java/org/polypheny/db/catalog/impl/PolyCatalog.java +++ b/core/src/main/java/org/polypheny/db/catalog/impl/PolyCatalog.java @@ -406,9 +406,9 @@ public void dropNamespace( long id ) { @Override - public long createAdapter( String uniqueName, String clazz, long defaultNamespace, AdapterType type, Map settings, DeployMode mode ) { + public long createAdapter( String uniqueName, String clazz, AdapterType type, Map settings, DeployMode mode ) { long id = idBuilder.getNewAdapterId(); - adapters.put( id, new LogicalAdapter( id, uniqueName, clazz, type, mode, settings, defaultNamespace ) ); + adapters.put( id, new LogicalAdapter( id, uniqueName, clazz, type, mode, settings ) ); change(); return id; } diff --git a/core/src/test/java/org/polypheny/db/catalog/MockCatalog.java b/core/src/test/java/org/polypheny/db/catalog/MockCatalog.java index c04a51cf02..7a3f583fa3 100644 --- a/core/src/test/java/org/polypheny/db/catalog/MockCatalog.java +++ b/core/src/test/java/org/polypheny/db/catalog/MockCatalog.java @@ -172,7 +172,7 @@ public void dropNamespace( long id ) { @Override - public long createAdapter( String uniqueName, String clazz, long defaultNamespace, AdapterType type, Map settings, DeployMode mode ) { + public long createAdapter( String uniqueName, String clazz, AdapterType type, Map settings, DeployMode mode ) { throw new NotImplementedException(); } From a7f11ba8e85696ab5aeff480006a907002e1097f Mon Sep 17 00:00:00 2001 From: datomo Date: Tue, 2 Apr 2024 16:13:46 +0200 Subject: [PATCH 024/132] fixes for multiple queries results --- .../src/main/java/org/polypheny/db/avatica/DbmsMeta.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 plugins/avatica-interface/src/main/java/org/polypheny/db/avatica/DbmsMeta.java diff --git a/plugins/avatica-interface/src/main/java/org/polypheny/db/avatica/DbmsMeta.java b/plugins/avatica-interface/src/main/java/org/polypheny/db/avatica/DbmsMeta.java new file mode 100644 index 0000000000..e69de29bb2 From 7f1ea64b3e6d0ec16bdfc8bd81b224b5796ed082 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Wed, 3 Apr 2024 17:46:16 +0200 Subject: [PATCH 025/132] Prevent appending of alias for CAST expression that keep their name --- .../db/algebra/polyalg/PolyAlgUtils.java | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java index da75958d7e..41bd9962b4 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java @@ -20,6 +20,9 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; +import java.util.StringJoiner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.type.AlgDataTypeField; import org.polypheny.db.rex.RexCall; @@ -38,9 +41,21 @@ import org.polypheny.db.rex.RexSubQuery; import org.polypheny.db.rex.RexTableIndexRef; import org.polypheny.db.rex.RexVisitor; +import org.polypheny.db.type.PolyType; public class PolyAlgUtils { + private static final Pattern CAST_PATTERN; + + + static { + StringJoiner joiner = new StringJoiner( "|", "CAST\\(([^)]+)\\):(", ")" ); + for ( PolyType type : PolyType.values() ) { + joiner.add( type.getName() ); + } + CAST_PATTERN = Pattern.compile( joiner.toString() ); // matches group "my_field" in "CAST(my_field):INTEGER" + } + public static String getFieldNameFromIndex( AlgNode alg, int idx ) { for ( AlgNode input : alg.getInputs() ) { @@ -55,7 +70,7 @@ public static String getFieldNameFromIndex( AlgNode alg, int idx ) { public static String appendAlias( String exp, String alias ) { - if ( alias == null || alias.equals( exp ) ) { + if ( alias == null || alias.equals( exp ) || isCastWithSameName( exp, alias ) ) { return exp; } return exp + " AS " + alias; @@ -64,7 +79,7 @@ public static String appendAlias( String exp, String alias ) { /** * Each element in exps is compared with the corresponding element in aliases. - * If they differ, the alias is appended to the element, separated by the keyword {@code AS}. + * If they differ (and not just by a CAST expression), the alias is appended to the element, separated by the keyword {@code AS}. * For example {@code AVG(age) AS average}. * * @param exps List of strings to be assigned an alias @@ -81,6 +96,12 @@ public static List appendAliases( List exps, List aliase } + private static boolean isCastWithSameName( String exp, String alias ) { + Matcher m = CAST_PATTERN.matcher( exp ); + return m.find() && m.group( 1 ).equals( alias ); + } + + /** * Joins the values for a multivalued attribute into a single string. * If values contains more than one element, the returned string is surrounded with brackets to represent a list. @@ -95,7 +116,7 @@ public static String joinMultiValued( List values, boolean omitBrackets } - public static List getAuxProjections( AlgNode child, Set fieldNames) { + public static List getAuxProjections( AlgNode child, Set fieldNames ) { List projections = new ArrayList<>(); for ( AlgDataTypeField field : child.getTupleType().getFields() ) { String name = field.getName(); @@ -184,7 +205,8 @@ public String visitDynamicParam( RexDynamicParam dynamicParam ) { @Override public String visitRangeRef( RexRangeRef rangeRef ) { - return "rangeRef: " + rangeRef; + // Regular RexNode trees do not contain this construct + return rangeRef.toString(); } From 7be62139b086fc23cf6aeef70d7736bd03bbee44 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Wed, 3 Apr 2024 18:22:42 +0200 Subject: [PATCH 026/132] Allow for empty inner expressions --- core/src/main/codegen/PolyAlgParser.jj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/codegen/PolyAlgParser.jj b/core/src/main/codegen/PolyAlgParser.jj index 3fbdb21340..dd4ce88d74 100644 --- a/core/src/main/codegen/PolyAlgParser.jj +++ b/core/src/main/codegen/PolyAlgParser.jj @@ -141,13 +141,13 @@ void OuterExpression() : InnerExpression() | Literal() - ) [OuterExpression()] // outer expressions cannot contain separators, as they could not always be differentiated from a ListArgument + )+ // outer expressions cannot contain separators, as they could not always be differentiated from a ListArgument } void InnerExpression() : // An expression which appears within parentheses {} { - ( + (( InnerExpression() | InnerExpression() @@ -155,7 +155,7 @@ void InnerExpression() : // An expression which appears within parentheses Literal() | // inner expressions can contain , since we know it cannot be an alias for an argument - ) ()* [InnerExpression()] // inner expressions can contain separators! + ) ()* )* // inner expressions can contain separators! } void Literal() : From d3e9db4758d68dd58f1b94823704060e371edbb2 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Wed, 3 Apr 2024 18:23:45 +0200 Subject: [PATCH 027/132] Indent PolyAlgebra debug outputs --- .../org/polypheny/db/algebra/AbstractAlgNode.java | 14 +++++++++----- .../java/org/polypheny/db/algebra/AlgNode.java | 7 ++++++- .../java/org/polypheny/db/plan/AlgOptUtil.java | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java index 63b3a1c93c..bfad0518ce 100644 --- a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java +++ b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java @@ -357,9 +357,12 @@ public AlgWriter explainTerms( AlgWriter pw ) { @Override - public void buildPolyAlgebra( StringBuilder sb ) { + public void buildPolyAlgebra( StringBuilder sb, String prefix ) { + final String INDENT = " "; + String nextPrefix = prefix == null ? null : prefix + INDENT; + PolyAlgDeclaration decl = getPolyAlgDeclaration(); - sb.append( decl.opName ); + sb.append( prefix == null ? "" : prefix ).append( decl.opName ); sb.append( collectAttributes().serializeArguments( this ) ); int size = getInputs().size(); @@ -375,13 +378,14 @@ public void buildPolyAlgebra( StringBuilder sb ) { StringBuilder csb = new StringBuilder(); if ( projections.isEmpty() ) { - child.buildPolyAlgebra( csb ); + child.buildPolyAlgebra( csb, nextPrefix ); } else { - csb.append( PolyAlgRegistry.getDeclaration( LogicalRelProject.class ).opName ) + csb.append( nextPrefix ) + .append( PolyAlgRegistry.getDeclaration( LogicalRelProject.class ).opName ) .append( "#[" ) .append( PolyAlgUtils.joinMultiValued( projections, true ) ) .append( "](\n" ); - child.buildPolyAlgebra( csb ); + child.buildPolyAlgebra( csb, nextPrefix == null ? null : nextPrefix + INDENT ); csb.append( ")" ); } sb.append( csb ); diff --git a/core/src/main/java/org/polypheny/db/algebra/AlgNode.java b/core/src/main/java/org/polypheny/db/algebra/AlgNode.java index da09c8110c..25acfd1487 100644 --- a/core/src/main/java/org/polypheny/db/algebra/AlgNode.java +++ b/core/src/main/java/org/polypheny/db/algebra/AlgNode.java @@ -245,8 +245,13 @@ public interface AlgNode extends AlgOptNode, Cloneable { * The basic structure of PolyAlgebra is {@code OPERATOR[attributes](children)}. * * @param sb StringBuilder for building the representation + * @param prefix Prefix to be added in front of each operator (resulting in operators having a visual indentation) or null if not desired */ - void buildPolyAlgebra( StringBuilder sb ); + void buildPolyAlgebra( StringBuilder sb, String prefix ); + + default void buildPolyAlgebra( StringBuilder sb) { + buildPolyAlgebra( sb, null ); + } /** * Retrieves the PolyAlgDeclaration for this AlgNode implementation. diff --git a/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java b/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java index d8f3e4fd58..96ac89bc34 100644 --- a/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java +++ b/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java @@ -1363,7 +1363,7 @@ public static void registerAbstractAlgs( AlgPlanner planner ) { public static String dumpPlan( String header, AlgNode alg, ExplainFormat format, ExplainLevel detailLevel ) { //TODO: Delete lines for testing PolyAlg serialization StringBuilder sb = new StringBuilder(); - alg.buildPolyAlgebra( sb ); + alg.buildPolyAlgebra( sb, "" ); System.out.println( "===== " + header + " =====" ); System.out.println( sb ); System.out.print( "----> " ); From f0c4979f9d3666ec98a9c1d7c2557228395f6ab2 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Wed, 3 Apr 2024 18:58:16 +0200 Subject: [PATCH 028/132] Omit printing routed query plan --- .../java/org/polypheny/db/plan/AlgOptUtil.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java b/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java index 96ac89bc34..858d1e36a9 100644 --- a/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java +++ b/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java @@ -1362,13 +1362,15 @@ public static void registerAbstractAlgs( AlgPlanner planner ) { */ public static String dumpPlan( String header, AlgNode alg, ExplainFormat format, ExplainLevel detailLevel ) { //TODO: Delete lines for testing PolyAlg serialization - StringBuilder sb = new StringBuilder(); - alg.buildPolyAlgebra( sb, "" ); - System.out.println( "===== " + header + " =====" ); - System.out.println( sb ); - System.out.print( "----> " ); - PolyAlgParser.parse( sb.toString() ); - System.out.println(); + if ( !header.startsWith( "Routed" ) ) { + StringBuilder sb = new StringBuilder(); + alg.buildPolyAlgebra( sb, "" ); + System.out.println( "===== " + header + " =====" ); + System.out.println( sb ); + System.out.print( "----> " ); + PolyAlgParser.parse( sb.toString() ); + System.out.println(); + } StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter( sw ); From c936fc3a13454d33e078955eada69685480a8959 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Fri, 5 Apr 2024 16:53:12 +0200 Subject: [PATCH 029/132] Use existing uniquify method for generating unique fields --- .../java/org/polypheny/db/util/ValidatorUtil.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/util/ValidatorUtil.java b/core/src/main/java/org/polypheny/db/util/ValidatorUtil.java index e06dcb4d83..203172df4b 100644 --- a/core/src/main/java/org/polypheny/db/util/ValidatorUtil.java +++ b/core/src/main/java/org/polypheny/db/util/ValidatorUtil.java @@ -115,17 +115,9 @@ private static void addFields( List fieldList, List Date: Fri, 5 Apr 2024 16:53:21 +0200 Subject: [PATCH 030/132] Replace with unique field names in PolyArg serialization --- .../polypheny/db/algebra/AbstractAlgNode.java | 26 +++++------ .../logical/relational/LogicalRelSort.java | 2 +- .../db/algebra/polyalg/PolyAlgUtils.java | 45 +++++++------------ .../db/algebra/polyalg/arguments/AggArg.java | 14 +++--- .../db/algebra/polyalg/arguments/AnyArg.java | 5 ++- .../algebra/polyalg/arguments/BooleanArg.java | 5 ++- .../polyalg/arguments/CollationArg.java | 13 +++--- .../polyalg/arguments/CorrelationArg.java | 5 ++- .../algebra/polyalg/arguments/EntityArg.java | 5 ++- .../db/algebra/polyalg/arguments/EnumArg.java | 5 ++- .../algebra/polyalg/arguments/FieldArg.java | 14 +++--- .../db/algebra/polyalg/arguments/IntArg.java | 5 ++- .../db/algebra/polyalg/arguments/ListArg.java | 11 ++--- .../algebra/polyalg/arguments/PolyAlgArg.java | 15 ++++--- .../polyalg/arguments/PolyAlgArgs.java | 7 +-- .../db/algebra/polyalg/arguments/RexArg.java | 14 +++--- 16 files changed, 91 insertions(+), 100 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java index bfad0518ce..3de4150fd1 100644 --- a/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java +++ b/core/src/main/java/org/polypheny/db/algebra/AbstractAlgNode.java @@ -360,10 +360,11 @@ public AlgWriter explainTerms( AlgWriter pw ) { public void buildPolyAlgebra( StringBuilder sb, String prefix ) { final String INDENT = " "; String nextPrefix = prefix == null ? null : prefix + INDENT; + List inputFieldNames = PolyAlgUtils.uniquifiedInputFieldNames( this ); PolyAlgDeclaration decl = getPolyAlgDeclaration(); sb.append( prefix == null ? "" : prefix ).append( decl.opName ); - sb.append( collectAttributes().serializeArguments( this ) ); + sb.append( collectAttributes().serializeArguments( this, inputFieldNames ) ); int size = getInputs().size(); if ( size == 0 ) { @@ -371,24 +372,21 @@ public void buildPolyAlgebra( StringBuilder sb, String prefix ) { } sb.append( "(\n" ); - Set fieldNames = new HashSet<>(); + int inputIdx = 0; for ( AlgNode child : getInputs() ) { + List projections = PolyAlgUtils.getAuxProjections( child, inputFieldNames, inputIdx ); + inputIdx += child.getTupleType().getFieldCount(); - List projections = PolyAlgUtils.getAuxProjections( child, fieldNames ); - - StringBuilder csb = new StringBuilder(); if ( projections.isEmpty() ) { - child.buildPolyAlgebra( csb, nextPrefix ); + child.buildPolyAlgebra( sb, nextPrefix ); } else { - csb.append( nextPrefix ) - .append( PolyAlgRegistry.getDeclaration( LogicalRelProject.class ).opName ) - .append( "#[" ) - .append( PolyAlgUtils.joinMultiValued( projections, true ) ) - .append( "](\n" ); - child.buildPolyAlgebra( csb, nextPrefix == null ? null : nextPrefix + INDENT ); - csb.append( ")" ); + sb.append( nextPrefix ) + .append( PolyAlgRegistry.getDeclaration( LogicalRelProject.class ).opName ).append( "#" ) // TODO: select Project depending on data model, logical / physical + .append( "[" ).append( PolyAlgUtils.joinMultiValued( projections, true ) ).append( "]") + .append("(\n" ); + child.buildPolyAlgebra( sb, nextPrefix == null ? null : nextPrefix + INDENT ); + sb.append( ")" ); } - sb.append( csb ); size--; if ( size > 0 ) { diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java index cbd0365e39..e4ec2f57e8 100644 --- a/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java +++ b/core/src/main/java/org/polypheny/db/algebra/logical/relational/LogicalRelSort.java @@ -105,7 +105,7 @@ public PolyAlgArgs collectAttributes() { PolyAlgArg collArg = new ListArg<>( collation.getFieldCollations(), - c -> new CollationArg( c, this ), + c -> new CollationArg( c ), args.getDecl().canUnpackValues() ); args.put( "sort", collArg ) diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java index 41bd9962b4..3fec770b68 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java @@ -23,6 +23,7 @@ import java.util.StringJoiner; import java.util.regex.Matcher; import java.util.regex.Pattern; +import lombok.NonNull; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.type.AlgDataTypeField; import org.polypheny.db.rex.RexCall; @@ -42,6 +43,7 @@ import org.polypheny.db.rex.RexTableIndexRef; import org.polypheny.db.rex.RexVisitor; import org.polypheny.db.type.PolyType; +import org.polypheny.db.util.ValidatorUtil; public class PolyAlgUtils { @@ -57,18 +59,6 @@ public class PolyAlgUtils { } - public static String getFieldNameFromIndex( AlgNode alg, int idx ) { - for ( AlgNode input : alg.getInputs() ) { - List fields = input.getTupleType().getFields(); - if ( idx < fields.size() ) { - return fields.get( idx ).getName(); - } - idx += fields.size(); - } - return Integer.toString( idx ); - } - - public static String appendAlias( String exp, String alias ) { if ( alias == null || alias.equals( exp ) || isCastWithSameName( exp, alias ) ) { return exp; @@ -116,38 +106,33 @@ public static String joinMultiValued( List values, boolean omitBrackets } - public static List getAuxProjections( AlgNode child, Set fieldNames ) { + public static List getAuxProjections( AlgNode child, List inputFieldNames, int startIndex ) { List projections = new ArrayList<>(); - for ( AlgDataTypeField field : child.getTupleType().getFields() ) { - String name = field.getName(); - if ( fieldNames.contains( name ) ) { - int i = 0; - String prefix = name; - do { - name = prefix + i; - i++; - } while ( fieldNames.contains( name ) ); - projections.add( prefix + " AS " + name ); + List names = child.getTupleType().getFieldNames(); + for ( int i = 0; i < names.size(); i++ ) { + String name = names.get( i ); + String uniqueName = inputFieldNames.get( startIndex + i ); + if ( !name.equals( uniqueName ) ) { + projections.add( name + " AS " + uniqueName ); } - fieldNames.add( name ); } return projections; } - public static List getFieldNames( AlgNode context ) { + public static List uniquifiedInputFieldNames( AlgNode context ) { if ( context == null ) { return List.of(); } - return context.getInputs().stream() - .flatMap( node -> node.getTupleType().getFields().stream() ) - .map( AlgDataTypeField::getName ) + List names = context.getInputs().stream() + .flatMap( node -> node.getTupleType().getFieldNames().stream() ) .toList(); + return ValidatorUtil.uniquify( names, ValidatorUtil.ATTEMPT_SUGGESTER, true ); } - public static String digestWithNames( RexNode expr, AlgNode context ) { - return expr.accept( new NameReplacer( getFieldNames( context ) ) ); + public static String digestWithNames( RexNode expr, List inputFieldNames ) { + return expr.accept( new NameReplacer( inputFieldNames ) ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java index 52878fc69d..62cfd70b09 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AggArg.java @@ -16,6 +16,8 @@ package org.polypheny.db.algebra.polyalg.arguments; +import java.util.List; +import lombok.NonNull; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.core.Aggregate; import org.polypheny.db.algebra.core.AggregateCall; @@ -39,14 +41,8 @@ public ParamType getType() { @Override - public String toPolyAlg() { - return toPolyAlg( null ); - } - - - @Override - public String toPolyAlg( AlgNode context ) { - String str = agg.toString( PolyAlgUtils.getFieldNames( context ) ); + public String toPolyAlg( AlgNode context, @NonNull List inputFieldNames ) { + String str = agg.toString( inputFieldNames.isEmpty() ? null : inputFieldNames ); String name = agg.getName(); if ( name == null ) { // TODO: make sure agg.getName() is never null @@ -55,7 +51,7 @@ public String toPolyAlg( AlgNode context ) { if ( i != -1 ) { i += instance.getGroupSet().asList().size(); } - name = "$f" + i; + name = "$ffff" + i; } return PolyAlgUtils.appendAlias( str, name ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AnyArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AnyArg.java index 888a621455..ba8e684802 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AnyArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/AnyArg.java @@ -16,6 +16,9 @@ package org.polypheny.db.algebra.polyalg.arguments; +import java.util.List; +import lombok.NonNull; +import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; /** @@ -37,7 +40,7 @@ public ParamType getType() { @Override - public String toPolyAlg() { + public String toPolyAlg( AlgNode context, @NonNull List inputFieldNames ) { return arg.toString(); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/BooleanArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/BooleanArg.java index c7c9c6a165..4050d4969f 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/BooleanArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/BooleanArg.java @@ -16,6 +16,9 @@ package org.polypheny.db.algebra.polyalg.arguments; +import java.util.List; +import lombok.NonNull; +import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; public class BooleanArg implements PolyAlgArg { @@ -35,7 +38,7 @@ public ParamType getType() { @Override - public String toPolyAlg() { + public String toPolyAlg( AlgNode context, @NonNull List inputFieldNames ) { return Boolean.toString( arg ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CollationArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CollationArg.java index 588dac7381..1c6ddc98cb 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CollationArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CollationArg.java @@ -16,20 +16,21 @@ package org.polypheny.db.algebra.polyalg.arguments; +import java.util.List; +import lombok.NonNull; import org.polypheny.db.algebra.AlgFieldCollation; import org.polypheny.db.algebra.AlgNode; +import org.polypheny.db.algebra.core.Aggregate; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; import org.polypheny.db.algebra.polyalg.PolyAlgUtils; public class CollationArg implements PolyAlgArg { private final AlgFieldCollation arg; - private final AlgNode algNode; - public CollationArg( AlgFieldCollation arg, AlgNode fieldNameProvider ) { + public CollationArg( AlgFieldCollation arg ) { this.arg = arg; - this.algNode = fieldNameProvider; } @@ -38,10 +39,10 @@ public ParamType getType() { return ParamType.COLLATION; } - @Override - public String toPolyAlg() { - String str = PolyAlgUtils.getFieldNameFromIndex( algNode, arg.getFieldIndex() ); + public String toPolyAlg( AlgNode context, @NonNull List inputFieldNames ) { + int idx = arg.getFieldIndex(); + String str = inputFieldNames.size() > idx ? inputFieldNames.get( idx ) : Integer.toString( idx ); if ( arg.direction != AlgFieldCollation.Direction.ASCENDING || arg.nullDirection != arg.direction.defaultNullDirection() ) { str += " " + arg.shortString(); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CorrelationArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CorrelationArg.java index 02cba39ff7..ddf435d224 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CorrelationArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/CorrelationArg.java @@ -16,6 +16,9 @@ package org.polypheny.db.algebra.polyalg.arguments; +import java.util.List; +import lombok.NonNull; +import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.core.CorrelationId; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; @@ -36,7 +39,7 @@ public ParamType getType() { @Override - public String toPolyAlg() { + public String toPolyAlg( AlgNode context, @NonNull List inputFieldNames ) { return arg.toString(); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EntityArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EntityArg.java index b335a30110..24392a57cb 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EntityArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EntityArg.java @@ -16,6 +16,9 @@ package org.polypheny.db.algebra.polyalg.arguments; +import java.util.List; +import lombok.NonNull; +import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; import org.polypheny.db.catalog.entity.Entity; @@ -36,7 +39,7 @@ public ParamType getType() { @Override - public String toPolyAlg() { + public String toPolyAlg( AlgNode context, @NonNull List inputFieldNames ) { return e.getNamespaceName() + "." + e.name; } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EnumArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EnumArg.java index 83bfe36796..95818c7ff1 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EnumArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/EnumArg.java @@ -16,6 +16,9 @@ package org.polypheny.db.algebra.polyalg.arguments; +import java.util.List; +import lombok.NonNull; +import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; public class EnumArg> implements PolyAlgArg{ @@ -37,7 +40,7 @@ public ParamType getType() { @Override - public String toPolyAlg() { + public String toPolyAlg( AlgNode context, @NonNull List inputFieldNames ) { return arg.name(); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java index 214615c57b..fce5adb431 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/FieldArg.java @@ -16,6 +16,8 @@ package org.polypheny.db.algebra.polyalg.arguments; +import java.util.List; +import lombok.NonNull; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; import org.polypheny.db.algebra.polyalg.PolyAlgUtils; @@ -35,15 +37,9 @@ public ParamType getType() { @Override - public String toPolyAlg() { - return toPolyAlg(null); - } - - - @Override - public String toPolyAlg( AlgNode context ) { - if ( context != null ) { - return PolyAlgUtils.getFieldNameFromIndex( context, field ); + public String toPolyAlg( AlgNode context, @NonNull List inputFieldNames ) { + if (inputFieldNames.size() > field) { + return inputFieldNames.get( field ); } return Integer.toString( field ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/IntArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/IntArg.java index d7a0d063fb..0d22f245d6 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/IntArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/IntArg.java @@ -16,6 +16,9 @@ package org.polypheny.db.algebra.polyalg.arguments; +import java.util.List; +import lombok.NonNull; +import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; public class IntArg implements PolyAlgArg { @@ -35,7 +38,7 @@ public ParamType getType() { @Override - public String toPolyAlg() { + public String toPolyAlg( AlgNode context, @NonNull List inputFieldNames ) { return Integer.toString( arg ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java index f0c8d00da5..86fb9fc897 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/ListArg.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.function.Function; import lombok.Getter; +import lombok.NonNull; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; import org.polypheny.db.algebra.polyalg.PolyAlgUtils; @@ -69,14 +70,8 @@ public ParamType getType() { @Override - public String toPolyAlg() { - return toPolyAlg( null ); - } - - - @Override - public String toPolyAlg( AlgNode context ) { - List strArgs = args.stream().map( a -> a.toPolyAlg( context ) ).toList(); + public String toPolyAlg( AlgNode context, @NonNull List inputFieldNames ) { + List strArgs = args.stream().map( a -> a.toPolyAlg( context, inputFieldNames ) ).toList(); if ( aliases != null ) { strArgs = PolyAlgUtils.appendAliases( strArgs, aliases ); diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArg.java index 2e8c8e3b41..7fe9bf9fb9 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArg.java @@ -16,6 +16,8 @@ package org.polypheny.db.algebra.polyalg.arguments; +import java.util.List; +import lombok.NonNull; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; @@ -23,10 +25,13 @@ public interface PolyAlgArg { ParamType getType(); - String toPolyAlg(); - - default String toPolyAlg( AlgNode context ) { - return toPolyAlg(); - } + /** + * Returns the PolyAlg representation of this argument. + * + * @param context the AlgNode this argument belongs to + * @param inputFieldNames list of field names of all children with duplicate names uniquified + * @return string representing the PolyAlg representation of this argument + */ + String toPolyAlg( AlgNode context, @NonNull List inputFieldNames ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java index 135b63f9a4..cf95e2b769 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/PolyAlgArgs.java @@ -17,6 +17,7 @@ package org.polypheny.db.algebra.polyalg.arguments; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.StringJoiner; import lombok.Getter; @@ -40,18 +41,18 @@ public PolyAlgArgs( PolyAlgDeclaration declaration ) { } - public String serializeArguments( AlgNode context ) { + public String serializeArguments( AlgNode context, List inputFieldNames ) { StringJoiner joiner = new StringJoiner( ", ", "[", "]" ); for ( Parameter p : decl.posParams ) { assert args.containsKey( p ); PolyAlgArg arg = getArg( p ); - joiner.add( arg.toPolyAlg( context ) ); + joiner.add( arg.toPolyAlg( context, inputFieldNames ) ); } for ( Parameter p : decl.kwParams ) { if ( args.containsKey( p ) ) { PolyAlgArg arg = getArg( p ); - String value = arg.toPolyAlg( context ); + String value = arg.toPolyAlg( context, inputFieldNames ); if ( !p.getDefaultValue().equals( value ) ) { joiner.add( p.getName() + "=" + value ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java index b10a3c017f..0c260287b5 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/arguments/RexArg.java @@ -16,7 +16,9 @@ package org.polypheny.db.algebra.polyalg.arguments; +import java.util.List; import lombok.Getter; +import lombok.NonNull; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.polyalg.PolyAlgDeclaration.ParamType; import org.polypheny.db.algebra.polyalg.PolyAlgUtils; @@ -47,21 +49,15 @@ public ParamType getType() { @Override - public String toPolyAlg() { - return toPolyAlg( null ); - } - - - @Override - public String toPolyAlg( AlgNode context ) { + public String toPolyAlg( AlgNode context, @NonNull List inputFieldNames ) { String str = node == null ? "" : node.toString(); if ( omitTrue && str.equals( "true" ) ) { return ""; } - if ( context == null || node == null ) { + if ( inputFieldNames.isEmpty() || node == null ) { return str; } - return PolyAlgUtils.digestWithNames( node, context ); + return PolyAlgUtils.digestWithNames( node, inputFieldNames ); } } From f6e71e84a7d1b68cb1e8a03ed9c252877536e6c6 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Fri, 5 Apr 2024 18:35:49 +0200 Subject: [PATCH 031/132] Move toString(RexVisitor) back to NameReplacer --- .../db/algebra/polyalg/PolyAlgUtils.java | 173 ++++++++++++++++-- .../java/org/polypheny/db/rex/RexCall.java | 39 +--- .../java/org/polypheny/db/rex/RexLiteral.java | 2 +- .../java/org/polypheny/db/rex/RexOver.java | 10 +- .../org/polypheny/db/rex/RexSubQuery.java | 9 +- .../java/org/polypheny/db/rex/RexWindow.java | 24 +-- 6 files changed, 168 insertions(+), 89 deletions(-) diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java index 3fec770b68..9615304240 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java @@ -17,20 +17,24 @@ package org.polypheny.db.algebra.polyalg; +import java.io.PrintWriter; +import java.io.StringWriter; import java.util.ArrayList; import java.util.List; -import java.util.Set; import java.util.StringJoiner; import java.util.regex.Matcher; import java.util.regex.Pattern; -import lombok.NonNull; import org.polypheny.db.algebra.AlgNode; -import org.polypheny.db.algebra.type.AlgDataTypeField; +import org.polypheny.db.algebra.constant.Kind; +import org.polypheny.db.algebra.constant.Syntax; +import org.polypheny.db.plan.AlgOptUtil; import org.polypheny.db.rex.RexCall; import org.polypheny.db.rex.RexCorrelVariable; +import org.polypheny.db.rex.RexDigestIncludeType; import org.polypheny.db.rex.RexDynamicParam; import org.polypheny.db.rex.RexElementRef; import org.polypheny.db.rex.RexFieldAccess; +import org.polypheny.db.rex.RexFieldCollation; import org.polypheny.db.rex.RexIndexRef; import org.polypheny.db.rex.RexLiteral; import org.polypheny.db.rex.RexLocalRef; @@ -42,6 +46,8 @@ import org.polypheny.db.rex.RexSubQuery; import org.polypheny.db.rex.RexTableIndexRef; import org.polypheny.db.rex.RexVisitor; +import org.polypheny.db.rex.RexWindow; +import org.polypheny.db.rex.RexWindowBound; import org.polypheny.db.type.PolyType; import org.polypheny.db.util.ValidatorUtil; @@ -154,7 +160,7 @@ public String visitIndexRef( RexIndexRef inputRef ) { @Override public String visitLocalRef( RexLocalRef localRef ) { - return "LocalRef: " + localRef; + return "===LocalRef=== " + localRef; } @@ -166,25 +172,56 @@ public String visitLiteral( RexLiteral literal ) { @Override public String visitCall( RexCall call ) { - return call.toString( this ); + // This code closely follows call.toString(), but uses the visitor for nested RexNodes + + boolean withType = call.isA( Kind.CAST ) || call.isA( Kind.NEW_SPECIFICATION ); + final StringBuilder sb = new StringBuilder( call.op.getName() ); + if ( (!call.operands.isEmpty()) && (call.op.getSyntax() == Syntax.FUNCTION_ID) ) { + // Don't print params for empty arg list. For example, we want "SYSTEM_USER", not "SYSTEM_USER()". + } else { + sb.append( "(" ); + appendOperands( call, sb ); + sb.append( ")" ); + } + if ( withType ) { + sb.append( ":" ); + // NOTE jvs 16-Jan-2005: for digests, it is very important to use the full type string. + sb.append( call.type.getFullTypeString() ); + } + return sb.toString(); } @Override public String visitOver( RexOver over ) { - return over.toString( this ); + boolean withType = over.isA( Kind.CAST ) || over.isA( Kind.NEW_SPECIFICATION ); + final StringBuilder sb = new StringBuilder( over.op.getName() ); + sb.append( "(" ); + if ( over.isDistinct() ) { + sb.append( "DISTINCT " ); + } + appendOperands( over, sb ); + sb.append( ")" ); + if ( withType ) { + sb.append( ":" ); + sb.append( over.type.getFullTypeString() ); + } + sb.append( " OVER (" ) + .append( visitRexWindow( over.getWindow() ) ) + .append( ")" ); + return sb.toString(); } @Override public String visitCorrelVariable( RexCorrelVariable correlVariable ) { - return "correlVariable: " + correlVariable; + return correlVariable.getName(); } @Override public String visitDynamicParam( RexDynamicParam dynamicParam ) { - return "dynamicParam: " + dynamicParam; + return "===dynamicParam=== " + dynamicParam; } @@ -197,41 +234,141 @@ public String visitRangeRef( RexRangeRef rangeRef ) { @Override public String visitFieldAccess( RexFieldAccess fieldAccess ) { - return "fieldAccess: " + fieldAccess; + return fieldAccess.getReferenceExpr().accept( this ) + "." + fieldAccess.getField().getName(); } @Override public String visitSubQuery( RexSubQuery subQuery ) { - /* TODO: handling subquery when constructing PolyAlg representation - in method computeDigest( boolean withType, RexVisitor visitor ), - sb.append( AlgOptUtil.toString( alg ) ); - */ - return "subQuery: " + subQuery; + /* TODO: make sure subquery is parsed correctly + */ + final StringBuilder sb = new StringBuilder( subQuery.op.getName() ); + sb.append( "(" ); + for ( RexNode operand : subQuery.operands ) { + sb.append( operand ); + sb.append( ", " ); + } + sb.append( "{\n" ); + subQuery.alg.buildPolyAlgebra( sb ); + sb.append( "})" ); + return "subQuery: " + sb.toString(); } @Override public String visitTableInputRef( RexTableIndexRef fieldRef ) { - return "tableInputRef: " + fieldRef; + return "===tableInputRef=== " + fieldRef; } @Override public String visitPatternFieldRef( RexPatternFieldRef fieldRef ) { - return "patternFieldRef: " + fieldRef; + return "===patternFieldRef=== " + fieldRef; } @Override public String visitNameRef( RexNameRef nameRef ) { - return "nameRef: " + nameRef; + return "===nameRef=== " + nameRef; } @Override public String visitElementRef( RexElementRef rexElementRef ) { - return "elementRef: " + rexElementRef; + return "===elementRef=== " + rexElementRef; + } + + + private void appendOperands( RexCall call, StringBuilder sb ) { + for ( int i = 0; i < call.operands.size(); i++ ) { + if ( i > 0 ) { + sb.append( ", " ); + } + RexNode operand = call.operands.get( i ); + if ( !(operand instanceof RexLiteral) ) { + sb.append( operand.accept( this ) ); + continue; + } + // Type information might be omitted in certain cases to improve readability + // For instance, AND/OR arguments should be BOOLEAN, so AND(true, null) is better than AND(true, null:BOOLEAN), and we keep the same info +($0, 2) is better than +($0, 2:BIGINT). Note: if $0 has BIGINT, + // then 2 is expected to be of BIGINT type as well. + RexDigestIncludeType includeType = RexDigestIncludeType.OPTIONAL; + if ( (call.isA( Kind.AND ) || call.isA( Kind.OR )) && operand.getType().getPolyType() == PolyType.BOOLEAN ) { + includeType = RexDigestIncludeType.NO_TYPE; + } + if ( RexCall.SIMPLE_BINARY_OPS.contains( call.getKind() ) ) { + RexNode otherArg = call.operands.get( 1 - i ); + if ( (!(otherArg instanceof RexLiteral) || ((RexLiteral) otherArg).digestIncludesType() == RexDigestIncludeType.NO_TYPE) && RexCall.equalSansNullability( operand.getType(), otherArg.getType() ) ) { + includeType = RexDigestIncludeType.NO_TYPE; + } + } + sb.append( ((RexLiteral) operand).computeDigest( includeType ) ); + } + } + + + private String visitRexWindow( RexWindow window ) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter( sw ); + int clauseCount = 0; + if ( window.partitionKeys.size() > 0 ) { + if ( clauseCount++ > 0 ) { + pw.print( ' ' ); + } + pw.print( "PARTITION BY " ); + for ( int i = 0; i < window.partitionKeys.size(); i++ ) { + if ( i > 0 ) { + pw.print( ", " ); + } + RexNode partitionKey = window.partitionKeys.get( i ); + pw.print( partitionKey.accept( this ) ); + } + } + if ( window.orderKeys.size() > 0 ) { + if ( clauseCount++ > 0 ) { + pw.print( ' ' ); + } + pw.print( "ORDER BY " ); + for ( int i = 0; i < window.orderKeys.size(); i++ ) { + if ( i > 0 ) { + pw.print( ", " ); + } + RexFieldCollation orderKey = window.orderKeys.get( i ); + pw.print( orderKey.toString( this ) ); + } + } + if ( window.getLowerBound() == null ) { + // No ROWS or RANGE clause + } else if ( window.getUpperBound() == null ) { + if ( clauseCount++ > 0 ) { + pw.print( ' ' ); + } + if ( window.isRows() ) { + pw.print( "ROWS " ); + } else { + pw.print( "RANGE " ); + } + pw.print( visitRexWindowBound( window.getLowerBound() ) ); + } else { + if ( clauseCount++ > 0 ) { + pw.print( ' ' ); + } + if ( window.isRows() ) { + pw.print( "ROWS BETWEEN " ); + } else { + pw.print( "RANGE BETWEEN " ); + } + pw.print( visitRexWindowBound( window.getLowerBound() ) ); + pw.print( " AND " ); + pw.print( visitRexWindowBound( window.getUpperBound() ) ); + } + return sw.toString(); + } + + + private String visitRexWindowBound( RexWindowBound bound ) { + // at this point it is simply much easier to rely on the toString method of the RexWindowBound subclasses. + return bound.toString( this ); } } diff --git a/core/src/main/java/org/polypheny/db/rex/RexCall.java b/core/src/main/java/org/polypheny/db/rex/RexCall.java index 6c72f3979d..7e3468205c 100644 --- a/core/src/main/java/org/polypheny/db/rex/RexCall.java +++ b/core/src/main/java/org/polypheny/db/rex/RexCall.java @@ -69,7 +69,7 @@ public class RexCall extends RexNode { public final ImmutableList operands; public final AlgDataType type; - private static final Set SIMPLE_BINARY_OPS; + public static final Set SIMPLE_BINARY_OPS; static { @@ -83,7 +83,6 @@ public RexCall( AlgDataType type, Operator op, RexNode... operands ) { this( type, op, ImmutableList.copyOf( operands ) ); } - public RexCall( AlgDataType type, Operator op, List operands ) { this.type = Objects.requireNonNull( type ); this.op = Objects.requireNonNull( op ); @@ -102,26 +101,13 @@ public RexCall( AlgDataType type, Operator op, List operands * @see RexLiteral#computeDigest(RexDigestIncludeType) */ protected final StringBuilder appendOperands( StringBuilder sb ) { - return appendOperands( sb, null ); - } - - - /** - * Like appendOperands( StringBuilder sb), but additionally takes a visitor for generating the - * string representation of any operands that are not RexLiterals. - * - * @param sb destination - * @param visitor RexVisitor which visits any non-literal operand for generating the string representation. - * @return original StringBuilder for fluent API - */ - protected final StringBuilder appendOperands( StringBuilder sb, RexVisitor visitor ) { for ( int i = 0; i < operands.size(); i++ ) { if ( i > 0 ) { sb.append( ", " ); } RexNode operand = operands.get( i ); if ( !(operand instanceof RexLiteral) ) { - sb.append( visitor == null ? operand : operand.accept( visitor ) ); + sb.append( operand ); continue; } // Type information might be omitted in certain cases to improve readability @@ -151,7 +137,7 @@ protected final StringBuilder appendOperands( StringBuilder sb, RexVisitor visitor ) { final StringBuilder sb = new StringBuilder( op.getName() ); if ( (operands.isEmpty()) && (op.getSyntax() == Syntax.FUNCTION_ID) ) { // Don't print params for empty arg list. For example, we want "SYSTEM_USER", not "SYSTEM_USER()". } else { sb.append( "(" ); - appendOperands( sb, visitor ); + appendOperands( sb ); sb.append( ")" ); } if ( withType ) { @@ -199,18 +180,6 @@ private static boolean equalSansNullability( AlgDataType a, AlgDataType b ) { } - /** - * Computes a string representation where the given visitor is used for generating - * the string of each operand. - * - * @param visitor RexVisitor that visits every operand for generating the string representation used - * @return String representation of this call, where operands are customized by the visitor. - */ - public final @Nonnull String toString( RexVisitor visitor ) { - return Objects.requireNonNull( computeDigest( isA( Kind.CAST ) || isA( Kind.NEW_SPECIFICATION ), visitor ) ); - } - - @Override public R accept( RexVisitor visitor ) { return visitor.visitCall( this ); diff --git a/core/src/main/java/org/polypheny/db/rex/RexLiteral.java b/core/src/main/java/org/polypheny/db/rex/RexLiteral.java index 925a87830a..b860f2babe 100644 --- a/core/src/main/java/org/polypheny/db/rex/RexLiteral.java +++ b/core/src/main/java/org/polypheny/db/rex/RexLiteral.java @@ -245,7 +245,7 @@ public String computeDigest( RexDigestIncludeType includeType ) { * @return true if {@link RexDigestIncludeType#OPTIONAL} digest would include data type * @see RexCall#computeDigest(boolean) */ - RexDigestIncludeType digestIncludesType() { + public RexDigestIncludeType digestIncludesType() { return shouldIncludeType( value, type ); } diff --git a/core/src/main/java/org/polypheny/db/rex/RexOver.java b/core/src/main/java/org/polypheny/db/rex/RexOver.java index d7a912a996..721969ae6d 100644 --- a/core/src/main/java/org/polypheny/db/rex/RexOver.java +++ b/core/src/main/java/org/polypheny/db/rex/RexOver.java @@ -102,25 +102,19 @@ public boolean isDistinct() { @Override protected @Nonnull String computeDigest( boolean withType ) { - return computeDigest( withType, null ); - } - - - @Override - protected @Nonnull String computeDigest( boolean withType, RexVisitor visitor ) { final StringBuilder sb = new StringBuilder( op.getName() ); sb.append( "(" ); if ( distinct ) { sb.append( "DISTINCT " ); } - appendOperands( sb, visitor ); + appendOperands( sb ); sb.append( ")" ); if ( withType ) { sb.append( ":" ); sb.append( type.getFullTypeString() ); } sb.append( " OVER (" ) - .append( window.toString( visitor ) ) + .append( window ) .append( ")" ); return sb.toString(); } diff --git a/core/src/main/java/org/polypheny/db/rex/RexSubQuery.java b/core/src/main/java/org/polypheny/db/rex/RexSubQuery.java index 174d63dbcd..8c37a5e11e 100644 --- a/core/src/main/java/org/polypheny/db/rex/RexSubQuery.java +++ b/core/src/main/java/org/polypheny/db/rex/RexSubQuery.java @@ -142,17 +142,10 @@ public R accept( RexBiVisitor visitor, P arg ) { @Override protected @Nonnull String computeDigest( boolean withType ) { - return computeDigest( withType, null ); - } - - - @Override - protected @Nonnull - String computeDigest( boolean withType, RexVisitor visitor ) { final StringBuilder sb = new StringBuilder( op.getName() ); sb.append( "(" ); for ( RexNode operand : operands ) { - sb.append( visitor == null ? operand : operand.accept( visitor ) ); + sb.append( operand ); sb.append( ", " ); } sb.append( "{\n" ); diff --git a/core/src/main/java/org/polypheny/db/rex/RexWindow.java b/core/src/main/java/org/polypheny/db/rex/RexWindow.java index 88a5103be3..01715b0a2a 100644 --- a/core/src/main/java/org/polypheny/db/rex/RexWindow.java +++ b/core/src/main/java/org/polypheny/db/rex/RexWindow.java @@ -77,14 +77,6 @@ public String toString() { } - public String toString( RexVisitor visitor ) { - if ( visitor == null ) { - return toString(); - } - return computeDigest( visitor ); - } - - public int hashCode() { return digest.hashCode(); } @@ -100,11 +92,6 @@ public boolean equals( Object that ) { private String computeDigest() { - return computeDigest( null ); - } - - - private String computeDigest( RexVisitor visitor ) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter( sw ); int clauseCount = 0; @@ -118,7 +105,7 @@ private String computeDigest( RexVisitor visitor ) { pw.print( ", " ); } RexNode partitionKey = partitionKeys.get( i ); - pw.print( visitor == null ? partitionKey.toString() : partitionKey.accept( visitor ) ); + pw.print( partitionKey.toString() ); } } if ( orderKeys.size() > 0 ) { @@ -131,7 +118,7 @@ private String computeDigest( RexVisitor visitor ) { pw.print( ", " ); } RexFieldCollation orderKey = orderKeys.get( i ); - pw.print( orderKey.toString( visitor ) ); + pw.print( orderKey.toString() ); } } if ( lowerBound == null ) { @@ -145,7 +132,7 @@ private String computeDigest( RexVisitor visitor ) { } else { pw.print( "RANGE " ); } - pw.print( lowerBound.toString( visitor ) ); + pw.print( lowerBound.toString() ); } else { if ( clauseCount++ > 0 ) { pw.print( ' ' ); @@ -155,9 +142,9 @@ private String computeDigest( RexVisitor visitor ) { } else { pw.print( "RANGE BETWEEN " ); } - pw.print( lowerBound.toString( visitor ) ); + pw.print( lowerBound.toString() ); pw.print( " AND " ); - pw.print( upperBound.toString( visitor ) ); + pw.print( upperBound.toString() ); } return sw.toString(); } @@ -176,6 +163,5 @@ public RexWindowBound getUpperBound() { public boolean isRows() { return isRows; } - } From c360b3050a6e4db4e70e387244a0a98c1fbe47ec Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Mon, 8 Apr 2024 12:40:39 +0200 Subject: [PATCH 032/132] Add classes required for semantic analysis of PolyAlg --- core/src/main/codegen/PolyAlgParser.jj | 198 ++++++++++++++---- .../parser/PolyAlgAbstractParserImpl.java | 34 +++ .../parser/PolyAlgAliasedArgument.java | 33 +++ .../polyalg/parser/PolyAlgArgument.java | 27 +++ .../polyalg/parser/PolyAlgLiteral.java | 27 +++ .../polyalg/parser/PolyAlgNamedArgument.java | 33 +++ .../algebra/polyalg/parser/PolyAlgNode.java | 84 ++++++++ .../polyalg/parser/PolyAlgOperator.java | 37 ++++ .../polyalg/parser/PolyAlgParseException.java | 37 ++++ .../algebra/polyalg/parser/PolyAlgParser.java | 64 ++++++ .../org/polypheny/db/plan/AlgOptUtil.java | 13 +- 11 files changed, 548 insertions(+), 39 deletions(-) create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgAbstractParserImpl.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgAliasedArgument.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgArgument.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgLiteral.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgNamedArgument.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgNode.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgOperator.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgParseException.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgParser.java diff --git a/core/src/main/codegen/PolyAlgParser.jj b/core/src/main/codegen/PolyAlgParser.jj index dd4ce88d74..c210c39ee5 100644 --- a/core/src/main/codegen/PolyAlgParser.jj +++ b/core/src/main/codegen/PolyAlgParser.jj @@ -5,20 +5,42 @@ options { UNICODE_INPUT = true; } -PARSER_BEGIN(PolyAlgParser) +PARSER_BEGIN(PolyAlgParserImpl) package org.polypheny.db.algebra.polyalg.parser; import java.io.StringReader; +import java.io.Reader; +import org.polypheny.db.languages.ParserFactory; +import org.polypheny.db.languages.ParserPos; +import org.polypheny.db.algebra.polyalg.parser.PolyAlgAbstractParserImpl; +import org.polypheny.db.algebra.polyalg.parser.PolyAlgLiteral; +import java.util.Arrays; +import java.util.List; +import java.util.ArrayList; /** * Parses Poly Algebra. */ -public class PolyAlgParser { +public class PolyAlgParserImpl extends PolyAlgAbstractParserImpl { + + /** + * ParserFactory implementation for creating parser. + */ + public static final ParserFactory FACTORY = new ParserFactory() { + public PolyAlgAbstractParserImpl getParser(Reader reader) { + final PolyAlgParserImpl parser = new PolyAlgParserImpl(reader); + /*if (reader instanceof SourceStringReader) { + final String mql = ((SourceStringReader) reader).getSourceString(); + parser.setOriginalMql(mql); + }*/ + return parser; + } + }; /** Main entry point. */ public static void parse(String str) { - PolyAlgParser parser = new PolyAlgParser(new StringReader(str)); + PolyAlgParserImpl parser = new PolyAlgParserImpl(new StringReader(str)); try { @@ -31,9 +53,60 @@ public class PolyAlgParser { } } + public PolyAlgParseException normalizeException(Throwable ex) { + try { + return convertException(ex); + } catch (ParseException e) { + throw new AssertionError(e); + } + } + + PolyAlgParseException convertException(Throwable ex) throws ParseException { + if (ex instanceof PolyAlgParseException) { + return (PolyAlgParseException) ex; + } + + ParserPos pos = null; + int[][] expectedTokenSequences = null; + String[] tokenImage = null; + if (ex instanceof ParseException) { + ParseException pex = (ParseException) ex; + expectedTokenSequences = pex.expectedTokenSequences; + tokenImage = pex.tokenImage; + if (pex.currentToken != null) { + final Token token = pex.currentToken.next; + pos = new ParserPos( + token.beginLine, + token.beginColumn, + token.endLine, + token.endColumn); + } + } else if (ex instanceof TokenMgrError) { + TokenMgrError tme = (TokenMgrError) ex; + expectedTokenSequences = null; + tokenImage = null; + // Example: + // Lexical error at line 3, column 24. Encountered "#" after "a". + final java.util.regex.Pattern pattern = java.util.regex.Pattern.compile( + "(?s)Lexical error at line ([0-9]+), column ([0-9]+).*"); + java.util.regex.Matcher matcher = pattern.matcher(ex.getMessage()); + if (matcher.matches()) { + int line = Integer.parseInt(matcher.group(1)); + int column = Integer.parseInt(matcher.group(2)); + pos = new ParserPos(line, column, line, column); + } + } + return new PolyAlgParseException(ex.getMessage(), pos, expectedTokenSequences, tokenImage, ex); + } + + + public PolyAlgNode parsePolyAlgEof() throws Exception { + return Input(); + } + } -PARSER_END(PolyAlgParser) +PARSER_END(PolyAlgParserImpl) SKIP : { @@ -79,51 +152,89 @@ TOKEN : "'"> } +JAVACODE protected ParserPos getPos() +{ + return new ParserPos( + token.beginLine, + token.beginColumn, + token.endLine, + token.endColumn); +} + /** Root production. */ -void Input() : -{} +PolyAlgNode Input() : +{ + PolyAlgNode n; +} { - Operator() + n = Operator() + {return n;} } -void Operator() : -{} +PolyAlgOperator Operator() : +{ + String opName; + List args = null; + List children = null; +} { - OpName() [Arguments()] [ [ChildOperators()] ] + opName = OpName() [args = Arguments()] [ [children = ChildOperators()] ] + {return new PolyAlgOperator(opName, args, children, getPos());} } -void ChildOperators() : -{} +List ChildOperators() : +{ + PolyAlgOperator o; + List children = new ArrayList<>(); +} { - Operator() ( Operator())* + o = Operator() {children.add(o);} ( o = Operator() {children.add(o);})* + {return children;} } -void Arguments() : -{} +List Arguments() : +{ + PolyAlgNamedArgument n; + List args = new ArrayList<>(); +} { - NamedArgument() ( NamedArgument())* + n = NamedArgument() {args.add(n);} ( n = NamedArgument() {args.add(n);})* + {return args;} } -void NamedArgument() : -{} +PolyAlgNamedArgument NamedArgument() : +{ + String name = null; + PolyAlgAliasedArgument arg; +} { - [LOOKAHEAD(2) ParamName() ] AliasedArgument() + [LOOKAHEAD(2) name = ParamName() ] arg = AliasedArgument() + {return new PolyAlgNamedArgument(name, arg, getPos());} } -void AliasedArgument() : -{} +PolyAlgAliasedArgument AliasedArgument() : +{ + PolyAlgArgument arg; + String alias = null; +} { - Argument() [ AliasName() ] + arg = Argument() [ alias = AliasName() ] + {return new PolyAlgAliasedArgument(arg, alias, getPos()); } } -void Argument() : -{} +PolyAlgArgument Argument() : { - OuterExpression() - | - ListArgument() + PolyAlgArgument arg = new PolyAlgArgument(); +} +{ + ( + OuterExpression() + | + ListArgument() + ) + {return arg;} } void ListArgument() : @@ -172,22 +283,33 @@ void Literal() : } -void OpName() : -{} +String OpName() : +{ + String name = "opName"; +} { - - | - + ( + + | + + ) + {return name;} } -void AliasName() : -{} +String AliasName() : +{ + String name; +} { - OpName() + name = OpName() + {return name;} } -void ParamName() : -{} +String ParamName() : +{ + String name; +} { - OpName() + name = OpName() + {return name;} } \ No newline at end of file diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgAbstractParserImpl.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgAbstractParserImpl.java new file mode 100644 index 0000000000..1ea9210ed2 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgAbstractParserImpl.java @@ -0,0 +1,34 @@ +/* + * 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.polyalg.parser; + +import org.polypheny.db.languages.NodeParseException; +import org.polypheny.db.languages.ParserImpl; + +public abstract class PolyAlgAbstractParserImpl implements ParserImpl { + + public abstract PolyAlgNode parsePolyAlgEof() throws Exception; + + /** + * Removes or transforms misleading information from a parse exception or error, and converts to {@link NodeParseException}. + * + * @param ex dirty excn + * @return clean excn + */ + public abstract PolyAlgParseException normalizeException( Throwable ex ); + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgAliasedArgument.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgAliasedArgument.java new file mode 100644 index 0000000000..999adb47c0 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgAliasedArgument.java @@ -0,0 +1,33 @@ +/* + * 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.polyalg.parser; + +import org.polypheny.db.languages.ParserPos; + +public class PolyAlgAliasedArgument extends PolyAlgNode { + + private final PolyAlgArgument argument; + private final String alias; + + + public PolyAlgAliasedArgument( PolyAlgArgument argument, String alias, ParserPos pos ) { + super( pos ); + this.argument = argument; + this.alias = alias; + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgArgument.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgArgument.java new file mode 100644 index 0000000000..71c8b44ad7 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgArgument.java @@ -0,0 +1,27 @@ +/* + * 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.polyalg.parser; + +import org.polypheny.db.languages.ParserPos; + +public class PolyAlgArgument extends PolyAlgNode { + + public PolyAlgArgument() { + super( null ); + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgLiteral.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgLiteral.java new file mode 100644 index 0000000000..80d08dca07 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgLiteral.java @@ -0,0 +1,27 @@ +/* + * 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.polyalg.parser; + +import org.polypheny.db.languages.ParserPos; + +public class PolyAlgLiteral extends PolyAlgNode { + + public PolyAlgLiteral() { + super( null ); + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgNamedArgument.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgNamedArgument.java new file mode 100644 index 0000000000..04319b599e --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgNamedArgument.java @@ -0,0 +1,33 @@ +/* + * 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.polyalg.parser; + +import org.polypheny.db.languages.ParserPos; + +public class PolyAlgNamedArgument extends PolyAlgNode { + + private final String name; + private final PolyAlgAliasedArgument aliasedArg; + + + public PolyAlgNamedArgument( String name, PolyAlgAliasedArgument aliasedArg, ParserPos pos ) { + super( pos ); + this.name = name; + this.aliasedArg = aliasedArg; + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgNode.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgNode.java new file mode 100644 index 0000000000..cad842c5d2 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgNode.java @@ -0,0 +1,84 @@ +/* + * 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.polyalg.parser; + +import java.util.Set; +import lombok.Getter; +import org.jetbrains.annotations.Nullable; +import org.polypheny.db.algebra.constant.Kind; +import org.polypheny.db.languages.ParserPos; +import org.polypheny.db.languages.QueryLanguage; +import org.polypheny.db.nodes.Node; +import org.polypheny.db.nodes.NodeVisitor; +import org.polypheny.db.util.Litmus; + +/** + * At this point this class + */ +@Getter +public abstract class PolyAlgNode implements Node { + + protected final ParserPos pos; + + + protected PolyAlgNode( ParserPos pos ) { + this.pos = pos; + } + + + @Override + public Node clone( ParserPos pos ) { + return null; + } + + + @Override + public Kind getKind() { + return null; + } + + + @Override + public QueryLanguage getLanguage() { + return null; + } + + + @Override + public boolean isA( Set category ) { + return category.contains( this.getKind() ); + } + + + @Override + public boolean equalsDeep( Node node, Litmus litmus ) { + return false; + } + + + @Override + public @Nullable String getEntity() { + return null; + } + + + @Override + public R accept( NodeVisitor visitor ) { + return null; + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgOperator.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgOperator.java new file mode 100644 index 0000000000..f7bc3d53c7 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgOperator.java @@ -0,0 +1,37 @@ +/* + * 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.polyalg.parser; + +import java.util.List; +import org.polypheny.db.languages.ParserPos; + +public class PolyAlgOperator extends PolyAlgNode { + + private final String opName; + private final List arguments; + private final List children; + + + public PolyAlgOperator( String opName, List arguments, List children, ParserPos pos ) { + super( pos ); + + this.opName = opName; + this.arguments = arguments == null ? List.of() : arguments; + this.children = children == null ? List.of() : children; + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgParseException.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgParseException.java new file mode 100644 index 0000000000..3ae9a16504 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgParseException.java @@ -0,0 +1,37 @@ +/* + * 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.polyalg.parser; + +import org.polypheny.db.languages.NodeParseException; +import org.polypheny.db.languages.ParserPos; + +public class PolyAlgParseException extends NodeParseException { + + /** + * Creates a PolyAlgParseException. + * + * @param message Message + * @param pos Position + * @param expectedTokenSequences Token sequences + * @param tokenImages Token images + * @param parserException Parser exception + */ + public PolyAlgParseException( String message, ParserPos pos, int[][] expectedTokenSequences, String[] tokenImages, Throwable parserException ) { + super( message, pos, expectedTokenSequences, tokenImages, parserException ); + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgParser.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgParser.java new file mode 100644 index 0000000000..fd1e2ca1fe --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgParser.java @@ -0,0 +1,64 @@ +/* + * 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.polyalg.parser; + +import java.io.Reader; +import org.polypheny.db.languages.NodeParseException; +import org.polypheny.db.languages.Parser; +import org.polypheny.db.languages.ParserImpl; +import org.polypheny.db.nodes.Node; +import org.polypheny.db.util.SourceStringReader; + +public class PolyAlgParser implements Parser { + + private final PolyAlgAbstractParserImpl parser; + + + public PolyAlgParser( PolyAlgAbstractParserImpl parser ) { + this.parser = parser; + } + + + public static PolyAlgParser create( String polyAlg ) { + return create( new SourceStringReader( polyAlg ) ); + } + + + public static PolyAlgParser create( Reader reader ) { + ParserImpl parser = PolyAlgParserImpl.FACTORY.getParser( reader ); + return new PolyAlgParser( (PolyAlgAbstractParserImpl) parser ); + + } + + + @Override + public Node parseQuery() throws NodeParseException { + try { + return parser.parsePolyAlgEof(); + + } catch ( Throwable ex ) { + throw parser.normalizeException( ex ); + } + } + + + @Override + public Node parseStmt() throws NodeParseException { + return parseQuery(); + } + +} diff --git a/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java b/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java index 858d1e36a9..a07e8c5ded 100644 --- a/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java +++ b/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java @@ -84,6 +84,7 @@ import org.polypheny.db.algebra.logical.relational.LogicalRelProject; import org.polypheny.db.algebra.metadata.AlgMetadataQuery; import org.polypheny.db.algebra.operators.OperatorName; +import org.polypheny.db.algebra.polyalg.parser.PolyAlgNode; import org.polypheny.db.algebra.polyalg.parser.PolyAlgParser; import org.polypheny.db.algebra.rules.AggregateProjectPullUpConstantsRule; import org.polypheny.db.algebra.rules.DateRangeRules; @@ -1368,7 +1369,17 @@ public static String dumpPlan( String header, AlgNode alg, ExplainFormat format, System.out.println( "===== " + header + " =====" ); System.out.println( sb ); System.out.print( "----> " ); - PolyAlgParser.parse( sb.toString() ); + + try { + PolyAlgParser parser = PolyAlgParser.create( sb.toString() ); + PolyAlgNode node = (PolyAlgNode) parser.parseQuery(); + System.out.println( "Successfully parsed input!" ); + } catch ( Exception e ) { + System.out.println( "Could not parse input correctly:" ); + System.out.println( e.getMessage() ); + e.printStackTrace(); + } + System.out.println(); } From 6a4528d42883cfd478e5d82e1cfdd264b13021f6 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Tue, 9 Apr 2024 12:18:35 +0200 Subject: [PATCH 033/132] Expand capabilities of PolyAlgParser --- core/src/main/codegen/PolyAlgParser.jj | 131 ++++++++++++------ .../db/algebra/polyalg/PolyAlgUtils.java | 3 +- .../parser/PolyAlgAbstractParserImpl.java | 1 + .../polyalg/parser/PolyAlgArgument.java | 27 ---- .../{ => nodes}/PolyAlgAliasedArgument.java | 8 +- .../parser/nodes/PolyAlgExpression.java | 56 ++++++++ .../parser/{ => nodes}/PolyAlgLiteral.java | 13 +- .../{ => nodes}/PolyAlgNamedArgument.java | 2 +- .../parser/{ => nodes}/PolyAlgNode.java | 2 +- .../polyalg/parser/nodes/PolyAlgNodeList.java | 95 +++++++++++++ .../parser/{ => nodes}/PolyAlgOperator.java | 2 +- .../org/polypheny/db/plan/AlgOptUtil.java | 2 +- 12 files changed, 262 insertions(+), 80 deletions(-) delete mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgArgument.java rename core/src/main/java/org/polypheny/db/algebra/polyalg/parser/{ => nodes}/PolyAlgAliasedArgument.java (78%) create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgExpression.java rename core/src/main/java/org/polypheny/db/algebra/polyalg/parser/{ => nodes}/PolyAlgLiteral.java (71%) rename core/src/main/java/org/polypheny/db/algebra/polyalg/parser/{ => nodes}/PolyAlgNamedArgument.java (94%) rename core/src/main/java/org/polypheny/db/algebra/polyalg/parser/{ => nodes}/PolyAlgNode.java (97%) create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgNodeList.java rename core/src/main/java/org/polypheny/db/algebra/polyalg/parser/{ => nodes}/PolyAlgOperator.java (95%) diff --git a/core/src/main/codegen/PolyAlgParser.jj b/core/src/main/codegen/PolyAlgParser.jj index c210c39ee5..95beaec013 100644 --- a/core/src/main/codegen/PolyAlgParser.jj +++ b/core/src/main/codegen/PolyAlgParser.jj @@ -13,8 +13,13 @@ import java.io.StringReader; import java.io.Reader; import org.polypheny.db.languages.ParserFactory; import org.polypheny.db.languages.ParserPos; -import org.polypheny.db.algebra.polyalg.parser.PolyAlgAbstractParserImpl; -import org.polypheny.db.algebra.polyalg.parser.PolyAlgLiteral; +import org.polypheny.db.algebra.polyalg.parser.nodes.PolyAlgLiteral; +import org.polypheny.db.algebra.polyalg.parser.nodes.PolyAlgAliasedArgument; +import org.polypheny.db.algebra.polyalg.parser.nodes.PolyAlgNamedArgument; +import org.polypheny.db.algebra.polyalg.parser.nodes.PolyAlgNode; +import org.polypheny.db.algebra.polyalg.parser.nodes.PolyAlgOperator; +import org.polypheny.db.algebra.polyalg.parser.nodes.PolyAlgNodeList; +import org.polypheny.db.algebra.polyalg.parser.nodes.PolyAlgExpression; import java.util.Arrays; import java.util.List; import java.util.ArrayList; @@ -127,6 +132,7 @@ TOKEN : | | | | | | ) ( | | )+> | )+ (".")? ()*> @@ -216,7 +222,7 @@ PolyAlgNamedArgument NamedArgument() : PolyAlgAliasedArgument AliasedArgument() : { - PolyAlgArgument arg; + PolyAlgNode arg; String alias = null; } { @@ -224,41 +230,73 @@ PolyAlgAliasedArgument AliasedArgument() : {return new PolyAlgAliasedArgument(arg, alias, getPos()); } } -PolyAlgArgument Argument() : +PolyAlgNode Argument() : { - PolyAlgArgument arg = new PolyAlgArgument(); + PolyAlgNode n; } { ( - OuterExpression() + n = Expression() | - ListArgument() + n = ListArgument() ) - {return arg;} + {return n;} } -void ListArgument() : -{} +PolyAlgNode ListArgument() : // we return a PolyAlgNodeList instead of a List as an Argument() could also be a PolyAlgExpression +{ + List args = new ArrayList<>(); + PolyAlgNode n; +} { - AliasedArgument() ( AliasedArgument())* + n = AliasedArgument() {args.add(n);} ( n = AliasedArgument() {args.add(n);})* + {return new PolyAlgNodeList(args, getPos());} } -void OuterExpression() : -{} +PolyAlgExpression Expression(): +{ + List literals = new ArrayList<>(); + List childExps = null; + Token t; + PolyAlgLiteral l; + String cast = null; + PolyAlgExpression exp; +} +{ + (l = Literal() {literals.add(l);})+ [ childExps = ChildExpressions() ] [ t = {cast = t.image;}] // TODO: handle OVER + {return new PolyAlgExpression(literals, childExps, cast, getPos());} + | + exp = Expression() // optional outer parentheses + {return exp;} +} + +/*PolyAlgNode OuterExpression() : // outer expressions cannot contain separators, as they could not always be differentiated from a ListArgument +{ + PolyAlgNode n = new PolyAlgLiteral(); // only temporary +} { ( - InnerExpression() - | - InnerExpression() + AnyExpression() | - Literal() - )+ // outer expressions cannot contain separators, as they could not always be differentiated from a ListArgument -} + OuterExpression() // optional outer parentheses + ) + + + + + {return n;} +}*/ -void InnerExpression() : // An expression which appears within parentheses -{} +List ChildExpressions() : // List of expressions separated by +{ + List exps = new ArrayList<>(); + PolyAlgExpression e; +} { - (( + e = Expression() {exps.add(e);} ( e = Expression() {exps.add(e);})* + {return exps;} + + /*(( InnerExpression() | InnerExpression() @@ -266,42 +304,55 @@ void InnerExpression() : // An expression which appears within parentheses Literal() | // inner expressions can contain , since we know it cannot be an alias for an argument - ) ()* )* // inner expressions can contain separators! + ) ()* )* // inner expressions can contain separators!*/ } -void Literal() : -{} + +PolyAlgLiteral Literal() : { - - | - - | - - | - - | - + Token t; + boolean isNumber = false; + +} +{ + ( + t = + | + t = {isNumber = true;} + | + t = + | + t = + | + t = + ) + {return new PolyAlgLiteral(t.image, isNumber, getPos());} + } String OpName() : { - String name = "opName"; + Token t; } { ( - - | - + t = ) - {return name;} + {return t.image;} } String AliasName() : { + Token t; String name; } { - name = OpName() + ( + name = OpName() + | + t = + {name = t.image;} + ) {return name;} } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java index 9615304240..9c02e47399 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgUtils.java @@ -27,7 +27,6 @@ import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.constant.Kind; import org.polypheny.db.algebra.constant.Syntax; -import org.polypheny.db.plan.AlgOptUtil; import org.polypheny.db.rex.RexCall; import org.polypheny.db.rex.RexCorrelVariable; import org.polypheny.db.rex.RexDigestIncludeType; @@ -166,7 +165,7 @@ public String visitLocalRef( RexLocalRef localRef ) { @Override public String visitLiteral( RexLiteral literal ) { - return literal.toString(); + return literal.computeDigest( RexDigestIncludeType.OPTIONAL ); } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgAbstractParserImpl.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgAbstractParserImpl.java index 1ea9210ed2..7e75845b9c 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgAbstractParserImpl.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgAbstractParserImpl.java @@ -16,6 +16,7 @@ package org.polypheny.db.algebra.polyalg.parser; +import org.polypheny.db.algebra.polyalg.parser.nodes.PolyAlgNode; import org.polypheny.db.languages.NodeParseException; import org.polypheny.db.languages.ParserImpl; diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgArgument.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgArgument.java deleted file mode 100644 index 71c8b44ad7..0000000000 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgArgument.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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.polyalg.parser; - -import org.polypheny.db.languages.ParserPos; - -public class PolyAlgArgument extends PolyAlgNode { - - public PolyAlgArgument() { - super( null ); - } - -} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgAliasedArgument.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgAliasedArgument.java similarity index 78% rename from core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgAliasedArgument.java rename to core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgAliasedArgument.java index 999adb47c0..18546e3525 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgAliasedArgument.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgAliasedArgument.java @@ -14,19 +14,19 @@ * limitations under the License. */ -package org.polypheny.db.algebra.polyalg.parser; +package org.polypheny.db.algebra.polyalg.parser.nodes; import org.polypheny.db.languages.ParserPos; public class PolyAlgAliasedArgument extends PolyAlgNode { - private final PolyAlgArgument argument; + private final PolyAlgNode arg; private final String alias; - public PolyAlgAliasedArgument( PolyAlgArgument argument, String alias, ParserPos pos ) { + public PolyAlgAliasedArgument( PolyAlgNode arg, String alias, ParserPos pos ) { super( pos ); - this.argument = argument; + this.arg = arg; this.alias = alias; } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgExpression.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgExpression.java new file mode 100644 index 0000000000..49e1ec6e3f --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgExpression.java @@ -0,0 +1,56 @@ +/* + * 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.polyalg.parser.nodes; + +import java.util.List; +import lombok.Getter; +import lombok.NonNull; +import org.polypheny.db.languages.ParserPos; + +/** + * One-size-fits-all class for any RexNodes or even literals not wrapped in a RexNode + */ + +@Getter +public class PolyAlgExpression extends PolyAlgNode { + + private final List literals; + private final List childExps; + private final String cast; + + + public PolyAlgExpression( @NonNull List literals, List childExps, String cast, ParserPos pos ) { + super( pos ); + assert !literals.isEmpty(); + + this.literals = literals; + this.childExps = childExps; + this.cast = cast; + + } + + + public boolean isCall() { + // if childExps is an empty list, we have a call with 0 arguments + return childExps == null; + } + + public boolean hasCast() { + return cast != null; + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgLiteral.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgLiteral.java similarity index 71% rename from core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgLiteral.java rename to core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgLiteral.java index 80d08dca07..8023b2a436 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgLiteral.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgLiteral.java @@ -14,14 +14,21 @@ * limitations under the License. */ -package org.polypheny.db.algebra.polyalg.parser; +package org.polypheny.db.algebra.polyalg.parser.nodes; import org.polypheny.db.languages.ParserPos; public class PolyAlgLiteral extends PolyAlgNode { - public PolyAlgLiteral() { - super( null ); + private final String str; + private final boolean isNumber; + + + public PolyAlgLiteral( String str, boolean isNumber, ParserPos pos ) { + super( pos ); + + this.str = str; + this.isNumber = isNumber; } } diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgNamedArgument.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgNamedArgument.java similarity index 94% rename from core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgNamedArgument.java rename to core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgNamedArgument.java index 04319b599e..2b6c87172d 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgNamedArgument.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgNamedArgument.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.polypheny.db.algebra.polyalg.parser; +package org.polypheny.db.algebra.polyalg.parser.nodes; import org.polypheny.db.languages.ParserPos; diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgNode.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgNode.java similarity index 97% rename from core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgNode.java rename to core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgNode.java index cad842c5d2..e19ce8a1f9 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgNode.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgNode.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.polypheny.db.algebra.polyalg.parser; +package org.polypheny.db.algebra.polyalg.parser.nodes; import java.util.Set; import lombok.Getter; diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgNodeList.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgNodeList.java new file mode 100644 index 0000000000..e9ab5be5de --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgNodeList.java @@ -0,0 +1,95 @@ +/* + * 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.polyalg.parser.nodes; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.polypheny.db.languages.ParserPos; +import org.polypheny.db.nodes.Node; +import org.polypheny.db.nodes.NodeList; + +public class PolyAlgNodeList extends PolyAlgNode implements NodeList { + + private final List list; + @Getter + private final List polyAlgList; + + + public PolyAlgNodeList( ParserPos pos ) { + super( pos ); + list = new ArrayList<>(); + polyAlgList = new ArrayList<>(); + } + + + public PolyAlgNodeList( Collection collection, ParserPos pos ) { + super( pos ); + list = new ArrayList<>( collection ); + polyAlgList = new ArrayList<>( collection.stream().map( e -> (PolyAlgNode) e ).toList() ); + } + + + @Override + public List getList() { + return list; + } + + + @Override + public void add( Node node ) { + list.add( node ); + polyAlgList.add( (PolyAlgNode) node ); + + } + + + @Override + public Node get( int n ) { + return list.get( n ); + } + + + @Override + public Node set( int n, Node node ) { + polyAlgList.set( n, (PolyAlgNode) node ); + return list.set( n, node ); + } + + + @Override + public int size() { + return list.size(); + } + + + @Override + public Node[] toArray() { + return list.toArray( new Node[0]); + } + + + @NotNull + @Override + public Iterator iterator() { + return list.iterator(); + } + +} diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgOperator.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgOperator.java similarity index 95% rename from core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgOperator.java rename to core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgOperator.java index f7bc3d53c7..0e475d4b4f 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgOperator.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/parser/nodes/PolyAlgOperator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.polypheny.db.algebra.polyalg.parser; +package org.polypheny.db.algebra.polyalg.parser.nodes; import java.util.List; import org.polypheny.db.languages.ParserPos; diff --git a/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java b/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java index a07e8c5ded..e23b79c978 100644 --- a/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java +++ b/core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java @@ -84,7 +84,7 @@ import org.polypheny.db.algebra.logical.relational.LogicalRelProject; import org.polypheny.db.algebra.metadata.AlgMetadataQuery; import org.polypheny.db.algebra.operators.OperatorName; -import org.polypheny.db.algebra.polyalg.parser.PolyAlgNode; +import org.polypheny.db.algebra.polyalg.parser.nodes.PolyAlgNode; import org.polypheny.db.algebra.polyalg.parser.PolyAlgParser; import org.polypheny.db.algebra.rules.AggregateProjectPullUpConstantsRule; import org.polypheny.db.algebra.rules.DateRangeRules; From 286ba2302252cfa10ac2fdbb891d4aa617c848af Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Tue, 9 Apr 2024 18:57:53 +0200 Subject: [PATCH 034/132] Create PolyAlgToAlgConverter --- core/src/main/codegen/PolyAlgParser.jj | 10 +- .../org/polypheny/db/algebra/AlgNode.java | 22 +- .../algebra/polyalg/PolyAlgDeclaration.java | 124 +++++++-- .../db/algebra/polyalg/PolyAlgRegistry.java | 30 ++- .../algebra/polyalg/arguments/BooleanArg.java | 3 + .../polyalg/arguments/CollationArg.java | 8 +- .../polyalg/arguments/CorrelationArg.java | 4 +- .../db/algebra/polyalg/arguments/ListArg.java | 12 + .../polyalg/arguments/PolyAlgArgs.java | 50 +++- .../db/algebra/polyalg/arguments/RexArg.java | 24 +- .../polyalg/parser/PolyAlgToAlgConverter.java | 241 ++++++++++++++++++ .../parser/nodes/PolyAlgAliasedArgument.java | 2 + .../parser/nodes/PolyAlgExpression.java | 57 +++++ .../polyalg/parser/nodes/PolyAlgLiteral.java | 20 ++ .../parser/nodes/PolyAlgNamedArgument.java | 7 + .../polyalg/parser/nodes/PolyAlgOperator.java | 3 + .../org/polypheny/db/plan/AlgOptUtil.java | 6 + 17 files changed, 550 insertions(+), 73 deletions(-) create mode 100644 core/src/main/java/org/polypheny/db/algebra/polyalg/parser/PolyAlgToAlgConverter.java diff --git a/core/src/main/codegen/PolyAlgParser.jj b/core/src/main/codegen/PolyAlgParser.jj index 95beaec013..677f96bae2 100644 --- a/core/src/main/codegen/PolyAlgParser.jj +++ b/core/src/main/codegen/PolyAlgParser.jj @@ -134,7 +134,7 @@ TOKEN : | | -| | ) ( | | )+> +| | ) ( | | )*> | )+ (".")? ()*> | <#LETTER: ["_","a"-"z","A"-"Z","ö", "Ö", "ä", "Ä", "ü", "Ü", "à", "À", "ç","Ç", "á", "Á", "è", "È","í","Í", "î", "Î","ó","Ó","ò", "ô", "Ô", "Ò" , "í", "Í", "ë", "Ë", "â", "Â", "ï", "Ï", "é", "É", "ñ", "Ñ", "ß"] > | <#DIGIT: ["0"-"9"]> @@ -260,14 +260,14 @@ PolyAlgExpression Expression(): Token t; PolyAlgLiteral l; String cast = null; - PolyAlgExpression exp; + PolyAlgExpression exp = null; } { - (l = Literal() {literals.add(l);})+ [ childExps = ChildExpressions() ] [ t = {cast = t.image;}] // TODO: handle OVER + (l = Literal() {literals.add(l);})+ [ [childExps = ChildExpressions()] ] [ t = {cast = t.image;}] // TODO: handle OVER {return new PolyAlgExpression(literals, childExps, cast, getPos());} | - exp = Expression() // optional outer parentheses - {return exp;} + [exp = Expression()] // optional outer parentheses + {return exp == null ? new PolyAlgExpression(List.of(), null, null, getPos()) : exp;} } /*PolyAlgNode OuterExpression() : // outer expressions cannot contain separators, as they could not always be differentiated from a ListArgument diff --git a/core/src/main/java/org/polypheny/db/algebra/AlgNode.java b/core/src/main/java/org/polypheny/db/algebra/AlgNode.java index 25acfd1487..e8081b797a 100644 --- a/core/src/main/java/org/polypheny/db/algebra/AlgNode.java +++ b/core/src/main/java/org/polypheny/db/algebra/AlgNode.java @@ -249,7 +249,7 @@ public interface AlgNode extends AlgOptNode, Cloneable { */ void buildPolyAlgebra( StringBuilder sb, String prefix ); - default void buildPolyAlgebra( StringBuilder sb) { + default void buildPolyAlgebra( StringBuilder sb ) { buildPolyAlgebra( sb, null ); } @@ -271,26 +271,6 @@ default void buildPolyAlgebra( StringBuilder sb) { */ PolyAlgArgs collectAttributes(); - /** - * Creates an instance of {@code AlgNode} using reflection, based on the provided class, arguments, and children. - * Implementations of this interface should implement {@code public static AlgNode create(PolyAlgArgs args, List children)}. - * Otherwise, it will result in a NoSuchMethodException. - * - * @param clazz The class representing the implementation of {@code AlgNode}. - * @param args The arguments required for instantiation, whose {@code PolyAlgDeclaration} must correspond to the provided class. - * @param children The list of child nodes or an empty list if this node has no children - * @return A new instance of the provided class - * @throws RuntimeException If there is no method with the specified signature or an error occurred during instance creation - */ - static AlgNode create( Class clazz, PolyAlgArgs args, List children ) { - try { - Method method = clazz.getMethod( "create", PolyAlgArgs.class, List.class ); - return (AlgNode) method.invoke( null, args, children ); - } catch ( NoSuchMethodException | IllegalAccessException | InvocationTargetException e ) { - throw new RuntimeException( e ); - } - } - /** * Receives notification that this expression is about to be registered. The implementation of this method must at least register all child expressions. * diff --git a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java index 142e4e185e..460bec0ba7 100644 --- a/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java +++ b/core/src/main/java/org/polypheny/db/algebra/polyalg/PolyAlgDeclaration.java @@ -19,12 +19,29 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import java.util.HashSet; +import java.util.List; import java.util.Set; +import java.util.function.BiFunction; import java.util.stream.Collectors; import lombok.Builder; import lombok.Data; +import lombok.Getter; import lombok.NonNull; import lombok.Singular; +import org.polypheny.db.algebra.AlgNode; +import org.polypheny.db.algebra.polyalg.arguments.AggArg; +import org.polypheny.db.algebra.polyalg.arguments.AnyArg; +import org.polypheny.db.algebra.polyalg.arguments.BooleanArg; +import org.polypheny.db.algebra.polyalg.arguments.CollationArg; +import org.polypheny.db.algebra.polyalg.arguments.CorrelationArg; +import org.polypheny.db.algebra.polyalg.arguments.EntityArg; +import org.polypheny.db.algebra.polyalg.arguments.EnumArg; +import org.polypheny.db.algebra.polyalg.arguments.FieldArg; +import org.polypheny.db.algebra.polyalg.arguments.IntArg; +import org.polypheny.db.algebra.polyalg.arguments.ListArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArg; +import org.polypheny.db.algebra.polyalg.arguments.PolyAlgArgs; +import org.polypheny.db.algebra.polyalg.arguments.RexArg; public class PolyAlgDeclaration { @@ -38,11 +55,20 @@ public class PolyAlgDeclaration { public final ImmutableList kwParams; private final ImmutableMap paramLookup; + private final BiFunction, AlgNode> creator; + @Builder - public PolyAlgDeclaration( @NonNull String opName, @Singular ImmutableList opAliases, @Singular ImmutableList opTags, int numInputs, @Singular ImmutableList params ) { + public PolyAlgDeclaration( + @NonNull String opName, + @Singular ImmutableList opAliases, + BiFunction, AlgNode> creator, + @Singular ImmutableList opTags, + int numInputs, + @Singular ImmutableList params ) { this.opName = opName; this.opAliases = (opAliases != null) ? opAliases : ImmutableList.of(); + this.creator = creator; this.numInputs = numInputs; this.opTags = (opTags != null) ? opTags : ImmutableList.of(); params = (params != null) ? params : ImmutableList.of(); @@ -53,6 +79,8 @@ public PolyAlgDeclaration( @NonNull String opName, @Singular ImmutableList bPos = ImmutableList.builder(); ImmutableList.Builder bKey = ImmutableList.builder(); for ( Parameter p : params ) { + assert p.hasValidDefault(); + bMap.put( p.name, p ); bMap.putAll( p.aliases.stream().collect( Collectors.toMap( a -> a, a -> p ) ) ); @@ -68,11 +96,32 @@ public PolyAlgDeclaration( @NonNull String opName, @Singular ImmutableList children ) { + return creator.apply( args, children ); + } + + + /** + * Retrieves the positional parameter at the specified position. + * + * @param i The position of the parameter to retrieve. + * @return The parameter at the specified position, or {@code null} if the position is out of bounds. + */ public Parameter getPos( int i ) { + if ( i < 0 || i >= posParams.size() ) { + return null; + } return posParams.get( i ); } + /** + * Retrieves the parameter (positional or keyword) associated with the specified name. + * It is also possible to specify an alias name. + * + * @param name The name of the parameter to retrieve. + * @return The parameter associated with the specified name, or {@code null} if no parameter is found. + */ public Parameter getParam( String name ) { return paramLookup.get( name ); } @@ -108,6 +157,11 @@ public boolean canUnpackValues() { } + public boolean containsParam( Parameter p ) { + return posParams.contains( p ) || kwParams.contains( p ); + } + + /** * Depending on whether a defaultValue is specified, a Parameter can result in two types of corresponding arguments: *