Skip to content
This repository was archived by the owner on Jul 6, 2023. It is now read-only.

Commit c371924

Browse files
committed
New CLI arg "--param" to add parameters to the session.
1 parent 2d526ea commit c371924

22 files changed

+411
-118
lines changed

cypher-shell/src/integration-test/java/org/neo4j/shell/MainIntegrationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,6 @@ private ShellAndConnection getShell( CliArgs cliArgs )
146146
cliArgs.getEncryption(),
147147
cliArgs.getDatabase() );
148148

149-
return new ShellAndConnection( new CypherShell( logger, prettyConfig, true ), connectionConfig );
149+
return new ShellAndConnection( new CypherShell( logger, prettyConfig, true, new ShellParameterMap() ), connectionConfig );
150150
}
151151
}

cypher-shell/src/integration-test/java/org/neo4j/shell/commands/CypherShellFailureIntegrationTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@
77

88
import org.neo4j.driver.exceptions.AuthenticationException;
99
import org.neo4j.shell.CypherShell;
10+
import org.neo4j.shell.ShellParameterMap;
1011
import org.neo4j.shell.StringLinePrinter;
1112
import org.neo4j.shell.cli.Format;
1213
import org.neo4j.shell.exception.CommandException;
1314
import org.neo4j.shell.prettyprint.PrettyConfig;
1415

15-
import static org.neo4j.driver.internal.messaging.request.MultiDatabaseUtil.ABSENT_DB_NAME;
16-
1716
public class CypherShellFailureIntegrationTest extends CypherShellIntegrationTest {
1817
@Rule
1918
public final ExpectedException thrown = ExpectedException.none();
@@ -23,7 +22,7 @@ public class CypherShellFailureIntegrationTest extends CypherShellIntegrationTes
2322
@Before
2423
public void setUp() {
2524
linePrinter.clear();
26-
shell = new CypherShell(linePrinter, new PrettyConfig(Format.VERBOSE, true, 1000), false);
25+
shell = new CypherShell(linePrinter, new PrettyConfig(Format.VERBOSE, true, 1000), false, new ShellParameterMap());
2726
}
2827

2928
@Test

cypher-shell/src/integration-test/java/org/neo4j/shell/commands/CypherShellMultiDatabaseIntegrationTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.neo4j.driver.exceptions.ClientException;
1010
import org.neo4j.shell.ConnectionConfig;
1111
import org.neo4j.shell.CypherShell;
12+
import org.neo4j.shell.ShellParameterMap;
1213
import org.neo4j.shell.StringLinePrinter;
1314
import org.neo4j.shell.cli.Format;
1415
import org.neo4j.shell.exception.CommandException;
@@ -39,7 +40,7 @@ public class CypherShellMultiDatabaseIntegrationTest
3940
public void setUp() throws Exception
4041
{
4142
linePrinter.clear();
42-
shell = new CypherShell( linePrinter, new PrettyConfig( Format.PLAIN, true, 1000 ), false );
43+
shell = new CypherShell( linePrinter, new PrettyConfig( Format.PLAIN, true, 1000 ), false, new ShellParameterMap() );
4344
useCommand = new Use( shell );
4445
beginCommand = new Begin( shell );
4546
rollbackCommand = new Rollback( shell );
@@ -134,7 +135,7 @@ public void switchingToNonExistingDatabaseShouldGiveErrorResponseFromServer() th
134135
@Test
135136
public void switchingToNonExistingDatabaseShouldGiveErrorResponseFromServerInteractive() throws CommandException
136137
{
137-
shell = new CypherShell( linePrinter, new PrettyConfig( Format.PLAIN, true, 1000 ), true );
138+
shell = new CypherShell( linePrinter, new PrettyConfig( Format.PLAIN, true, 1000 ), true, new ShellParameterMap() );
138139
useCommand = new Use( shell );
139140
shell.connect( new ConnectionConfig( "bolt://", "localhost", 7687, "neo4j", "neo", false, ABSENT_DB_NAME ) );
140141

cypher-shell/src/integration-test/java/org/neo4j/shell/commands/CypherShellPlainIntegrationTest.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
package org.neo4j.shell.commands;
22

3-
43
import org.junit.After;
54
import org.junit.Before;
65
import org.junit.Rule;
76
import org.junit.Test;
87
import org.junit.rules.ExpectedException;
9-
import org.neo4j.shell.ConnectionConfig;
8+
109
import org.neo4j.shell.CypherShell;
10+
import org.neo4j.shell.ShellParameterMap;
1111
import org.neo4j.shell.StringLinePrinter;
1212
import org.neo4j.shell.cli.Format;
1313
import org.neo4j.shell.exception.CommandException;
1414
import org.neo4j.shell.prettyprint.PrettyConfig;
1515

1616
import static org.hamcrest.CoreMatchers.containsString;
1717
import static org.hamcrest.MatcherAssert.assertThat;
18-
import static org.neo4j.driver.internal.messaging.request.MultiDatabaseUtil.ABSENT_DB_NAME;
18+
import static org.junit.Assert.assertEquals;
1919
import static org.neo4j.shell.prettyprint.OutputFormatter.NEWLINE;
2020

2121
public class CypherShellPlainIntegrationTest extends CypherShellIntegrationTest {
@@ -27,7 +27,7 @@ public class CypherShellPlainIntegrationTest extends CypherShellIntegrationTest
2727
@Before
2828
public void setUp() throws Exception {
2929
linePrinter.clear();
30-
shell = new CypherShell(linePrinter, new PrettyConfig(Format.PLAIN, true, 1000), false);
30+
shell = new CypherShell(linePrinter, new PrettyConfig(Format.PLAIN, true, 1000), false, new ShellParameterMap());
3131
connect( "neo" );
3232
}
3333

@@ -79,4 +79,21 @@ public void cypherWithExplainStatements() throws CommandException {
7979
assertThat(actual, containsString("Planner: \"COST\""));
8080
assertThat(actual, containsString("Runtime: \"INTERPRETED\""));
8181
}
82+
83+
@Test
84+
public void shouldUseParamFromCLIArgs() throws CommandException {
85+
// given a CLI arg
86+
ShellParameterMap parameterMap = new ShellParameterMap();
87+
parameterMap.setParameter( "foo", "'bar'" );
88+
shell = new CypherShell( linePrinter, new PrettyConfig( Format.PLAIN, true, 1000), false, parameterMap );
89+
connect( "neo" );
90+
91+
//when
92+
shell.execute("CYPHER RETURN $foo");
93+
94+
//then
95+
String actual = linePrinter.output();
96+
assertThat(actual, containsString("$foo"));
97+
assertThat(actual, containsString("bar"));
98+
}
8299
}

cypher-shell/src/integration-test/java/org/neo4j/shell/commands/CypherShellVerboseIntegrationTest.java

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,21 @@
55
import org.junit.Rule;
66
import org.junit.Test;
77
import org.junit.rules.ExpectedException;
8-
import org.neo4j.shell.ConnectionConfig;
8+
99
import org.neo4j.shell.CypherShell;
10+
import org.neo4j.shell.ShellParameterMap;
1011
import org.neo4j.shell.StringLinePrinter;
1112
import org.neo4j.shell.cli.Format;
1213
import org.neo4j.shell.exception.CommandException;
1314
import org.neo4j.shell.prettyprint.PrettyConfig;
1415

15-
import static org.hamcrest.CoreMatchers.*;
16+
import static org.hamcrest.CoreMatchers.containsString;
17+
import static org.hamcrest.CoreMatchers.equalTo;
18+
import static org.hamcrest.CoreMatchers.not;
1619
import static org.hamcrest.MatcherAssert.assertThat;
1720
import static org.junit.Assert.assertEquals;
1821
import static org.junit.Assert.assertTrue;
1922
import static org.junit.Assume.assumeTrue;
20-
import static org.neo4j.driver.internal.messaging.request.MultiDatabaseUtil.ABSENT_DB_NAME;
2123
import static org.neo4j.shell.Versions.majorVersion;
2224
import static org.neo4j.shell.Versions.minorVersion;
2325

@@ -33,7 +35,7 @@ public class CypherShellVerboseIntegrationTest extends CypherShellIntegrationTes
3335
@Before
3436
public void setUp() throws Exception {
3537
linePrinter.clear();
36-
shell = new CypherShell(linePrinter, new PrettyConfig(Format.VERBOSE, true, 1000), false);
38+
shell = new CypherShell(linePrinter, new PrettyConfig(Format.VERBOSE, true, 1000), false, new ShellParameterMap());
3739
rollbackCommand = new Rollback(shell);
3840
commitCommand = new Commit(shell);
3941
beginCommand = new Begin(shell);
@@ -152,37 +154,37 @@ public void commitScenario() throws CommandException {
152154

153155
@Test
154156
public void paramsAndListVariables() throws CommandException {
155-
assertTrue(shell.allParameterValues().isEmpty());
157+
assertTrue(shell.getParamaterMap().allParameterValues().isEmpty());
156158

157159
long randomLong = System.currentTimeMillis();
158160
String stringInput = "\"randomString\"";
159-
shell.setParameter("string", stringInput);
160-
Object paramValue = shell.setParameter("bob", String.valueOf(randomLong));
161+
shell.getParamaterMap().setParameter("string", stringInput);
162+
Object paramValue = shell.getParamaterMap().setParameter("bob", String.valueOf(randomLong));
161163
assertEquals(randomLong, paramValue);
162164

163165
shell.execute("RETURN { bob }, $string");
164166

165167
String result = linePrinter.output();
166168
assertThat(result, containsString("| { bob }"));
167169
assertThat(result, containsString("| " + randomLong + " | " + stringInput + " |"));
168-
assertEquals(randomLong, shell.allParameterValues().get("bob"));
169-
assertEquals("randomString", shell.allParameterValues().get("string"));
170+
assertEquals(randomLong, shell.getParamaterMap().allParameterValues().get("bob"));
171+
assertEquals("randomString", shell.getParamaterMap().allParameterValues().get("string"));
170172
}
171173

172174
@Test
173175
public void paramsAndListVariablesWithSpecialCharacters() throws CommandException {
174-
assertTrue(shell.allParameterValues().isEmpty());
176+
assertTrue(shell.getParamaterMap().allParameterValues().isEmpty());
175177

176178
long randomLong = System.currentTimeMillis();
177-
Object paramValue = shell.setParameter("`bob`", String.valueOf(randomLong));
179+
Object paramValue = shell.getParamaterMap().setParameter("`bob`", String.valueOf(randomLong));
178180
assertEquals(randomLong, paramValue);
179181

180182
shell.execute("RETURN { `bob` }");
181183

182184
String result = linePrinter.output();
183185
assertThat(result, containsString("| { `bob` }"));
184186
assertThat(result, containsString("\n| " + randomLong+ " |\n"));
185-
assertEquals(randomLong, shell.allParameterValues().get("bob"));
187+
assertEquals(randomLong, shell.getParamaterMap().allParameterValues().get("bob"));
186188
}
187189

188190
@Test

cypher-shell/src/main/java/org/neo4j/shell/CypherShell.java

Lines changed: 18 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,51 @@
11
package org.neo4j.shell;
22

3-
import org.neo4j.cypher.internal.evaluator.EvaluationException;
4-
import org.neo4j.cypher.internal.evaluator.Evaluator;
5-
import org.neo4j.cypher.internal.evaluator.ExpressionEvaluator;
63
import org.neo4j.driver.exceptions.Neo4jException;
74
import org.neo4j.shell.commands.Command;
85
import org.neo4j.shell.commands.CommandExecutable;
96
import org.neo4j.shell.commands.CommandHelper;
107
import org.neo4j.shell.exception.CommandException;
118
import org.neo4j.shell.exception.ExitException;
12-
import org.neo4j.shell.prettyprint.CypherVariablesFormatter;
139
import org.neo4j.shell.prettyprint.LinePrinter;
1410
import org.neo4j.shell.prettyprint.PrettyConfig;
1511
import org.neo4j.shell.prettyprint.PrettyPrinter;
1612
import org.neo4j.shell.state.BoltResult;
1713
import org.neo4j.shell.state.BoltStateHandler;
18-
import org.neo4j.shell.state.ParamValue;
1914

2015
import javax.annotation.Nonnull;
21-
import java.util.HashMap;
2216
import java.util.List;
23-
import java.util.Map;
2417
import java.util.Optional;
2518
import java.util.regex.Matcher;
2619
import java.util.regex.Pattern;
27-
import java.util.stream.Collectors;
2820

2921
/**
3022
* A possibly interactive shell for evaluating cypher statements.
3123
*/
32-
public class CypherShell implements StatementExecuter, Connector, TransactionHandler, ParameterMap, DatabaseManager {
24+
public class CypherShell implements StatementExecuter, Connector, TransactionHandler, DatabaseManager {
3325
// Final space to catch newline
34-
protected static final Pattern cmdNamePattern = Pattern.compile("^\\s*(?<name>[^\\s]+)\\b(?<args>.*)\\s*$");
35-
protected final Map<String, ParamValue> queryParams = new HashMap<>();
26+
private static final Pattern cmdNamePattern = Pattern.compile("^\\s*(?<name>[^\\s]+)\\b(?<args>.*)\\s*$");
27+
private final ParameterMap parameterMap;
3628
private final LinePrinter linePrinter;
3729
private final BoltStateHandler boltStateHandler;
3830
private final PrettyPrinter prettyPrinter;
3931
private CommandHelper commandHelper;
40-
private ExpressionEvaluator evaluator = Evaluator.expressionEvaluator();
4132
private String lastNeo4jErrorCode;
4233

4334
public CypherShell(@Nonnull LinePrinter linePrinter,
4435
@Nonnull PrettyConfig prettyConfig,
45-
boolean isInteractive) {
46-
this(linePrinter, new BoltStateHandler(isInteractive), new PrettyPrinter(prettyConfig));
36+
boolean isInteractive,
37+
ParameterMap parameterMap) {
38+
this(linePrinter, new BoltStateHandler(isInteractive), new PrettyPrinter(prettyConfig), parameterMap);
4739
}
4840

4941
protected CypherShell(@Nonnull LinePrinter linePrinter,
5042
@Nonnull BoltStateHandler boltStateHandler,
51-
@Nonnull PrettyPrinter prettyPrinter) {
43+
@Nonnull PrettyPrinter prettyPrinter,
44+
ParameterMap parameterMap) {
5245
this.linePrinter = linePrinter;
5346
this.boltStateHandler = boltStateHandler;
5447
this.prettyPrinter = prettyPrinter;
48+
this.parameterMap = parameterMap;
5549
addRuntimeHookToResetShell();
5650
}
5751

@@ -97,7 +91,7 @@ public String lastNeo4jErrorCode() {
9791
*/
9892
private void executeCypher(@Nonnull final String cypher) throws CommandException {
9993
try {
100-
final Optional<BoltResult> result = boltStateHandler.runCypher( cypher, allParameterValues() );
94+
final Optional<BoltResult> result = boltStateHandler.runCypher( cypher, parameterMap.allParameterValues() );
10195
result.ifPresent(boltResult -> prettyPrinter.format(boltResult, linePrinter));
10296
lastNeo4jErrorCode = null;
10397
} catch (Neo4jException e) {
@@ -178,35 +172,6 @@ public boolean isTransactionOpen() {
178172
return boltStateHandler.isTransactionOpen();
179173
}
180174

181-
@Override
182-
@Nonnull
183-
public Object setParameter(@Nonnull String name, @Nonnull String valueString) throws CommandException {
184-
try {
185-
String parameterName = CypherVariablesFormatter.unescapedCypherVariable(name);
186-
Object value = evaluator.evaluate(valueString, Object.class);
187-
queryParams.put(parameterName, new ParamValue(valueString, value));
188-
return value;
189-
} catch (EvaluationException e) {
190-
throw new CommandException(e.getMessage(), e);
191-
}
192-
}
193-
194-
@Override
195-
@Nonnull
196-
public Map<String, Object> allParameterValues() {
197-
return queryParams.entrySet()
198-
.stream()
199-
.collect(Collectors.toMap(
200-
Map.Entry::getKey,
201-
value -> value.getValue().getValue()));
202-
}
203-
204-
@Nonnull
205-
@Override
206-
public Map<String, ParamValue> getAllAsUserInput() {
207-
return queryParams;
208-
}
209-
210175
void setCommandHelper(@Nonnull CommandHelper commandHelper) {
211176
this.commandHelper = commandHelper;
212177
}
@@ -243,4 +208,12 @@ public String getActualDatabaseAsReportedByServer()
243208
{
244209
return boltStateHandler.getActualDatabaseAsReportedByServer();
245210
}
211+
212+
/**
213+
* @return the parameter map.
214+
*/
215+
public ParameterMap getParamaterMap()
216+
{
217+
return parameterMap;
218+
}
246219
}

cypher-shell/src/main/java/org/neo4j/shell/Main.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
package org.neo4j.shell;
22

33
import jline.console.ConsoleReader;
4+
5+
import java.io.InputStream;
6+
import java.io.PrintStream;
7+
import javax.annotation.Nonnull;
8+
import javax.annotation.Nullable;
9+
410
import org.neo4j.driver.exceptions.AuthenticationException;
511
import org.neo4j.shell.build.Build;
612
import org.neo4j.shell.cli.CliArgHelper;
@@ -11,11 +17,7 @@
1117
import org.neo4j.shell.log.Logger;
1218
import org.neo4j.shell.prettyprint.PrettyConfig;
1319

14-
import javax.annotation.Nonnull;
15-
import javax.annotation.Nullable;
16-
import java.io.InputStream;
1720
import java.io.OutputStream;
18-
import java.io.PrintStream;
1921

2022
import static org.neo4j.shell.ShellRunner.isInputInteractive;
2123
import static org.neo4j.shell.ShellRunner.isOutputInteractive;
@@ -38,7 +40,7 @@ public static void main(String[] args) {
3840
main.startShell(cliArgs);
3941
}
4042

41-
Main() {
43+
private Main() {
4244
this(System.in, System.out);
4345
}
4446

@@ -72,7 +74,7 @@ void startShell(@Nonnull CliArgs cliArgs) {
7274
cliArgs.getDatabase());
7375

7476
try {
75-
CypherShell shell = new CypherShell(logger, prettyConfig, ShellRunner.shouldBeInteractive( cliArgs ));
77+
CypherShell shell = new CypherShell(logger, prettyConfig, ShellRunner.shouldBeInteractive( cliArgs ), cliArgs.getParameters());
7678
// Can only prompt for password if input has not been redirected
7779
connectMaybeInteractively(shell, connectionConfig, isInputInteractive(), isOutputInteractive());
7880

0 commit comments

Comments
 (0)