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

Commit b84a0c2

Browse files
committed
Pass a cypher file as a parameter
By using `-f` or `--file` we can pass in a file of cypher to execute. Works mostly in the same way as piping cypher statements to the shell.
1 parent 7ecada0 commit b84a0c2

File tree

8 files changed

+115
-5
lines changed

8 files changed

+115
-5
lines changed

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

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,23 @@
77

88
import java.io.ByteArrayInputStream;
99
import java.io.ByteArrayOutputStream;
10+
import java.io.IOException;
1011
import java.io.InputStream;
1112
import java.io.PrintStream;
1213

1314
import org.neo4j.driver.exceptions.ServiceUnavailableException;
1415
import org.neo4j.shell.cli.CliArgs;
1516
import org.neo4j.shell.log.AnsiLogger;
1617
import org.neo4j.shell.log.Logger;
18+
import org.neo4j.shell.prettyprint.LinePrinter;
1719
import org.neo4j.shell.prettyprint.PrettyConfig;
20+
import org.neo4j.shell.prettyprint.ToStringLinePrinter;
1821

22+
import static java.lang.String.format;
23+
import static org.hamcrest.MatcherAssert.assertThat;
1924
import static org.junit.Assert.assertEquals;
2025
import static org.junit.Assert.assertTrue;
26+
import static org.mockito.Mockito.mock;
2127

2228
public class MainIntegrationTest
2329
{
@@ -77,7 +83,7 @@ public void promptsOnWrongAuthenticationIfInteractive() throws Exception {
7783
assertEquals("neo", connectionConfig.password());
7884

7985
String out = baos.toString();
80-
assertEquals( String.format( "username: neo4j%npassword: ***%n" ), out );
86+
assertEquals( format( "username: neo4j%npassword: ***%n" ), out );
8187
}
8288

8389
@Test
@@ -133,9 +139,54 @@ public void wrongPortWithNeo4j() throws Exception
133139
main.connectMaybeInteractively( shell, connectionConfig, true, true );
134140
}
135141

142+
@Test
143+
public void shouldReadCypherStatementsFromFile() throws Exception {
144+
// given
145+
CliArgs cliArgs = new CliArgs();
146+
cliArgs.setInputFilename( fileFromResource("test.cypher") );
147+
148+
// when
149+
ToStringLinePrinter linePrinter = new ToStringLinePrinter();
150+
ShellAndConnection sac = getShell( cliArgs, linePrinter );
151+
CypherShell shell = sac.shell;
152+
ConnectionConfig connectionConfig = sac.connectionConfig;
153+
main.connectMaybeInteractively( shell, connectionConfig, true, true );
154+
ShellRunner shellRunner = ShellRunner.getShellRunner(cliArgs, shell, mock(Logger.class), connectionConfig);
155+
shellRunner.runUntilEnd();
156+
157+
// then
158+
assertEquals( format("result%n42%n"), linePrinter.result() );
159+
}
160+
161+
@Test
162+
public void shouldFailIfInputFileDoesntExist() throws Exception {
163+
// given
164+
CliArgs cliArgs = new CliArgs();
165+
cliArgs.setInputFilename( "what.cypher" );
166+
167+
// when
168+
ShellAndConnection sac = getShell( cliArgs );
169+
CypherShell shell = sac.shell;
170+
main.connectMaybeInteractively( shell, sac.connectionConfig, true, true );
171+
172+
// expect
173+
exception.expect( IOException.class);
174+
ShellRunner.getShellRunner(cliArgs, shell, mock(Logger.class), sac.connectionConfig );
175+
}
176+
177+
private String fileFromResource(String filename)
178+
{
179+
return getClass().getClassLoader().getResource(filename).getFile();
180+
}
181+
136182
private ShellAndConnection getShell( CliArgs cliArgs )
137183
{
138184
Logger logger = new AnsiLogger( cliArgs.getDebugMode() );
185+
return getShell( cliArgs, logger );
186+
}
187+
188+
private ShellAndConnection getShell( CliArgs cliArgs, LinePrinter linePrinter )
189+
{
139190
PrettyConfig prettyConfig = new PrettyConfig( cliArgs );
140191
ConnectionConfig connectionConfig = new ConnectionConfig(
141192
cliArgs.getScheme(),
@@ -146,6 +197,6 @@ private ShellAndConnection getShell( CliArgs cliArgs )
146197
cliArgs.getEncryption(),
147198
cliArgs.getDatabase() );
148199

149-
return new ShellAndConnection( new CypherShell( logger, prettyConfig, true, new ShellParameterMap() ), connectionConfig );
200+
return new ShellAndConnection( new CypherShell( linePrinter, prettyConfig, true, new ShellParameterMap() ), connectionConfig );
150201
}
151202
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
RETURN 42 AS result;

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

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@
99
import org.neo4j.shell.parser.ShellStatementParser;
1010

1111
import javax.annotation.Nonnull;
12+
import java.io.BufferedInputStream;
13+
import java.io.File;
14+
import java.io.FileInputStream;
15+
import java.io.FileNotFoundException;
1216
import java.io.IOException;
17+
import java.io.InputStream;
1318

1419
import static org.fusesource.jansi.internal.CLibrary.STDIN_FILENO;
1520
import static org.fusesource.jansi.internal.CLibrary.STDOUT_FILENO;
@@ -54,8 +59,9 @@ static ShellRunner getShellRunner(@Nonnull CliArgs cliArgs,
5459
return new InteractiveShellRunner(cypherShell, cypherShell, cypherShell, logger, new ShellStatementParser(),
5560
System.in, FileHistorian.getDefaultHistoryFile(), userMessagesHandler, connectionConfig);
5661
} else {
62+
5763
return new NonInteractiveShellRunner(cliArgs.getFailBehavior(), cypherShell, logger,
58-
new ShellStatementParser(), System.in);
64+
new ShellStatementParser(), getInputStream(cliArgs));
5965
}
6066
}
6167

@@ -64,7 +70,8 @@ static ShellRunner getShellRunner(@Nonnull CliArgs cliArgs,
6470
* @return true if an interactive shellrunner should be used, false otherwise
6571
*/
6672
static boolean shouldBeInteractive(@Nonnull CliArgs cliArgs) {
67-
if (cliArgs.getNonInteractive()) {
73+
if ( cliArgs.getNonInteractive() || cliArgs.getInputFilename() != null )
74+
{
6875
return false;
6976
}
7077

@@ -114,4 +121,18 @@ static boolean isOutputInteractive() {
114121
return System.console() != null;
115122
}
116123
}
124+
125+
/**
126+
* If an input file has been defined use that, otherwise use STDIN
127+
* @throws FileNotFoundException if the provided input file doesn't exist
128+
*/
129+
static InputStream getInputStream(CliArgs cliArgs) throws FileNotFoundException
130+
{
131+
if ( cliArgs.getInputFilename() == null)
132+
{
133+
return System.in;
134+
} else {
135+
return new BufferedInputStream( new FileInputStream( new File(cliArgs.getInputFilename()) ));
136+
}
137+
}
117138
}

cypher-shell/src/main/java/org/neo4j/shell/cli/CliArgHelper.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ private static CliArgs getCliArgs( CliArgs cliArgs, ArgumentParser parser, Names
9898
}
9999
cliArgs.setEncryption(ns.getBoolean("encryption"));
100100
cliArgs.setDatabase(ns.getString("database"));
101+
cliArgs.setInputFilename(ns.getString( "file" ) );
101102

102103
//----------------
103104
// Other arguments
@@ -167,6 +168,8 @@ private static ArgumentParser setupParser(ParameterMap parameterMap)
167168
connGroup.addArgument("-d", "--database")
168169
.help("database to connect to. Can also be specified using environment variable " + ConnectionConfig.DATABASE_ENV_VAR)
169170
.setDefault("");
171+
connGroup.addArgument("-f", "--file")
172+
.help("Pass a file with cypher statements to be executed.");
170173

171174
MutuallyExclusiveGroup failGroup = parser.addMutuallyExclusiveGroup();
172175
failGroup.addArgument("--fail-fast")

cypher-shell/src/main/java/org/neo4j/shell/cli/CliArgs.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public class CliArgs {
3232
private boolean driverVersion = false;
3333
private int numSampleRows = DEFAULT_NUM_SAMPLE_ROWS;
3434
private boolean wrap = true;
35+
private String inputFilename = null;
3536
private ParameterMap parameters = new ShellParameterMap();
3637

3738
/**
@@ -111,6 +112,14 @@ public void setNonInteractive(boolean nonInteractive) {
111112
this.nonInteractive = nonInteractive;
112113
}
113114

115+
/**
116+
* Sets a filename where to read Cypher statements from, much like piping statements from a file.
117+
*/
118+
public void setInputFilename(String inputFilename)
119+
{
120+
this.inputFilename = inputFilename;
121+
}
122+
114123
/**
115124
* Enable/disable debug mode
116125
*/
@@ -174,6 +183,11 @@ public boolean getNonInteractive() {
174183
return nonInteractive;
175184
}
176185

186+
public String getInputFilename()
187+
{
188+
return inputFilename;
189+
}
190+
177191
public boolean getVersion() {
178192
return version;
179193
}

cypher-shell/src/test/java/org/neo4j/shell/MainTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ public void promptsForPassIfUserExistsIfInteractive() throws Exception {
199199
}
200200

201201
@Test
202-
public void promptsSielntlyForPassIfUserExistsIfOutputRedirected() throws Exception {
202+
public void promptsSilentlyForPassIfUserExistsIfOutputRedirected() throws Exception {
203203
doThrow(authException).doNothing().when(shell).connect(connectionConfig);
204204
doReturn("bob").when(connectionConfig).username();
205205

cypher-shell/src/test/java/org/neo4j/shell/cli/CliArgHelperTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,4 +240,17 @@ public void shouldFailForInvalidSyntaxForArg() throws Exception {
240240
CliArgHelper.parseAndThrow( "-P", "foo: => 'nanana'");
241241
}
242242

243+
@Test
244+
public void testDefaultInputFileName() {
245+
CliArgs arguments = CliArgHelper.parse();
246+
assertNotNull( arguments );
247+
assertNull( arguments.getInputFilename() );
248+
}
249+
250+
@Test
251+
public void testSetInputFileName() {
252+
CliArgs arguments = CliArgHelper.parse("--file", "foo");
253+
assertNotNull( arguments );
254+
assertEquals( "foo", arguments.getInputFilename() );
255+
}
243256
}

cypher-shell/src/test/java/org/neo4j/shell/cli/CliArgsTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,11 @@ public void getParameters()
108108
// so setting them cannot be tested here.
109109
assertEquals( Collections.EMPTY_MAP, cliArgs.getParameters().allParameterValues() );
110110
}
111+
112+
@Test
113+
public void setInputFile()
114+
{
115+
cliArgs.setInputFilename("foo");
116+
assertEquals("foo", cliArgs.getInputFilename());
117+
}
111118
}

0 commit comments

Comments
 (0)