Skip to content

Commit

Permalink
Finish up 2024 in style. (#1152)
Browse files Browse the repository at this point in the history
@meistermeier and I doing team-sdn-ogm things, adding the `FINISH` clause.

Co-authored-by: Gerrit Meier <[email protected]>
  • Loading branch information
michael-simons and meistermeier committed Dec 20, 2024
1 parent 4ff3dd5 commit 11a480c
Show file tree
Hide file tree
Showing 10 changed files with 239 additions and 24 deletions.
2 changes: 1 addition & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
:artifactId: neo4j-cypher-dsl

// This will be next version and also the one that will be put into the manual for the main branch
:neo4j-cypher-dsl-version: 2024.3.3-SNAPSHOT
:neo4j-cypher-dsl-version: 2024.4.0-SNAPSHOT
// This is the latest released version, used only in the readme
:neo4j-cypher-dsl-version-latest: 2024.3.2

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import org.neo4j.cypherdsl.core.Cypher;
import org.neo4j.cypherdsl.core.ExposesRelationships;
import org.neo4j.cypherdsl.core.Expression;
import org.neo4j.cypherdsl.core.Finish;
import org.neo4j.cypherdsl.core.FunctionInvocation;
import org.neo4j.cypherdsl.core.Hint;
import org.neo4j.cypherdsl.core.KeyValueMapEntry;
Expand Down Expand Up @@ -98,7 +99,7 @@ final class CypherDslASTFactory implements ASTFactory<
Statement,
Statement,
Clause,
Clause,
Finish,
Return,
Expression,
List<Expression>,
Expand Down Expand Up @@ -318,8 +319,8 @@ public Clause functionUseClause(InputPosition p, Expression function) {
}

@Override
public Clause newFinishClause(InputPosition p) {
throw new UnsupportedOperationException();
public Finish newFinishClause(InputPosition p) {
return Finish.create();
}

public List<Expression> newReturnItems(InputPosition p, boolean returnAll, List<Expression> returnItems) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class HandleNewMethods {
"isNotNormalized", "normalizeExpression",
"insertClause", "insertPathPattern", "subqueryInTransactionsBatchParameters",
"subqueryInTransactionsConcurrencyParameters", "subqueryInTransactionsErrorParameters",
"grantRoles", "showRoles", "renameRole", "revokeRoles", "newFinishClause",
"grantRoles", "showRoles", "renameRole", "revokeRoles",
"auth", "authId", "password", "passwordChangeRequired", "dynamicLabelLeaf", "databasePrivilegeScope" })
void newMethodsShouldNotBeSupportedOOTB(String methodName) {
var factory = CypherDslASTFactory.getInstance(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
class DefaultStatementBuilder implements StatementBuilder,
OngoingUpdate, OngoingMerge, OngoingReadingWithWhere, OngoingReadingWithoutWhere, OngoingMatchAndUpdate,
BuildableMatchAndUpdate,
BuildableOngoingMergeAction, ExposesSubqueryCall.BuildableSubquery, StatementBuilder.VoidCall {
BuildableOngoingMergeAction, ExposesSubqueryCall.BuildableSubquery, StatementBuilder.VoidCall, StatementBuilder.Terminal {

/**
* Current list of reading or update clauses to be generated.
Expand Down Expand Up @@ -407,10 +407,10 @@ public Statement build() {
return buildImpl(null);
}

protected final Statement buildImpl(Return returning) {
protected final Statement buildImpl(Clause returnOrFinish) {

SinglePartQuery singlePartQuery = SinglePartQuery.create(
buildListOfVisitables(false), returning);
buildListOfVisitables(false), returnOrFinish);

if (multiPartElements.isEmpty()) {
return singlePartQuery;
Expand Down Expand Up @@ -560,6 +560,11 @@ public final OngoingReadingWithoutWhere usingJoinOn(SymbolicName... names) {
return new ForeachBuilder(variable);
}

@Override
public @NotNull Terminal finish() {
return new DefaultStatementWithFinishBuilder();
}

final class ForeachBuilder implements ForeachSourceStep, ForeachUpdateStep {

private final SymbolicName variable;
Expand Down Expand Up @@ -708,6 +713,14 @@ public ResultStatement build() {
}
}

protected final class DefaultStatementWithFinishBuilder implements Terminal {

@Override
public @NotNull Statement build() {
return (ResultStatement) DefaultStatementBuilder.this.buildImpl(Finish.create());
}
}

/**
* Helper class aggregating a couple of interface, collecting conditions and returned objects.
*/
Expand Down Expand Up @@ -1077,6 +1090,11 @@ public LoadCSVStatementBuilder.OngoingLoadCSV loadCSV(URI from, boolean withHead
.addWith(buildWith())
.foreach(variable);
}

@Override
public @NotNull StatementBuilder.Terminal finish() {
return DefaultStatementBuilder.this;
}
}

/**
Expand Down Expand Up @@ -1480,6 +1498,13 @@ public Statement build() {
DefaultStatementBuilder.this.addUpdatingClause(builder.build());
return DefaultStatementBuilder.this.foreach(variable);
}

@Override
public @NotNull StatementBuilder.Terminal finish() {

DefaultStatementBuilder.this.addUpdatingClause(builder.build());
return new DefaultStatementWithFinishBuilder();
}
}

// Static builder and support classes
Expand Down Expand Up @@ -1622,7 +1647,7 @@ public ProcedureCall build() {
}

static final class YieldingStandaloneCallBuilder extends AbstractCallBuilder
implements ExposesWhere<StatementBuilder.OngoingReadingWithWhere>, ExposesReturning, OngoingStandaloneCallWithReturnFields {
implements ExposesWhere<StatementBuilder.OngoingReadingWithWhere>, ExposesReturning, ExposesFinish, OngoingStandaloneCallWithReturnFields {

private final YieldItems yieldItems;

Expand Down Expand Up @@ -1730,6 +1755,11 @@ public ExposesAndThen<OngoingStandaloneCallWithReturnFields, Statement> andThen(
this.delegate.currentSinglePartElements.add(statement);
return this;
}

@Override
public @NotNull StatementBuilder.Terminal finish() {
return new DefaultStatementBuilder(this.buildCall());
}
}

final class InQueryCallBuilder extends AbstractCallBuilder implements
Expand Down Expand Up @@ -1865,6 +1895,11 @@ public VoidCall withoutResults() {
DefaultStatementBuilder.this.currentSinglePartElements.add(this.buildCall());
return DefaultStatementBuilder.this.foreach(variable);
}

@Override
public @NotNull StatementBuilder.Terminal finish() {
return DefaultStatementBuilder.this;
}
}

static final class ConditionBuilder {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2019-2024 "Neo4j,"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* 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
*
* https://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.neo4j.cypherdsl.core;

import static org.apiguardian.api.API.Status.STABLE;

import org.apiguardian.api.API;
import org.jetbrains.annotations.NotNull;
import org.neo4j.cypherdsl.core.annotations.CheckReturnValue;

/**
* A step to finish the query without the need to return anything.
*
* @author Gerrit Meier
*/
@API(status = STABLE, since = "2024.4.0")
public interface ExposesFinish {

@NotNull @CheckReturnValue
StatementBuilder.Terminal finish();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2019-2024 "Neo4j,"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* 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
*
* https://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.neo4j.cypherdsl.core;

import static org.apiguardian.api.API.Status.STABLE;

import org.apiguardian.api.API;
import org.neo4j.cypherdsl.core.ast.Visitor;

/**
* @author Gerrit Meier
* @author Michael J. Simons
*/
@API(status = STABLE, since = "2024.4.0")
public final class Finish implements Clause {

private static final Expression FINISH_EXPRESSION = new RawLiteral.RawElement("FINISH");

private Finish() {

}

public static Finish create() {
return new Finish();
}

@Override
public void accept(Visitor visitor) {
visitor.enter(this);
FINISH_EXPRESSION.accept(visitor);
visitor.leave(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,19 @@
@API(status = INTERNAL, since = "1.0")
class SinglePartQuery extends AbstractStatement implements SingleQuery {

static SinglePartQuery create(List<Visitable> precedingClauses, Return aReturn) {
static SinglePartQuery create(List<Visitable> precedingClauses, Clause returnOrFinish) {

if (precedingClauses.isEmpty() || precedingClauses.get(precedingClauses.size() - 1) instanceof Match) {
Assertions.notNull(aReturn, "A return clause is required.");
Assertions.notNull(returnOrFinish, "A returning or finishing clause is required.");
}

if (aReturn == null) {
if (returnOrFinish == null) {
if (precedingClauses.get(precedingClauses.size() - 1) instanceof ResultStatement) {
return new SinglePartQueryAsResultStatementWrapper(precedingClauses);
}
return new SinglePartQuery(precedingClauses);
} else {
return new SinglePartQueryWithResult(precedingClauses, aReturn);
return new SinglePartQueryWithFinishingClause(precedingClauses, returnOrFinish);
}
}

Expand All @@ -76,21 +76,21 @@ private SinglePartQueryAsResultStatementWrapper(List<Visitable> precedingClauses
}
}

static final class SinglePartQueryWithResult extends SinglePartQuery implements ResultStatement {
static final class SinglePartQueryWithFinishingClause extends SinglePartQuery implements ResultStatement {

private final Return aReturn;
private final Clause finishingClause;

private SinglePartQueryWithResult(List<Visitable> precedingClauses, Return aReturn) {
private SinglePartQueryWithFinishingClause(List<Visitable> precedingClauses, Clause finishingClause) {
super(precedingClauses);

this.aReturn = aReturn;
this.finishingClause = finishingClause;
}

@Override
public void accept(Visitor visitor) {
visitor.enter(this);
super.precedingClauses.forEach(c -> c.accept(visitor));
aReturn.accept(visitor);
finishingClause.accept(visitor);
visitor.leave(this);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@
*/
@API(status = STABLE, since = "1.0")
public interface StatementBuilder
extends ExposesMatch, ExposesCreate, ExposesMerge, ExposesUnwind, ExposesReturning, ExposesSubqueryCall, ExposesWith {
extends ExposesMatch, ExposesCreate, ExposesMerge, ExposesUnwind, ExposesReturning, ExposesFinish, ExposesSubqueryCall, ExposesWith {

/**
* An ongoing update statement that can be used to chain more update statements or add a with or return clause.
*
* @since 1.0
*/
interface OngoingUpdate extends BuildableStatement<Statement>,
ExposesCreate, ExposesMerge, ExposesDelete, ExposesReturning, ExposesWith, ExposesSet, ExposesForeach {
ExposesCreate, ExposesMerge, ExposesDelete, ExposesReturning, ExposesFinish, ExposesWith, ExposesSet, ExposesForeach {
}

/**
Expand Down Expand Up @@ -103,7 +103,7 @@ interface OngoingReadingWithWhere extends OngoingReading, ExposesMatch,
* @since 1.0
*/
interface OngoingReading
extends ExposesReturning, ExposesWith, ExposesUpdatingClause, ExposesUnwind, ExposesCreate, ExposesMatch,
extends ExposesReturning, ExposesFinish, ExposesWith, ExposesUpdatingClause, ExposesUnwind, ExposesCreate, ExposesMatch,
ExposesCall<OngoingInQueryCallWithoutArguments>, ExposesSubqueryCall {
}

Expand Down Expand Up @@ -430,6 +430,16 @@ interface TerminalExposesLimit extends BuildableStatement<ResultStatement> {
BuildableStatement<ResultStatement> limit(Expression expression);
}

/**
* Terminal operation that only allows access to {@link BuildableStatement}.
* A marker interface to clarify the intention instead of just exposing the {@code BuildableStatement}.
*
* @since 2024.3.0
*/
interface Terminal extends BuildableStatement<Statement> {

}

/**
* See {@link TerminalExposesOrderBy}, but on a with clause.
*
Expand Down Expand Up @@ -837,7 +847,7 @@ interface ExposesSetAndRemove extends ExposesSet, ExposesSetLabel<BuildableMatch
*
* @since 1.0
*/
interface OngoingMatchAndUpdate extends ExposesReturning, ExposesWith, ExposesUpdatingClause, ExposesCreate {
interface OngoingMatchAndUpdate extends ExposesReturning, ExposesFinish, ExposesWith, ExposesUpdatingClause, ExposesCreate {
}

/**
Expand Down Expand Up @@ -1013,7 +1023,7 @@ sealed interface OngoingStandaloneCallWithReturnFields extends
StatementBuilder.BuildableStatement<Statement>,
ExposesMatch,
ExposesWhere<StatementBuilder.OngoingReadingWithWhere>,
ExposesReturning, ExposesWith, ExposesSubqueryCall,
ExposesReturning, ExposesFinish, ExposesWith, ExposesSubqueryCall,
ExposesAndThen<OngoingStandaloneCallWithReturnFields, Statement>
permits DefaultStatementBuilder.YieldingStandaloneCallBuilder {
}
Expand Down Expand Up @@ -1062,6 +1072,6 @@ interface VoidCall extends OngoingReading {
* An in-query call exposing where and return clauses.
*/
interface OngoingInQueryCallWithReturnFields extends
ExposesMatch, ExposesWhere<StatementBuilder.OngoingReadingWithWhere>, ExposesReturning, ExposesWith, ExposesSubqueryCall, ExposesForeach {
ExposesMatch, ExposesWhere<StatementBuilder.OngoingReadingWithWhere>, ExposesReturning, ExposesFinish, ExposesWith, ExposesSubqueryCall, ExposesForeach {
}
}
Loading

0 comments on commit 11a480c

Please sign in to comment.