liquibase / liquigraph Goto Github PK
View Code? Open in Web Editor NEWMigrations for Neo4j
Home Page: https://www.liquigraph.org
License: Apache License 2.0
Migrations for Neo4j
Home Page: https://www.liquigraph.org
License: Apache License 2.0
Possible options:
While changesets are immutable and incremental by default, the user should be able to specify, at changeset level, that :
Note that a changeset can be run always but not allowed to change (run always = true, run on change = false) ;)
It's feasible a release may not go to plan when deploying large applications with many dependencies. In these cases it's likely that the application will be 'rolled back' to bring the application up again as quickly as possible. It would be useful to have a roll-back feature in Liquigraph that allows users to revert the database to a previous state.
./liquigraph.run -help
Exception in thread "main" com.beust.jcommander.ParameterException: The following options are required: --graph-db-uri, -g --changelog, -c
at com.beust.jcommander.JCommander.validateOptions(JCommander.java:320)
at com.beust.jcommander.JCommander.parse(JCommander.java:282)
at com.beust.jcommander.JCommander.parse(JCommander.java:264)
at com.beust.jcommander.JCommander.<init>(JCommander.java:209)
at org.liquigraph.cli.LiquigraphCli.main(LiquigraphCli.java:72)
wuqour:liquigraph mh$ ./liquigraph.run --help
Exception in thread "main" com.beust.jcommander.ParameterException: The following options are required: --graph-db-uri, -g --changelog, -c
at com.beust.jcommander.JCommander.validateOptions(JCommander.java:320)
at com.beust.jcommander.JCommander.parse(JCommander.java:282)
at com.beust.jcommander.JCommander.parse(JCommander.java:264)
at com.beust.jcommander.JCommander.<init>(JCommander.java:209)
at org.liquigraph.cli.LiquigraphCli.main(LiquigraphCli.java:72)
Currently, the implementations of GraphDatabaseRule
perform some cleanup at the end of a test, by silently closing the connection if it's still open. It should actually fail the test if the connection wasn't properly closed by the production code.
Indeed, only 1 process can access a given graph directory at once, and Liquigraph tries to start a new instance based on the dir URI.
The only option is to allow users to directly pass a GraphDatabaseService to Configuration(Builder).
A precondition acts as a guard and is defined by a Cypher statement resulting in a boolean result. The result should be named "result", e.g.:
RETURN true AS result
is a valid precondition query, whereas:
MATCH (bob:MyLabel) RETURN bob
is not. bob
should be of boolean type and aliased or directly named result
.
It is defined at changeset level. If the Cypher precondition fails, the user must define an error policy: either MARK_AS_RAN or FAIL.
With the first setting, the changeset execution will be skipped but marked as if it was successfully executed.
With the second one, the changeset execution will fail, interrupting Liquigraph execution.
I created a changeset with 17 create statements. When running liquigraph it would hang for a minute then throw the error below.
Splitting the 17 changesets into two seperate changesets fixed the error.
12:32:53.167 [main] ERROR o.l.core.io.lock.LockableConnection - Cannot remove __LiquigraphLock during cleanup.
java.sql.SQLException: Error executing statement
at org.neo4j.jdbc.internal.rest.TransactionalQueryExecutor.executeQuery(TransactionalQueryExecutor.java:224) ~[liquigraph-cli.jar:na]
at org.neo4j.jdbc.internal.Neo4jConnection.executeQuery(Neo4jConnection.java:370) ~[liquigraph-cli.jar:na]
at org.neo4j.jdbc.internal.Neo4jPreparedStatement.execute(Neo4jPreparedStatement.java:55) ~[liquigraph-cli.jar:na]
at org.liquigraph.core.io.lock.LockableConnection.releaseLock(LockableConnection.java:310) [liquigraph-cli.jar:na]
at org.liquigraph.core.io.lock.LockableConnection.close(LockableConnection.java:89) [liquigraph-cli.jar:na]
at org.liquigraph.core.io.lock.LockableConnection.acquire(LockableConnection.java:71) [liquigraph-cli.jar:na]
at org.liquigraph.core.io.GraphJdbcConnector.connect(GraphJdbcConnector.java:43) [liquigraph-cli.jar:na]
at org.liquigraph.core.api.MigrationRunner.runMigrations(MigrationRunner.java:68) [liquigraph-cli.jar:na]
at org.liquigraph.core.api.Liquigraph.runMigrations(Liquigraph.java:63) [liquigraph-cli.jar:na]
at org.liquigraph.cli.LiquigraphCli.main(LiquigraphCli.java:119) [liquigraph-cli.jar:na]
Caused by: org.restlet.resource.ResourceException: Error executing statement
at org.restlet.resource.ClientResource.doError(ClientResource.java:612) ~[liquigraph-cli.jar:na]
at org.neo4j.jdbc.internal.rest.Resources$TransactionClientResource.doError(Resources.java:283) ~[liquigraph-cli.jar:na]
at org.restlet.resource.ClientResource.handleInbound(ClientResource.java:1202) ~[liquigraph-cli.jar:na]
at org.restlet.resource.ClientResource.handle(ClientResource.java:1069) ~[liquigraph-cli.jar:na]
at org.restlet.resource.ClientResource.handle(ClientResource.java:1044) ~[liquigraph-cli.jar:na]
at org.restlet.resource.ClientResource.post(ClientResource.java:1453) ~[liquigraph-cli.jar:na]
at org.neo4j.jdbc.internal.rest.TransactionalQueryExecutor.post(TransactionalQueryExecutor.java:98) ~[liquigraph-cli.jar:na]
at org.neo4j.jdbc.internal.rest.TransactionalQueryExecutor.begin(TransactionalQueryExecutor.java:76) ~[liquigraph-cli.jar:na]
at org.neo4j.jdbc.internal.rest.TransactionalQueryExecutor.executeQuery(TransactionalQueryExecutor.java:214) ~[liquigraph-cli.jar:na]
... 9 common frames omitted
Error executing statement (404) - {"results":[],"errors":[{"code":"Neo.ClientError.Transaction.UnknownId","message":"Unrecognized transaction id. Transaction may have timed out and been rolled back."}]}
at org.restlet.resource.ClientResource.doError(ClientResource.java:612)
at org.neo4j.jdbc.internal.rest.Resources$TransactionClientResource.doError(Resources.java:283)
at org.restlet.resource.ClientResource.handleInbound(ClientResource.java:1202)
at org.restlet.resource.ClientResource.handle(ClientResource.java:1069)
at org.restlet.resource.ClientResource.handle(ClientResource.java:1044)
at org.restlet.resource.ClientResource.handle(ClientResource.java:950)
at org.restlet.resource.ClientResource.delete(ClientResource.java:570)
at org.neo4j.jdbc.internal.rest.TransactionalQueryExecutor.rollback(TransactionalQueryExecutor.java:187)
at org.neo4j.jdbc.internal.Neo4jConnection.close(Neo4jConnection.java:245)
at org.liquigraph.core.io.lock.LockableConnection.close(LockableConnection.java:90)
at org.liquigraph.core.io.lock.LockableConnection.acquire(LockableConnection.java:71)
at org.liquigraph.core.io.GraphJdbcConnector.connect(GraphJdbcConnector.java:43)
at org.liquigraph.core.api.MigrationRunner.runMigrations(MigrationRunner.java:68)
at org.liquigraph.core.api.Liquigraph.runMigrations(Liquigraph.java:63)
at org.liquigraph.cli.LiquigraphCli.main(LiquigraphCli.java:119)
Exception in thread "main" org.liquigraph.core.exception.LiquigraphLockException: Cannot create __LiquigraphLock lock
Likely another Liquigraph execution is going on or has crashed.
at org.liquigraph.core.io.lock.LockableConnection.tryWriteLock(LockableConnection.java:358)
at org.liquigraph.core.io.lock.LockableConnection.acquireLock(LockableConnection.java:323)
at org.liquigraph.core.io.lock.LockableConnection.acquire(LockableConnection.java:67)
at org.liquigraph.core.io.GraphJdbcConnector.connect(GraphJdbcConnector.java:43)
at org.liquigraph.core.api.MigrationRunner.runMigrations(MigrationRunner.java:68)
at org.liquigraph.core.api.Liquigraph.runMigrations(Liquigraph.java:63)
at org.liquigraph.cli.LiquigraphCli.main(LiquigraphCli.java:119)
Caused by: java.sql.SQLException: Error executing query CREATE (:__LiquigraphLock {name:'John', uuid:{1}})
with params {1=4689adcb-4f39-493a-a82a-faa7f8bf24be}
at org.neo4j.jdbc.internal.Neo4jConnection.executeQuery(Neo4jConnection.java:379)
at org.neo4j.jdbc.internal.Neo4jPreparedStatement.execute(Neo4jPreparedStatement.java:55)
at org.liquigraph.core.io.lock.LockableConnection.tryWriteLock(LockableConnection.java:354)
... 6 more
Caused by: java.lang.RuntimeException: Error executing cypher statement(s) [{code=Neo.ClientError.Schema.ConstraintViolation, message=Node 6 already exists with label __LiquigraphLock and property "name"=[John]}]
at org.neo4j.jdbc.internal.rest.StreamingParser.handleErrors(StreamingParser.java:341)
at org.neo4j.jdbc.internal.rest.StreamingParser.skipTo(StreamingParser.java:315)
at org.neo4j.jdbc.internal.rest.StreamingParser.nextResult(StreamingParser.java:130)
at org.neo4j.jdbc.internal.rest.StreamingParser$2.hasNext(StreamingParser.java:265)
at org.neo4j.jdbc.internal.rest.TransactionalQueryExecutor.executeQuery(TransactionalQueryExecutor.java:215)
at org.neo4j.jdbc.internal.Neo4jConnection.executeQuery(Neo4jConnection.java:370)
... 8 more
Are there any plans to do a native Gradle plugin for liquigraph or are you aware of one that someone has written? I couldn't find any through Google.
The product looks great and I'm tempted to use it but don't have time to trial and error a maven/cli gradle integration at the moment.
If you do plan to write one I see liquibase have written one which could be a good starting point: https://github.com/liquibase/liquibase-gradle-plugin
Currently failing:
instantiates_a_remote_graph_database(org.liquigraph.core.writer.GraphJdbcConnectorTest) Time elapsed: 0.015 sec <<< ERROR!
java.lang.NoClassDefFoundError: org/neo4j/graphdb/mockfs/EphemeralFileSystemAbstraction
at org.neo4j.test.ImpermanentGraphDatabase.createFileSystemAbstraction(ImpermanentGraphDatabase.java:201)
at org.neo4j.kernel.InternalAbstractGraphDatabase.create(InternalAbstractGraphDatabase.java:415)
at org.neo4j.kernel.InternalAbstractGraphDatabase.run(InternalAbstractGraphDatabase.java:321)
at org.neo4j.kernel.EmbeddedGraphDatabase.<init>(EmbeddedGraphDatabase.java:59)
at org.neo4j.test.ImpermanentGraphDatabase.<init>(ImpermanentGraphDatabase.java:139)
at org.neo4j.test.ImpermanentGraphDatabase.<init>(ImpermanentGraphDatabase.java:123)
at org.neo4j.test.ImpermanentGraphDatabase.<init>(ImpermanentGraphDatabase.java:97)
at org.neo4j.test.ImpermanentGraphDatabase.<init>(ImpermanentGraphDatabase.java:88)
at org.neo4j.test.ImpermanentGraphDatabase.<init>(ImpermanentGraphDatabase.java:65)
at org.neo4j.jdbc.internal.embedded.EmbeddedDatabases.defaultImpermanentDb(EmbeddedDatabases.java:104)
at org.neo4j.jdbc.internal.embedded.EmbeddedDatabases.createDatabase(EmbeddedDatabases.java:73)
at org.neo4j.jdbc.internal.embedded.EmbeddedDatabases.createExecutor(EmbeddedDatabases.java:109)
at org.neo4j.jdbc.Driver.createExecutor(Driver.java:146)
at org.neo4j.jdbc.internal.Neo4jConnection.createExecutor(Neo4jConnection.java:131)
at org.neo4j.jdbc.internal.Neo4jConnection.<init>(Neo4jConnection.java:79)
at org.neo4j.jdbc.internal.Connections$4.doCreate(Connections.java:65)
at org.neo4j.jdbc.internal.Connections.create(Connections.java:80)
at org.neo4j.jdbc.Driver.connect(Driver.java:80)
at org.neo4j.jdbc.Driver.connect(Driver.java:42)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:270)
at org.liquigraph.core.writer.GraphJdbcConnector.connect(GraphJdbcConnector.java:16)
at org.liquigraph.core.writer.GraphJdbcConnectorTest.instantiates_a_remote_graph_database(GraphJdbcConnectorTest.java:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:168)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Caused by: java.lang.ClassNotFoundException: org.neo4j.graphdb.mockfs.EphemeralFileSystemAbstraction
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 54 more
We added a new file to our changeset. Since adding it it seems liquigraph hangs. There is no output from liquigraph that details what's going on.
If we remove the file it works. If we only have one query in the - it works. We assumed it would be related to tabs or line endings however the file is in line with everything else.
Can you offer any input on how to proceed? Is there a log file anywhere we can refer to?
Liquigraph can only be run twice with the following changelog:
<changelog>
<changeset id="create-node" run-always="true">
<query>CREATE (n:Node)</query>
</changeset>
</changelog>
The first time, it will record the execution with a MERGE
query equivalent to:
MATCH (changelog:__LiquigraphChangelog)
CREATE (changelog)<-[:EXECUTED_WITHIN_CHANGELOG {order: 1}]-(:__LiquigraphChangeset {id: "create-node"})
(other properties of the changeset omitted). All is well.
The second time, due to the presence of the order
property inside the MERGE
clause, it will record another execution, despite the method being called "upsert":
MATCH (changelog:__LiquigraphChangelog)
CREATE (changelog)<-[:EXECUTED_WITHIN_CHANGELOG {order: 2}]-(:__LiquigraphChangeset {id: "create-node"})
If you try to run Liquibase a third time, it will complain that you have less declared changesets than have been executed (persisted).
I think the fix is actually simple. Instead of
MATCH (changelog:__LiquigraphChangelog)
MERGE (changelog)<-[:EXECUTED_WITHIN_CHANGELOG {order: {1}}]-(changeset:__LiquigraphChangeset {id: {2}})
ON MATCH SET changeset.checksum = {3},
changeset.query = {4}
ON CREATE SET changeset.author = {5},
changeset.query = {4}
changeset.checksum = {3}
the CHANGESET_UPSERT
query should be
MATCH (changelog:__LiquigraphChangelog)
MERGE (changelog)<-[exec:EXECUTED_WITHIN_CHANGELOG]-(changeset:__LiquigraphChangeset {id: {2}})
ON MATCH SET changeset.checksum = {3},
changeset.query = {4}
ON CREATE SET changeset.author = {5},
changeset.query = {4}
changeset.checksum = {3},
exec.order = {1}
(not tested at all, though, but it's the gist of the fix).
I'll try preparing a pull request.
Assuming that I'm understanding the use case for contexts, it appears that there's a bug in the PersistedChangesetValidator. Basically, if you run a migration with context, then only the invoked changesets are persisted. On a subsequent run the validator is comparing the index of the persisted value against the index of the complete changelog, so they never match and migration always fails.
Perhaps, the absolute index of the changeset should be stored in the graph and then compared against the absolute index of the changelog list.
A context is a user-defined identifier, declared at changeset level.
A context is specified at execution time. If none are defined, all changesets will be executed.
If contexts are defined, one match amongst them is enough for candidate changesets to be executed.
./liquigraph.run --changelog="test/migrations/changelog.xml" --graph-db-uri=jdbc:neo4j://localhost:7474/ --dry-run-output-directory=/tmp
Exception in thread "main" com.beust.jcommander.ParameterException: The following options are required: --graph-db-uri, -g --changelog, -c
at com.beust.jcommander.JCommander.validateOptions(JCommander.java:320)
at com.beust.jcommander.JCommander.parse(JCommander.java:282)
at com.beust.jcommander.JCommander.parse(JCommander.java:264)
at com.beust.jcommander.JCommander.<init>(JCommander.java:209)
at org.liquigraph.cli.LiquigraphCli.main(LiquigraphCli.java:72)
wuqour:liquigraph mh$ ./liquigraph.run -c "test/migrations/changelog.xml" -g jdbc:neo4j://localhost:7474/ --dry-run-output-directory=/tmp
Exception in thread "main" com.beust.jcommander.ParameterException: The following options are required: --graph-db-uri, -g --changelog, -c
at com.beust.jcommander.JCommander.validateOptions(JCommander.java:320)
at com.beust.jcommander.JCommander.parse(JCommander.java:282)
at com.beust.jcommander.JCommander.parse(JCommander.java:264)
at com.beust.jcommander.JCommander.<init>(JCommander.java:209)
at org.liquigraph.cli.LiquigraphCli.main(LiquigraphCli.java:72)
While applying the postcondition commits onto master_3.x
, I noticed that in some tests (e.g. ChangelogGraphWriteTestSuite
, ResultSets
have been moved out of the try-with-resources declaration and into the body, which would seem to indicate they shouldn't be closed anymore.
However, in other tests (e.g. LiquigraphTestSuite
), they remain in the try-with-resources declaration.
Should it be done consistently across test (and maybe production) code?
... thus preventing users from typos and helping them with autocompletion and this kind of goodies.
When migrating a large quantity of data, executing all the queries in a single transaction can lead to OutOfMemoryErrors in Neo4j.
I think this could be mitigated by repeating queries (using LIMIT
to migrate batches) returning a single boolean value, like the pre-conditions. The query would be run until it returns false
.
Another way could be to use separate "post-conditions" to validate whether the query needs to be repeated, to split the responsibilities.
Is there a technical reason that you cannot define multiple queries per changeset? I assume that a changeset is run in a transaction.
It would be useful to be able to add Tags to Liquigraph. This would allow users to add versioning to their database allowing installation of specific versions and roll back to previous versions (assuming rollback is implemented) .
We're running a multiple dockerized Neo4J instances which contain a small set of identical data. We'd like to add the data at the Neo4J container launch. We dockerized liquigraph to run alongside the Neo4J container launch however the -p flag doesn't appear to work. This means we can't add data without manual intervention to key the password.
Is it possible to use the -p flag?
Exception in thread "main" com.beust.jcommander.ParameterException: Was passed main parameter 'password' but no main parameter was defined
at com.beust.jcommander.JCommander.getMainParameter(JCommander.java:914)
at com.beust.jcommander.JCommander.parseValues(JCommander.java:759)
at com.beust.jcommander.JCommander.parse(JCommander.java:282)
at com.beust.jcommander.JCommander.parse(JCommander.java:265)
at com.beust.jcommander.JCommander.<init>(JCommander.java:210)
at org.liquigraph.cli.LiquigraphCli.main(LiquigraphCli.java:95
I got validation exception and could not find in your current version good changelog.xml with xsd.
and I got your example from the site:
<changelog>
<changeset id="hello-world" author="you">
<query>CREATE (n:Sentence {text:'Hello monde!'}) RETURN n</query>
</changeset>
<changeset id="hello-world-fixed" author="you">
<query>MATCH (n:Sentence {text:'Hello monde!'}) SET n.text='Hello world!' RETURN n</query>
</changeset>
</changelog>
Caused by: java.lang.IllegalArgumentException:
cvc-elt.1: Cannot find the declaration of element 'changelog'.
at org.liquigraph.core.io.xml.ChangelogParser.parseChangelog(ChangelogParser.java:64) ~[liquigraph-core-1.0-RC3.jar:na]
at org.liquigraph.core.io.xml.ChangelogParser.parse(ChangelogParser.java:56) ~[liquigraph-core-1.0-RC3.jar:na]
at org.liquigraph.core.api.MigrationRunner.parseChangesets(MigrationRunner.java:84) ~[liquigraph-core-1.0-RC3.jar:na]
at org.liquigraph.core.api.MigrationRunner.runMigrations(MigrationRunner.java:66) ~[liquigraph-core-1.0-RC3.jar:na]
at org.liquigraph.core.api.Liquigraph.runMigrations(Liquigraph.java:63) ~[liquigraph-core-1.0-RC3.jar:na]
Currently showing HTTP client activity in stdout.
The documentation says:
Finally, a changeset is uniquely identified within the changelog by its mandatory ID and author attributes.
However, the queries are only based on the id
, so the documentation should probably be fixed.
Moreover, the minimum Neo4j version seems to be 2.0.x (though the documentation does not mention it explicitly, and should also be fixed for that as well ๐), which already supports uniqueness constraints. I think it might be a good idea to add such a constraint on __LiquigraphChangeset.id
, which would have prevented the "corruption" I got when I stumbled on #58.
If you write a changeset with multiple queries (in my tests I had 2 queries) liquigraph will run fine the first time but if you rerun it, it throws an exception when calculating the queries checksum. I believe it's because the order the queries are being retrieved matter to calculate the checksum:
MATCH (changelog:__LiquigraphChangelog)<-[exec:EXECUTED_WITHIN_CHANGELOG]-(changeset:__LiquigraphChangeset) WITH changeset, exec MATCH (changeset)<-[:EXECUTED_WITHIN_CHANGESET]-(query:__LiquigraphQuery) WITH changeset, query, exec ORDER BY exec.time ASC, query.order ASC WITH changeset, COLLECT(query.query) AS queries, exec RETURN { id: changeset.id, author:changeset.author, checksum:changeset.checksum, query:queries} AS changeset
is used in ChangelogGraphReader but the expression query.order ASC
is moot as we are not currently storing that (at least the xsd doesn't allow it as QueryType is a simple string). This can cause indeterministic behavior when calculating the checksums.
I have a very simple changeset, just containing a single index.
<changelog>
<changeset id="initial-indexes" author="lili">
<query>CREATE INDEX ON :Foo(name)</query>
</changeset>
</changelog>
When trying to run it with liquigraph 1.0.0.RC2 on a clean localhost instance of neo4j 2.2.1 it crashes with an exception:
Caused by: java.lang.RuntimeException: Error executing cypher statement(s) [{code=Neo.ClientError.Transaction.InvalidType, message=Cannot perform schema updates in a transaction that has performed data updates.}]
However, if I change the CREATE INDEX to something not modifying the schema, e.g. CREATE a node, then it loads fine. Looks to me that liquigraph would need to use separate transactions for creating indexes and updating its own data. I have no other queries in the changeset so I assume it's the changeset-tracking data that's being inserted within the same transaction.
There is likely a solution similar to the one written in Maven plugin: with an URLClassLoader, we should achieve the loading we want.
This would greatly simplify the script (no Python needed anymore).
A changelog is a set of changelog xor changesets.
Both are defined relatively to the classpath.
A changelog can either include other changelogs or changesets.
A changeset is defined by 1 Cypher query. It is uniquely identified by a mandatory logical ID. It has also the following mandatory author attribute. Changesets are immutable and run only once by default.
The declaration order of changesets is the execution order. New changesets must be defined after executed changesets.
Currently fails with client (and probably with MVN plugin):
Exception in thread "main" java.lang.IllegalArgumentException: InputStream cannot be null
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:117)
at org.liquigraph.core.io.xml.ImportResolver.document(ImportResolver.java:79)
at org.liquigraph.core.io.xml.ImportResolver.resolveImports(ImportResolver.java:45)
at org.liquigraph.core.io.xml.ImportResolver.resolve(ImportResolver.java:57)
at org.liquigraph.core.io.xml.ImportResolver.resolveImports(ImportResolver.java:45)
at org.liquigraph.core.io.xml.ChangelogPreprocessor.preProcess(ChangelogPreprocessor.java:29)
at org.liquigraph.core.io.xml.ChangelogParser.parseChangelog(ChangelogParser.java:61)
at org.liquigraph.core.io.xml.ChangelogParser.parse(ChangelogParser.java:56)
at org.liquigraph.core.api.MigrationRunner.parseChangesets(MigrationRunner.java:84)
at org.liquigraph.core.api.MigrationRunner.runMigrations(MigrationRunner.java:66)
at org.liquigraph.core.api.Liquigraph.runMigrations(Liquigraph.java:63)
at org.liquigraph.cli.LiquigraphCli.main(LiquigraphCli.java:119)
It just outputs the Cypher queries that would be executed, in order, in target/output.cypher
.
Currently, all changesets have to be declared within the same changelog.
Allowing nested changelogs would allow to organize changesets as users see fit, e.g. per software release.
As advised by @jexp, https://github.com/neo4j-contrib/neo4j-jdbc is the way to go!
It'll actually make Liquigraph configuration easier \o/
3 modes should be available :
I'm using liquigraph inside a spring-boot application. Normally you are given an already defined java.sql.DataSource
which you can use to obtain a connection. Unfortunately liquigraph doesn't support this. Therefore I'm currently using a hack to get the URL/Username/Password and providing this to liquigraph.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.