move sequelize to cirosantilli.github.io

This commit is contained in:
Ciro Santilli
2021-10-31 13:16:49 +00:00
parent 46ab416889
commit cfcee886f0
20 changed files with 1 additions and 2140 deletions

View File

@ -4,12 +4,8 @@
"description": "https://cirosantilli.com/linux-kernel-module-cheat#node-js",
"main": "alphanumeric.js",
"dependencies": {
"express": "^4.17.1",
"express": "4.17.1",
"mocha": "8.3.2",
"pg": "8.5.1",
"pg-hstore": "2.3.3",
"sequelize": "6.5.1",
"sqlite3": "5.0.2",
"ts-node": "10.0.0"
},
"devDependencies": {},

View File

@ -1,149 +0,0 @@
#!/usr/bin/env node
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
(async () => {
const Comment = sequelize.define('Comment', {
body: { type: DataTypes.STRING },
});
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
});
User.hasMany(Comment)
Comment.belongsTo(User)
console.dir(User);
await sequelize.sync({force: true});
const u0 = await User.create({name: 'u0'})
const u1 = await User.create({name: 'u1'})
await Comment.create({body: 'u0c0', UserId: u0.id});
await Comment.create({body: 'u0c1', UserId: u0.id});
await Comment.create({body: 'u1c0', UserId: u1.id});
// Direct way.
{
const u0Comments = await Comment.findAll({
where: { UserId: u0.id },
order: [['id', 'ASC']],
});
assert(u0Comments[0].body === 'u0c0');
assert(u0Comments[1].body === 'u0c1');
assert(u0Comments[0].UserId === u0.id);
assert(u0Comments[1].UserId === u0.id);
// Not added as an object by default. Would require extra query.
assert(u0Comments[0].User === undefined);
assert(u0Comments[1].User === undefined);
}
// Include data from the other side of the association in the query.
{
const u0Comments = await Comment.findAll({
where: { UserId: u0.id },
order: [['id', 'ASC']],
include: User,
// Equivalent alternatives in this case.
//include: [User],
//include: [{ model: User }],
});
assert(u0Comments[0].body === 'u0c0');
assert(u0Comments[1].body === 'u0c1');
assert(u0Comments[0].UserId === u0.id);
assert(u0Comments[1].UserId === u0.id);
// These did get added now.
assert(u0Comments[0].User.name === 'u0');
assert(u0Comments[1].User.name === 'u0');
}
// Nicer higher level way.
{
const u0Comments = await u0.getComments({
include: [{ model: User }],
order: [['id', 'ASC']],
});
assert(u0Comments[0].body === 'u0c0');
assert(u0Comments[1].body === 'u0c1');
assert(u0Comments[0].User.name === 'u0');
assert(u0Comments[1].User.name === 'u0');
}
// If you REALLY wanted to not repeat the UserId magic constant everywhere, you could use User.associations.Comments.foreignKey
// But it is such a mouthful, that nobody likely ever uses it?
// https://stackoverflow.com/questions/34059081/how-do-i-reference-an-association-when-creating-a-row-in-sequelize-without-assum
{
await Comment.create({body: 'u0c2', [User.associations.Comments.foreignKey]: u0.id});
// Syntax that we really would like instead.
//await Comment.create({body: 'u0c2', User: u0});
assert((await Comment.findAll({
where: { [User.associations.Comments.foreignKey]: u0.id },
})).length === 3);
}
// Removal auto-cascades.
{
const u0id = u0.id
await u0.destroy()
assert((await Comment.findAll({
where: { UserId: u0id },
})).length === 0);
assert((await Comment.findAll({
where: { UserId: u1.id },
})).length === 1);
}
// as aliases.
// Allows us to use a nicer name for a relation rather than the exact class name.
// E.g. here we name the User of a Comment as a "author".
// And mandatory do diambiguate multiple associations with a single type.
{
const CommentAs = sequelize.define('CommentAs', {
body: { type: DataTypes.STRING },
}, {});
const UserAs = sequelize.define('UserAs', {
name: { type: DataTypes.STRING },
}, {});
UserAs.hasMany(CommentAs)
CommentAs.belongsTo(UserAs, {as: 'author'})
await sequelize.sync({force: true});
const u0 = await UserAs.create({name: 'u0'})
const u1 = await UserAs.create({name: 'u1'})
await CommentAs.create({body: 'u0c0', authorId: u0.id});
await CommentAs.create({body: 'u0c1', authorId: u0.id});
await CommentAs.create({body: 'u1c0', authorId: u1.id});
{
const u0Comments = await CommentAs.findAll({
where: { authorId: u0.id },
order: [['id', 'ASC']],
// Instead of include: UserAs
include: 'author',
});
assert(u0Comments[0].body === 'u0c0');
assert(u0Comments[1].body === 'u0c1');
assert(u0Comments[0].authorId === u0.id);
assert(u0Comments[1].authorId === u0.id);
assert(u0Comments[0].author.name === 'u0');
assert(u0Comments[1].author.name === 'u0');
}
// Trying with the higher level getter.
{
// TODO
// u0.getComments is not a function
//const u0Comments = await u0.getComments({
// include: 'author',
//});
//assert(u0Comments[0].body === 'u0c0');
//assert(u0Comments[1].body === 'u0c1');
//assert(u0Comments[0].author.name === 'u0');
//assert(u0Comments[1].author.name === 'u0');
}
}
await sequelize.close();
})();

View File

@ -1,162 +0,0 @@
#!/usr/bin/env node
// https://stackoverflow.com/questions/22958683/how-to-implement-many-to-many-association-in-sequelize/67973948#67973948
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
(async () => {
// Create the tables.
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
}, {});
const Post = sequelize.define('Post', {
body: { type: DataTypes.STRING },
}, {});
// UserLikesPost is the name of the relation table.
// Sequelize creates it automatically for us.
// On SQLite that table looks like this:
// CREATE TABLE `UserLikesPost` (
// `createdAt` DATETIME NOT NULL,
// `updatedAt` DATETIME NOT NULL,
// `UserId` INTEGER NOT NULL REFERENCES `Users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
// `PostId` INTEGER NOT NULL REFERENCES `Posts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
// PRIMARY KEY (`UserId`, `PostId`)
// );
User.belongsToMany(Post, {through: 'UserLikesPost'});
Post.belongsToMany(User, {through: 'UserLikesPost'});
await sequelize.sync({force: true});
// Create some users and likes.
const user0 = await User.create({name: 'user0'})
const user1 = await User.create({name: 'user1'})
const user2 = await User.create({name: 'user2'})
const post0 = await Post.create({body: 'post0'});
const post1 = await Post.create({body: 'post1'});
const post2 = await Post.create({body: 'post2'});
// Autogenerated add* methods
// Make user0 like post0
await user0.addPost(post0)
// Also works.
//await user0.addPost(post0.id)
// Make user0 and user2 like post1
await post1.addUsers([user0, user2])
// Autogenerated get* methods
// Get likes by a user.
const user0Likes = await user0.getPosts({order: [['body', 'ASC']]})
assert(user0Likes[0].body === 'post0');
assert(user0Likes[1].body === 'post1');
assert(user0Likes.length === 2);
assert.strictEqual(await user0.countPosts(), 2)
const user1Likes = await user1.getPosts({order: [['body', 'ASC']]})
assert(user1Likes.length === 0);
const user2Likes = await user2.getPosts({order: [['body', 'ASC']]})
assert(user2Likes[0].body === 'post1');
assert(user2Likes.length === 1);
// Same as get but with the user ID instead of the model object.
{
const user0Likes = await Post.findAll({
include: [{
model: User,
where: {id: user0.id},
}],
order: [['body', 'ASC']],
})
assert(user0Likes[0].body === 'post0');
assert(user0Likes[1].body === 'post1');
assert(user0Likes.length === 2);
}
// Yet another way that can be more useful in nested includes.
{
const user0Likes = (await User.findOne({
where: {id: user0.id},
include: [{
model: Post,
}],
order: [[Post, 'body', 'ASC']],
})).Posts
assert(user0Likes[0].body === 'post0');
assert(user0Likes[1].body === 'post1');
assert(user0Likes.length === 2);
}
// Get users that liked a given likes.
const post0Likers = await post0.getUsers({order: [['name', 'ASC']]})
assert(post0Likers[0].name === 'user0');
assert(post0Likers.length === 1);
const post1Likers = await post1.getUsers({order: [['name', 'ASC']]})
assert(post1Likers[0].name === 'user0');
assert(post1Likers[1].name === 'user2');
assert(post1Likers.length === 2);
const post2Likers = await post2.getUsers({order: [['name', 'ASC']]})
assert(post2Likers.length === 0);
// Autogenerated has* methods
// Check if user likes post.
assert( await user0.hasPost(post0))
assert( await user0.hasPost(post0.id)) // same
assert( await user0.hasPost(post1))
assert(!await user0.hasPost(post2))
// Check if post is liked by user.
assert( await post0.hasUser(user0))
assert(!await post0.hasUser(user1))
assert(!await post0.hasUser(user2))
// AND of multiple has checks at once.
assert( await user0.hasPosts([post0, post1]))
assert(!await user0.hasPosts([post0, post1, post2]))
// Autogenerated count* methods
assert(await user0.countPosts() === 2)
assert(await post0.countUsers() === 1)
// Autogenerated remove* methods
// user0 doesn't like post0 anymore.
await user0.removePost(post0)
// user0 and user 2 don't like post1 anymore.
await post1.removeUsers([user0, user2])
// Check that no-one likes anything anymore.
assert(await user0.countPosts() === 0)
assert(await post0.countUsers() === 0)
// Autogenerated create* method
// Create a new post and automatically make user0 like it.
const post3 = await user0.createPost({'body': 'post3'})
assert(await user0.hasPost(post3))
assert(await post3.hasUser(user0))
// Autogenerated set* method
// Make user0 like exactly these posts. Unlike anything else.
await user0.setPosts([post1, post2])
assert(!await user0.hasPost(post0))
assert( await user0.hasPost(post1))
assert( await user0.hasPost(post2))
assert(!await user0.hasPost(post3))
await sequelize.close();
})();

View File

@ -1,116 +0,0 @@
#!/usr/bin/env node
// https://stackoverflow.com/questions/22958683/how-to-implement-many-to-many-association-in-sequelize/67973948#67973948
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
(async () => {
// Create the tables.
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
});
const Post = sequelize.define('Post', {
body: { type: DataTypes.STRING },
});
const UserLikesPost = sequelize.define('UserLikesPost', {
UserId: {
type: DataTypes.INTEGER,
references: {
model: User,
key: 'id'
}
},
PostId: {
type: DataTypes.INTEGER,
references: {
model: Post,
key: 'id'
}
},
score: {
type: DataTypes.INTEGER,
},
});
// UserLikesPost is the name of the relation table.
// Sequelize creates it automatically for us.
// On SQLite that table looks like this:
// CREATE TABLE `UserLikesPost` (
// `createdAt` DATETIME NOT NULL,
// `updatedAt` DATETIME NOT NULL,
// `UserId` INTEGER NOT NULL REFERENCES `Users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
// `PostId` INTEGER NOT NULL REFERENCES `Posts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
// `Score` INTEGER,
// PRIMARY KEY (`UserId`, `PostId`)
// );
User.belongsToMany(Post, {through: UserLikesPost});
Post.belongsToMany(User, {through: UserLikesPost});
await sequelize.sync({force: true});
// Create some users and likes.
const user0 = await User.create({name: 'user0'})
const user1 = await User.create({name: 'user1'})
const user2 = await User.create({name: 'user2'})
const post0 = await Post.create({body: 'post0'});
const post1 = await Post.create({body: 'post1'});
const post2 = await Post.create({body: 'post2'});
// Autogenerated add* methods
// Make some useres like some posts.
await user0.addPost(post0, {through: {score: 1}})
await user1.addPost(post1, {through: {score: 2}})
await user1.addPost(post2, {through: {score: 3}})
// Find what user0 likes.
const user0Likes = await user0.getPosts({order: [['body', 'ASC']]})
assert(user0Likes[0].body === 'post0');
assert(user0Likes[0].UserLikesPost.score === 1);
assert(user0Likes.length === 1);
// Find what user1 likes.
const user1Likes = await user1.getPosts({order: [['body', 'ASC']]})
assert(user1Likes[0].body === 'post1');
assert(user1Likes[0].UserLikesPost.score === 2);
assert(user1Likes[1].body === 'post2');
assert(user1Likes[1].UserLikesPost.score === 3);
assert(user1Likes.length === 2);
// Where on the custom through table column.
// https://stackoverflow.com/questions/38857156/how-to-query-many-to-many-relationship-sequelize
{
const user1LikesWithScore3 = await Post.findAll({
include: [{
model: User,
where: {id: user1.id},
through: {where: {score: 3}},
}],
})
assert(user1LikesWithScore3[0].body === 'post2');
assert(user1LikesWithScore3[0].UserLikesPost.score === 3);
assert(user1LikesWithScore3.length === 1);
}
// TODO: this doesn't work. Possible at all in a single addUsers call?
// Make user0 and user2 like post1
// This method automatically generated.
//await post1.addUsers(
// [user0, user2],
// {through: [
// {score: 2},
// {score: 3},
// ]}
//)
await sequelize.close();
})();

View File

@ -1,157 +0,0 @@
#!/usr/bin/env node
// Two associations between two specific models. Requires us to use alias with `as:`
// to disambiguate them.
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
(async () => {
// Create the tables.
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
}, {});
const Post = sequelize.define('Post', {
body: { type: DataTypes.STRING },
}, {});
User.belongsToMany(Post, {through: 'UserLikesPost', as: 'likedPosts'});
Post.belongsToMany(User, {through: 'UserLikesPost', as: 'likers'});
User.belongsToMany(Post, {through: 'UserFollowsPost', as: 'followedPosts'});
Post.belongsToMany(User, {through: 'UserFollowsPost', as: 'followers'});
await sequelize.sync({force: true});
// Create some users and likes.
const user0 = await User.create({name: 'user0'})
const user1 = await User.create({name: 'user1'})
const user2 = await User.create({name: 'user2'})
const post0 = await Post.create({body: 'post0'});
const post1 = await Post.create({body: 'post1'});
const post2 = await Post.create({body: 'post2'});
// Autogenerated add* methods
// Setup likes and follows.
await user0.addLikedPost(post0)
await post1.addLikers([user0, user2])
await user1.addFollowedPosts([post0, post1])
await post1.addFollower(user2)
// Autogenerated get* methods
// Get likes by a user.
const user0Likes = await user0.getLikedPosts({order: [['body', 'ASC']]})
assert(user0Likes[0].body === 'post0');
assert(user0Likes[1].body === 'post1');
assert(user0Likes.length === 2);
const user1Likes = await user1.getLikedPosts({order: [['body', 'ASC']]})
assert(user1Likes.length === 0);
const user2Likes = await user2.getLikedPosts({order: [['body', 'ASC']]})
assert(user2Likes[0].body === 'post1');
assert(user2Likes.length === 1);
// Get users that liked a given post.
const post0Likers = await post0.getLikers({order: [['name', 'ASC']]})
assert(post0Likers[0].name === 'user0');
assert(post0Likers.length === 1);
const post1Likers = await post1.getLikers({order: [['name', 'ASC']]})
assert(post1Likers[0].name === 'user0');
assert(post1Likers[1].name === 'user2');
assert(post1Likers.length === 2);
const post2Likers = await post2.getLikers({order: [['name', 'ASC']]})
assert(post2Likers.length === 0);
// Get follows by a user.
const user0Follows = await user0.getFollowedPosts({order: [['body', 'ASC']]})
assert(user0Follows.length === 0);
const user1Follows = await user1.getFollowedPosts({order: [['body', 'ASC']]})
assert(user1Follows[0].body === 'post0');
assert(user1Follows[1].body === 'post1');
assert(user1Follows.length === 2);
const user2Follows = await user2.getFollowedPosts({order: [['body', 'ASC']]})
assert(user2Follows[0].body === 'post1');
assert(user2Follows.length === 1);
// Get users that followed a given post.
const post0Followers = await post0.getFollowers({order: [['name', 'ASC']]})
assert(post0Followers[0].name === 'user1');
assert(post0Followers.length === 1);
const post1Followers = await post1.getFollowers({order: [['name', 'ASC']]})
assert(post1Followers[0].name === 'user1');
assert(post1Followers[1].name === 'user2');
assert(post1Followers.length === 2);
const post2Followers = await post2.getFollowers({order: [['name', 'ASC']]})
assert(post2Followers.length === 0);
// Same as getLikedPosts but with the user ID instead of the model object.
// as is mandatory to disambiguate which one we want to get.
{
const user0Likes = await Post.findAll({
include: [{
model: User,
as: 'likers',
where: {id: user0.id},
}],
order: [['body', 'ASC']],
})
assert(user0Likes[0].body === 'post0');
assert(user0Likes[1].body === 'post1');
assert(user0Likes.length === 2);
}
// Alternatively, we can also pass the association object instead of model + as.
// This is actually nicer!
{
const user0Likes = await Post.findAll({
include: [{
association: Post.associations.likers,
where: {id: user0.id},
}],
order: [['body', 'ASC']],
})
assert(user0Likes[0].body === 'post0');
assert(user0Likes[1].body === 'post1');
assert(user0Likes.length === 2);
}
// Yet another way that can be more useful in nested includes.
{
const user0Likes = (await User.findOne({
where: {id: user0.id},
include: [{
model: Post,
as: 'likedPosts',
}],
order: [[{model: Post, as: 'likedPosts'}, 'body', 'ASC']],
})).likedPosts
assert(user0Likes[0].body === 'post0');
assert(user0Likes[1].body === 'post1');
assert(user0Likes.length === 2);
}
await sequelize.close();
})();

View File

@ -1,124 +0,0 @@
#!/usr/bin/env node
// https://stackoverflow.com/questions/22958683/how-to-implement-many-to-many-association-in-sequelize/67973948#67973948
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
define: {
timestamps: false
},
});
(async () => {
// Create the tables.
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
}, {});
User.belongsToMany(User, {through: 'UserFollowUser', as: 'Follows'});
await sequelize.sync({force: true});
// Create some users.
const user0 = await User.create({name: 'user0'})
const user1 = await User.create({name: 'user1'})
const user2 = await User.create({name: 'user2'})
const user3 = await User.create({name: 'user3'})
// Make user0 follow user1 and user2
await user0.addFollows([user1, user2])
// Make user2 and user3 follow user0
await user2.addFollow(user0)
await user3.addFollow(user0)
// Check that the follows worked.
const user0Follows = await user0.getFollows({order: [['name', 'ASC']]})
assert(user0Follows[0].name === 'user1');
assert(user0Follows[1].name === 'user2');
assert(user0Follows.length === 2);
const user1Follows = await user1.getFollows({order: [['name', 'ASC']]})
assert(user1Follows.length === 0);
const user2Follows = await user2.getFollows({order: [['name', 'ASC']]})
assert(user2Follows[0].name === 'user0');
assert(user2Follows.length === 1);
const user3Follows = await user3.getFollows({order: [['name', 'ASC']]})
assert(user3Follows[0].name === 'user0');
assert(user3Follows.length === 1);
// Same but with ID instead of object.
// Also get rid of all useless fields from the trough table.
{
const user0Follows = (await User.findOne({
where: {id: user0.id},
attributes: [],
include: [{
model: User,
as: 'Follows',
through: {attributes: []},
}],
})).Follows
assert(user0Follows[0].name === 'user1');
assert(user0Follows[1].name === 'user2');
assert(user0Follows.length === 2);
}
//// Yet another method with the many-to-many reversed.
//// TODO close to working, but on is being ignored...
//{
// const user0Follows = await User.findAll({
// include: [{
// model: User,
// as: 'Follows',
// on: {
// '$User.UserFollowUser.FollowIdasdf$': { [Sequelize.Op.col]: 'User.user_id' },
// '$User.UserFollowUser.UserId$': user0.id,
// },
// attributes: [],
// through: {attributes: []},
// }],
// order: [['name', 'ASC']],
// })
// // TODO
// //assert(user0Follows[0].name === 'user1');
// //assert(user0Follows[1].name === 'user2');
// //assert(user0Follows.length === 2);
//}
// Find users that follow user0
{
const followsUser0 = await User.findAll({
include: [{
model: User,
as: 'Follows',
where: {id: user0.id},
attributes: [],
through: {attributes: []}
}],
order: [['name', 'ASC']],
})
assert(followsUser0[0].name === 'user2');
assert(followsUser0[1].name === 'user3');
assert(followsUser0.length === 2);
}
// has methods
assert(!await user0.hasFollow(user0))
assert(!await user0.hasFollow(user0.id))
assert( await user0.hasFollow(user1))
assert( await user0.hasFollow(user2))
assert(!await user0.hasFollow(user3))
// Count method
assert(await user0.countFollows() === 2)
await sequelize.close();
})();

View File

@ -1,114 +0,0 @@
#!/usr/bin/env node
// Like association_many_to_many_same_model but with a super many to many,
// i.e. explicit through table relations).
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes, Op } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
define: {
timestamps: false
},
});
(async () => {
// Create the tables.
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
});
const UserFollowUser = sequelize.define('UserFollowUser', {
UserId: {
type: DataTypes.INTEGER,
references: {
model: User,
key: 'id'
}
},
FollowId: {
type: DataTypes.INTEGER,
references: {
model: User,
key: 'id'
}
},
}
);
// Super many to many. Only works with explicit table for some reason.
User.belongsToMany(User, {through: UserFollowUser, as: 'Follows'});
UserFollowUser.belongsTo(User)
User.hasMany(UserFollowUser)
await sequelize.sync({force: true});
// Create some users.
const user0 = await User.create({name: 'user0'})
const user1 = await User.create({name: 'user1'})
const user2 = await User.create({name: 'user2'})
const user3 = await User.create({name: 'user3'})
await user0.addFollows([user1, user2])
await user2.addFollow(user0)
await user3.addFollow(user0)
// Find all users that a user follows.
const user0Follows = await user0.getFollows({order: [['name', 'ASC']]})
assert(user0Follows[0].name === 'user1');
assert(user0Follows[1].name === 'user2');
assert(user0Follows.length === 2);
const user1Follows = await user1.getFollows({order: [['name', 'ASC']]})
assert(user1Follows.length === 0);
const user2Follows = await user2.getFollows({order: [['name', 'ASC']]})
assert(user2Follows[0].name === 'user0');
assert(user2Follows.length === 1);
const user3Follows = await user3.getFollows({order: [['name', 'ASC']]})
assert(user3Follows[0].name === 'user0');
assert(user3Follows.length === 1);
// Same but with explicit id.
{
const user0Follows = (await User.findOne({
where: {id: user0.id},
attributes: [],
include: [{
model: User,
as: 'Follows',
through: {attributes: []},
}],
})).Follows
assert(user0Follows[0].name === 'user1');
assert(user0Follows[1].name === 'user2');
assert(user0Follows.length === 2);
}
// Another method with the many-to-many reversed.
// Using the super many to many is the only way I know of doing this so far.
// which is a pain.
{
const user0Follows = await User.findAll({
include: [{
model: UserFollowUser,
attributes: [],
on: {
FollowId: { [Op.col]: 'User.id' },
},
where: {UserId: user0.id}
}],
order: [['name', 'ASC']],
})
assert(user0Follows[0].name === 'user1');
assert(user0Follows[1].name === 'user2');
assert(user0Follows.length === 2);
}
await sequelize.close();
})();

View File

@ -1,70 +0,0 @@
#!/usr/bin/env node
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
(async () => {
// Create the tables.
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
}, {});
const Post = sequelize.define('Post', {
body: { type: DataTypes.STRING },
}, {});
User.hasMany(Post);
Post.belongsTo(User);
await sequelize.sync({force: true});
// Create data.
const users = await User.bulkCreate([
{name: 'user0'},
{name: 'user1'},
{name: 'user2'},
{name: 'user3'},
])
const posts = await Post.bulkCreate([
{body: 'body00', UserId: users[0].id},
{body: 'body01', UserId: users[0].id},
{body: 'body10', UserId: users[1].id},
{body: 'body11', UserId: users[1].id},
{body: 'body20', UserId: users[2].id},
{body: 'body21', UserId: users[2].id},
{body: 'body30', UserId: users[3].id},
{body: 'body31', UserId: users[3].id},
])
// Get user from post and vice versa.
const user0Posts = await users[0].getPosts({order: [['body', 'ASC']]})
assert(user0Posts[0].body === 'body00')
assert(user0Posts[1].body === 'body01')
assert(user0Posts.length === 2)
const user1Posts = await users[1].getPosts({order: [['body', 'ASC']]})
assert(user1Posts[0].body === 'body10')
assert(user1Posts[1].body === 'body11')
assert(user1Posts.length === 2)
const post00User = await posts[0].getUser()
assert(post00User.name === 'user0')
const post01User = await posts[1].getUser()
assert(post01User.name === 'user0')
const post10User = await posts[2].getUser()
assert(post10User.name === 'user1')
const post11User = await posts[3].getUser()
assert(post11User.name === 'user1')
await sequelize.close();
})();

View File

@ -1,123 +0,0 @@
#!/usr/bin/env node
// Two associations between two models: posts
// now have the author, and a mandatory reviewer.
// Requires us to use as do disambiguate them.
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
define: {
timestamps: false
},
});
(async () => {
// Create the tables.
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
}, {});
const Post = sequelize.define('Post', {
body: { type: DataTypes.STRING },
}, {});
// TODO possible without specifying foreignKey? Feels like duplication.
// But without it, hasMany creates a column called UserId, in addition
// to the desired authorId, and then bad things happen.
User.hasMany(Post, {as: 'authoredPosts', foreignKey: 'authorId'});
Post.belongsTo(User, {as: 'author', foreignKey: 'authorId'});
User.hasMany(Post, {as: 'reviewedPosts', foreignKey: 'reviewerId'});
Post.belongsTo(User, {as: 'reviewer', foreignKey: 'reviewerId'});
await sequelize.sync({force: true});
// Create data.
const users = await User.bulkCreate([
{name: 'user0'},
{name: 'user1'},
{name: 'user2'},
{name: 'user3'},
])
const posts = await Post.bulkCreate([
{body: 'body00', authorId: users[0].id, reviewerId: users[0].id},
{body: 'body01', authorId: users[0].id, reviewerId: users[1].id},
{body: 'body10', authorId: users[1].id, reviewerId: users[2].id},
{body: 'body11', authorId: users[1].id, reviewerId: users[3].id},
{body: 'body20', authorId: users[2].id, reviewerId: users[0].id},
{body: 'body21', authorId: users[2].id, reviewerId: users[1].id},
{body: 'body30', authorId: users[3].id, reviewerId: users[2].id},
{body: 'body31', authorId: users[3].id, reviewerId: users[3].id},
])
// Get user from post and vice versa.
const user0AuthoredPosts = await users[0].getAuthoredPosts()
assert(user0AuthoredPosts[0].body === 'body00')
assert(user0AuthoredPosts[1].body === 'body01')
assert(user0AuthoredPosts.length === 2)
const user1AuthoredPosts = await users[1].getAuthoredPosts()
assert(user1AuthoredPosts[0].body === 'body10')
assert(user1AuthoredPosts[1].body === 'body11')
assert(user1AuthoredPosts.length === 2)
const user0ReviewedPosts = await users[0].getReviewedPosts()
assert(user0ReviewedPosts[0].body === 'body00')
assert(user0ReviewedPosts[1].body === 'body20')
assert(user0ReviewedPosts.length === 2)
const user1ReviewedPosts = await users[1].getReviewedPosts()
assert(user1ReviewedPosts[0].body === 'body01')
assert(user1ReviewedPosts[1].body === 'body21')
assert(user1ReviewedPosts.length === 2)
assert((await posts[0].getAuthor()).name === 'user0')
assert((await posts[1].getAuthor()).name === 'user0')
assert((await posts[2].getAuthor()).name === 'user1')
assert((await posts[3].getAuthor()).name === 'user1')
assert((await posts[0].getReviewer()).name === 'user0')
assert((await posts[1].getReviewer()).name === 'user1')
assert((await posts[2].getReviewer()).name === 'user2')
assert((await posts[3].getReviewer()).name === 'user3')
// Same as getAuthoredPosts but with the user ID instead of the model object.
{
const user0AuthoredPosts = await Post.findAll({
include: [{
model: User,
// We need the `as` here to disambiguate.
as: 'author',
where: {id: users[0].id},
}],
order: [['body', 'ASC']],
})
assert(user0AuthoredPosts[0].body === 'body00');
assert(user0AuthoredPosts[1].body === 'body01');
assert(user0AuthoredPosts.length === 2);
}
// Yet another way that can be more useful in nested includes.
{
const user0AuthoredPosts = (await User.findOne({
where: {id: users[0].id},
include: [{
model: Post,
as: 'authoredPosts',
}],
order: [[{model: Post, as: 'authoredPosts'}, 'body', 'ASC']],
})).authoredPosts
assert(user0AuthoredPosts[0].body === 'body00');
assert(user0AuthoredPosts[1].body === 'body01');
assert(user0AuthoredPosts.length === 2);
}
await sequelize.close();
})();

View File

@ -1,294 +0,0 @@
#!/usr/bin/env node
// Find all posts by users that a given user follows.
// https://stackoverflow.com/questions/42632943/sequelize-multiple-where-clause
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
define: {
timestamps: false
},
});
(async () => {
// Create the tables.
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
});
const Post = sequelize.define('Post', {
body: { type: DataTypes.STRING },
});
User.belongsToMany(User, {through: 'UserFollowUser', as: 'Follows'});
User.hasMany(Post);
Post.belongsTo(User);
await sequelize.sync({force: true});
// Create data.
const users = await User.bulkCreate([
{name: 'user0'},
{name: 'user1'},
{name: 'user2'},
{name: 'user3'},
])
const posts = await Post.bulkCreate([
{body: 'body00', UserId: users[0].id},
{body: 'body01', UserId: users[0].id},
{body: 'body10', UserId: users[1].id},
{body: 'body11', UserId: users[1].id},
{body: 'body20', UserId: users[2].id},
{body: 'body21', UserId: users[2].id},
{body: 'body30', UserId: users[3].id},
{body: 'body31', UserId: users[3].id},
])
await users[0].addFollows([users[1], users[2]])
// Get all posts by authors that user0 follows.
// The posts are placed inside their respetive authors under .Posts
// so we loop to gather all of them.
{
const user0Follows = (await User.findByPk(users[0].id, {
include: [
{
model: User,
as: 'Follows',
include: [
{
model: Post,
}
],
},
],
})).Follows
const postsFound = []
for (const followedUser of user0Follows) {
postsFound.push(...followedUser.Posts)
}
postsFound.sort((x, y) => { return x.body < y.body ? -1 : x.body > y.body ? 1 : 0 })
assert(postsFound[0].body === 'body10')
assert(postsFound[1].body === 'body11')
assert(postsFound[2].body === 'body20')
assert(postsFound[3].body === 'body21')
assert(postsFound.length === 4)
}
// Similar to the above, but now with ordering, offset and limit.
// The posts are placed inside their respetive authors under .Posts
// The only difference is that posts that we didn't select got removed.
{
const user0Follows = (await User.findByPk(users[0].id, {
offset: 1,
limit: 2,
// TODO why is this needed? It does try to make a subquery otherwise, and then it doesn't work.
// https://selleo.com/til/posts/ddesmudzmi-offset-pagination-with-subquery-in-sequelize-
subQuery: false,
include: [
{
model: User,
as: 'Follows',
include: [
{
model: Post,
}
],
},
],
})).Follows
assert(user0Follows[0].name === 'user1')
assert(user0Follows[1].name === 'user2')
assert(user0Follows.length === 2)
const postsFound = []
for (const followedUser of user0Follows) {
postsFound.push(...followedUser.Posts)
}
postsFound.sort((x, y) => { return x.body < y.body ? -1 : x.body > y.body ? 1 : 0 })
assert(postsFound[0].body === 'body11')
assert(postsFound[1].body === 'body20')
assert(postsFound.length === 2)
// Same as above, but now with DESC ordering.
{
const user0Follows = (await User.findByPk(users[0].id, {
order: [[
{model: User, as: 'Follows'},
Post,
'body',
'DESC'
]],
offset: 1,
limit: 2,
subQuery: false,
include: [
{
model: User,
as: 'Follows',
include: [
{
model: Post,
}
],
},
],
})).Follows
// Note how user ordering is also reversed from an ASC.
// it likely takes the use that has the first post.
assert(user0Follows[0].name === 'user2')
assert(user0Follows[1].name === 'user1')
assert(user0Follows.length === 2)
const postsFound = []
for (const followedUser of user0Follows) {
postsFound.push(...followedUser.Posts)
}
// In this very specific data case, this would not be needed.
// because user2 has the second post body and user1 has the first
// alphabetically.
postsFound.sort((x, y) => { return x.body < y.body ? 1 : x.body > y.body ? -1 : 0 })
// Note that what happens is that some of the
assert(postsFound[0].body === 'body20')
assert(postsFound[1].body === 'body11')
assert(postsFound.length === 2)
}
// Here user2 would have no post hits due to the limit,
// so it is entirely pruned from the user list as desired.
// Otherwise we would fetch a lot of unwanted user data
// in a large database.
const user0FollowsLimit2 = (await User.findByPk(users[0].id, {
limit: 2,
subQuery: false,
include: [
{
model: User,
as: 'Follows',
include: [ { model: Post } ],
},
],
})).Follows
assert(user0FollowsLimit2[0].name === 'user1')
assert(user0FollowsLimit2.length === 1)
// Get just the count of the posts authored by useres followed by user0.
// attributes: [] excludes all other data from the SELECT of the querries
// to optimize things a bit.
// https://stackoverflow.com/questions/37817808/counting-associated-entries-with-sequelize
{
const user0Follows = await User.findByPk(users[0].id, {
attributes: [
[Sequelize.fn('COUNT', Sequelize.col('Follows.Posts.id')), 'count']
],
include: [
{
model: User,
as: 'Follows',
attributes: [],
through: {attributes: []},
include: [{
model: Post,
attributes: [],
}],
},
],
})
assert.strictEqual(user0Follows.dataValues.count, 4);
}
// Case in which our post-sorting is needed.
// TODO: possible to get sequelize to do this for us by returning
// a flat array directly?
// It's not big deal since the LIMITed result should be small,
// but feels wasteful.
// https://stackoverflow.com/questions/41502699/return-flat-object-from-sequelize-with-association
// https://github.com/sequelize/sequelize/issues/4419
{
await Post.truncate({restartIdentity: true})
const posts = await Post.bulkCreate([
{body: 'body0', UserId: users[0].id},
{body: 'body1', UserId: users[1].id},
{body: 'body2', UserId: users[2].id},
{body: 'body3', UserId: users[3].id},
{body: 'body4', UserId: users[0].id},
{body: 'body5', UserId: users[1].id},
{body: 'body6', UserId: users[2].id},
{body: 'body7', UserId: users[3].id},
])
const user0Follows = (await User.findByPk(users[0].id, {
order: [[
{model: User, as: 'Follows'},
Post,
'body',
'DESC'
]],
subQuery: false,
include: [
{
model: User,
as: 'Follows',
include: [
{
model: Post,
}
],
},
],
})).Follows
assert(user0Follows[0].name === 'user2')
assert(user0Follows[1].name === 'user1')
assert(user0Follows.length === 2)
const postsFound = []
for (const followedUser of user0Follows) {
postsFound.push(...followedUser.Posts)
}
// We need this here, otherwise we would get all user2 posts first:
// body6, body2, body5, body1
postsFound.sort((x, y) => { return x.body < y.body ? 1 : x.body > y.body ? -1 : 0 })
assert(postsFound[0].body === 'body6')
assert(postsFound[1].body === 'body5')
assert(postsFound[2].body === 'body2')
assert(postsFound[3].body === 'body1')
assert(postsFound.length === 4)
}
// This almost achieves the flat array return. We just have to understand the undocumented custom on:
// to specify from which side of the UserFollowsUser we are coming. The on:
// is ignored without super many to many unfortunately, the below just returns all posts.
// We only managed to achieve this with super many to many so far.
{
const postsFound = await Post.findAll({
order: [[
'body',
'DESC'
]],
subQuery: false,
include: [
{
model: User,
//on: {idasdf: '$Post.User.FollowId$'},
include: [
{
model: User,
as: 'Follows',
where: {id: users[0].id},
}
],
},
],
})
//console.error(postsFound.length);
//assert.strictEqual(postsFound[0].body, 'body6')
//assert.strictEqual(postsFound[1].body, 'body5')
//assert.strictEqual(postsFound[2].body, 'body2')
//assert.strictEqual(postsFound[3].body, 'body1')
assert.strictEqual(postsFound.length, 4)
}
}
await sequelize.close();
})();

View File

@ -1,111 +0,0 @@
#!/usr/bin/env node
// Like association_nested_include.js but with a super many to many.
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes, Op } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
define: {
timestamps: false
},
});
(async () => {
// Create the tables.
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
});
const Post = sequelize.define('Post', {
body: { type: DataTypes.STRING },
});
const UserFollowUser = sequelize.define('UserFollowUser', {
UserId: {
type: DataTypes.INTEGER,
references: {
model: User,
key: 'id'
}
},
FollowId: {
type: DataTypes.INTEGER,
references: {
model: User,
key: 'id'
}
},
}
);
// Super many to many.
User.belongsToMany(User, {through: UserFollowUser, as: 'Follows'});
UserFollowUser.belongsTo(User)
User.hasMany(UserFollowUser)
User.hasMany(Post);
Post.belongsTo(User);
await sequelize.sync({force: true});
// Create data.
const users = await User.bulkCreate([
{name: 'user0'},
{name: 'user1'},
{name: 'user2'},
{name: 'user3'},
])
const posts = await Post.bulkCreate([
{body: 'body0', UserId: users[0].id},
{body: 'body1', UserId: users[1].id},
{body: 'body2', UserId: users[2].id},
{body: 'body3', UserId: users[3].id},
{body: 'body4', UserId: users[0].id},
{body: 'body5', UserId: users[1].id},
{body: 'body6', UserId: users[2].id},
{body: 'body7', UserId: users[3].id},
])
await users[0].addFollows([users[1], users[2]])
// Get all the posts by authors that user0 follows.
// without any post process sorting. We only managed to to this
// with a super many to many, because that allows us to specify
// a reversed order in the through table with `on`, since we need to
// match with `FollowId` and not `UserId`.
{
const postsFound = await Post.findAll({
order: [[
'body',
'DESC'
]],
include: [
{
model: User,
attributes: [],
required: true,
include: [
{
model: UserFollowUser,
on: {
FollowId: {[Op.col]: 'User.id' },
},
attributes: [],
where: {UserId: users[0].id},
}
],
},
],
})
assert.strictEqual(postsFound[0].body, 'body6')
assert.strictEqual(postsFound[1].body, 'body5')
assert.strictEqual(postsFound[2].body, 'body2')
assert.strictEqual(postsFound[3].body, 'body1')
assert.strictEqual(postsFound.length, 4)
}
await sequelize.close();
})();

View File

@ -1,61 +0,0 @@
#!/usr/bin/env node
// https://github.com/sequelize/sequelize/issues/3534
// https://github.com/sequelize/sequelize/issues/8586
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
(async () => {
const IntegerNames = sequelize.define('IntegerNames',
{
value: {
type: DataTypes.INTEGER,
allowNull: false,
unique: true,
},
name: {
type: DataTypes.STRING,
},
name2: {
type: DataTypes.STRING,
},
},
{
hooks: {
beforeValidate: (integerName, options) => {
integerName.name2 = integerName.name + 'asdf'
// This fixes the failure.
//options.fields.push('name2');
}
,}
},
);
await IntegerNames.sync({force: true})
await IntegerNames.create({value: 2, name: 'two'});
await IntegerNames.create({value: 3, name: 'three'});
await IntegerNames.create({value: 5, name: 'five'});
const integerName = await IntegerNames.findOne({ where: { value: 2 } });
assert.strictEqual(integerName.name, 'two');
assert.strictEqual(integerName.name2, 'twoasdf');
integerName.name = 'TWO'
integerName.save();
const integerName2 = await IntegerNames.findOne({ where: { value: 2 } });
assert.strictEqual(integerName2.name, 'TWO');
// Fails.
//assert.strictEqual(integerName2.name2, 'TWOasdf');
await sequelize.close();
})();

View File

@ -1,127 +0,0 @@
#!/usr/bin/env node
// Trying to get everything in the database camel cased, columns lowercase, tables uppercase.
// The defaults documented on getting started documentation do uppercase foreign keys, an
// lowercase non-foreign keys. It's a mess.
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
define: {
timestamps: false
},
});
(async () => {
// Create the tables.
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
});
const Post = sequelize.define('Post', {
body: { type: DataTypes.STRING },
});
const UserFollowsUser = sequelize.define('UserFollowsUser', {
userId: {
type: DataTypes.INTEGER,
references: {
model: User,
key: 'id'
}
},
followId: {
type: DataTypes.INTEGER,
references: {
model: User,
key: 'id'
}
},
});
User.belongsToMany(User, {
through: UserFollowsUser,
as: 'follows',
foreignKey: 'userId',
otherKey: 'followId',
});
User.hasMany(Post, {foreignKey: 'authorId'});
Post.belongsTo(User, {foreignKey: 'authorId'});
await sequelize.sync({force: true});
// Create data.
const users = await User.bulkCreate([
{name: 'user0'},
{name: 'user1'},
{name: 'user2'},
{name: 'user3'},
])
const posts = await Post.bulkCreate([
{body: 'body00', authorId: users[0].id},
{body: 'body01', authorId: users[0].id},
{body: 'body10', authorId: users[1].id},
{body: 'body11', authorId: users[1].id},
{body: 'body20', authorId: users[2].id},
{body: 'body21', authorId: users[2].id},
{body: 'body30', authorId: users[3].id},
{body: 'body31', authorId: users[3].id},
])
await users[0].addFollows([users[1], users[2]])
// Check case of auto-getters.
const user0Posts = await users[0].getPosts({order: [['body', 'ASC']]})
assert(user0Posts[0].body === 'body00')
assert(user0Posts[1].body === 'body01')
assert(user0Posts.length === 2)
const user1Posts = await users[1].getPosts({order: [['body', 'ASC']]})
assert(user1Posts[0].body === 'body10')
assert(user1Posts[1].body === 'body11')
assert(user1Posts.length === 2)
const post00User = await posts[0].getUser()
assert(post00User.name === 'user0')
const post01User = await posts[1].getUser()
assert(post01User.name === 'user0')
const post10User = await posts[2].getUser()
assert(post10User.name === 'user1')
const post11User = await posts[3].getUser()
assert(post11User.name === 'user1')
// Check case of as;
{
const user0Follows = (await User.findByPk(users[0].id, {
include: [
{
model: User,
as: 'follows',
include: [
{
model: Post,
}
],
},
],
})).follows
const postsFound = []
for (const followedUser of user0Follows) {
postsFound.push(...followedUser.Posts)
}
postsFound.sort((x, y) => { return x.body < y.body ? -1 : x.body > y.body ? 1 : 0 })
assert(postsFound[0].body === 'body10')
assert(postsFound[1].body === 'body11')
assert(postsFound[2].body === 'body20')
assert(postsFound[3].body === 'body21')
assert(postsFound.length === 4)
}
await sequelize.close();
})();

View File

@ -1,47 +0,0 @@
#!/usr/bin/env node
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
define: {
timestamps: false
},
});
(async () => {
const Tag = sequelize.define('Tag', {
name: {
type: DataTypes.STRING,
unique: true,
},
});
await sequelize.sync({force: true})
await Tag.create({name: 't0'})
// Individual create does not have the option for some reason.
// Apparently you're just supposed to catch.
// https://github.com/sequelize/sequelize/issues/4513
//await Tag.create({name: 't0', ignoreDuplicates: true})
// SQLite: INSERT OR IGNORE INTO as desired.
const tags = await Tag.bulkCreate(
[
{name: 't0'},
{name: 't1'},
{name: 't1'},
{name: 't2'},
],
{
ignoreDuplicates: true,
}
)
const tagsFound = await Tag.findAll({order: [['name', 'ASC']]})
assert.strictEqual(tagsFound[0].name, 't0')
assert.strictEqual(tagsFound[1].name, 't1')
assert.strictEqual(tagsFound[2].name, 't2')
assert.strictEqual(tagsFound.length, 3)
await sequelize.close();
})();

View File

@ -1,33 +0,0 @@
#!/usr/bin/env node
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
(async () => {
await sequelize.authenticate();
const IntegerNames = sequelize.define('IntegerNames', {
value: {
type: DataTypes.INTEGER,
},
name: {
type: DataTypes.STRING,
},
});
await IntegerNames.sync({force: true})
await IntegerNames.create({value: 2, name: 'two'});
await IntegerNames.create({value: 3, name: 'three'});
await IntegerNames.create({value: 5, name: 'five'});
const integerName5 = await IntegerNames.findOne({ where: { value: 5 } });
integerName5.increment('value')
// Sequelize updates, but others don't...
console.error(integerName5.value);
const integerName6 = await IntegerNames.findOne({ where: { value: 6 } });
assert.strictEqual(integerName6.name, 'five')
await sequelize.close();
})();

View File

@ -1,146 +0,0 @@
#!/usr/bin/env node
// https://cirosantilli.com/sequelize
//
// Before running this:
// * ensure that you can use peer authentication without password
// from the command line, i.e. `psql` works
// * create the database for our test:
// ``
// createdb lkmc-nodejs
// ``
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes, Op } = require('sequelize');
// To use the URI syntax, we need an explcit username and password.
// But the second constructor works with peer authentication.
// https://stackoverflow.com/questions/46207155/sequelize-and-peer-authentication-for-postgres
//
// Fails
//const sequelize = new Sequelize('postgres://user:password@localhost:5432/lkmc-nodejs')
//
// Works with peer authentication:
//const sequelize = new Sequelize('lkmc-nodejs', undefined, undefined, {
// host: '/var/run/postgresql',
// dialect: 'postgres',
// logging: false,
//});
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
// OMG fuck this asynchronous bullshit:
// https://stackoverflow.com/questions/39928452/execute-sequelize-queries-synchronously/43250120
(async () => {
// Connection sanity check.
// https://stackoverflow.com/questions/19429152/check-mysql-connection-in-sequelize/31115934
await sequelize.authenticate();
const IntegerNames = sequelize.define('IntegerNames', {
value: {
type: DataTypes.INTEGER,
allowNull: false,
unique: true,
},
name: {
type: DataTypes.STRING,
},
});
// Create the database defined by `sequelize.define`.
await IntegerNames.sync({force: true})
// After this:
//
// psql lkmc-nodejs -c '\dt'
//
// gives:
//
// List of relations
// Schema | Name | Type | Owner
// --------+--------------+-------+-------
// public | IntegerNames | table | ciro
// (2 rows)
//
// and:
//
// psql lkmc-nodejs -c '\d+ "IntegerNames"'
//
// gives:
//
// Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
// -----------+--------------------------+-----------+----------+--------------------------------------------+----------+--------------+-------------
// id | integer | | not null | nextval('"IntegerNames_id_seq"'::regclass) | plain | |
// value | integer | | not null | | plain | |
// name | character varying(255) | | | | extended | |
// createdAt | timestamp with time zone | | not null | | plain | |
// updatedAt | timestamp with time zone | | not null | | plain | |
// Indexes:
// "IntegerNames_pkey" PRIMARY KEY, btree (id)
await IntegerNames.create({value: 2, name: 'two'});
await IntegerNames.create({value: 3, name: 'three'});
await IntegerNames.create({value: 5, name: 'five'});
// psql lkmc-nodejs -c 'SELECT * FROM "IntegerNames";'
//
// gives:
//
// id | value | name | createdAt | updatedAt
// ----+-------+-------+----------------------------+----------------------------
// 1 | 2 | two | 2021-03-19 19:12:08.436+00 | 2021-03-19 19:12:08.436+00
// 2 | 3 | three | 2021-03-19 19:12:08.436+00 | 2021-03-19 19:12:08.436+00
// 3 | 5 | five | 2021-03-19 19:12:08.437+00 | 2021-03-19 19:12:08.437+00
// (3 rows)
let integerNames = await IntegerNames.findAll({
where: {
value: 2
}
});
assert.strictEqual(integerNames[0].name, 'two');
assert.strictEqual(integerNames.length, 1);
// SELECT and destroy: https://stackoverflow.com/questions/8402597/sequelize-js-delete-query
await IntegerNames.destroy({
where: {
value: { [Op.gt]: 2 },
},
limit: 1,
});
integerNames = await IntegerNames.findAll({order: [['value', 'ASC']]})
assert.strictEqual(integerNames[0].name, 'two');
assert.strictEqual(integerNames[1].name, 'five');
assert.strictEqual(integerNames.length, 2);
// Truncate all tables.
// https://stackoverflow.com/questions/47816162/wipe-all-tables-in-a-schema-sequelize-nodejs/66985334#66985334
await sequelize.truncate();
assert.strictEqual(await IntegerNames.count(), 0);
// Datetime. Automatically converts to/from date objects.
const Dates = sequelize.define('Dates', {
date: {
type: DataTypes.DATE,
},
}, {});
await Dates.sync({force: true})
let dateCreate = await Dates.create({date: new Date(2000, 0, 1, 2, 3, 4, 5)});
await Dates.create({date: new Date(2000, 0, 1, 2, 3, 4, 6)});
await Dates.create({date: new Date(2000, 0, 1, 2, 3, 4, 7)});
let date = await Dates.findOne({
order: [
['date', 'ASC'],
],
});
assert.strictEqual(date.date.getTime(), new Date(2000, 0, 1, 2, 3, 4, 5).getTime());
assert.strictEqual(date.date.getTime(), dateCreate.date.getTime());
// Otherwise it hangs for 10 seconds, it seems that it keeps the connection alive.
// https://stackoverflow.com/questions/28253831/recreating-database-sequelizejs-is-slow
// https://github.com/sequelize/sequelize/issues/8468
await sequelize.close();
})();

View File

@ -1,110 +0,0 @@
#!/usr/bin/env node
// https://stackoverflow.com/questions/17708620/sequelize-changing-model-schema-on-production
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
(async () => {
{
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
const IntegerNames = sequelize.define('IntegerNames', {
value: { type: DataTypes.INTEGER, },
name: { type: DataTypes.STRING, },
}, {});
await IntegerNames.sync({force: true})
await IntegerNames.create({value: 2, name: 'two'});
await IntegerNames.create({value: 3, name: 'three'});
await sequelize.close();
}
// Alter by adding column..
{
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
const IntegerNames = sequelize.define('IntegerNames', {
value: { type: DataTypes.INTEGER, },
name: { type: DataTypes.STRING, },
nameEs: { type: DataTypes.STRING, },
}, {});
await IntegerNames.sync({alter: true})
await IntegerNames.create({value: 5, name: 'five' , nameEs: 'cinco'});
await IntegerNames.create({value: 7, name: 'seven', nameEs: 'siete'});
const integerNames = await IntegerNames.findAll({
order: [['value', 'ASC']],
});
assert(integerNames[0].value === 2);
assert(integerNames[0].name === 'two');
assert(integerNames[0].nameEs === null);
assert(integerNames[1].name === 'three');
assert(integerNames[1].nameEs === null);
assert(integerNames[2].name === 'five');
assert(integerNames[2].nameEs === 'cinco');
assert(integerNames[3].name === 'seven');
assert(integerNames[3].nameEs === 'siete');
await sequelize.close();
}
// Alter by removing column. undefined instead of null,
// because the values really aren't present in the database anymore.
{
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
const IntegerNames = sequelize.define('IntegerNames', {
value: { type: DataTypes.INTEGER, },
name: { type: DataTypes.STRING, },
}, {});
await IntegerNames.sync({alter: true})
const integerNames = await IntegerNames.findAll({
order: [['value', 'ASC']],
});
assert(integerNames[0].value === 2);
assert(integerNames[0].name === 'two');
assert(integerNames[0].nameEs === undefined);
assert(integerNames[1].name === 'three');
assert(integerNames[1].nameEs === undefined);
assert(integerNames[2].name === 'five');
assert(integerNames[2].nameEs === undefined);
assert(integerNames[3].name === 'seven');
assert(integerNames[3].nameEs === undefined);
await sequelize.close();
}
// Alter a type.
// Hmm, docs suggest data would get dropped, but I only see typecast without alter.drop,
// so shy does it work still?. sqlite from CLI does confirm that it is now a VARCHAR(255)
// column.
{
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
const IntegerNames = sequelize.define('IntegerNames', {
value: { type: DataTypes.STRING, },
name: { type: DataTypes.STRING, },
}, {});
await IntegerNames.sync({alter: true})
const integerNames = await IntegerNames.findAll({
order: [['value', 'ASC']],
});
assert(integerNames[0].value === '2');
assert(integerNames[0].name === 'two');
assert(integerNames[1].value === '3');
assert(integerNames[1].name === 'three');
assert(integerNames[2].value === '5');
assert(integerNames[2].name === 'five');
assert(integerNames[3].value === '7');
assert(integerNames[3].name === 'seven');
await sequelize.close();
}
})();

View File

@ -1,36 +0,0 @@
#!/usr/bin/env node
// https://stackoverflow.com/questions/39765582/in-sequelize-model-destroy-truncate-true-does-not-reset-primary-key
const assert = require('assert')
const path = require('path')
const { Sequelize, DataTypes } = require('sequelize')
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
})
;(async () => {
const IntegerNames = sequelize.define('IntegerNames', {
value: {
type: DataTypes.INTEGER,
allowNull: false,
unique: true,
},
name: {
type: DataTypes.STRING,
},
}, {})
await IntegerNames.sync({force: true})
await IntegerNames.create({value: 2, name: 'two'})
await IntegerNames.create({value: 3, name: 'three'})
console.error((await IntegerNames.findOne({where: {value: 2}})).id)
await IntegerNames.truncate({cascade: true})
await IntegerNames.create({value: 5, name: 'five'})
await IntegerNames.create({value: 7, name: 'seven'})
console.error((await IntegerNames.findOne({where: {value: 5}})).id)
await sequelize.close()
})();

View File

@ -1,86 +0,0 @@
#!/usr/bin/env node
// https://stackoverflow.com/questions/54898994/bulkupdate-in-sequelize-orm/69044138#69044138
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes, Op } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
(async () => {
const Inverses = sequelize.define('Inverses',
{
value: {
type: DataTypes.INTEGER,
primaryKey: true,
},
inverse: {
type: DataTypes.INTEGER,
},
name: {
type: DataTypes.STRING,
},
},
{ timestamps: false }
);
await Inverses.sync({force: true})
await Inverses.create({value: 2, inverse: -2, name: 'two'});
await Inverses.create({value: 3, inverse: -3, name: 'three'});
await Inverses.create({value: 5, inverse: -5, name: 'five'});
// Initial state.
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).inverse, -2);
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).inverse, -3);
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).inverse, -5);
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).name, 'two');
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).name, 'three');
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).name, 'five');
assert.strictEqual(await Inverses.count(), 3);
// Update to fixed value.
await Inverses.update(
{ inverse: 0, },
{ where: { value: { [Op.gt]: 2 } } },
);
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).inverse, -2);
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).inverse, 0);
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).inverse, 0);
assert.strictEqual(await Inverses.count(), 3);
// Update to match another column.
await Inverses.update(
{ inverse: sequelize.col('value'), },
{ where: { value: { [Op.gt]: 2 } } },
);
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).inverse, -2);
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).inverse, 3);
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).inverse, 5);
assert.strictEqual(await Inverses.count(), 3);
// Update to match another column with modification.
await Inverses.update(
{ inverse: sequelize.fn('1 + ', sequelize.col('value')), },
{ where: { value: { [Op.gt]: 2 } } },
);
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).inverse, -2);
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).inverse, 4);
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).inverse, 6);
assert.strictEqual(await Inverses.count(), 3);
// A string function test.
await Inverses.update(
{ name: sequelize.fn('upper', sequelize.col('name')), },
{ where: { value: { [Op.gt]: 2 } } },
);
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).name, 'two');
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).name, 'THREE');
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).name, 'FIVE');
assert.strictEqual(await Inverses.count(), 3);
await sequelize.close();
})();

View File

@ -1,69 +0,0 @@
#!/usr/bin/env node
// https://stackoverflow.com/questions/54898994/bulkupdate-in-sequelize-orm/69044138#69044138
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
(async () => {
const Integer = sequelize.define('Integer',
{
value: {
type: DataTypes.INTEGER,
unique: true, // mandatory
primaryKey: true,
},
name: {
type: DataTypes.STRING,
},
inverse: {
type: DataTypes.INTEGER,
},
},
{
timestamps: false,
}
);
await Integer.sync({force: true})
await Integer.create({value: 2, inverse: -2, name: 'two'});
await Integer.create({value: 3, inverse: -3, name: 'three'});
await Integer.create({value: 5, inverse: -5, name: 'five'});
// Initial state.
assert.strictEqual((await Integer.findOne({ where: { value: 2 } })).name, 'two');
assert.strictEqual((await Integer.findOne({ where: { value: 3 } })).name, 'three');
assert.strictEqual((await Integer.findOne({ where: { value: 5 } })).name, 'five');
assert.strictEqual((await Integer.findOne({ where: { value: 2 } })).inverse, -2);
assert.strictEqual((await Integer.findOne({ where: { value: 3 } })).inverse, -3);
assert.strictEqual((await Integer.findOne({ where: { value: 5 } })).inverse, -5);
assert.strictEqual(await Integer.count(), 3);
// Update.
await Integer.bulkCreate(
[
{value: 2, name: 'TWO'},
{value: 3, name: 'THREE'},
{value: 7, name: 'SEVEN'},
],
{ updateOnDuplicate: ["name"] }
);
// Final state.
assert.strictEqual((await Integer.findOne({ where: { value: 2 } })).name, 'TWO');
assert.strictEqual((await Integer.findOne({ where: { value: 3 } })).name, 'THREE');
assert.strictEqual((await Integer.findOne({ where: { value: 5 } })).name, 'five');
assert.strictEqual((await Integer.findOne({ where: { value: 7 } })).name, 'SEVEN');
assert.strictEqual((await Integer.findOne({ where: { value: 2 } })).inverse, -2);
assert.strictEqual((await Integer.findOne({ where: { value: 3 } })).inverse, -3);
assert.strictEqual((await Integer.findOne({ where: { value: 5 } })).inverse, -5);
assert.strictEqual(await Integer.count(), 4);
await sequelize.close();
})();