Sequelize Migration Error - node.js

I'm using Sequelize 2.0.0-rc3 and there's an error I'm encountering; it seems like I'm writing the migration correctly but I'm getting an error trying to run it. I'm using Postgresql on the backend. Everything seems to be working fine; this is a new, isolated issue. The Document table and id column exists (created it in a previous migration, but discovered it's not auto-incrementing id's; so tried creating this migration to add auto-incrementing).
var p = require('bluebird');
module.exports = {
up: function (migration, DataTypes, done) {
var promises = [];
promises.push(
migration.changeColumn(
'Document',
'id',
{
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
}
));
p.all(promises).then(done.bind(null, null)).catch(function (err) {
console.error('Migration Failed: ', err);
done(err);
});
},
down: function (migration, DataTypes, done) {
done();
}
};
Possibly unhandled TypeError: Cannot call method 'push' of undefined
at Object.module.exports.QueryGenerator.dataTypeMapping (/Users/csimpson/code/temp-cause-server/node_modules/sequelize/lib/dialects/postgres/query-generator.js:848:32)
at Object.module.exports.QueryGenerator.pgDataTypeMapping (/Users/csimpson/code/temp-cause-server/node_modules/sequelize/lib/dialects/postgres/query-generator.js:843:19)
at Object.module.exports.QueryGenerator.changeColumnQuery (/Users/csimpson/code/temp-cause-server/node_modules/sequelize/lib/dialects/postgres/query-generator.js:250:31)
at module.exports.QueryInterface.changeColumn (/Users/csimpson/code/temp-cause-server/node_modules/sequelize/lib/query-interface.js:345:37)
at module.exports.Migration.(anonymous function) [as changeColumn] (/Users/csimpson/code/temp-cause-server/node_modules/sequelize/lib/migration.js:26:50)
at /Users/csimpson/code/temp-cause-server/database/migrations/20141216000001-alter-id-increment.js:8:41
at tryCatch1 (/Users/csimpson/code/temp-cause-server/node_modules/sequelize/node_modules/bluebird/js/main/util.js:45:21)
at Promise$_callHandler [as _callHandler] (/Users/csimpson/code/temp-cause-server/node_modules/sequelize/node_modules/bluebird/js/main/promise.js:660:13)
at Promise$_settlePromiseFromHandler [as _settlePromiseFromHandler] (/Users/csimpson/code/temp-cause-server/node_modules/sequelize/node_modules/bluebird/js/main/promise.js:675:18)
at Promise$_settlePromiseAt (/Users/csimpson/code/temp-cause-server/node_modules/sequelize/node_modules/bluebird/js/main/promise.js:845:14)

I ran into the Possibly unhandled TypeError: Cannot call method 'push' of undefined error as well. I was also trying to add an id field to an existing table, one I had created in the previous migration.
My fix had two parts:
1) Add unique: true to the id column.
2) Undo the previous migration (where I created the table that I want to add an id column to), and then run both migrations at once.
Until I did both of these, my migration attempts failed.

Related

`sequelize.sync({alter:true})` showing error when trying to add column in the existing table

I am using sequelize to create table schema with snowflake. To achieve the same I am using snowflake-sdk
Right now I am able to create new tables and add the data into an existing table, but I also want to write the code to alter the schema of any existing table.
For that, there is one option mentioned on the website sync({alter: true})
(https://sequelize.org/docs/v6/core-concepts/model-basics/#model-synchronization)
Here is my nodejs code -
// create new Table
const Test = sequelize.define(
"TEST_BG",
{
firstName: DataTypes.TEXT,
lastName: DataTypes.TEXT,
favoriteColor: DataTypes.TEXT,
age: DataTypes.INTEGER,
occupation: DataTypes.TEXT,
address: DataTypes.TEXT,
},
{
timestamps: false,
}
);
(async () => {
// Code here
console.log("Connection has been established successfully.");
await Test.sync({ alter: true }).then(() => {
console.log("alter complete");
});
})();
But I am getting this error when I am trying to do the same.
Executing (default): SHOW FULL COLUMNS FROM "TEST_BG";
DatabaseError [SequelizeDatabaseError]: SQL compilation error:
syntax error line 1 at position 5 unexpected 'FULL'.
at Query.formatError (C:\projects\snowflake\node-poc\node_modules\sequelize\lib\dialects\snowflake\query.js:207:16)
at Query.run (C:\projects\snowflake\node-poc\node_modules\sequelize\lib\dialects\snowflake\query.js:57:18)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async C:\projects\snowflake\node-poc\node_modules\sequelize\lib\sequelize.js:314:16
at async SnowflakeQueryInterface.describeTable (C:\projects\snowflake\node-poc\node_modules\sequelize\lib\dialects\abstract\query-interface.js:166:20)
at async Promise.all (index 0)
at async TEST_BG.sync (C:\projects\snowflake\node-poc\node_modules\sequelize\lib\model.js:947:26)
at async Sequelize.sync (C:\projects\snowflake\node-poc\node_modules\sequelize\lib\sequelize.js:376:9)
at async C:\projects\snowflake\node-poc\src\main.ts:47:3
Initially I created table without that address column. After that when I am trying to add address column using sequelize.sync({ alter: true }) I am getting the error.
Any idea what I am missing here?
I believe this is a bug in Sequelize. The query generator (in version 6 and latest main)
https://github.com/sequelize/sequelize/blob/fd4afa6a89c111c6d6d0c94f0b98bf421b5357b6/src/dialects/snowflake/query-generator.js#L162
https://github.com/sequelize/sequelize/blob/f6045f8f1cc48b8bb01d1ce9df0596083d3ebcf2/src/dialects/snowflake/query-generator-typescript.ts#L9
uses
SHOW FULL COLUMNS FROM
even though this does not seem to be a valid command in Snowflake.

TypeError: Cannot read properties of undefined (reading 'findAll') <nodejs>

I was trying to make an API using Node.js and Sequelize (MySQL). The API has many models and associations. I made migrations after making the models.
Now that I'm making the service file, when I make a request to the login route, I encounter that error.
I have tried many things and read a lot of guides for this issue. But I still have that.
(Typos checked!) -- (The modules imported properly)
Could you please suggest me a solution?
I appreciate you in advance!
Error
const results = await db.user.findOne({where:{phoneNumber: body.phoneNumber}})
^
TypeError: Cannot read properties of undefined (reading 'findOne')
at login (C:\Users\Ali\Desktop\Learning\Mafia-api\user\user.service.js:5:35)
at Layer.handle [as handle_request] (C:\Users\Ali\Desktop\Learning\Mafia-api\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\Ali\Desktop\Learning\Mafia-api\node_modules\express\lib\router\route.js:144:13)
at Route.dispatch (C:\Users\Ali\Desktop\Learning\Mafia-api\node_modules\express\lib\router\route.js:114:3)
at Layer.handle [as handle_request] (C:\Users\Ali\Desktop\Learning\Mafia-api\node_modules\express\lib\router\layer.js:95:5)
at C:\Users\Ali\Desktop\Learning\Mafia-api\node_modules\express\lib\router\index.js:284:15
at Function.process_params (C:\Users\Ali\Desktop\Learning\Mafia-api\node_modules\express\lib\router\index.js:346:12)
at next (C:\Users\Ali\Desktop\Learning\Mafia-api\node_modules\express\lib\router\index.js:280:10)
at Function.handle (C:\Users\Ali\Desktop\Learning\Mafia-api\node_modules\express\lib\router\index.js:175:3)
at router (C:\Users\Ali\Desktop\Learning\Mafia-api\node_modules\express\lib\router\index.js:47:12)
[nodemon] app crashed - waiting for file changes before starting...
Model: user.js
module.exports = async (sequelize, DataTypes) => {
const user = await sequelize.define('users', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true,
},
phoneNumber: {
type: DataTypes.STRING(20),
allowNull: false,
unique: true
},
displayName: {
type: DataTypes.STRING,
allowNull: false,
unique: true
}
})
user.association = model => {
user.hasMany(model.currencyWallet);
user.hasMany(model.userSetting);
}
return user
}
Service: user.service.js
const db = require('../models');
async function login(req, res) {
const body = req.body;
const results = await db.user.findOne({where:{phoneNumber: body.phoneNumber}})
res.json({
success: 0,
message: 'Results found!'
})
}
module.exports = {
login
}
Index.js
const express = require('express');
const app = express();
const userRouter = require('./user/user.router');
const PORT = 5000
const HOST = 'localhost'
const db = require('./models');
app.use(express.json());
app.use('/', userRouter);
db.sequelize.sync().then(() => {
app.listen(PORT, () => console.log(`Server running on http://${HOST}:${PORT}`));
})
config.json
"development": {
"username": "xxxx",
"password": xxxx,
"database": "nameofthegamegoeshere",
"host": "xxx.x.x.x",
"dialect": "mysql"
}
In Model: user.js you are definign the model as users
But in user.service.js you're calling the model as user
Change this line in User model
...
const user = await sequelize.define('users',
...
To this line
const user = await sequelize.define('user',... // should be user, not users
Hope it'll fix your problem.
db.user.findOne error goes here so is db.user really get to database?
i think use import seprate as **const user = require('../models').user**
and then use
user.findall()
I fortunately found the solution of my problem myself!
It took me a lot of time and effort to find the problem and debug it but it's not a very complicated problem!
In one of my models, user.js that I mentioned earlier, I was using async/await syntax to define a table.
IT'S NOT TRUE ...
After I removed the async/await from my model, user.js file, the problem gone away!
So, user.js should be like this (without any async/await expression):
-- Solution --
module.exports = (sequelize, DataTypes) => {
const user = sequelize.define('users', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true,
},
phoneNumber: {
type: DataTypes.STRING(20),
allowNull: false,
unique: true
},
displayName: {
type: DataTypes.STRING,
allowNull: false,
unique: true
}
})
user.association = model => {
user.hasMany(model.currencyWallet);
user.hasMany(model.userSetting);
}
return user
}
Explanation
This problem occurred because I had some issue to understand how Javascript Promises work.
I recommend to read more about 1- Callback functions and 2- Promises respectively in order to understand the issue and it's solution. Specially if you're also a beginner like me :)
This is one of the useful resources to check:
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Promises
When I use async/await to make a model, It returns a Promise.
const user = await sequelize.define('users', {some-code-in-here})
Then the promise state turns to <"pending">. It means that something is on process or we are waiting...
Because the state of that promise is on "pending", no result object would be expected to be in user and as the result, the value of user will be undefined.
This is the reason that the error says: "It can't read properties of undefined".
Once the promise state turns to "settled", it will return a result (when succeeds) or an error (when fails).
But in this case, the state of that promise is still on "pending" when the program use it as user.
By removing async/await, it will immediately executes the define() function and put the result in user. So there is no problem to make use of user anymore.
~ I hope this post can help to solve many people's problem and saves a lot of time :) ~

How to Create a table in Sequelize to store in Postgressql with NodeJS

Am a newbie to Postgres and Sequelize i have successfully connected to DB trying to create a table in DB that is where am struck am getting an error the tablename doesn't exist
sequelize.authenticate().then(() => {
console.log("Success!");
var News = sequelize.define('likes', {
title: {
type: Sequelize.STRING
},
content: {
type: Sequelize.STRING
}
}, {
freezeTableName: true
});
News.create({
title: 'Getting Started with PostgreSQL and Sequelize',
content: 'Hello there'
});
News.findAll({}).then((data) => {
console.log(data);
}).catch((err) => {
console.log(err);
});
}).catch((err) => {
console.log(err);
});
Where am making a mistake? It says error: relation "likes" doesn't exist. Any kind of help is appreciated
Sequelize only creates tables through sync or migrations. Your model, News has a sync method, that when called will do one of a few things
If called with no params, it will create the table if it doesn't exist
if called like this News.sync({ force: true }) it will drop the current table if it exists and make a new one.
if called like this News.sync({ alter: true }) it will add any new fields that are not in the model yet (this is a v4 feature).
These techniques can be useful when rapidly prototyping, but the best solution is to use migrations. Migrations allow you to keep track of changes to your database across development, different git branches, and production. Its by far the best solution, but does come with a small amount of upfront cost and buy-in.
If you're working on a hackathon style project, I'd just go with {alter: true}, but if you're building something you're going to be working on for a while, definitely get to know the migrations API.

Sequelize validate throws [object object] error

I'm trying out Sequelize's built in validators. Model definition:
module.exports = function(sequelize, DataTypes) {
var Device = sequelize.define('Device', {
model_name: {
type: DataTypes.STRING,
validate: {
notNull: {
args: true,
msg: 'Model name needed'
}
}
}
...
with bulkCreate
Device.bulkCreate(csvOutput, { validate: true })
.then(function() {
console.log('Records inserted into database')
})
.catch(function(err) {
console.log('Error encountered: ' + err.message)
})
To test, I tried to insert a blank field for model_name. I tried also to include a proper model name.
Both scenarios above produce an error that is simply [object Object]. I could not seem to figure out why. Hope someone can shed some light here!
Note: the error goes away if i remove validate from the Model entirely.
I found the answer, and i'm posting it here in case this could be helpful to anyone.
Changing this line console.log('Error encountered: ' + err.message) to just console.log(err) allows the error message to display properly on the console.
The string concatenation prevents the error message from showing (allowing only [object Object] to be displayed).
With the error message, the problem became obvious the validation notNull is deprecated and should be replaced by the column attribute allowNull (note this is a column attribute, not a validator)

How can I change the type of a property in Geddy

How can I change the type of an existing property in Geddy?
I believe I need to change the type as set when defining the properties in the model file:
this.defineProperties({
title: {type: 'string', required: true},
description: {type: 'text'},
status: {type: 'boolean'}
});
I also think I need to alter the table in a migration. I'm using the 'changeColumn' function as documented here http://geddyjs.org/guide#models
var StatusToBoolean = function () {
this.up = function (next) {
this.changeColumn("step", 'status', 'boolean', function (err, data) {
if (err) { throw err; }
next();
});
};
this.down = function (next) {
this.changeColumn('step', 'status', 'string', function (err, data) {
if (err) { throw err; }
next();
});
};
};
exports.StatusToBoolean = StatusToBoolean;
However, when I run this migration I get a 'SQLITE_ERROR: near "ALTER"' error:
Hindenburg:to_do Tom$ geddy jake db:migrate --trace
Running migrations for development environment...
Running status_to_boolean (up)
jake aborted.
Error: SQLITE_ERROR: near "ALTER": syntax error
Hindenburg:to_do Tom$
This makes me think I'm doing something wrong. I tried the '--trace' option (as you can see), but that didn't give any helpful information.
I also suspect that I need to actually change some of the data in the table (so that it can map to the new datatype), but the documentation is unclear on how to do that.
Any help is appreciated. Thanks.
Unfortunately SQLite doesn't support ALTER COLUMN (http://www.sqlite.org/lang_altertable.html). This is only a problem in the SQLite adapter, and it doesn't affect Postgres or MySQL. There are also workarounds, as described here: How do I rename a column in a SQLite database table? You could write a migration that performs these steps. Version 0.4.16 of Geddy's ORM (now on NPM) now includes a friendly error message when you try to do this with the SQLite adapter.

Resources