Skip to content

Commit

Permalink
feat: new break statement in scripts to exit from a loop/foreach
Browse files Browse the repository at this point in the history
Fixed issue #1647
  • Loading branch information
lvca committed Jul 8, 2024
1 parent 6e5b0af commit dff804c
Show file tree
Hide file tree
Showing 12 changed files with 4,886 additions and 4,663 deletions.
15 changes: 15 additions & 0 deletions engine/src/main/grammar/SQLGrammar.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ TOKEN:
|
<BY: ("b"|"B")("y"|"Y")>
|
<BREAK: ("b"|"B")("r"|"R")("e"|"E")("a"|"A")("k"|"K")>
|
<LIMIT: ("l"|"L")("i"|"I")("m"|"M")("i"|"I")("t"|"T")>
|
<SKIP2: ("s"|"S")("k"|"K")("i"|"I")("p"|"P")>
Expand Down Expand Up @@ -4139,6 +4141,13 @@ RollbackStatement RollbackStatement():
{return jjtThis;}
}

BreakStatement BreakStatement():
{ }
{
<BREAK>
{return jjtThis;}
}

ReturnStatement ReturnStatement():
{ }
{
Expand All @@ -4165,6 +4174,8 @@ IfStatement IfStatement():
|
last = ForEachBlock() {jjtThis.statements.add(last); }
|
last = BreakStatement() {jjtThis.statements.add(last); }
|
<SEMICOLON>
)*
<RBRACE>
Expand Down Expand Up @@ -4210,6 +4221,8 @@ ForEachBlock ForEachBlock():
|
last = WhileBlock() {jjtThis.statements.add(last); }
|
last = BreakStatement() {jjtThis.statements.add(last); }
|
<SEMICOLON>
)*
<RBRACE>
Expand All @@ -4235,6 +4248,8 @@ WhileBlock WhileBlock():
|
last = WhileBlock() {jjtThis.statements.add(last); }
|
last = BreakStatement() {jjtThis.statements.add(last); }
|
<SEMICOLON>
)*
<RBRACE>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright © 2021-present Arcade Data Ltd (info@arcadedata.com)
*
* 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.
*
* SPDX-FileCopyrightText: 2021-present Arcade Data Ltd (info@arcadedata.com)
* SPDX-License-Identifier: Apache-2.0
*/
package com.arcadedb.query.sql.executor;

import com.arcadedb.exception.TimeoutException;
import com.arcadedb.query.sql.parser.BreakStatement;
import com.arcadedb.query.sql.parser.SimpleExecStatement;

/**
* @author Luca Garulli (l.garulli@arcadedata.com)
*/
public class BreakStep extends AbstractExecutionStep {
public BreakStep(final CommandContext context) {
super(context);
}

@Override
public ResultSet syncPull(final CommandContext context, final int nRecords) throws TimeoutException {
return BreakStatement.BREAK_RESULTSET;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public ResultSet syncPull(final CommandContext context, final int nRecords) thro
context.setVariable(loopVariable.getStringValue(), iterator.next());
final ScriptExecutionPlan plan = initPlan(context);
final ExecutionStepInternal result = plan.executeFull();

if (result != null) {
this.finalResult = result;
return result.syncPull(context, nRecords);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* Created by luigidellaquila on 08/08/16.
*/

import com.arcadedb.query.sql.parser.BreakStatement;
import com.arcadedb.query.sql.parser.Statement;

import java.util.*;
Expand Down Expand Up @@ -59,6 +60,10 @@ public void close() {
@Override
public ResultSet fetchNext(final int n) {
doExecute(n);

if (lastStep instanceof BreakStep)
return BreakStatement.BREAK_RESULTSET;

return new ResultSet() {

@Override
Expand Down Expand Up @@ -94,6 +99,12 @@ private void doExecute(final int n) {
finalResult = new InternalResultSet();
if (lastStep != null) {
ResultSet partial = lastStep.syncPull(context, n);

if (partial == BreakStatement.BREAK_RESULTSET) {
lastStep = new BreakStep(context);
return;
}

while (partial.hasNext()) {
while (partial.hasNext()) {
((InternalResultSet) finalResult).add(partial.next());
Expand Down Expand Up @@ -174,7 +185,7 @@ public boolean containsReturn() {
* @return
*/
public ExecutionStepInternal executeUntilReturn() {
if (steps.size() > 0) {
if (!steps.isEmpty()) {
lastStep = steps.get(steps.size() - 1);
for (int i = 0; i < steps.size() - 1; i++) {
final ScriptLineStep step = steps.get(i);
Expand Down Expand Up @@ -215,6 +226,9 @@ public ExecutionStepInternal executeFull() {

ResultSet lastResult = step.syncPull(context, DEFAULT_FETCH_RECORDS_PER_PULL);

if (lastResult == BreakStatement.BREAK_RESULTSET)
return new BreakStep(context);

while (lastResult.hasNext()) {
while (lastResult.hasNext())
lastResult.next();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package com.arcadedb.query.sql.executor;

import com.arcadedb.exception.TimeoutException;
import com.arcadedb.query.sql.parser.BreakStatement;
import com.arcadedb.query.sql.parser.IfStatement;
import com.arcadedb.query.sql.parser.ReturnStatement;
import com.arcadedb.query.sql.parser.Statement;
Expand Down Expand Up @@ -51,8 +52,11 @@ else if (plan instanceof UpdateExecutionPlan)
((UpdateExecutionPlan) plan).executeInternal();
else if (plan instanceof DDLExecutionPlan)
((DDLExecutionPlan) plan).executeInternal();
else if (plan instanceof SingleOpExecutionPlan)
((SingleOpExecutionPlan) plan).executeInternal();
else if (plan instanceof SingleOpExecutionPlan) {
final ResultSet res = ((SingleOpExecutionPlan) plan).executeInternal();
if (res == BreakStatement.BREAK_RESULTSET)
return res;
}

executed = true;
}
Expand All @@ -63,12 +67,11 @@ public boolean containsReturn() {
if (plan instanceof ScriptExecutionPlan)
return ((ScriptExecutionPlan) plan).containsReturn();

if (plan instanceof SingleOpExecutionPlan) {
else if (plan instanceof SingleOpExecutionPlan) {
if (((SingleOpExecutionPlan) plan).statement instanceof ReturnStatement)
return true;
}

if (plan instanceof IfExecutionPlan) {
} else if (plan instanceof IfExecutionPlan) {
final IfStep step = (IfStep) plan.getSteps().get(0);
if (step.positivePlan != null && step.positivePlan.containsReturn())
return true;
Expand All @@ -78,9 +81,7 @@ else if (step.positiveStatements != null) {
return true;
}
}
}

if (plan instanceof ForEachExecutionPlan)
} else if (plan instanceof ForEachExecutionPlan)
return ((ForEachExecutionPlan) plan).containsReturn();

return false;
Expand All @@ -102,14 +103,13 @@ private boolean containsReturn(final Statement stm) {
public ExecutionStepInternal executeUntilReturn(final CommandContext context) {
if (plan instanceof ScriptExecutionPlan)
return ((ScriptExecutionPlan) plan).executeUntilReturn();

if (plan instanceof SingleOpExecutionPlan) {
else if (plan instanceof SingleOpExecutionPlan) {
if (((SingleOpExecutionPlan) plan).statement instanceof ReturnStatement)
return new ReturnStep(((SingleOpExecutionPlan) plan).statement, context);
}

if (plan instanceof IfExecutionPlan)
} else if (plan instanceof IfExecutionPlan)
return ((IfExecutionPlan) plan).executeUntilReturn();
else if (plan instanceof BreakStatement)
return new BreakStep(context);

throw new NoSuchElementException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package com.arcadedb.query.sql.executor;

import com.arcadedb.exception.CommandExecutionException;
import com.arcadedb.query.sql.parser.BreakStatement;
import com.arcadedb.query.sql.parser.SimpleExecStatement;

import java.util.*;
Expand All @@ -45,9 +46,9 @@ public ResultSet fetchNext(final int n) {
if (!executed) {
executed = true;
result = statement.executeSimple(this.context);
if (result instanceof InternalResultSet) {
if (result instanceof InternalResultSet)
((InternalResultSet) result).plan = this;
}

}
return new ResultSet() {
int fetched = 0;
Expand All @@ -70,7 +71,6 @@ public Result next() {
public void close() {
result.close();
}

};
}

Expand All @@ -84,14 +84,15 @@ public boolean canBeCached() {
}

public ResultSet executeInternal() throws CommandExecutionException {
if (executed) {
if (executed)
throw new CommandExecutionException("Trying to execute a result-set twice. Please use reset()");
}

executed = true;

result = statement.executeSimple(this.context);
if (result instanceof InternalResultSet) {
if (result instanceof InternalResultSet)
((InternalResultSet) result).plan = this;
}

return result;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* Generated By:JJTree: Do not edit this line. BreakStatement.java Version 7.0 */
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=false,TRACK_TOKENS=true,NODE_PREFIX=,NODE_EXTENDS=,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
package com.arcadedb.query.sql.parser;

import com.arcadedb.query.sql.executor.CommandContext;
import com.arcadedb.query.sql.executor.InternalResultSet;
import com.arcadedb.query.sql.executor.Result;
import com.arcadedb.query.sql.executor.ResultSet;

import java.util.*;

public class BreakStatement extends SimpleExecStatement {
public static final ResultSet BREAK_RESULTSET = new ResultSet() {
@Override
public boolean hasNext() {
return false;
}

@Override
public Result next() {
return null;
}
};

public BreakStatement(int id) {
super(id);
}

@Override
public ResultSet executeSimple(final CommandContext context) {
return BREAK_RESULTSET;
}

@Override
public void toString(final Map<String, Object> params, final StringBuilder builder) {
builder.append("RETURN");
}
}
/* JavaCC - OriginalChecksum=7c151cab41b31cd675cea2f3becdc628 (do not edit this line) */
Loading

0 comments on commit dff804c

Please sign in to comment.