Skip to content

Commit

Permalink
sql: do not increase row-count if INSERT OR IGNORE fails
Browse files Browse the repository at this point in the history
If INSERT statement is executed with IGNORE error action (i.e.
INSERT OR IGNORE ...), it will return number of rows inserted.
For example:

CREATE TABLE t (i INT PRIMARY KEY, a INT check (a > 0));
INSERT OR IGNORE INTO t VALUES (1, 1), (2, -1), (3, 2);

Should return:
---
- row_count: 2
...

However it was three before this patch. So, let's account number
of successful insertions in case of INSERT OR IGNORE.

Follow-up #4188
  • Loading branch information
ImeevMA committed Jul 22, 2019
1 parent 23fbfaf commit 0378b5f
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 17 deletions.
40 changes: 23 additions & 17 deletions src/box/sql/vdbe.c
Original file line number Diff line number Diff line change
Expand Up @@ -4198,8 +4198,6 @@ case OP_IdxReplace:
case OP_IdxInsert: {
pIn2 = &aMem[pOp->p1];
assert((pIn2->flags & MEM_Blob) != 0);
if (pOp->p5 & OPFLAG_NCHANGE)
p->nChange++;
if (ExpandBlob(pIn2) != 0)
goto abort_due_to_error;
struct space *space;
Expand All @@ -4222,26 +4220,34 @@ case OP_IdxInsert: {
rc = tarantoolsqlEphemeralInsert(space, pIn2->z,
pIn2->z + pIn2->n);
}
if (rc == 0 && pOp->p3 > 0 && ((aMem[pOp->p3].flags) & MEM_Null) != 0) {
if (rc != 0) {
if ((pOp->p5 & OPFLAG_OE_IGNORE) != 0) {
/*
* Ignore any kind of fails and do not
* raise error message. If we are in
* trigger, increment ignore raised
* counter.
*/
rc = 0;
if (p->pFrame != NULL)
p->ignoreRaised++;
break;
}
if ((pOp->p5 & OPFLAG_OE_FAIL) != 0) {
p->errorAction = ON_CONFLICT_ACTION_FAIL;
} else if ((pOp->p5 & OPFLAG_OE_ROLLBACK) != 0) {
p->errorAction = ON_CONFLICT_ACTION_ROLLBACK;
}
goto abort_due_to_error;
}
if ((pOp->p5 & OPFLAG_NCHANGE) != 0)
p->nChange++;
if (pOp->p3 > 0 && ((aMem[pOp->p3].flags) & MEM_Null) != 0) {
assert(space->sequence != NULL);
int64_t value = sequence_get_value(space->sequence);
if (vdbe_add_new_autoinc_id(p, value) != 0)
goto abort_due_to_error;
}

if (pOp->p5 & OPFLAG_OE_IGNORE) {
/* Ignore any kind of failes and do not raise error message */
rc = 0;
/* If we are in trigger, increment ignore raised counter */
if (p->pFrame)
p->ignoreRaised++;
} else if (pOp->p5 & OPFLAG_OE_FAIL) {
p->errorAction = ON_CONFLICT_ACTION_FAIL;
} else if (pOp->p5 & OPFLAG_OE_ROLLBACK) {
p->errorAction = ON_CONFLICT_ACTION_ROLLBACK;
}
if (rc != 0)
goto abort_due_to_error;
break;
}

Expand Down
30 changes: 30 additions & 0 deletions test/sql/row-count.result
Original file line number Diff line number Diff line change
Expand Up @@ -335,3 +335,33 @@ box.execute("DROP TABLE t1;")
---
- row_count: 1
...
--
-- gh-4188: make sure that in case of INSERT OR IGNORE only
-- successful inserts are counted.
--
box.execute("CREATE TABLE t (i INT PRIMARY KEY AUTOINCREMENT, a INT check (a > 0));")
---
- row_count: 1
...
box.execute("INSERT OR IGNORE INTO t VALUES (null, 1), (null, -1), (null, 2);")
---
- autoincrement_ids:
- 1
- 3
row_count: 2
...
box.execute("SELECT * FROM t;")
---
- metadata:
- name: I
type: integer
- name: A
type: integer
rows:
- [1, 1]
- [3, 2]
...
box.execute("DROP TABLE t;")
---
- row_count: 1
...
8 changes: 8 additions & 0 deletions test/sql/row-count.test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,11 @@ box.execute("DROP TABLE t2;")
box.execute("DROP TABLE t3;")
box.execute("DROP TABLE t1;")

--
-- gh-4188: make sure that in case of INSERT OR IGNORE only
-- successful inserts are counted.
--
box.execute("CREATE TABLE t (i INT PRIMARY KEY AUTOINCREMENT, a INT check (a > 0));")
box.execute("INSERT OR IGNORE INTO t VALUES (null, 1), (null, -1), (null, 2);")
box.execute("SELECT * FROM t;")
box.execute("DROP TABLE t;")

0 comments on commit 0378b5f

Please sign in to comment.