PostgreSQL - SequelizeDatabaseError with join table (Code: 42P01) - postgresql

I am trying to create a join table for many to many relationships.
I am getting the following error:
"name": "SequelizeDatabaseError",
"parent": {
"name": "error",
"length": 110,
"severity": "ERROR",
"code": "42P01",
"position": "13",
"file": "parse_relation.c",
"line": "1160",
"routine": "parserOpenTable",
"sql": "INSERT INTO \"user_routes\" (\"id\",\"userId\",\"routeId\",\"createdAt\",\"updatedAt\") VALUES (DEFAULT,'1','1','2017-11-15 03:57:21.791 +00:00','2017-11-15 03:57:21.791 +00:00') RETURNING *;"
},
The relationship is between User and Route:
module.exports = (sequelize, DataTypes) => {
const Route = sequelize.define("Route", {
open: {
type: DataTypes.BOOLEAN,
allowNull: true
}
});
Route.associate = models => {
Route.belongsToMany(models.User, {
through: "userRoutes",
as: "users"
});
};
return Route;
};
module.exports = (sequelize, DataTypes) => {
var User = sequelize.define("User", {
email: DataTypes.TEXT,
password: DataTypes.TEXT
});
User.associate = models => {
User.belongsToMany(models.Route, {
through: "userRoutes",
as: "routes"
});
};
return User;
};
Migration files for user and route does not have much but just the basics. For join table:
"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable("user_route", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
},
userId: {
type: Sequelize.INTEGER,
onDelete: "CASCADE",
references: {
model: "Users",
key: "id"
}
},
routeId: {
type: Sequelize.INTEGER,
onDelete: "CASCADE",
references: {
model: "Routes",
key: "id"
}
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable("user_route");
}
};
My controller and route is as following:
create(req, res) {
return UserRoutes.create({
userId: req.body.userId,
routeId: req.body.routeId
})
.then(userRoute => res.status(201).send(userRoute))
.catch(err => res.status(400).send(err));
},
app.post("/api/userRoutes", userRoutesController.create);
So when I try to post to that route, I get the error message on the top of the post.

I had this same error, and was similarly thrown by an unrelated issue (my SQL clause had single quotes that were all escaped, and, since the query ran when I removed them, I was focused on a way to remove the escaping). My problem was that my migration was generated with a table name that violated the PostgreSQL naming convention; when I corrected this (I had a capitalized first letter in my table name, so I edited the migration for a lowercase first letter and reran it), the error disappeared. Maybe that might fix yours?

After you created db, models and migrations, you need to run
sequelize db:migrate
before running your application.
If not, it will throw SequelizeDatabaseError as mentioned above.

If you look at the line:
"routine": "parserOpenTable"
We will see an error when opening the table.
Most likely, the error is due to the naming of the tables.
Pay attention to capital letters.
Example,
"./models/user.js": tableName "users", but in DBMS we have table "Users".
Just change tableName.

Related

SequelizeDatabaseError: the operator does not exist : integer = boolean when using special methods on model instance

I have two models in Many-to-Many association : Agency and Customer.
UPDATE : (here are the models and association definition)
Agency :
const agency = (sequelize, DataTypes) => {
const Agency = sequelize.define('agency', {
name: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true,
}
},
});
Agency.associate = models => {
Agency.hasMany(models.User, { onDelete: 'CASCADE' });
Agency.belongsToMany(models.Customer, { onDelete: 'SET NULL', through: 'CustomerAgencies'});
};
return Agency;
};
export default agency;
Customer :
const customer = (sequelize, DataTypes) => {
const Customer = sequelize.define('customer', {
email: {
type: DataTypes.STRING,
unique: true,
allowNull: false,
validate: {
notEmpty: true,
isEmail: true,
},
},
firstname: {
type: DataTypes.STRING,
allowNull: true,
validate: {
notEmpty: true,
}
},
lastname: {
type: DataTypes.STRING,
allowNull: true,
validate: {
notEmpty: true,
}
},
phone: {
type: DataTypes.INTEGER,
},
language: {
type: DataTypes.STRING,
},
});
Customer.associate = models => {
Customer.belongsToMany(models.Agency, { onDelete: 'SET NULL', through: 'CustomerAgencies'});
};
return Customer;
};
export default customer;
When i create some entries, there is no problem :
const agency = await models.Agency.findOrCreate({
where: { name: 'SunTour'},
defaults: {
name: 'SunTour'
}
});
const customer = await models.Customer.findOrCreate({
where: { email: 'paulo#example.com' },
defaults: {
email: 'paulo#example.com',
firstname: 'Paulo',
lastname: 'Dena',
phone: '0202020202',
},
});
But i'm trying to use the special methods of Sequelize that are available when two models are in relation.
Juste under the previous code example i wrote this to check is there is already an assocation between the two instances :
debug(await customer[0].hasAgency(agency));
The node server return me the error below for this line :
UnhandledPromiseRejectionWarning: SequelizeDatabaseError: the operator does not exist : integer = boolean
In the console the query executed is this one :
SELECT "agency"."id" FROM "agencies" AS "agency" INNER JOIN "CustomerAgencies" AS "CustomerAgencies" ON "agency"."id" = "CustomerAgencies"."agencyId" AND "CustomerAgencies"."customerId" = 1 WHERE ((("agency"."id" = 1 OR "agency"."id" = false)));
You can see that Sequelize query is using "agency.id = false" in his condition, i guess that's the problem.
Note : i'm using a PostGreSQL Database.
I guess the problem come from the PostGreSQL Database, but what can i do ?
Thanks in advance.

SailsJs/Postgresql - How to create a one way association or one-to-many relation via an unique field

I have two models:
PdfAnnotation.js:
module.exports = {
tableName: "pdf_annotations",
primaryKey: "pk_id",
attributes: {
pk_id: {
type: "number",
autoIncrement: true
},
annotation_id: {
type: "string",
unique: true,
required: true,
},
comments: {
collection: "pdfcomments",
via: "fk_annotation_id"
}
}
};
PdfComments.js:
module.exports = {
tableName: "pdf_comments",
primaryKey: "pk_id",
attributes: {
pk_id: {
type: "number",
autoIncrement: true,
},
fk_annotation_id: {
model: "pdfannotations",
},
comment_content: {
type: "string",
},
}
};
When I run these codes:
PdfAnnotations.create({
annotation_id: "test3",
});
PdfComments.create({
fk_annotation_id: 'test3',
comment_content: 'test',
});
I got this error:
I have followed the documentation: https://sailsjs.com/documentation/concepts/models-and-orm/associations/one-to-many.
The difference between my implementation and the docs is: the constraint I used for PdfComments to PdfAnnotations via an unique field annotation_id(string) not the primary key pk_id(number), so that I got the error.
For some reasons I don't want to use annotation_id as a primary key (such as its type is string)
I'm not familiar with Sails and its ORM, hope to see your help.
Try something like this:
const pdfannotation = await PdfAnnotations.create({
annotation_id: 'test3',
}).fetch();
const pdfcomment = await PdfComments.create({
fk_annotation_id: pdfannotation.id,
comment_content: 'test',
});

Sequelize Unique Constraint Across Two Tables

I have three tables: survey, survey_owners (join table), users. Surveys naturally have titles and are owned by users. A user can own multiple surveys and a survey can be owned by multiple users (many-to-many relationship).
I have the unique constraint setup on the survey_owners table so there are no duplicates, but now need to figure out how to enforce a unique constraint to address the following: A user should not be able to own multiple surveys with the same title.
That being said, a unique constraint CANNOT be placed on the 'title' column of the survey table because the uniqueness should be only be applied if a user already owns a survey with an identical name.
Any ideas how to implement this in the Sequelize migration and/or model(s)?
Current migration file for survey_owners
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('survey_owners', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
surveys_id: {
type: Sequelize.INTEGER,
onDelete: 'CASCADE',
references: {
model: 'surveys',
key: 'id'
}
},
users_id: {
type: Sequelize.INTEGER,
references: {
model: 'users',
key: 'id'
}
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
field: "created_at"
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
field: "updated_at"
}
})
.then(() => {
return queryInterface.addConstraint('survey_owners', ['surveys_id', 'users_id'], {
type: 'unique',
name: 'survey_owners'
});
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('survey_owners');
}
};
Unfortunately I could not find a way inside Sequelize to handle this constraint so I am handling the logic on the submit action and checking in a JS method. Not the best way but had to move on and this is working.

Postgres Include throws "name": "SequelizeEagerLoadingError"

I am having trouble figuring out why my include statement throws this error
"name": "SequelizeEagerLoadingError"
My controller function in question looks like this
retrieve (req, res) {
return User
.findOne({
where: {
token_id: req.params.token_id
},
include: [{
model: subscribedcurrency,
as: 'subscribed currency'
}]
})
.then(user => {
if (!user) {
return res.status(404).send({
message: 'User Not Found'
})
}
return res.status(200).send(user)
})
.catch(error => res.status(400).send(error))
},
The model for subscribedcurrency looks like this
module.exports = (sequelize, DataTypes) => {
var SubscribedCurrency = sequelize.define('SubscribedCurrency', {
symbol: {
type: DataTypes.STRING,
allowNull: false
},
name: {
type: DataTypes.STRING,
allowNull: false
},
priceAtSubscription: {
type: DataTypes.STRING,
allowNull: false
}
})
SubscribedCurrency.associate = (models) => {
SubscribedCurrency.hasMany(models.User, {
foreignKey: 'userId',
onDelete: 'CASCADE'
})
}
return SubscribedCurrency
}
I've tried changing how it queries, the primary key of User, just about everything I can think of. The relationship between User and subscribedCurrency is many to many.
without the include statement and the findOne query works perfect fine!
I think all you need is to remove as: 'subscribed currency' , as you haven't define association with alias.
So From this :
include: [{
model: subscribedcurrency,
as: 'subscribed currency'
}]
To this :
include: [{
model: subscribedcurrency,
}]

How to set up PostgreSQL database with associations between tables (foreign keys) with Sequelize

I'm using PostgreSQL, Sequelize, and Sequelize-cli.
Using sequelize-cli and some manipulation in an IDE I set up the following model and migration file (simplified for the example, I didn't include the "Users" migration file):
Model File
// models/annotation.js
module.exports = function (sequelize, DataTypes) {
var Annotation = sequelize.define('Annotation', {
userId: {
type: DataTypes.INTEGER,
references: {model: "User", key: 'id'},
},
url: DataTypes.STRING,
source: DataTypes.STRING,
body: DataTypes.TEXT,
exact: DataTypes.TEXT,
}, {
classMethods: {
associate: function (models) {
// associations can be defined here
Annotation.belongsTo(models.User, {foreignKey: "userId"});
},
},
});
return Annotation;
};
Corresponding migration file
// migrations/20161121050521-create-annotation.js
const User = require("../models/user");
module.exports = {
up: function(queryInterface, Sequelize) {
return queryInterface.createTable('Annotations', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
userId: {
type: Sequelize.INTEGER,
references: {model: User, key: 'id'},
allowNull: false
},
...
Referenced Model
// models/user.js
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('User', {
title: DataTypes.STRING,
name: DataTypes.STRING,
email: DataTypes.STRING,
}, {
classMethods: {
associate: function(models) {
// associations can be defined here
User.hasMany(models.Annotation, {foreignKey: "userId"});
}
}
});
return User;
};
I'm running the follow cli commands:
"dropdb -U postgres annotate && curl -XDELETE 'http://localhost:9200/_all'"
"createdb -U postgres annotate"
"node_modules/.bin/sequelize db:migrate"
When I migrate I get the following error:
SequelizeDatabaseError: relation "User" does not exist
From the documentation I was under the impression that Annotation.belongsTo(models.User would have been enough to establish the association, but when I did that my db tables didn't have any foreign key fields.
How can I establish tables with associations to one another?