mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 22:43:04 +01:00
Fixed (hopefully) savepoints implementation:
1) RELEASE SAVEPOINT statement is added 2) SAVEPOINT statement now re-establishes existing savepoint with the same name 3) all savepoint stuff is changed to use single BLR verb
This commit is contained in:
parent
a092329cf7
commit
112c7022b6
@ -248,8 +248,9 @@
|
||||
#define ROW_COUNT 504
|
||||
#define LOCK 505
|
||||
#define SAVEPOINT 506
|
||||
#define STATEMENT 507
|
||||
#define LEAVE 508
|
||||
#define INSERTING 509
|
||||
#define UPDATING 510
|
||||
#define DELETING 511
|
||||
#define RELEASE 507
|
||||
#define STATEMENT 508
|
||||
#define LEAVE 509
|
||||
#define INSERTING 510
|
||||
#define UPDATING 511
|
||||
#define DELETING 512
|
||||
|
@ -29,7 +29,7 @@
|
||||
* 2002.10.29 Nickolay Samofatov: Added support for savepoints
|
||||
*/
|
||||
/*
|
||||
$Id: gen.cpp,v 1.31 2003-04-08 00:31:20 brodsom Exp $
|
||||
$Id: gen.cpp,v 1.32 2003-06-10 13:39:04 dimitr Exp $
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
@ -1074,14 +1074,22 @@ void GEN_statement( DSQL_REQ request, DSQL_NOD node)
|
||||
case nod_end_savepoint:
|
||||
STUFF(blr_end_savepoint);
|
||||
return;
|
||||
|
||||
|
||||
case nod_user_savepoint:
|
||||
STUFF(blr_user_savepoint);
|
||||
STUFF(blr_savepoint_set);
|
||||
STUFF_CSTRING(((STR)node->nod_arg[e_sav_name])->str_data);
|
||||
return;
|
||||
|
||||
|
||||
case nod_release_savepoint:
|
||||
STUFF(blr_user_savepoint);
|
||||
STUFF(blr_savepoint_release);
|
||||
STUFF_CSTRING(((STR)node->nod_arg[e_sav_name])->str_data);
|
||||
return;
|
||||
|
||||
case nod_undo_savepoint:
|
||||
STUFF(blr_undo_savepoint);
|
||||
STUFF(blr_user_savepoint);
|
||||
STUFF(blr_savepoint_undo);
|
||||
STUFF_CSTRING(((STR)node->nod_arg[e_sav_name])->str_data);
|
||||
return;
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
* Contributor(s):
|
||||
*
|
||||
*
|
||||
* $Id: keywords.cpp,v 1.16 2003-04-06 11:20:03 dimitr Exp $
|
||||
* $Id: keywords.cpp,v 1.17 2003-06-10 13:39:05 dimitr Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -226,7 +226,8 @@ static const TOK tokens [] = {
|
||||
{REAL, "REAL", 1},
|
||||
{VERSION, "RECORD_VERSION", 1},
|
||||
{RECREATE, "RECREATE", 2},
|
||||
{REFERENCES, "REFERENCES", 1},
|
||||
{REFERENCES, "REFERENCES", 1},
|
||||
{RELEASE, "RELEASE", 2},
|
||||
{RESERVING, "RESERV", 1}, /* Alias of RESERVING */
|
||||
{RESERVING, "RESERVING", 1},
|
||||
{RESTRICT, "RESTRICT", 1},
|
||||
|
@ -326,6 +326,7 @@ typedef ENUM nod_t
|
||||
nod_redef_view, /* allows silent creation/overwriting of a view */
|
||||
nod_for_update, /* FOR UPDATE clause */
|
||||
nod_user_savepoint, /* savepoints support */
|
||||
nod_release_savepoint,
|
||||
nod_undo_savepoint,
|
||||
nod_label, /* label support */
|
||||
nod_exec_into /* EXECUTE STATEMENT INTO */
|
||||
|
7702
src/dsql/parse.cpp
7702
src/dsql/parse.cpp
File diff suppressed because it is too large
Load Diff
@ -489,6 +489,7 @@ static struct LexerState lex;
|
||||
%token ROW_COUNT
|
||||
%token LOCK
|
||||
%token SAVEPOINT
|
||||
%token RELEASE
|
||||
%token STATEMENT
|
||||
%token LEAVE
|
||||
%token INSERTING
|
||||
@ -543,8 +544,7 @@ statement : alter
|
||||
| replace
|
||||
| revoke
|
||||
| rollback
|
||||
| user_savepoint
|
||||
| undo_savepoint
|
||||
| savepoint
|
||||
| select
|
||||
| set
|
||||
| update
|
||||
@ -2639,9 +2639,18 @@ set_generator : SET GENERATOR symbol_generator_name TO signed_long_integer
|
||||
|
||||
/* transaction statements */
|
||||
|
||||
user_savepoint : SAVEPOINT symbol_savepoint_name
|
||||
savepoint : set_savepoint
|
||||
| release_savepoint
|
||||
| undo_savepoint
|
||||
;
|
||||
|
||||
set_savepoint : SAVEPOINT symbol_savepoint_name
|
||||
{ $$ = make_node (nod_user_savepoint, 1, $2); }
|
||||
;
|
||||
|
||||
release_savepoint : RELEASE SAVEPOINT symbol_savepoint_name
|
||||
{ $$ = make_node (nod_release_savepoint, 1, $3); }
|
||||
;
|
||||
|
||||
undo_savepoint : ROLLBACK optional_work TO optional_savepoint symbol_savepoint_name
|
||||
{ $$ = make_node (nod_undo_savepoint, 1, $5); }
|
||||
|
@ -1405,6 +1405,13 @@ DSQL_NOD PASS1_statement(DSQL_REQ request, DSQL_NOD input, USHORT proc_flag)
|
||||
request->req_type = REQ_SAVEPOINT;
|
||||
return input;
|
||||
|
||||
case nod_release_savepoint:
|
||||
if (request->req_flags & REQ_procedure)
|
||||
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 104, gds_arg_gds, gds_token_err, /* Token unknown */
|
||||
gds_arg_gds, gds_random, gds_arg_string, "RELEASE", 0);
|
||||
request->req_type = REQ_SAVEPOINT;
|
||||
return input;
|
||||
|
||||
case nod_undo_savepoint:
|
||||
if (request->req_flags & REQ_procedure)
|
||||
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 104, gds_arg_gds, gds_token_err, /* Token unknown */
|
||||
|
@ -282,15 +282,16 @@
|
||||
#define blr_nullsfirst (unsigned char)178
|
||||
#define blr_writelock (unsigned char)179
|
||||
|
||||
/* This codes are for user-defined savepoints
|
||||
as opposed to the system ones defined earlier */
|
||||
|
||||
#define blr_user_savepoint (unsigned char)180
|
||||
#define blr_undo_savepoint (unsigned char)181
|
||||
|
||||
/* This codes reuse BLR code space */
|
||||
/* These codes reuse BLR code space */
|
||||
|
||||
#define blr_post_arg (unsigned char)163
|
||||
#define blr_exec_into (unsigned char)164
|
||||
#define blr_user_savepoint (unsigned char)165
|
||||
|
||||
/* These codes are actions for user-defined savepoints */
|
||||
|
||||
#define blr_savepoint_set (unsigned char)0
|
||||
#define blr_savepoint_release (unsigned char)1
|
||||
#define blr_savepoint_undo (unsigned char)2
|
||||
|
||||
#endif /* _JRD_BLR_H_ */
|
||||
|
@ -82,7 +82,6 @@ static const VERB verbs[] = {
|
||||
PAIR(nod_message, blr_message, 0, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_modify, blr_modify, 0, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_user_savepoint, blr_user_savepoint, e_sav_length, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_undo_savepoint, blr_undo_savepoint, e_sav_length, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_receive, blr_receive, e_send_length, 1, STATEMENT, STATEMENT),
|
||||
PAIR(nod_select, blr_select, 0, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_send, blr_send, e_send_length, 1, STATEMENT, STATEMENT),
|
||||
|
@ -2412,7 +2412,6 @@ static JRD_NOD copy(
|
||||
break;
|
||||
|
||||
case nod_user_savepoint:
|
||||
case nod_undo_savepoint:
|
||||
args = e_sav_length;
|
||||
break;
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
||||
*
|
||||
*/
|
||||
/*
|
||||
$Id: exe.cpp,v 1.64 2003-06-01 16:22:47 skidder Exp $
|
||||
$Id: exe.cpp,v 1.65 2003-06-10 13:40:16 dimitr Exp $
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
@ -1819,8 +1819,6 @@ static JRD_NOD looper(TDBB tdbb, JRD_REQ request, JRD_NOD in_node)
|
||||
**************************************/
|
||||
|
||||
STA impure;
|
||||
SLONG sav_number;
|
||||
SAV savepoint;
|
||||
SSHORT which_erase_trig = 0;
|
||||
SSHORT which_sto_trig = 0;
|
||||
SSHORT which_mod_trig = 0;
|
||||
@ -2041,48 +2039,80 @@ static JRD_NOD looper(TDBB tdbb, JRD_REQ request, JRD_NOD in_node)
|
||||
node = node->nod_parent;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case nod_user_savepoint:
|
||||
if (transaction != dbb->dbb_sys_trans) {
|
||||
// Use the savepoint created by EXE_start
|
||||
transaction->tra_save_point->sav_flags |= SAV_user;
|
||||
strcpy(transaction->tra_save_point->sav_name, (TEXT*)node->nod_arg[e_sav_name]);
|
||||
}
|
||||
node = node->nod_parent;
|
||||
request->req_operation = jrd_req::req_return;
|
||||
break;
|
||||
|
||||
case nod_undo_savepoint:
|
||||
UCHAR operation = (UCHAR) node->nod_arg[e_sav_operation];
|
||||
TEXT * node_savepoint_name = (TEXT*) node->nod_arg[e_sav_name];
|
||||
|
||||
if (transaction != dbb->dbb_sys_trans) {
|
||||
// Skip the savepoint created by EXE_start
|
||||
savepoint = transaction->tra_save_point->sav_next;
|
||||
SAV savepoint = transaction->tra_save_point->sav_next;
|
||||
SAV previous = transaction->tra_save_point;
|
||||
|
||||
// Find savepoint to undo
|
||||
while(TRUE) {
|
||||
// Find savepoint
|
||||
bool found = false;
|
||||
while (true) {
|
||||
if (!savepoint || !(savepoint->sav_flags & SAV_user))
|
||||
ERR_post(gds_invalid_savepoint,
|
||||
gds_arg_string, (TEXT*) node->nod_arg[e_sav_name], 0);
|
||||
|
||||
if (!strcmp((TEXT*)node->nod_arg[e_sav_name],(TEXT*)savepoint->sav_name))
|
||||
break;
|
||||
|
||||
if (!strcmp(node_savepoint_name, savepoint->sav_name)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
previous = savepoint;
|
||||
savepoint = savepoint->sav_next;
|
||||
}
|
||||
sav_number = savepoint->sav_number;
|
||||
|
||||
// Actually undo the savepoint
|
||||
while ( transaction->tra_save_point &&
|
||||
transaction->tra_save_point->sav_number >= sav_number )
|
||||
{
|
||||
transaction->tra_save_point->sav_verb_count++;
|
||||
VERB_CLEANUP;
|
||||
if (!found && operation != blr_savepoint_set) {
|
||||
ERR_post(gds_invalid_savepoint,
|
||||
gds_arg_string, node_savepoint_name, 0);
|
||||
}
|
||||
|
||||
// Now set the savepoint again to allow to return to it later
|
||||
VIO_start_save_point(tdbb, transaction);
|
||||
transaction->tra_save_point->sav_flags |= SAV_user;
|
||||
strcpy(transaction->tra_save_point->sav_name, (TEXT*)node->nod_arg[e_sav_name]);
|
||||
SLONG sav_number = savepoint->sav_number;
|
||||
|
||||
if (operation == blr_savepoint_set) {
|
||||
|
||||
// Release the savepoint
|
||||
if (found) {
|
||||
previous->sav_next = savepoint->sav_next;
|
||||
SAV current = transaction->tra_save_point;
|
||||
transaction->tra_save_point = savepoint;
|
||||
VERB_CLEANUP;
|
||||
transaction->tra_save_point = current;
|
||||
}
|
||||
|
||||
// Use the savepoint created by EXE_start
|
||||
transaction->tra_save_point->sav_flags |= SAV_user;
|
||||
strcpy(transaction->tra_save_point->sav_name, node_savepoint_name);
|
||||
}
|
||||
else if (operation == blr_savepoint_release) {
|
||||
|
||||
// Release the savepoint and all subsequent ones
|
||||
while (transaction->tra_save_point &&
|
||||
transaction->tra_save_point->sav_number >= sav_number)
|
||||
{
|
||||
VERB_CLEANUP;
|
||||
}
|
||||
}
|
||||
else if (operation == blr_savepoint_undo) {
|
||||
|
||||
// Undo the savepoint
|
||||
while (transaction->tra_save_point &&
|
||||
transaction->tra_save_point->sav_number >= sav_number)
|
||||
{
|
||||
transaction->tra_save_point->sav_verb_count++;
|
||||
VERB_CLEANUP;
|
||||
}
|
||||
|
||||
// Now set the savepoint again to allow to return to it later
|
||||
VIO_start_save_point(tdbb, transaction);
|
||||
transaction->tra_save_point->sav_flags |= SAV_user;
|
||||
strcpy(transaction->tra_save_point->sav_name, node_savepoint_name);
|
||||
}
|
||||
else {
|
||||
BUGCHECK(232);
|
||||
}
|
||||
}
|
||||
node = node->nod_parent;
|
||||
request->req_operation = jrd_req::req_return;
|
||||
|
@ -263,9 +263,9 @@ typedef struct iasb {
|
||||
#define e_erase_rsb 3
|
||||
#define e_erase_length 4
|
||||
|
||||
/* used for both nod_user_savepoint and nod_undo_savepoint */
|
||||
#define e_sav_name 0
|
||||
#define e_sav_length 1
|
||||
#define e_sav_operation 0
|
||||
#define e_sav_name 1
|
||||
#define e_sav_length 2
|
||||
|
||||
#define e_mod_statement 0
|
||||
#define e_mod_sub_mod 1
|
||||
|
@ -27,7 +27,6 @@ NODE(nod_asn_list, asn_list, "")
|
||||
NODE(nod_dcl_variable, declare, "")
|
||||
NODE(nod_erase, erase, "")
|
||||
NODE(nod_user_savepoint, user_savepoint, "SAVEPOINT")
|
||||
NODE(nod_undo_savepoint, undo_savepoint, "ROLLBACK TO SAVEPOINT")
|
||||
NODE(nod_fetch, fetch, "")
|
||||
NODE(nod_for, for, "")
|
||||
NODE(nod_handler, handler, "")
|
||||
|
@ -34,7 +34,7 @@
|
||||
*
|
||||
*/
|
||||
/*
|
||||
$Id: par.cpp,v 1.41 2003-04-10 06:49:14 aafemt Exp $
|
||||
$Id: par.cpp,v 1.42 2003-06-10 13:40:19 dimitr Exp $
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
@ -2411,11 +2411,11 @@ static JRD_NOD parse(TDBB tdbb, CSB * csb, USHORT expected)
|
||||
case blr_start_savepoint:
|
||||
case blr_end_savepoint:
|
||||
break;
|
||||
|
||||
|
||||
case blr_user_savepoint:
|
||||
case blr_undo_savepoint:
|
||||
*arg++ = (JRD_NOD) BLR_BYTE;
|
||||
par_name(csb, name);
|
||||
*arg++ = (JRD_NOD)ALL_cstring(name);
|
||||
*arg++ = (JRD_NOD) ALL_cstring(name);
|
||||
break;
|
||||
|
||||
case blr_store:
|
||||
|
Loading…
Reference in New Issue
Block a user