Skip to content

Commit

Permalink
sql: add OP_Error opcode in VDBE
Browse files Browse the repository at this point in the history
This opcode is required to set an error using diag_set() without
halting VDBE. This will allow us to run destructors between error
setting and VDBE halting.

Needed for #4183
  • Loading branch information
ImeevMA committed Jun 25, 2019
1 parent 564ba89 commit 7cbb598
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 13 deletions.
38 changes: 25 additions & 13 deletions src/box/sql/build.c
Original file line number Diff line number Diff line change
Expand Up @@ -1066,14 +1066,21 @@ vdbe_emit_ck_constraint_create(struct Parse *parser,
sqlDbStrDup(db, ck_def->expr_str), P4_DYNAMIC);
sqlVdbeAddOp3(v, OP_MakeRecord, ck_constraint_reg, 5,
ck_constraint_reg + 5);
const char *error_msg =
/* Check that there is no CHECK with such name. */
const char *err =
tt_sprintf(tnt_errcode_desc(ER_CONSTRAINT_EXISTS),
ck_def->name);
if (vdbe_emit_halt_with_presence_test(parser, BOX_CK_CONSTRAINT_ID, 0,
ck_constraint_reg, 2,
ER_CONSTRAINT_EXISTS, error_msg,
false, OP_NoConflict) != 0)
return;
int cursor = parser->nTab++;
vdbe_emit_open_cursor(parser, cursor, 0,
space_by_id(BOX_CK_CONSTRAINT_ID));
sqlVdbeChangeP5(v, OPFLAG_SYSTEMSP);
sqlVdbeAddOp4Int(v, OP_NoConflict, cursor, v->nOp + 3,
ck_constraint_reg, 2);
sqlVdbeAddOp4(v, OP_Error, ER_CONSTRAINT_EXISTS, v->nOp + 1, 0, err,
P4_STATIC);
sqlVdbeAddOp1(v, OP_Halt, -1);
sqlVdbeAddOp1(v, OP_Close, cursor);

sqlVdbeAddOp3(v, OP_SInsert, BOX_CK_CONSTRAINT_ID, 0,
ck_constraint_reg + 5);
save_record(parser, BOX_CK_CONSTRAINT_ID, ck_constraint_reg, 2,
Expand Down Expand Up @@ -1131,14 +1138,19 @@ vdbe_emit_fk_constraint_create(struct Parse *parse_context,
* Lets check that constraint with this name hasn't
* been created before.
*/
const char *error_msg =
const char *err =
tt_sprintf(tnt_errcode_desc(ER_CONSTRAINT_EXISTS), name_copy);
if (vdbe_emit_halt_with_presence_test(parse_context,
BOX_FK_CONSTRAINT_ID, 0,
constr_tuple_reg, 2,
ER_CONSTRAINT_EXISTS, error_msg,
false, OP_NoConflict) != 0)
return;
int cursor = parse_context->nTab++;
vdbe_emit_open_cursor(parse_context, cursor, 0,
space_by_id(BOX_FK_CONSTRAINT_ID));
sqlVdbeChangeP5(vdbe, OPFLAG_SYSTEMSP);
sqlVdbeAddOp4Int(vdbe, OP_NoConflict, cursor, vdbe->nOp + 3,
constr_tuple_reg, 2);
sqlVdbeAddOp4(vdbe, OP_Error, ER_CONSTRAINT_EXISTS, vdbe->nOp + 1, 0,
err, P4_STATIC);
sqlVdbeAddOp1(vdbe, OP_Halt, -1);
sqlVdbeAddOp1(vdbe, OP_Close, cursor);

sqlVdbeAddOp2(vdbe, OP_Bool, fk->is_deferred, constr_tuple_reg + 3);
sqlVdbeAddOp4(vdbe, OP_String8, 0, constr_tuple_reg + 4, 0,
fk_constraint_match_strs[fk->match], P4_STATIC);
Expand Down
12 changes: 12 additions & 0 deletions src/box/sql/vdbe.c
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,18 @@ case OP_Goto: { /* jump */
goto jump_to_p2;
}

/* Opcode: Error P1 P2 * P4 *
*
* Setting an error and an unconditional jump to address P2.
*
* The P1 parameter is error code of the erroe. The P4 parameter
* is a description of the error.
*/
case OP_Error: { /* jump */
box_error_set(__FILE__, __LINE__, pOp->p1, pOp->p4.z);
goto jump_to_p2;
}

/* Opcode: Gosub P1 P2 * * *
*
* Write the current address onto register P1
Expand Down

0 comments on commit 7cbb598

Please sign in to comment.