Grails db-migration dbm-db-doc script fails - grails

I tried to run the "dbm-db-doc" script. It seems that the script is not working properly because it failed on a changelog that already been executed. This is the change:
changeSet(author: "Bernardo (generated)", id: "1436991688243-1") {
addColumn(tableName: "prepares_for_exam") {
column(name: "exam_id", type: "bigint")
}
grailsChange {
change {
sql.execute("UPDATE prepares_for_exam JOIN product ON prepares_for_exam.id = product.prepares_for_exam_id SET prepares_for_exam.exam_id = product.id")
}
rollback {
}
}
addNotNullConstraint(columnDataType: "bigint", tableName: "prepares_for_exam", columnName: "exam_id")
}
changeSet(author: "Bernardo (generated)", id: "1436991688243-32") {
dropColumn(columnName: "prepares_for_exam_id", tableName: "product")
}
And in the database, this changelog has been marked as "EXECUTED"
But when running the script it seems that the script wants to execute that changelog and fails because the column "product.prepares_for_exam_id" has already been dropped.
Full error:
|Starting dbm-db-doc for database root # jdbc:mysql://localhost:3306/xxx?autoReconnect=true&useUnicode=yes&characterEncoding=UTF-8
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'product.prepares_for_exam_id' in 'on clause'
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4237)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4169)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2617)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2778)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2828)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2777)
at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:949)
at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:795)
at Script1$_run_closure1_closure2_closure35_closure36.doCall(Script1.groovy:10)
at grails.plugin.databasemigration.GrailsChange.generateStatements(GrailsChange.groovy:159)
at liquibase.change.AbstractChange.getAffectedDatabaseObjects(AbstractChange.java:208)
at liquibase.changelog.visitor.DBDocVisitor.visit(DBDocVisitor.java:95)
at liquibase.changelog.ChangeLogIterator.run(ChangeLogIterator.java:58)
at liquibase.Liquibase.generateDocumentation(Liquibase.java:740)
at DbmDbDoc$_run_closure1_closure2.doCall(DbmDbDoc:27)
at _DatabaseMigrationCommon_groovy$_run_closure2_closure11.doCall(_DatabaseMigrationCommon_groovy:59)
at grails.plugin.databasemigration.MigrationUtils.executeInSession(MigrationUtils.groovy:133)
at _DatabaseMigrationCommon_groovy$_run_closure2.doCall(_DatabaseMigrationCommon_groovy:51)
at DbmDbDoc$_run_closure1.doCall(DbmDbDoc:26)
at org.grails.ide.api.impl.GrailsConnectorImpl.executeCommand(GrailsConnectorImpl.java:160)
at org.grails.ide.eclipse.longrunning.process.GrailsProcess.run(GrailsProcess.java:130)
at org.grails.ide.eclipse.longrunning.process.GrailsProcess.main(GrailsProcess.java:93)
Error |
org.codehaus.groovy.grails.cli.ScriptExitException
Error |
So my question is:
Is there a bug in the "dbm-db-doc"-script or did I messed up something with the changeset?

I am answering my own question because I found the sollution:
It seems that the migration plugin keeps executing the "grailsChange" part every time although the changeSet has been executed already (I have no clue why... answers welcome!)
The sollution is to not use "grailsChange" and use the normal "sql" command instead. This is the sollution:
changeSet(author: "Bernardo (generated)", id: "1436991688243-1") {
addColumn(tableName: "prepares_for_exam") {
column(name: "exam_id", type: "bigint")
}
sql(""" UPDATE prepares_for_exam JOIN product ON prepares_for_exam.id = product.prepares_for_exam_id SET prepares_for_exam.exam_id = product.id """ )
addNotNullConstraint(columnDataType: "bigint", tableName: "prepares_for_exam", columnName: "exam_id")
}

Related

Neo4j GraphQL how to check if node exists before connecting to it

B"H
I've seen this question and I want to do the same thing with the GraphQL driver for Neo4j. I think the answer lies somewhere in combining AND and OR operators found here, of some sort, but not sure how.
To illustrate the question, say I have this type:
type Comment {
id: ID #id
timeAdded: DateTime! #timestamp(
operations: [CREATE]
)
writer: User! #relationship(
type: "WRITTEN_BY",
direction: IN
)
content: String
}
type User {
id: ID #id
name: String
commentsWritten: [Comment!]! #relationship(
type: "WRITTEN_BY",
direction: OUT
)
}
type Mutation {
addComment(authorID: String)
}
and this resolver to add a new comment (where "Comment" is a reference to the OGM model of the Comment type):
addComment: async (
src,
args,
ctx
) => {
var authorID = args/*edit*/.authorID //let's say this is passed
//from request headers / JWT token or something
var adCom = await Comment.create({
input: [
{
content: args.content,
writer: {
connect: {
where: {
node: {
users: {
id: authorID
}
}
}
}
}
}
]
})
return adCom;
}
So it attempts to connect to that user with that ID. but if there is no user with that ID, I don't want to create anything [not only do I not want to connect it].
I could run another query to find a User with that ID, and test if it went through, but was wondering if it's possible to do everything in one call

Liquibase grails application does not start after upgrade

I upgraded my grails version from 3.8 to 4. In this step I upgraded the liquibase to 3.10.1.
Now my application won't startup any more. I get an error on this changeset:
changeSet(author: "prog1", id: "httpconnector-add-ignoreSSLVerification") {
addColumn(tableName: "inbound_connector") {
column(name: "ignoresslverification ", type: "boolean")
}
addColumn(tableName: "outbound_connector") {
column(name: "ignoresslverification ", type: "boolean")
}
sql("UPDATE outbound_connector set ignoresslverification = true")
sql("UPDATE inbound_connector set ignoresslverification = true")
}
I get this error:
liquibase.exception.MigrationFailedException: Migration failed for change set migrations/changelog.groovy::httpconnector-add-ignoreSSLVerification::ff:
Reason: liquibase.exception.DatabaseException: ERROR: column "ignoresslverification" of relation "outbound_connector" does not exist
Position: 31 [Failed SQL: (0) UPDATE outbound_connector set ignoresslverification = true]
What is the problem here?
I found the error: There is a blank at at column name. The old version ignored this, but the new version not.

Why does "run seedDb" fail when I add in relations between nodes moving from graphql to neo4j

I got the demo example from grand-stack and was able to start up graphql, start up the Neo4J sandbox and populate the test database using
npm run seedDb
However, when I try to write my own data entries to populate into a neo4j database, I cannot get the relation between nodes to work at all. The error message is the most non-useful message (and I believe it is from the apollo client, and is a status code 400 error). I simplified the code to the most simplest case to make it work, and it still does not. Here is the schema.graphql file:
type Patient {
id: ID!
name: String
reviews: [Review] #relation(name:"WROTE", direction:"OUT")
}
type Review {
id: ID!
stars: Int
text: String
date: Date
user: Patient #relation(name: "WROTE", direction: "IN")
}
and here is the seed-mutation.js file:
export default /* GraphQL */ `
mutation {
p1: CreatePatient(
id: "p1",
name: "John Doe 1"
) {
id
name
}
r1: CreateReview(id: "r1", stars: 4, text: "Great IPA selection!", date: { formatted: "2016-01-03"}) {
id
}
ar1: AddUserReviews(from: { id: "p1"}, to: { id: "r1" }) { from {id}}
}
`;
When I do "npm run seedDb", this yields the error message:
{ Error: Network error: Response not successful: Received status code 400
at new ApolloError (/Users/xxxx/Downloads/grand-stack-starter-master/api/node_modules/apollo-client/bundle.esm.js:60:28)
at Object.error (/Users/xxxx/Downloads/grand-stack-starter-master/api/node_modules/apollo-client/bundle.esm.js:1032:48)
at notifySubscription (/Users/xxxx/Downloads/grand-stack-starter-master/api/node_modules/zen-observable/lib/Observable.js:134:18)
at onNotify (/Users/xxxx/Downloads/grand-stack-starter-master/api/node_modules/zen-observable/lib/Observable.js:165:3)
at SubscriptionObserver.error (/Users/xxxx/Downloads/grand-stack-starter-master/api/node_modules/zen-observable/lib/Observable.js:224:7)
at /Users/xxxx/Downloads/grand-stack-starter-master/api/node_modules/apollo-link-http/src/httpLink.ts:184:20
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:228:7)
graphQLErrors: [],
networkError:
{ ServerError: Response not successful: Received status code 400
at Object.exports.throwServerError (/Users/xxxx/Downloads/grand-stack-starter-master/api/node_modules/apollo-link-http-common/src/index.ts:114:17)
at /Users/xxxx/Downloads/grand-stack-starter-master/api/node_modules/apollo-link-http-common/src/index.ts:145:11
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:228:7)
name: 'ServerError',
response:
Response {
size: 0,
timeout: 0,
[Symbol(Body internals)]: [Object],
[Symbol(Response internals)]: [Object] },
statusCode: 400,
result: { errors: [Array] } },
message: 'Network error: Response not successful: Received status code 400',
extraInfo: undefined }
I started with multiple complex codes and this is pretty much the most stripped down version. When I run the seedDB command after the seed-mutation.js file was modified to:
export default /* GraphQL */ `
mutation {
p1: CreatePatient(
id: "p1",
name: "John Doe 1"
) {
id
name
}
r1: CreateReview(id: "r1", stars: 4, text: "Great IPA selection!", date: { formatted: "2016-01-03"}) {
id
}
}
`;
the database gets populated, however the two nodes are not connected to each other, as expected (basically, this is the code with the AddUserReviews removed). How do I build the relation between the nodes through using graphql and seedDb? What am I missing?
You can use GraphQL Playground to inspect the GraphQL API (in the "Docs" tab):
to ensure the mutations you are calling have the correct name and arguments. From inspecting the schema, it looks like instead of AddUserReviews, you want AddPatientReviews?

Client-side mutation with RANGE_ADD type doesn't include edge inside request payload

I'm trying to create new object using client-side mutation described below:
import Relay from 'react-relay'
export default class CreateThemeMutation extends Relay.Mutation {
static fragments = {
admin: () => Relay.QL`fragment on Admin { id }`,
};
getMutation() {
return Relay.QL`mutation { createTheme }`
}
getFatQuery() {
return Relay.QL`
fragment on CreateThemePayload {
admin { themes }
themeEdge
}
`
}
getVariables() {
return {
name: this.props.name,
}
}
getConfigs() {
return [{
type: 'RANGE_ADD',
parentName: 'admin',
parentID: this.props.admin.id,
connectionName: 'themes',
edgeName: 'themeEdge',
rangeBehaviors: {
'': 'append',
},
}]
}
}
Root query field admin is quite similar to viewer so this shouldn't be a problem. The problem is I haven't found themeEdge (which I believe should present) within the request payload (admin { themes } is there though):
query: "mutation CreateThemeMutation($input_0:CreateThemeInput!){createTheme(input:$input_0){clientMutationId,...F3}} fragment F0 on Admin{id} fragment F1 on Admin{id,...F0} fragment F2 on Admin{_themes2gcwoM:themes(first:20,query:""){count,pageInfo{hasNextPage,hasPreviousPage,startCursor,endCursor},edges{node{id,name,createdAt},cursor}},id,...F1} fragment F3 on CreateThemePayload{admin{id,...F0,id,...F2}}"
variables: {input_0: {name: "test", clientMutationId: "0"}}
As a result outputFields.themeEdge.resolve inside the server-side mutation never get called and I see this message:
Warning: writeRelayUpdatePayload(): Expected response payload to include the newly created edge `themeEdge` and its `node` field. Did you forget to update the `RANGE_ADD` mutation config?
I've seen similar issue on github. However REQUIRED_CHILDREN isn't my case because the application has requested themes connection already. Am I missing something obvious? Should I paste more info? Thanks.
react-relay version: 0.6.1
I ran into the same issue and eventually solved it by making sure that my equivalent of themeEdge actually existed as an edge in my schema. If you grep your schema for themeEdge, does an object exist?
For reference, here's my edge definition tailored for you:
{
"name":"themeEdge",
"description":null,
"args":[],
"type":{
"kind":"NON_NULL",
"name":null,
"ofType":{
"kind":"OBJECT",
"name":"ThemeEdge",
"ofType":null
}
},
"isDeprecated":false,
"deprecationReason":null
}
and
{
"kind":"OBJECT",
"name":"ThemeEdge",
"description":"An edge in a connection.",
"fields":[{
"name":"node",
"description":"The item at the end of the edge.",
"args":[],
"type":{
"kind":"NON_NULL",
"name":null,
"ofType":{
"kind":"OBJECT",
"name":"Theme",
"ofType":null
}
},
"isDeprecated":false,
"deprecationReason":null
}
Also note that your rangeBehaviors must exactly match the query you use to retrieve your parent object. You can specify multiple queries as follows, which also shows the syntax for when your query contains multiple variables:
{
type: 'RANGE_ADD',
parentName: 'admin',
parentID: this.props.admin.id,
connectionName: 'themes',
edgeName: 'themeEdge',
rangeBehaviors: {
'': 'append',
'first(1).id($adminId)': 'append',
},
}

How to create a join table using sequelize and sqlite?

I am trying to establish a many-to-many relationship between tables in sqlite using sequelize.
I want to add records to a join table (assign tasks to a user) and retrieve data from that table. For some reason, this does not work. Here is my code:
var orm = new Sequelize('db_name', '', '', {
dialect: 'sqlite',
storage: path.join(__dirname, 'db_name')
});
var User = orm.define('User', {
username: {type: Sequelize.STRING, unique: true}
});
var Task = orm.define('Task', {
id: {type: Sequelize.STRING, unique: true},
taskName: Sequelize.STRING
});
Task.hasMany(User);
User.hasMany(Task);
Task.sync();
User.sync();
Having read documentation (http://sequelize.readthedocs.org/en/latest/api/associations/#hasmanytarget-options), I expect that a join table TasksUsers should be created. I also expect .addTask method do be available. Then in another file I have:
db.User.findOrCreate({where:{username: "fakeUser"}}); //this seems to work
//some code to populate "Tasks" table;
db.User.find({where: {username: "fakeUser"}}).
complete(function(err,user){
console.log("user", user); //the user is found
db.Task.find({where: {id: "some_value"}}).
complete(function(err, task) {
console.log("task", task); //the task is found, so it works up to this point
user.addTask(task). //this line does not work
complete(function(err, results){
console.log("posting error", err);
});
})
});
I get an error "Possibly unhandled SequelizeDatabaseError: Error: SQLITE_ERROR: no such table: TasksUsers". The user.getTasks() method (without any arguments in the parentheses) does not work for the same reason.
Another observation: for testing purposes, I added these lines of code after establishing hasMany relationships:
orm.query("SELECT name FROM sqlite_master WHERE type = 'table'").success(function (res) {
console.log("tables", res);
})
The result that I get is tables [ 'Tasks', 'Users' ]
The versions: sequelize 2.0.0-rc2, sqlite3 3.0.4. I would be very grateful for any help.

Resources