sequelize / sequelize/sequelize

Query using Op.ne operator returns unexpected results

Open
#17,661 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

pending-approval
Dominant language
TypeScript
Stars
30.4k
Forks
4.3k
Avg merge
1d 6h
Merged PRs (30d)
68

Description

Query using Op.ne operator returns unexpected results

Description: When querying the Organization model with the Op.ne (not equal) operator for the id field, the query fails to return the expected results, and it logs the SQL query with an undefined value for id

const exist = await Organization.findOne({
where: {
email: "bharat@gmail.com",
id: { [Op.ne]: 1 },
},
logging: console.log, // Log SQL for debugging
});

error Executing (default): SELECT "id", "name", "mobile_no", "email", "total_employee", "gst_no", "logo_img", "country", "country_code", "state", "city", "address", "pincode", "password", "current_plan", "current_plan_status", "is_sundayholiday", "createdby", "updateby", "is_deleted", "created_at", "updated_at" FROM "organization" AS "Organization" WHERE "Organization"."email" = 'bharat@gmail.com' AND "Organization"."id" != 1 LIMIT 1;
null .......exxx
Error: WHERE parameter "id" has invalid "undefined" value
at PostgresQueryGenerator.whereItemQuery (D:\tracker_project\backend\node_modules\sequelize\src\dialects\abstract\query-generator.js:2451:13)
at D:\tracker_project\backend\node_modules\sequelize\src\dialects\abstract\query-generator.js:2440:25
at Array.forEach ()
at PostgresQueryGenerator.whereItemsQuery (D:\tracker_project\backend\node_modules\sequelize\src\dialects\abstract\query-generator.js:2438:35)
at PostgresQueryGenerator.whereQuery (D:\tracker_project\backend\node_modules\sequelize\src\dialects\abstract\query-generator.js:2411:24)
at PostgresQueryGenerator.updateQuery (D:\tracker_project\backend\node_modules\sequelize\src\dialects\abstract\query-generator.js:515:116)
at PostgresQueryInterface.bulkUpdate (D:\tracker_project\backend\node_modules\sequelize\src\dialects\abstract\query-interface.js:924:37)
at Function.update (D:\tracker_project\backend\node_modules\sequelize\src\model.js:3352:54)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at updateOrganization (D:\tracker_project\backend\src\modules\organization\controllers\organization.controller.ts:27:26)

this my model definition
import { DataTypes, Model, Optional, Sequelize } from "sequelize";
import bcrypt from "bcrypt";
import sequelize from "../../../storageHandlers/database.handler";

export interface OrganizationAttributes {
id?: number;
name?: string | null;
mobile_no?: number;
email?: string | null;
total_employee?: number | null;
gst_no?: string | null;
logo_img?: string | null;
country?: string | null;
country_code?: string | null;
state?: string | null;
city?: string | null;
address?: string | null;
pincode?: string | null;
password?: string;
current_plan?: number | null;
current_plan_status?: string | null;
is_sundayholiday?: number | null;
createdby?: number | null;
updateby?: number | null;
is_deleted?: number;
created_at?: Date;
updated_at?: Date;
}

export interface OrganizationCreationAttributes
extends Optional<OrganizationAttributes, "created_at" | "updated_at" | "is_deleted"> {}

export class Organization
extends Model<OrganizationAttributes, OrganizationCreationAttributes>
implements OrganizationAttributes
{
public id!: number;
public name!: string | null;
public mobile_no!: number;
public email!: string | null;
public total_employee!: number | null;
public gst_no!: string | null;
public logo_img!: string | null;
public country!: string | null;
public country_code!: string | null;
public state!: string | null;
public city!: string | null;
public address!: string | null;
public pincode!: string | null;
public password!: string;
public current_plan!: number | null;
public current_plan_status!: string | null;
public is_sundayholiday!: number | null;
public createdby!: number | null;
public updateby!: number | null;
public is_deleted!: number;
public created_at!: Date;
public updated_at!: Date;

// Verify password
public async verifyPassword(plainPassword: string): Promise {
if (!this.password) {
throw new Error("Password not set for this organization");
}
return bcrypt.compare(plainPassword, this.password);
}
}

Organization.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING(100),
allowNull: true,
},
mobile_no: {
type: DataTypes.BIGINT,
allowNull: false,
},
email: {
type: DataTypes.STRING(100),
allowNull: true,
validate: {
isEmail: true, // Validate email format
},
},
total_employee: {
type: DataTypes.INTEGER,
allowNull: true,
},
gst_no: {
type: DataTypes.STRING(255),
allowNull: true,
},
logo_img: {
type: DataTypes.STRING(255),
allowNull: true,
},
country: {
type: DataTypes.STRING(100),
allowNull: true,
},
country_code: {
type: DataTypes.STRING(10),
allowNull: true,
},
state: {
type: DataTypes.STRING(100),
allowNull: true,
},
city: {
type: DataTypes.STRING(100),
allowNull: true,
},
address: {
type: DataTypes.STRING(255),
allowNull: true,
},
pincode: {
type: DataTypes.STRING(20),
allowNull: true,
},
password: {
type: DataTypes.STRING(255),
allowNull: false,
},
current_plan: {
type: DataTypes.INTEGER,
allowNull: true,
},
current_plan_status: {
type: DataTypes.STRING(50),
allowNull: true,
},
is_sundayholiday: {
type: DataTypes.INTEGER,
allowNull: true,
},
createdby: {
type: DataTypes.INTEGER,
allowNull: true,
},
updateby: {
type: DataTypes.INTEGER,
allowNull: true,
},
is_deleted: {
type: DataTypes.INTEGER,
defaultValue: 0,
},
created_at: {
type: DataTypes.DATE,
defaultValue: Sequelize.literal("CURRENT_TIMESTAMP"),
},
updated_at: {
type: DataTypes.DATE,
defaultValue: Sequelize.literal("CURRENT_TIMESTAMP"),
},
},
{
sequelize,
tableName: "organization",
timestamps: true,
updatedAt: "updated_at",
createdAt: "created_at",
hooks: {
beforeCreate: async (organization) => {
if (organization.password) {
const salt = await bcrypt.genSalt(10);
organization.password = await bcrypt.hash(organization.password, salt);
}
},
beforeUpdate: async (organization) => {
if (organization.password) {
const salt = await bcrypt.genSalt(10);
organization.password = await bcrypt.hash(organization.password, salt);
}
},
},
}
);

export default Organization;

dependency

"@types/express": "^5.0.0",
"@types/redis": "^4.0.11",
"bcrypt": "^5.1.1",
"dotenv": "^16.4.7",
"express": "^4.21.2",
"express-validator": "^7.2.1",
"ioredis": "^5.4.2",
"pg": "^8.13.1",
"pg-hstore": "^2.3.4",
"reflect-metadata": "^0.2.2",
"request": "^2.88.2",
"sequelize": "^6.37.5",
"ts-node": "^10.9.2"

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No Sequelize repository file or regression test is identified. Start by reducing the Organization.findOne example to a minimal PostgreSQL case and compare its generated SQL with the updateOrganization stack trace in src/modules/organization/controllers/organization.controller.ts. Done means a reproducible library failure with a focused regression test, or evidence that the undefined value originates in the application.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, postgresql, typescript
Domain
backend, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.