From 8eb6af71fc5f3d3f78d0e1d63bac36d1ba1e2817 Mon Sep 17 00:00:00 2001 From: Tobias Hafner Date: Wed, 18 Dec 2024 11:12:50 +0100 Subject: [PATCH] Use enumerables for doc identifiers --- .../enumerable/EnumerableRelIdentifier.java | 59 ++++++++++++++ ....java => EnumerableRelIdentifierRule.java} | 21 ++--- .../algebra/enumerable/EnumerableRules.java | 7 +- .../EnumerableDocIdentifier.java} | 10 +-- .../document/EnumerableDocIdentifierRule.java | 76 +++++++++++++++++++ .../document/LogicalDocIdentifier.java | 60 +++++++++++++++ .../org/polypheny/db/functions/Functions.java | 12 ++- .../transaction/locking/AlgTreeRewriter.java | 48 +++++++----- .../org/polypheny/db/util/BuiltInMethod.java | 3 +- 9 files changed, 254 insertions(+), 42 deletions(-) create mode 100644 core/src/main/java/org/polypheny/db/algebra/enumerable/EnumerableRelIdentifier.java rename core/src/main/java/org/polypheny/db/algebra/enumerable/{common/EnumerableIdentifierRule.java => EnumerableRelIdentifierRule.java} (56%) rename core/src/main/java/org/polypheny/db/algebra/enumerable/{common/EnumerableIdentifier.java => document/EnumerableDocIdentifier.java} (87%) create mode 100644 core/src/main/java/org/polypheny/db/algebra/enumerable/document/EnumerableDocIdentifierRule.java create mode 100644 core/src/main/java/org/polypheny/db/algebra/logical/document/LogicalDocIdentifier.java diff --git a/core/src/main/java/org/polypheny/db/algebra/enumerable/EnumerableRelIdentifier.java b/core/src/main/java/org/polypheny/db/algebra/enumerable/EnumerableRelIdentifier.java new file mode 100644 index 0000000000..d8048d2c19 --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/enumerable/EnumerableRelIdentifier.java @@ -0,0 +1,59 @@ +/* + * 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.enumerable; + +import org.apache.calcite.linq4j.tree.BlockBuilder; +import org.apache.calcite.linq4j.tree.Expression; +import org.apache.calcite.linq4j.tree.Expressions; +import org.polypheny.db.algebra.AlgNode; +import org.polypheny.db.algebra.core.common.Identifier; +import org.polypheny.db.algebra.metadata.AlgMetadataQuery; +import org.polypheny.db.catalog.entity.Entity; +import org.polypheny.db.plan.AlgCluster; +import org.polypheny.db.plan.AlgOptCost; +import org.polypheny.db.plan.AlgPlanner; +import org.polypheny.db.plan.AlgTraitSet; +import org.polypheny.db.util.BuiltInMethod; + +public class EnumerableRelIdentifier extends Identifier implements EnumerableAlg { + + protected EnumerableRelIdentifier( AlgCluster cluster, AlgTraitSet traits, Entity entity, AlgNode input ) { + super( cluster, traits, entity, input ); + assert getConvention() instanceof EnumerableConvention; + } + + @Override + public AlgOptCost computeSelfCost( AlgPlanner planner, AlgMetadataQuery mq ) { + double dRows = mq.getTupleCount( getInput() ); + return planner.getCostFactory().makeCost( dRows, 0, 0 ); + } + + @Override + public Result implement( EnumerableAlgImplementor implementor, Prefer pref ) { + final BlockBuilder builder = new BlockBuilder(); + final EnumerableAlg input = (EnumerableAlg) getInput(); + final Result result = implementor.visitChild( this, 0, input, Prefer.ANY ); + final PhysType physType = result.physType(); + + Expression input_ = builder.append( "input", result.block() ); + Expression identification_ = builder.append( "identification", Expressions.call( input_, BuiltInMethod.ADD_REL_IDENTIFIERS.method ) ); + + builder.add( Expressions.return_( null, identification_ ) ); + return implementor.result( physType, builder.toBlock() ); + + } +} diff --git a/core/src/main/java/org/polypheny/db/algebra/enumerable/common/EnumerableIdentifierRule.java b/core/src/main/java/org/polypheny/db/algebra/enumerable/EnumerableRelIdentifierRule.java similarity index 56% rename from core/src/main/java/org/polypheny/db/algebra/enumerable/common/EnumerableIdentifierRule.java rename to core/src/main/java/org/polypheny/db/algebra/enumerable/EnumerableRelIdentifierRule.java index 5573b5ef4d..176d391b51 100644 --- a/core/src/main/java/org/polypheny/db/algebra/enumerable/common/EnumerableIdentifierRule.java +++ b/core/src/main/java/org/polypheny/db/algebra/enumerable/EnumerableRelIdentifierRule.java @@ -14,34 +14,27 @@ * limitations under the License. */ -package org.polypheny.db.algebra.enumerable.common; +package org.polypheny.db.algebra.enumerable; import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.convert.ConverterRule; -import org.polypheny.db.algebra.core.common.Identifier; -import org.polypheny.db.algebra.enumerable.EnumerableConvention; import org.polypheny.db.algebra.logical.relational.LogicalRelIdentifier; import org.polypheny.db.plan.AlgTraitSet; import org.polypheny.db.plan.Convention; -public class EnumerableIdentifierRule extends ConverterRule { - - public static final EnumerableIdentifierRule REL_INSTANCE = new EnumerableIdentifierRule( LogicalRelIdentifier.class ); - - public static final EnumerableIdentifierRule DOC_INSTANCE = new EnumerableIdentifierRule( LogicalRelIdentifier.class ); - - - private EnumerableIdentifierRule( Class identifier ) { - super( identifier, Convention.NONE, EnumerableConvention.INSTANCE, "EnumerableIdentifierRule" ); +public class EnumerableRelIdentifierRule extends ConverterRule { + + EnumerableRelIdentifierRule() { + super( LogicalRelIdentifier.class, Convention.NONE, EnumerableConvention.INSTANCE, "EnumerableRelIdentifierRule" ); } @Override public AlgNode convert( AlgNode alg ) { - final Identifier identifier = (Identifier) alg; + final LogicalRelIdentifier identifier = (LogicalRelIdentifier) alg; final AlgTraitSet traits = identifier.getTraitSet().replace( EnumerableConvention.INSTANCE ); final AlgNode input = identifier.getInput(); - return new EnumerableIdentifier( identifier.getCluster(), traits, identifier.getEntity(), input ); + return new EnumerableRelIdentifier( identifier.getCluster(), traits, identifier.getEntity(), input ); } } diff --git a/core/src/main/java/org/polypheny/db/algebra/enumerable/EnumerableRules.java b/core/src/main/java/org/polypheny/db/algebra/enumerable/EnumerableRules.java index aecf5fd984..a490156050 100644 --- a/core/src/main/java/org/polypheny/db/algebra/enumerable/EnumerableRules.java +++ b/core/src/main/java/org/polypheny/db/algebra/enumerable/EnumerableRules.java @@ -42,8 +42,8 @@ import org.polypheny.db.algebra.enumerable.common.EnumerableConditionalExecuteTrueRule; import org.polypheny.db.algebra.enumerable.common.EnumerableConstraintEnforcerRule; import org.polypheny.db.algebra.enumerable.common.EnumerableContextSwitcherRule; -import org.polypheny.db.algebra.enumerable.common.EnumerableIdentifierRule; import org.polypheny.db.algebra.enumerable.common.EnumerableModifyCollectRule; +import org.polypheny.db.algebra.enumerable.document.EnumerableDocIdentifierRule; import org.polypheny.db.algebra.enumerable.document.EnumerableDocumentUnwindRule; import org.polypheny.db.algebra.enumerable.document.EnumerableDocumentValuesRule; import org.polypheny.db.algebra.enumerable.lpg.EnumerableLpgMatchRule; @@ -74,9 +74,10 @@ public class EnumerableRules { private EnumerableRules() { } - public static final EnumerableIdentifierRule ENUMERABLE_REL_IDENTIFIER_RULE = EnumerableIdentifierRule.REL_INSTANCE; - public static final EnumerableIdentifierRule ENUMERABLE_DOC_IDENTIFIER_RULE = EnumerableIdentifierRule.DOC_INSTANCE; + public static final EnumerableRelIdentifierRule ENUMERABLE_REL_IDENTIFIER_RULE = new EnumerableRelIdentifierRule(); + + public static final EnumerableDocIdentifierRule ENUMERABLE_DOC_IDENTIFIER_RULE = new EnumerableDocIdentifierRule(); public static final EnumerableConditionalExecuteRule ENUMERABLE_CONDITIONAL_EXECUTE_RULE = new EnumerableConditionalExecuteRule(); diff --git a/core/src/main/java/org/polypheny/db/algebra/enumerable/common/EnumerableIdentifier.java b/core/src/main/java/org/polypheny/db/algebra/enumerable/document/EnumerableDocIdentifier.java similarity index 87% rename from core/src/main/java/org/polypheny/db/algebra/enumerable/common/EnumerableIdentifier.java rename to core/src/main/java/org/polypheny/db/algebra/enumerable/document/EnumerableDocIdentifier.java index b458445180..cf0604e170 100644 --- a/core/src/main/java/org/polypheny/db/algebra/enumerable/common/EnumerableIdentifier.java +++ b/core/src/main/java/org/polypheny/db/algebra/enumerable/document/EnumerableDocIdentifier.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.polypheny.db.algebra.enumerable.common; +package org.polypheny.db.algebra.enumerable.document; import org.apache.calcite.linq4j.tree.BlockBuilder; import org.apache.calcite.linq4j.tree.Expression; @@ -33,9 +33,9 @@ import org.polypheny.db.plan.AlgTraitSet; import org.polypheny.db.util.BuiltInMethod; -public class EnumerableIdentifier extends Identifier implements EnumerableAlg { +public class EnumerableDocIdentifier extends Identifier implements EnumerableAlg { - protected EnumerableIdentifier( AlgCluster cluster, AlgTraitSet traits, Entity entity, AlgNode input ) { + protected EnumerableDocIdentifier( AlgCluster cluster, AlgTraitSet traits, Entity entity, AlgNode input ) { super( cluster, traits, entity, input ); assert getConvention() instanceof EnumerableConvention; } @@ -54,11 +54,9 @@ public Result implement( EnumerableAlgImplementor implementor, Prefer pref ) { final PhysType physType = result.physType(); Expression input_ = builder.append( "input", result.block() ); - Expression identification_ = builder.append( "identification", Expressions.call( input_, BuiltInMethod.ADD_IDENTIFIERS.method ) ); + Expression identification_ = builder.append( "identification", Expressions.call( input_, BuiltInMethod.ADD_DOC_IDENTIFIERS.method ) ); builder.add( Expressions.return_( null, identification_ ) ); return implementor.result( physType, builder.toBlock() ); - } - } diff --git a/core/src/main/java/org/polypheny/db/algebra/enumerable/document/EnumerableDocIdentifierRule.java b/core/src/main/java/org/polypheny/db/algebra/enumerable/document/EnumerableDocIdentifierRule.java new file mode 100644 index 0000000000..034696c67c --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/enumerable/document/EnumerableDocIdentifierRule.java @@ -0,0 +1,76 @@ +/* + * 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.enumerable.document; + +import org.apache.calcite.linq4j.tree.BlockBuilder; +import org.apache.calcite.linq4j.tree.Expression; +import org.apache.calcite.linq4j.tree.Expressions; +import org.polypheny.db.algebra.AlgNode; +import org.polypheny.db.algebra.convert.ConverterRule; +import org.polypheny.db.algebra.enumerable.EnumerableAlg; +import org.polypheny.db.algebra.enumerable.EnumerableAlg.Prefer; +import org.polypheny.db.algebra.enumerable.EnumerableAlg.Result; +import org.polypheny.db.algebra.enumerable.EnumerableAlgImplementor; +import org.polypheny.db.algebra.enumerable.EnumerableConvention; +import org.polypheny.db.algebra.enumerable.EnumerableRelIdentifier; +import org.polypheny.db.algebra.enumerable.PhysType; +import org.polypheny.db.algebra.logical.document.LogicalDocIdentifier; +import org.polypheny.db.algebra.logical.relational.LogicalRelIdentifier; +import org.polypheny.db.algebra.metadata.AlgMetadataQuery; +import org.polypheny.db.catalog.entity.Entity; +import org.polypheny.db.plan.AlgCluster; +import org.polypheny.db.plan.AlgOptCost; +import org.polypheny.db.plan.AlgPlanner; +import org.polypheny.db.plan.AlgTraitSet; +import org.polypheny.db.plan.Convention; +import org.polypheny.db.util.BuiltInMethod; + + + +/* + * 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. + */ + + +public class EnumerableDocIdentifierRule extends ConverterRule { + + public EnumerableDocIdentifierRule() { + super( LogicalRelIdentifier.class, Convention.NONE, EnumerableConvention.INSTANCE, "EnumerableDocIdentifierRule" ); + } + + @Override + public AlgNode convert( AlgNode alg ) { + final LogicalRelIdentifier identifier = (LogicalRelIdentifier) alg; + final AlgTraitSet traits = identifier.getTraitSet().replace( EnumerableConvention.INSTANCE ); + final AlgNode input = identifier.getInput(); + return new EnumerableDocIdentifier( identifier.getCluster(), traits, identifier.getEntity(), input ); + } + +} + diff --git a/core/src/main/java/org/polypheny/db/algebra/logical/document/LogicalDocIdentifier.java b/core/src/main/java/org/polypheny/db/algebra/logical/document/LogicalDocIdentifier.java new file mode 100644 index 0000000000..c6394b079b --- /dev/null +++ b/core/src/main/java/org/polypheny/db/algebra/logical/document/LogicalDocIdentifier.java @@ -0,0 +1,60 @@ +/* + * Copyright 2019-2024 The Polypheny Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.polypheny.db.algebra.logical.document; + +import java.util.List; +import org.polypheny.db.algebra.AlgNode; +import org.polypheny.db.algebra.core.common.Identifier; +import org.polypheny.db.algebra.core.document.DocumentAlg; +import org.polypheny.db.algebra.metadata.AlgMetadataQuery; +import org.polypheny.db.catalog.entity.Entity; +import org.polypheny.db.plan.AlgCluster; +import org.polypheny.db.plan.AlgOptCost; +import org.polypheny.db.plan.AlgPlanner; +import org.polypheny.db.plan.AlgTraitSet; + +public class LogicalDocIdentifier extends Identifier implements DocumentAlg { + protected LogicalDocIdentifier( Entity entitiy, AlgCluster cluster, AlgTraitSet traits, AlgNode input) { + super(cluster, traits, entitiy, input); + } + + public static LogicalDocIdentifier create(Entity document, final AlgNode input) { + final AlgCluster cluster = input.getCluster(); + final AlgTraitSet traits = input.getTraitSet(); + return new LogicalDocIdentifier( document, cluster, traits, input ); + } + + + @Override + public DocType getDocType() { + // ToDo TH: is this correct? + return DocType.VALUES; + } + + @Override + public AlgOptCost computeSelfCost( AlgPlanner planner, AlgMetadataQuery mq ) { + double dRows = mq.getTupleCount( getInput() ); + return planner.getCostFactory().makeCost( dRows, 0, 0 ); + } + + @Override + public AlgNode copy(AlgTraitSet traitSete, List inputs) { + return new LogicalDocIdentifier(entity, getCluster(), traitSete, sole(inputs) ); + } + + +} diff --git a/core/src/main/java/org/polypheny/db/functions/Functions.java b/core/src/main/java/org/polypheny/db/functions/Functions.java index 9a2805e489..3a532cc762 100644 --- a/core/src/main/java/org/polypheny/db/functions/Functions.java +++ b/core/src/main/java/org/polypheny/db/functions/Functions.java @@ -113,6 +113,7 @@ import org.polypheny.db.type.entity.PolyValue; import org.polypheny.db.type.entity.category.PolyNumber; import org.polypheny.db.type.entity.category.PolyTemporal; +import org.polypheny.db.type.entity.document.PolyDocument; import org.polypheny.db.type.entity.graph.PolyDictionary; import org.polypheny.db.type.entity.numerical.PolyBigDecimal; import org.polypheny.db.type.entity.numerical.PolyDouble; @@ -290,7 +291,7 @@ public static Enumerable batch( final DataContext context, final Enumerable

addIdentifiers(final Enumerable input) { + public static Enumerable addRelIdentifiers(final Enumerable input) { return input.select( oldRow -> { PolyValue[] newRow = new PolyValue[oldRow.length + 1]; newRow[0] = IdentifierUtils.getIdentifierAsPolyLong(); @@ -299,6 +300,15 @@ public static Enumerable addIdentifiers(final Enumerable addDocIdentifiers(final Enumerable input) { + return input.select( oldRow -> { + PolyDocument document = (PolyDocument) oldRow[0]; + document.put( IdentifierUtils.getIdentifierKeyAsPolyString(), IdentifierUtils.getIdentifierAsPolyLong() ); + return new PolyValue[]{document}; + } ); + } + @SuppressWarnings("unused") public static Enumerable streamRight( final DataContext context, final Enumerable input, final Function0> executorCall, final List polyTypes ) { diff --git a/core/src/main/java/org/polypheny/db/transaction/locking/AlgTreeRewriter.java b/core/src/main/java/org/polypheny/db/transaction/locking/AlgTreeRewriter.java index 743b6f3086..0332cc2af6 100644 --- a/core/src/main/java/org/polypheny/db/transaction/locking/AlgTreeRewriter.java +++ b/core/src/main/java/org/polypheny/db/transaction/locking/AlgTreeRewriter.java @@ -22,7 +22,6 @@ import org.polypheny.db.algebra.AlgNode; import org.polypheny.db.algebra.AlgRoot; import org.polypheny.db.algebra.AlgShuttleImpl; -import org.polypheny.db.algebra.core.common.Modify.Operation; import org.polypheny.db.algebra.logical.common.LogicalConditionalExecute; import org.polypheny.db.algebra.logical.common.LogicalConstraintEnforcer; import org.polypheny.db.algebra.logical.document.LogicalDocumentAggregate; @@ -227,16 +226,18 @@ public AlgNode visit( LogicalConditionalExecute lce ) { @Override public AlgNode visit( LogicalRelModify modify ) { - if ( modify.getOperation() != Operation.INSERT ) { - return visitChildren( modify ); + switch ( modify.getOperation() ) { + case INSERT: + AlgNode input = modify.getInput(); + LogicalRelIdentifier identifier = LogicalRelIdentifier.create( + modify.getEntity(), + input, + input.getTupleType() + ); + return modify.copy( modify.getTraitSet(), List.of( identifier ) ); + default: + return visitChildren( modify ); } - AlgNode input = modify.getInput(); - LogicalRelIdentifier identifier = LogicalRelIdentifier.create( - modify.getEntity(), - input, - input.getTupleType() - ); - return modify.copy( modify.getTraitSet(), List.of( identifier ) ); } @@ -259,8 +260,7 @@ public AlgNode visit( LogicalLpgScan scan ) { @Override - public AlgNode visit( LogicalLpgValues values ) - { + public AlgNode visit( LogicalLpgValues values ) { values.getNodes().forEach( n -> n.getProperties().put( IdentifierUtils.getIdentifierKeyAsPolyString(), IdentifierUtils.getIdentifierAsPolyLong() ) ); values.getEdges().forEach( n -> n.getProperties().put( IdentifierUtils.getIdentifierKeyAsPolyString(), IdentifierUtils.getIdentifierAsPolyLong() ) ); return values; @@ -311,10 +311,21 @@ public AlgNode visit( LogicalLpgTransformer transformer ) { @Override public AlgNode visit( LogicalDocumentModify modify ) { - if (modify.operation == Operation.UPDATE) { - IdentifierUtils.throwIfContainsIdentifierKey( modify.getUpdates().keySet() ); + switch ( modify.getOperation() ) { + case INSERT: + AlgNode input = modify.getInput(); + LogicalRelIdentifier identifier = LogicalRelIdentifier.create( + modify.getEntity(), + input, + input.getTupleType() + ); + return modify.copy( modify.getTraitSet(), List.of( identifier ) ); + case UPDATE: + IdentifierUtils.throwIfContainsIdentifierKey( modify.getUpdates().keySet() ); + return visitChildren( modify ); + default: + return visitChildren( modify ); } - return visitChildren( modify ); } @@ -356,11 +367,14 @@ public AlgNode visit( LogicalDocumentTransformer transformer ) { @Override public AlgNode visit( LogicalDocumentValues values ) { + /* IdentifierUtils.throwIfContainsIdentifierKey( values.getDocuments() ); List newDocuments = values.getDocuments().stream() - .peek(d -> d.put( IdentifierUtils.getIdentifierKeyAsPolyString(), IdentifierUtils.getIdentifierAsPolyLong() ) ) - .collect( Collectors.toCollection(LinkedList::new)); + .peek( d -> d.put( IdentifierUtils.getIdentifierKeyAsPolyString(), IdentifierUtils.getIdentifierAsPolyLong() ) ) + .collect( Collectors.toCollection( LinkedList::new ) ); return LogicalDocumentValues.create( values.getCluster(), newDocuments ); + */ + return values; } diff --git a/core/src/main/java/org/polypheny/db/util/BuiltInMethod.java b/core/src/main/java/org/polypheny/db/util/BuiltInMethod.java index 5a1300f364..0f926367c7 100644 --- a/core/src/main/java/org/polypheny/db/util/BuiltInMethod.java +++ b/core/src/main/java/org/polypheny/db/util/BuiltInMethod.java @@ -155,7 +155,8 @@ public enum BuiltInMethod { SWITCH_CONTEXT( DataContext.class, "switchContext" ), BATCH( Functions.class, "batch", DataContext.class, Enumerable.class ), STREAM_RIGHT( Functions.class, "streamRight", DataContext.class, Enumerable.class, Function0.class, List.class ), - ADD_IDENTIFIERS(Functions.class, "addIdentifiers", Enumerable.class), + ADD_REL_IDENTIFIERS(Functions.class, "addRelIdentifiers", Enumerable.class), + ADD_DOC_IDENTIFIERS(Functions.class, "addDocIdentifiers", Enumerable.class), ENFORCE_CONSTRAINT( Functions.class, "enforceConstraint", DataContext.class, Function0.class, Function0.class, List.class, List.class ), PARSE_ARRAY_FROM_TEXT( Functions.class, "reparse", String.class ), QUERYABLE_SELECT( Queryable.class, "select", FunctionExpression.class ),