8
0
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:
dimitr 2003-06-10 13:40:19 +00:00
parent a092329cf7
commit 112c7022b6
14 changed files with 3970 additions and 3913 deletions

View File

@ -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

View File

@ -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;

View File

@ -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},

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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); }

View File

@ -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 */

View File

@ -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_ */

View File

@ -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),

View File

@ -2412,7 +2412,6 @@ static JRD_NOD copy(
break;
case nod_user_savepoint:
case nod_undo_savepoint:
args = e_sav_length;
break;

View File

@ -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;

View File

@ -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

View File

@ -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, "")

View File

@ -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: