sidorares / sidorares/node-mysql2

InsertId not returned on upsert into table with a trigger

Open
#1,871 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
4.4k
Forks
680
Avg merge
9h 7m
Merged PRs (30d)
59

Description

Description

When upserting (on duplicate key update) into a table without a trigger, the insertId is always returned. When there is a trigger on the table, the insertId is not returned if the upsert results in no change to the row.

Steps to reproduce

SQL
create table t1 (
  id bigint(20) not null auto_increment,
  description1 varchar(45) default null,
  description2 varchar(45) default null,
  primary key (id),
  unique key idx_description_uq (description1)
) engine=InnoDB;

create table t2 (
  id bigint(20) not null,
  description1 varchar(45) default null,
  description2 varchar(45) default null
) engine=InnoDB;

create trigger trig after update on t1
	for each row
		insert into t2 (id, description1, description2) values (OLD.id, OLD.description1, OLD.description2);
Node
const mysql = require('mysql2/promise');
let connection;

makeCalls();

async function makeCalls() {
    connection = await mysql.createConnection({
    host: "localhost",
    port: 3306,
    user: "user",
    password: "password",
    database: "database"
  });

  await makeCall(1, 'test1');
  await makeCall(2, 'test1');
  await makeCall(3, 'test2');
}  

async function makeCall(run, description2) {    
  const [rows1] = await connection.execute(
    `insert into t1
        (description1, description2)
        values
        ('test1','${description2}') on duplicate key update id = last_insert_id(id), description1 = 'test1', description2 = '${description2}';`
    );
  console.log(`run ${run}: affectedRows ${rows1.affectedRows}, insertId ${rows1.insertId}`);
}
Output without trigger

run 1: affectedRows 1, insertId 1 <-initial insert
run 2: affectedRows 1, insertId 1 <-update, with the same data
run 3: affectedRows 2, insertId 1 <-update, with a change in data

Output with trigger

run 1: affectedRows 1, insertId 1 <-initial insert
run 2: affectedRows 1, insertId 0 <-update, with the same data
run 3: affectedRows 2, insertId 1 <-update, with a change in data

Environment

MySQL v5.7
mysql2 v2.3.3 and v3.1.2
node v14, v16 and v18.

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

Start by reproducing the behavior with the provided MySQL schema, trigger, and Node mysql2/promise execute example. Trace how the result metadata exposes affectedRows and insertId for an unchanged upsert, then add regression coverage showing that insertId is returned consistently with and without the trigger.

Written by the indexing model from the issue text.

Assessment

Tech stack
mysql, node.js, typescript
Domain
backend, database
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.