Skip to content

Commit

Permalink
fixes neo4j-contrib#1612: Neo4j 4 on Aura permissions adjustment due …
Browse files Browse the repository at this point in the history
…to PUBLIC role
  • Loading branch information
vga91 committed Feb 18, 2021
1 parent 72c4f56 commit 37daf81
Show file tree
Hide file tree
Showing 16 changed files with 179 additions and 1 deletion.
13 changes: 13 additions & 0 deletions core/src/main/java/apoc/cypher/Cypher.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import static java.lang.String.format;
import static java.lang.String.join;
import static java.util.stream.Collectors.toList;
import static org.neo4j.procedure.Mode.SCHEMA;
import static org.neo4j.procedure.Mode.WRITE;

/**
Expand Down Expand Up @@ -242,6 +243,18 @@ public Stream<MapResult> doIt(@Name("cypher") String statement, @Name("params")
return runCypherQuery(tx, statement, params);
}

@Procedure(mode = WRITE)
@Description("apoc.cypher.runWrite(fragment, params) yield value - alias for apoc.cypher.doIt")
public Stream<MapResult> runWrite(@Name("cypher") String statement, @Name("params") Map<String, Object> params) {
return doIt(statement, params);
}

@Procedure(mode = SCHEMA)
@Description("apoc.cypher.runSchema(fragment, params) yield value - executes query schema fragment with the given parameters")
public Stream<MapResult> runSchema(@Name("cypher") String statement, @Name("params") Map<String, Object> params) {
return runCypherQuery(tx, statement, params);
}

@Procedure("apoc.when")
@Description("apoc.when(condition, ifQuery, elseQuery:'', params:{}) yield value - based on the conditional, executes read-only ifQuery or elseQuery with the given parameters")
public Stream<MapResult> when(@Name("condition") boolean condition, @Name("ifQuery") String ifQuery, @Name(value="elseQuery", defaultValue = "") String elseQuery, @Name(value="params", defaultValue = "{}") Map<String, Object> params) {
Expand Down
36 changes: 35 additions & 1 deletion core/src/test/java/apoc/cypher/CypherTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
import org.junit.rules.ExpectedException;
import org.neo4j.configuration.GraphDatabaseSettings;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.QueryExecutionException;
import org.neo4j.graphdb.Result;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.schema.ConstraintDefinition;
import org.neo4j.graphdb.schema.IndexDefinition;
import org.neo4j.internal.helpers.collection.Iterables;
import org.neo4j.internal.helpers.collection.Iterators;
import org.neo4j.test.rule.DbmsRule;
import org.neo4j.test.rule.ImpermanentDbmsRule;
Expand All @@ -32,13 +34,16 @@
import static apoc.ApocConfig.APOC_IMPORT_FILE_ENABLED;
import static apoc.ApocConfig.apocConfig;
import static apoc.util.TestUtil.testCall;
import static apoc.util.TestUtil.testCallEmpty;
import static apoc.util.TestUtil.testFail;
import static apoc.util.TestUtil.testResult;
import static apoc.util.Util.map;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static org.hamcrest.Matchers.hasEntry;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

Expand Down Expand Up @@ -66,12 +71,41 @@ public static void setUp() {
public void clearDB() {
db.executeTransactionally("MATCH (n) DETACH DELETE n");
try (Transaction tx = db.beginTx()) {
tx.schema().getIndexes().forEach(IndexDefinition::drop);
tx.schema().getConstraints().forEach(ConstraintDefinition::drop);
tx.schema().getIndexes().forEach(IndexDefinition::drop);
tx.commit();
}
}

@Test
public void testDoIt() throws Exception {

testCallEmpty(db, "CALL apoc.cypher.doIt('CREATE (n:TestOne {a: $b})',{b: 32})", emptyMap());

testCall(db, "CALL apoc.cypher.doIt('Match (n:TestOne) return n',{})",
r -> assertEquals("TestOne", Iterables.single(((Node)((Map) r.get("value")).get("n")).getLabels()).name()));

testFail(db, "CALL apoc.cypher.doIt('CREATE INDEX test FOR (w:TestOne) ON (w.foo)',{})", QueryExecutionException.class);

testCallEmpty(db, "CALL apoc.cypher.runWrite('CREATE (n:TestTwo {a: $b})',{b: 32})", emptyMap());

testCall(db, "CALL apoc.cypher.runWrite('Match (n:TestTwo) return n',{})",
r -> assertEquals("TestTwo", Iterables.single(((Node)((Map) r.get("value")).get("n")).getLabels()).name()));

testFail(db, "CALL apoc.cypher.runWrite('CREATE INDEX test FOR (w:TestTwo) ON (w.foo)',{})", QueryExecutionException.class);
}

@Test
public void testRunSchema() throws Exception {
testCallEmpty(db, "CALL apoc.cypher.runSchema('CREATE INDEX test FOR (w:TestOne) ON (w.name)',{})", Collections.emptyMap());
testCallEmpty(db, "CALL apoc.cypher.runSchema('CREATE CONSTRAINT testConstraint ON (w:TestTwo) ASSERT w.baz IS UNIQUE',{})", Collections.emptyMap());

try (Transaction tx = db.beginTx()) {
assertNotNull(tx.schema().getConstraintByName("testConstraint"));
assertNotNull(tx.schema().getIndexByName("test"));
}
}

@Test
public void testRun() throws Exception {
testCall(db, "CALL apoc.cypher.run('RETURN $a + 7 as b',{a:3})",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
¦apoc.cypher.runFile(file :: STRING?, config = {} :: MAP?) :: (row :: INTEGER?, result :: MAP?)
¦apoc.cypher.runFiles(file :: LIST? OF STRING?, config = {} :: MAP?) :: (row :: INTEGER?, result :: MAP?)
¦apoc.cypher.runMany(cypher :: STRING?, params :: MAP?, config = {} :: MAP?) :: (row :: INTEGER?, result :: MAP?)
¦apoc.cypher.runSchema(cypher :: STRING?, params :: MAP?) :: (value :: MAP?)
¦apoc.cypher.runSchemaFile(file :: STRING?, config = {} :: MAP?) :: (row :: INTEGER?, result :: MAP?)
¦apoc.cypher.runSchemaFiles(file :: LIST? OF STRING?, config = {} :: MAP?) :: (row :: INTEGER?, result :: MAP?)
¦apoc.cypher.runTimeboxed(cypher :: STRING?, params :: MAP?, timeout :: INTEGER?) :: (value :: MAP?)
¦apoc.cypher.runWrite(cypher :: STRING?, params :: MAP?) :: (value :: MAP?)
¦apoc.cypher.runFirstColumn(cypher :: STRING?, params :: MAP?, expectMultipleValues = true :: BOOLEAN?) :: (ANY?)
¦apoc.cypher.runFirstColumnMany(cypher :: STRING?, params :: MAP?) :: (LIST? OF ANY?)
¦apoc.cypher.runFirstColumnSingle(cypher :: STRING?, params :: MAP?) :: (ANY?)
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
¦procedure¦apoc.cypher.runFile¦apoc.cypher.runFile(file :: STRING?, config = {} :: MAP?) :: (row :: INTEGER?, result :: MAP?)¦apoc.cypher.runFile(file or url,[{statistics:true,timeout:10,parameters:{}}]) - runs each statement in the file, all semicolon separated - currently no schema operations
¦procedure¦apoc.cypher.runFiles¦apoc.cypher.runFiles(file :: LIST? OF STRING?, config = {} :: MAP?) :: (row :: INTEGER?, result :: MAP?)¦apoc.cypher.runFiles([files or urls],[{statistics:true,timeout:10,parameters:{}}])) - runs each statement in the files, all semicolon separated
¦procedure¦apoc.cypher.runMany¦apoc.cypher.runMany(cypher :: STRING?, params :: MAP?, config = {} :: MAP?) :: (row :: INTEGER?, result :: MAP?)¦apoc.cypher.runMany('cypher;\nstatements;',\{params},[{statistics:true,timeout:10}]) - runs each semicolon separated statement and returns summary - currently no schema operations
¦procedure¦apoc.cypher.runSchema¦apoc.cypher.runSchema(cypher :: STRING?, params :: MAP?) :: (value :: MAP?)¦apoc.cypher.runSchema(fragment, params) yield value - executes query schema fragment with the given parameters
¦procedure¦apoc.cypher.runSchemaFile¦apoc.cypher.runSchemaFile(file :: STRING?, config = {} :: MAP?) :: (row :: INTEGER?, result :: MAP?)¦apoc.cypher.runSchemaFile(file or url,[{statistics:true,timeout:10}]) - allows only schema operations, runs each schema statement in the file, all semicolon separated
¦procedure¦apoc.cypher.runSchemaFiles¦apoc.cypher.runSchemaFiles(file :: LIST? OF STRING?, config = {} :: MAP?) :: (row :: INTEGER?, result :: MAP?)¦apoc.cypher.runSchemaFiles([files or urls],{statistics:true,timeout:10}) - allows only schema operations, runs each schema statement in the files, all semicolon separated
¦procedure¦apoc.cypher.runTimeboxed¦apoc.cypher.runTimeboxed(cypher :: STRING?, params :: MAP?, timeout :: INTEGER?) :: (value :: MAP?)¦apoc.cypher.runTimeboxed('cypherStatement',\{params}, timeout) - abort kernelTransaction after timeout ms if not finished
¦procedure¦apoc.cypher.runWrite¦apoc.cypher.runWrite(cypher :: STRING?, params :: MAP?) :: (value :: MAP?)¦apoc.cypher.runWrite(fragment, params) yield value - alias for apoc.cypher.doIt
¦function¦apoc.cypher.runFirstColumn¦apoc.cypher.runFirstColumn(cypher :: STRING?, params :: MAP?, expectMultipleValues = true :: BOOLEAN?) :: (ANY?)¦use either apoc.cypher.runFirstColumnMany for a list return or apoc.cypher.runFirstColumnSingle for returning the first row of the first column
¦function¦apoc.cypher.runFirstColumnMany¦apoc.cypher.runFirstColumnMany(cypher :: STRING?, params :: MAP?) :: (LIST? OF ANY?)¦apoc.cypher.runFirstColumnMany(statement, params) - executes statement with given parameters, returns first column only collected into a list, params are available as identifiers
¦function¦apoc.cypher.runFirstColumnSingle¦apoc.cypher.runFirstColumnSingle(cypher :: STRING?, params :: MAP?) :: (ANY?)¦apoc.cypher.runFirstColumnSingle(statement, params) - executes statement with given parameters, returns first element of the first column only, params are available as identifiers
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
¦signature
¦apoc.cypher.runSchema(cypher :: STRING?, params :: MAP?) :: (value :: MAP?)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
¦xref::overview/apoc.cypher/apoc.cypher.runSchema.adoc[apoc.cypher.runSchema icon:book[]] +

`apoc.cypher.runSchema(fragment, params) yield value` - executes query schema fragment with the given parameters
¦label:procedure[]
¦label:apoc-core[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
¦signature
¦apoc.cypher.runWrite(cypher :: STRING?, params :: MAP?) :: (value :: MAP?)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
¦xref::overview/apoc.cypher/apoc.cypher.runWrite.adoc[apoc.cypher.runWrite icon:book[]] +

`apoc.cypher.runWrite(fragment, params) yield value` - alias for apoc.cypher.doIt
¦label:procedure[]
¦label:apoc-core[]
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,11 @@
¦procedure¦apoc.cypher.runFile¦apoc.cypher.runFile(file :: STRING?, config = {} :: MAP?) :: (row :: INTEGER?, result :: MAP?)¦apoc.cypher.runFile(file or url,[{statistics:true,timeout:10,parameters:{}}]) - runs each statement in the file, all semicolon separated - currently no schema operations¦false¦xref::cypher-execution/index.adoc
¦procedure¦apoc.cypher.runFiles¦apoc.cypher.runFiles(file :: LIST? OF STRING?, config = {} :: MAP?) :: (row :: INTEGER?, result :: MAP?)¦apoc.cypher.runFiles([files or urls],[{statistics:true,timeout:10,parameters:{}}])) - runs each statement in the files, all semicolon separated¦false¦xref::cypher-execution/index.adoc
¦procedure¦apoc.cypher.runMany¦apoc.cypher.runMany(cypher :: STRING?, params :: MAP?, config = {} :: MAP?) :: (row :: INTEGER?, result :: MAP?)¦apoc.cypher.runMany('cypher;\nstatements;',\{params},[{statistics:true,timeout:10}]) - runs each semicolon separated statement and returns summary - currently no schema operations¦true¦xref::cypher-execution/index.adoc
¦procedure¦apoc.cypher.runSchema¦apoc.cypher.runSchema(cypher :: STRING?, params :: MAP?) :: (value :: MAP?)¦apoc.cypher.runSchema(fragment, params) yield value - executes query schema fragment with the given parameters¦true¦xref::cypher-execution/index.adoc
¦procedure¦apoc.cypher.runSchemaFile¦apoc.cypher.runSchemaFile(file :: STRING?, config = {} :: MAP?) :: (row :: INTEGER?, result :: MAP?)¦apoc.cypher.runSchemaFile(file or url,[{statistics:true,timeout:10}]) - allows only schema operations, runs each schema statement in the file, all semicolon separated¦false¦xref::cypher-execution/index.adoc
¦procedure¦apoc.cypher.runSchemaFiles¦apoc.cypher.runSchemaFiles(file :: LIST? OF STRING?, config = {} :: MAP?) :: (row :: INTEGER?, result :: MAP?)¦apoc.cypher.runSchemaFiles([files or urls],{statistics:true,timeout:10}) - allows only schema operations, runs each schema statement in the files, all semicolon separated¦false¦xref::cypher-execution/index.adoc
¦procedure¦apoc.cypher.runTimeboxed¦apoc.cypher.runTimeboxed(cypher :: STRING?, params :: MAP?, timeout :: INTEGER?) :: (value :: MAP?)¦apoc.cypher.runTimeboxed('cypherStatement',\{params}, timeout) - abort kernelTransaction after timeout ms if not finished¦true¦xref::cypher-execution/index.adoc
¦procedure¦apoc.cypher.runWrite¦apoc.cypher.runWrite(cypher :: STRING?, params :: MAP?) :: (value :: MAP?)¦apoc.cypher.runWrite(fragment, params) yield value - alias for apoc.cypher.doIt¦true¦xref::cypher-execution/index.adoc
¦procedure¦apoc.date.expire¦apoc.date.expire(node :: NODE?, time :: INTEGER?, timeUnit :: STRING?) :: VOID¦CALL apoc.date.expire(node,time,'time-unit') - expire node at specified time by setting :TTL label and `ttl` property¦false¦
¦procedure¦apoc.date.expireIn¦apoc.date.expireIn(node :: NODE?, timeDelta :: INTEGER?, timeUnit :: STRING?) :: VOID¦CALL apoc.date.expireIn(node,time,'time-unit') - expire node after specified length of time time by setting :TTL label and `ttl` property¦false¦
¦procedure¦apoc.do.case¦apoc.do.case(conditionals :: LIST? OF ANY?, elseQuery = :: STRING?, params = {} :: MAP?) :: (value :: MAP?)¦apoc.do.case([condition, query, condition, query, ...], elseQuery:'', params:{}) yield value - given a list of conditional / writing query pairs, executes the query associated with the first conditional evaluating to true (or the else query if none are true) with the given parameters¦true¦xref::cypher-execution/conditionals.adoc
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
////
This file is generated by DocsTest, so don't change it!
////

= apoc.cypher.runSchema
:description: This section contains reference documentation for the apoc.cypher.runSchema procedure.

label:procedure[] label:apoc-core[]

[.emphasis]
apoc.cypher.runSchema(fragment, params) yield value - executes query schema fragment with the given parameters

== Signature

[source]
----
apoc.cypher.runSchema(cypher :: STRING?, params :: MAP?) :: (value :: MAP?)
----

== Input parameters
[.procedures, opts=header]
|===
| Name | Type | Default
|cypher|STRING?|null
|params|MAP?|null
|===

== Output parameters
[.procedures, opts=header]
|===
| Name | Type
|value|MAP?
|===

[[usage-apoc.cypher.runSchema]]
== Usage Examples
include::partial$usage/apoc.cypher.runSchema.adoc[]

xref::cypher-execution/index.adoc[More documentation of apoc.cypher.runSchema,role=more information]

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
////
This file is generated by DocsTest, so don't change it!
////

= apoc.cypher.runWrite
:description: This section contains reference documentation for the apoc.cypher.runWrite procedure.

label:procedure[] label:apoc-core[]

[.emphasis]
apoc.cypher.runWrite(fragment, params) yield value - alias for apoc.cypher.doIt

== Signature

[source]
----
apoc.cypher.runWrite(cypher :: STRING?, params :: MAP?) :: (value :: MAP?)
----

== Input parameters
[.procedures, opts=header]
|===
| Name | Type | Default
|cypher|STRING?|null
|params|MAP?|null
|===

== Output parameters
[.procedures, opts=header]
|===
| Name | Type
|value|MAP?
|===

xref::cypher-execution/index.adoc[More documentation of apoc.cypher.runWrite,role=more information]

10 changes: 10 additions & 0 deletions docs/asciidoc/modules/ROOT/pages/overview/apoc.cypher/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ apoc.cypher.runFiles([files or urls],[{statistics:true,timeout:10,parameters:{}}
apoc.cypher.runMany('cypher;\nstatements;',\{params},[{statistics:true,timeout:10}]) - runs each semicolon separated statement and returns summary - currently no schema operations
|label:procedure[]
|label:apoc-core[]
|xref::overview/apoc.cypher/apoc.cypher.runSchema.adoc[apoc.cypher.runSchema icon:book[]]

apoc.cypher.runSchema(fragment, params) yield value - executes query schema fragment with the given parameters
|label:procedure[]
|label:apoc-core[]
|xref::overview/apoc.cypher/apoc.cypher.runSchemaFile.adoc[apoc.cypher.runSchemaFile icon:book[]]

apoc.cypher.runSchemaFile(file or url,[{statistics:true,timeout:10}]) - allows only schema operations, runs each schema statement in the file, all semicolon separated
Expand All @@ -68,6 +73,11 @@ apoc.cypher.runSchemaFiles([files or urls],{statistics:true,timeout:10}) - allow
apoc.cypher.runTimeboxed('cypherStatement',\{params}, timeout) - abort kernelTransaction after timeout ms if not finished
|label:procedure[]
|label:apoc-core[]
|xref::overview/apoc.cypher/apoc.cypher.runWrite.adoc[apoc.cypher.runWrite icon:book[]]

apoc.cypher.runWrite(fragment, params) yield value - alias for apoc.cypher.doIt
|label:procedure[]
|label:apoc-core[]
|xref::overview/apoc.cypher/apoc.cypher.runFirstColumn.adoc[apoc.cypher.runFirstColumn icon:book[]]

use either apoc.cypher.runFirstColumnMany for a list return or apoc.cypher.runFirstColumnSingle for returning the first row of the first column
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,11 @@ apoc.cypher.runFiles([files or urls],[{statistics:true,timeout:10,parameters:{}}
apoc.cypher.runMany('cypher;\nstatements;',\{params},[{statistics:true,timeout:10}]) - runs each semicolon separated statement and returns summary - currently no schema operations
|label:procedure[]
|label:apoc-core[]
|xref::overview/apoc.cypher/apoc.cypher.runSchema.adoc[apoc.cypher.runSchema icon:book[]]

apoc.cypher.runSchema(fragment, params) yield value - executes query schema fragment with the given parameters
|label:procedure[]
|label:apoc-core[]
|xref::overview/apoc.cypher/apoc.cypher.runSchemaFile.adoc[apoc.cypher.runSchemaFile icon:book[]]

apoc.cypher.runSchemaFile(file or url,[{statistics:true,timeout:10}]) - allows only schema operations, runs each schema statement in the file, all semicolon separated
Expand All @@ -925,6 +930,11 @@ apoc.cypher.runSchemaFiles([files or urls],{statistics:true,timeout:10}) - allow
apoc.cypher.runTimeboxed('cypherStatement',\{params}, timeout) - abort kernelTransaction after timeout ms if not finished
|label:procedure[]
|label:apoc-core[]
|xref::overview/apoc.cypher/apoc.cypher.runWrite.adoc[apoc.cypher.runWrite icon:book[]]

apoc.cypher.runWrite(fragment, params) yield value - alias for apoc.cypher.doIt
|label:procedure[]
|label:apoc-core[]
|xref::overview/apoc.cypher/apoc.cypher.runFirstColumn.adoc[apoc.cypher.runFirstColumn icon:book[]]

use either apoc.cypher.runFirstColumnMany for a list return or apoc.cypher.runFirstColumnSingle for returning the first row of the first column
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,11 @@ This file is generated by DocsTest, so don't change it!
*** xref::overview/apoc.cypher/apoc.cypher.runFile.adoc[]
*** xref::overview/apoc.cypher/apoc.cypher.runFiles.adoc[]
*** xref::overview/apoc.cypher/apoc.cypher.runMany.adoc[]
*** xref::overview/apoc.cypher/apoc.cypher.runSchema.adoc[]
*** xref::overview/apoc.cypher/apoc.cypher.runSchemaFile.adoc[]
*** xref::overview/apoc.cypher/apoc.cypher.runSchemaFiles.adoc[]
*** xref::overview/apoc.cypher/apoc.cypher.runTimeboxed.adoc[]
*** xref::overview/apoc.cypher/apoc.cypher.runWrite.adoc[]
*** xref::overview/apoc.cypher/apoc.cypher.runFirstColumn.adoc[]
*** xref::overview/apoc.cypher/apoc.cypher.runFirstColumnMany.adoc[]
*** xref::overview/apoc.cypher/apoc.cypher.runFirstColumnSingle.adoc[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,5 @@ RETURN value;
| {node: (:Tag)}
| {node: (:Location)}
|===

Please note that if you want to use schema operation, you have to use xref::overview/apoc.cypher/apoc.cypher.runSchema.adoc[apoc.cypher.runSchema] procedure
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[source,cypher]
----
CALL apoc.cypher.runSchema('CREATE INDEX test FOR (w:Test) ON (w.$name)',{})
----

or

[source,cypher]
----
CALL apoc.cypher.runSchema('CREATE CONSTRAINT $name ON (w:Test) ASSERT w.baz IS UNIQUE',{})
----

0 comments on commit 37daf81

Please sign in to comment.