mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 18:43:03 +01:00
1. Reworked internal_info implementation in both DSQL and JRD.
New helper class created to serve it properly. 2. Added exception re-raise semantics. Syntax: EXCEPTION; If there was handled exception, re-initiate it, otherwise evaluate to no-op. 3. Implemented run-time exception messages. Syntax: EXCEPTION <exception_name> [<value>]; If <value> is specified, evaluate it and use instead of RDB$EXCEPTION_MESSAGE. 4. Added new SQLCODE and GDSCODE system variables. Available in procedures/triggers only. If there wasn't any exception raised, return zero (success), otherwise return an error code. 5. Implemented ROWS_AFFECTED system variable. Available in procedures/triggers only. Count rows affected by the last INSERT/UPDATE/DELETE statement. For any other statement, result is always zero.
This commit is contained in:
parent
6a497e85f9
commit
536d8c0552
@ -29,7 +29,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
$Id: dsql.cpp,v 1.23 2002-09-25 17:12:06 skidder Exp $
|
$Id: dsql.cpp,v 1.24 2002-09-28 14:03:39 dimitr Exp $
|
||||||
*/
|
*/
|
||||||
/**************************************************************
|
/**************************************************************
|
||||||
V4 Multi-threading changes.
|
V4 Multi-threading changes.
|
||||||
@ -2046,6 +2046,7 @@ void DSQL_pretty(NOD node, int column)
|
|||||||
verb = "insert";
|
verb = "insert";
|
||||||
break;
|
break;
|
||||||
case nod_internal_info:
|
case nod_internal_info:
|
||||||
|
case nod_proc_internal_info:
|
||||||
verb = "internal info";
|
verb = "internal info";
|
||||||
break;
|
break;
|
||||||
case nod_join:
|
case nod_join:
|
||||||
|
@ -246,3 +246,4 @@
|
|||||||
#define USING 502
|
#define USING 502
|
||||||
#define NULLS 503
|
#define NULLS 503
|
||||||
#define LAST 504
|
#define LAST 504
|
||||||
|
#define ROWS_AFFECTED 505
|
||||||
|
@ -20,12 +20,14 @@
|
|||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
* Contributor(s): ______________________________________
|
* Contributor(s): ______________________________________
|
||||||
* 2001.6.21 Claudio Valderrama: BREAK and SUBSTRING.
|
* 2001.6.21 Claudio Valderrama: BREAK and SUBSTRING.
|
||||||
* 2001.07.28: John Bellardo: Added code to generate blr_skip.
|
* 2001.07.28 John Bellardo: Added code to generate blr_skip.
|
||||||
* 2002.07.30: Arno Brinkman: Added code, procedures to generate COALESCE, CASE
|
* 2002.07.30 Arno Brinkman: Added code, procedures to generate COALESCE, CASE
|
||||||
*
|
* 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
|
||||||
|
* exception handling in SPs/triggers,
|
||||||
|
* implemented ROWS_AFFECTED system variable
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
$Id: gen.cpp,v 1.11 2002-09-25 17:12:06 skidder Exp $
|
$Id: gen.cpp,v 1.12 2002-09-28 14:03:39 dimitr Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "firebird.h"
|
#include "firebird.h"
|
||||||
@ -43,6 +45,7 @@ $Id: gen.cpp,v 1.11 2002-09-25 17:12:06 skidder Exp $
|
|||||||
#include "../dsql/gen_proto.h"
|
#include "../dsql/gen_proto.h"
|
||||||
#include "../dsql/make_proto.h"
|
#include "../dsql/make_proto.h"
|
||||||
#include "../dsql/metd_proto.h"
|
#include "../dsql/metd_proto.h"
|
||||||
|
#include "../dsql/misc_func.h"
|
||||||
#include "../jrd/thd_proto.h"
|
#include "../jrd/thd_proto.h"
|
||||||
#include "../jrd/dsc_proto.h"
|
#include "../jrd/dsc_proto.h"
|
||||||
#include "gen/iberror.h"
|
#include "gen/iberror.h"
|
||||||
@ -83,15 +86,6 @@ static CONST SCHAR db_key_name[] = "DB_KEY";
|
|||||||
#define NEGATE_VALUE TRUE
|
#define NEGATE_VALUE TRUE
|
||||||
#define USE_VALUE FALSE
|
#define USE_VALUE FALSE
|
||||||
|
|
||||||
/* Internal info request types */
|
|
||||||
|
|
||||||
enum internal_info_req
|
|
||||||
{
|
|
||||||
connection_id = 1,
|
|
||||||
transaction_id = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
UCHAR GEN_expand_buffer( REQ request, UCHAR byte)
|
UCHAR GEN_expand_buffer( REQ request, UCHAR byte)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
@ -440,6 +434,7 @@ void GEN_expr( REQ request, NOD node)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case nod_internal_info:
|
case nod_internal_info:
|
||||||
|
case nod_proc_internal_info:
|
||||||
operator_ = blr_internal_info;
|
operator_ = blr_internal_info;
|
||||||
break;
|
break;
|
||||||
case nod_upcase:
|
case nod_upcase:
|
||||||
@ -889,8 +884,7 @@ void GEN_statement( REQ request, NOD node)
|
|||||||
NOD temp, *ptr, *end;
|
NOD temp, *ptr, *end;
|
||||||
CTX context;
|
CTX context;
|
||||||
MSG message;
|
MSG message;
|
||||||
STR name;
|
STR name, string;
|
||||||
STR string;
|
|
||||||
TEXT *p;
|
TEXT *p;
|
||||||
ULONG id_length;
|
ULONG id_length;
|
||||||
|
|
||||||
@ -1048,8 +1042,8 @@ void GEN_statement( REQ request, NOD node)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case nod_breakleave:
|
case nod_breakleave:
|
||||||
STUFF (blr_leave);
|
STUFF(blr_leave);
|
||||||
STUFF ((int) node->nod_arg [e_break_number]);
|
STUFF((int) node->nod_arg[e_break_number]);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case nod_store:
|
case nod_store:
|
||||||
@ -1077,17 +1071,46 @@ void GEN_statement( REQ request, NOD node)
|
|||||||
|
|
||||||
case nod_exception_stmt:
|
case nod_exception_stmt:
|
||||||
STUFF(blr_abort);
|
STUFF(blr_abort);
|
||||||
STUFF(blr_exception);
|
string = (STR) node->nod_arg[e_xcp_name];
|
||||||
string = (STR) node->nod_arg[0];
|
temp = node->nod_arg[e_xcp_msg];
|
||||||
if (!(string->str_flags & STR_delimited_id)) {
|
/* if exception name is undefined,
|
||||||
|
it means we have re-initiate semantics here,
|
||||||
|
so blr_raise verb should be generated */
|
||||||
|
if (!string)
|
||||||
|
{
|
||||||
|
STUFF(blr_raise);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* if exception value is defined,
|
||||||
|
it means we have user-defined exception message here,
|
||||||
|
so blr_exception_msg verb should be generated */
|
||||||
|
if (temp)
|
||||||
|
{
|
||||||
|
STUFF(blr_exception_msg);
|
||||||
|
}
|
||||||
|
/* otherwise go usual way,
|
||||||
|
i.e. generate blr_exception */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
STUFF(blr_exception);
|
||||||
|
}
|
||||||
|
if (!(string->str_flags & STR_delimited_id))
|
||||||
|
{
|
||||||
id_length = string->str_length;
|
id_length = string->str_length;
|
||||||
for (p = reinterpret_cast < char *>(string->str_data); *p;
|
for (p = reinterpret_cast<char*>(string->str_data); *p;
|
||||||
id_length--) {
|
id_length--)
|
||||||
|
{
|
||||||
*p = UPPER(*p);
|
*p = UPPER(*p);
|
||||||
*p++;
|
*p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
STUFF_CSTRING(string->str_data);
|
STUFF_CSTRING(string->str_data);
|
||||||
|
/* if exception value is defined,
|
||||||
|
generate appropriate BLR verbs */
|
||||||
|
if (temp)
|
||||||
|
{
|
||||||
|
GEN_expr(request, temp);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case nod_while:
|
case nod_while:
|
||||||
@ -2198,20 +2221,11 @@ static void gen_select( REQ request, NOD rse)
|
|||||||
parameter->par_name = parameter->par_alias = "USER";
|
parameter->par_name = parameter->par_alias = "USER";
|
||||||
else if (item->nod_type == nod_current_role)
|
else if (item->nod_type == nod_current_role)
|
||||||
parameter->par_name = parameter->par_alias = "ROLE";
|
parameter->par_name = parameter->par_alias = "ROLE";
|
||||||
else if (item->nod_type == nod_internal_info)
|
else if (item->nod_type == nod_internal_info || item->nod_type == nod_proc_internal_info)
|
||||||
{
|
{
|
||||||
internal_info_req request =
|
internal_info_id id =
|
||||||
*reinterpret_cast<internal_info_req*>(item->nod_arg[0]->nod_desc.dsc_address);
|
*reinterpret_cast<internal_info_id*>(item->nod_arg[0]->nod_desc.dsc_address);
|
||||||
|
parameter->par_name = parameter->par_alias = InternalInfo::getAlias(id);
|
||||||
switch (request)
|
|
||||||
{
|
|
||||||
case connection_id:
|
|
||||||
parameter->par_name = parameter->par_alias = "CONNECTION_ID";
|
|
||||||
break;
|
|
||||||
case transaction_id:
|
|
||||||
parameter->par_name = parameter->par_alias = "TRANSACTION_ID";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (item->nod_type == nod_substr) {
|
else if (item->nod_type == nod_substr) {
|
||||||
/* CVC: SQL starts at 1 but C starts at zero. */
|
/* CVC: SQL starts at 1 but C starts at zero. */
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* $Id: keywords.cpp,v 1.7 2002-09-10 18:28:19 skidder Exp $
|
* $Id: keywords.cpp,v 1.8 2002-09-28 14:03:39 dimitr Exp $
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -232,6 +232,7 @@ static CONST TOK tokens [] = {
|
|||||||
{RIGHT, "RIGHT", 1},
|
{RIGHT, "RIGHT", 1},
|
||||||
{ROLE, "ROLE", 1},
|
{ROLE, "ROLE", 1},
|
||||||
{ROLLBACK, "ROLLBACK", 1},
|
{ROLLBACK, "ROLLBACK", 1},
|
||||||
|
{ROWS_AFFECTED, "ROWS_AFFECTED", 2},
|
||||||
{DATABASE, "SCHEMA", 1}, /* Alias of DATABASE */
|
{DATABASE, "SCHEMA", 1}, /* Alias of DATABASE */
|
||||||
{SECOND, "SECOND", 2},
|
{SECOND, "SECOND", 2},
|
||||||
{SEGMENT, "SEGMENT", 1},
|
{SEGMENT, "SEGMENT", 1},
|
||||||
|
@ -929,6 +929,7 @@ void MAKE_desc( DSC * desc, NOD node)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case nod_internal_info:
|
case nod_internal_info:
|
||||||
|
case nod_proc_internal_info:
|
||||||
desc->dsc_dtype = dtype_long;
|
desc->dsc_dtype = dtype_long;
|
||||||
desc->dsc_scale = 0;
|
desc->dsc_scale = 0;
|
||||||
desc->dsc_flags = 0;
|
desc->dsc_flags = 0;
|
||||||
|
40
src/dsql/misc_func.cpp
Normal file
40
src/dsql/misc_func.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* PROGRAM: Miscellaneous internal functions support (DSQL layer)
|
||||||
|
* MODULE: misc_func.cpp
|
||||||
|
* DESCRIPTION: DSQL helper.
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Interbase Public
|
||||||
|
* License Version 1.0 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy
|
||||||
|
* of the License at http://www.Inprise.com/IPL.html
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an
|
||||||
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code was created by Inprise Corporation
|
||||||
|
* and its predecessors. Portions created by Inprise Corporation are
|
||||||
|
* Copyright (C) Inprise Corporation.
|
||||||
|
*
|
||||||
|
* All Rights Reserved.
|
||||||
|
* Contributor(s): ______________________________________
|
||||||
|
*
|
||||||
|
* 2002.09.20 Dmitry Yemanov: Created all this stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../dsql/misc_func.h"
|
||||||
|
|
||||||
|
char* InternalInfo::alias_array[max_internal_id] = {
|
||||||
|
"<UNKNOWN>",
|
||||||
|
"CONNECTION_ID",
|
||||||
|
"TRANSACTION_ID",
|
||||||
|
"GDSCODE",
|
||||||
|
"SQLCODE",
|
||||||
|
"ROWS_AFFECTED"
|
||||||
|
};
|
||||||
|
|
||||||
|
char *InternalInfo::getAlias(internal_info_id info_id)
|
||||||
|
{
|
||||||
|
return alias_array[info_id];
|
||||||
|
}
|
38
src/dsql/misc_func.h
Normal file
38
src/dsql/misc_func.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* PROGRAM: Miscellaneous internal functions support (DSQL layer)
|
||||||
|
* MODULE: misc_func.h
|
||||||
|
* DESCRIPTION: DSQL helper.
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Interbase Public
|
||||||
|
* License Version 1.0 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy
|
||||||
|
* of the License at http://www.Inprise.com/IPL.html
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an
|
||||||
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code was created by Inprise Corporation
|
||||||
|
* and its predecessors. Portions created by Inprise Corporation are
|
||||||
|
* Copyright (C) Inprise Corporation.
|
||||||
|
*
|
||||||
|
* All Rights Reserved.
|
||||||
|
* Contributor(s): ______________________________________
|
||||||
|
*
|
||||||
|
* 2002.09.20 Dmitry Yemanov: Created all this stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DSQL_MISC_FUNC_H_
|
||||||
|
#define _DSQL_MISC_FUNC_H_
|
||||||
|
|
||||||
|
#include "../jrd/misc_func_ids.h"
|
||||||
|
|
||||||
|
class InternalInfo {
|
||||||
|
private:
|
||||||
|
static char *alias_array[max_internal_id];
|
||||||
|
public:
|
||||||
|
static char *getAlias(internal_info_id);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _DSQL_MISC_FUNC_H_
|
@ -315,6 +315,7 @@ typedef ENUM nod_t
|
|||||||
nod_redef_procedure, /* allows silent creation/overwriting of a procedure. */
|
nod_redef_procedure, /* allows silent creation/overwriting of a procedure. */
|
||||||
nod_exec_sql, /* EXECUTE VARCHAR */
|
nod_exec_sql, /* EXECUTE VARCHAR */
|
||||||
nod_internal_info, /* internal engine info */
|
nod_internal_info, /* internal engine info */
|
||||||
|
nod_proc_internal_info,
|
||||||
nod_searched_case, /* searched CASE function */
|
nod_searched_case, /* searched CASE function */
|
||||||
nod_simple_case, /* simple CASE function */
|
nod_simple_case, /* simple CASE function */
|
||||||
nod_coalesce, /* COALESCE function */
|
nod_coalesce, /* COALESCE function */
|
||||||
@ -436,6 +437,10 @@ typedef nod *NOD;
|
|||||||
#define e_internal_info 0 /* nod_internal_info */
|
#define e_internal_info 0 /* nod_internal_info */
|
||||||
#define e_internal_info_count 1
|
#define e_internal_info_count 1
|
||||||
|
|
||||||
|
#define e_xcp_name 0 /* nod_exception_stmt */
|
||||||
|
#define e_xcp_msg 1
|
||||||
|
#define e_xcp_count 2
|
||||||
|
|
||||||
#define e_rtn_procedure 0 /* nod_procedure */
|
#define e_rtn_procedure 0 /* nod_procedure */
|
||||||
#define e_rtn_count 1
|
#define e_rtn_count 1
|
||||||
|
|
||||||
|
6905
src/dsql/parse.cpp
6905
src/dsql/parse.cpp
File diff suppressed because it is too large
Load Diff
@ -51,9 +51,11 @@
|
|||||||
* 2002.08.07 Dmitry Yemanov: INT64/LARGEINT are replaced with BIGINT and available in dialect 3 only
|
* 2002.08.07 Dmitry Yemanov: INT64/LARGEINT are replaced with BIGINT and available in dialect 3 only
|
||||||
* 2002.08.31 Dmitry Yemanov: allowed user-defined index names for PK/FK/UK constraints
|
* 2002.08.31 Dmitry Yemanov: allowed user-defined index names for PK/FK/UK constraints
|
||||||
* 2002.09.01 Dmitry Yemanov: RECREATE VIEW
|
* 2002.09.01 Dmitry Yemanov: RECREATE VIEW
|
||||||
|
* 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
|
||||||
|
* exception handling in SPs/triggers,
|
||||||
|
* implemented ROWS_AFFECTED system variable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#if defined(DEV_BUILD) && defined(WIN32) && defined(SUPERSERVER)
|
#if defined(DEV_BUILD) && defined(WIN32) && defined(SUPERSERVER)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
/*#include <wincon.h>*/
|
/*#include <wincon.h>*/
|
||||||
@ -78,9 +80,9 @@
|
|||||||
#include "../dsql/make_proto.h"
|
#include "../dsql/make_proto.h"
|
||||||
#include "../dsql/parse_proto.h"
|
#include "../dsql/parse_proto.h"
|
||||||
#include "../dsql/keywords.h"
|
#include "../dsql/keywords.h"
|
||||||
|
#include "../dsql/misc_func.h"
|
||||||
#include "../jrd/gds_proto.h"
|
#include "../jrd/gds_proto.h"
|
||||||
#include "../jrd/thd_proto.h"
|
#include "../jrd/thd_proto.h"
|
||||||
/* #include "../jrd/err_proto.h" */
|
|
||||||
#include "../wal/wal.h"
|
#include "../wal/wal.h"
|
||||||
|
|
||||||
/* Can't include ../jrd/err_proto.h here because it pulls jrd.h. */
|
/* Can't include ../jrd/err_proto.h here because it pulls jrd.h. */
|
||||||
@ -408,6 +410,7 @@ static void yyerror (TEXT *);
|
|||||||
%token USING
|
%token USING
|
||||||
%token NULLS
|
%token NULLS
|
||||||
%token LAST
|
%token LAST
|
||||||
|
%token ROWS_AFFECTED
|
||||||
|
|
||||||
/* precedence declarations for expression evaluation */
|
/* precedence declarations for expression evaluation */
|
||||||
|
|
||||||
@ -1434,21 +1437,16 @@ proc_block : proc_statement
|
|||||||
| full_proc_block
|
| full_proc_block
|
||||||
;
|
;
|
||||||
|
|
||||||
full_proc_block : BEGIN
|
full_proc_block : BEGIN full_proc_block_body END
|
||||||
END
|
{ $$ = $2; }
|
||||||
{ $$ = make_node (nod_block, e_blk_count,
|
;
|
||||||
NULL, NULL);}
|
|
||||||
| BEGIN
|
full_proc_block_body : proc_statements
|
||||||
proc_statements
|
{ $$ = make_node (nod_block, e_blk_count, make_list ($1), NULL); }
|
||||||
END
|
| proc_statements excp_hndl_statements
|
||||||
{ $$ = make_node (nod_block, e_blk_count,
|
{ $$ = make_node (nod_block, e_blk_count, make_list ($1), make_list ($2)); }
|
||||||
make_list ($2), NULL);}
|
|
|
||||||
| BEGIN
|
{ $$ = make_node (nod_block, e_blk_count, NULL, NULL);}
|
||||||
proc_statements
|
|
||||||
excp_statements
|
|
||||||
END
|
|
||||||
{ $$ = make_node (nod_block, e_blk_count,
|
|
||||||
make_list ($2), make_list ($3));}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
proc_statements : proc_block
|
proc_statements : proc_block
|
||||||
@ -1458,8 +1456,8 @@ proc_statements : proc_block
|
|||||||
|
|
||||||
proc_statement : assignment ';'
|
proc_statement : assignment ';'
|
||||||
| delete ';'
|
| delete ';'
|
||||||
| EXCEPTION symbol_exception_name ';'
|
| excp_statement
|
||||||
{ $$ = make_node (nod_exception_stmt, 1, $2); }
|
| raise_statement
|
||||||
| exec_procedure
|
| exec_procedure
|
||||||
| exec_sql
|
| exec_sql
|
||||||
| for_select
|
| for_select
|
||||||
@ -1478,6 +1476,16 @@ proc_statement : assignment ';'
|
|||||||
{ $$ = make_node (nod_breakleave, e_break_count, NULL); }
|
{ $$ = make_node (nod_breakleave, e_break_count, NULL); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
excp_statement : EXCEPTION symbol_exception_name ';'
|
||||||
|
{ $$ = make_node (nod_exception_stmt, e_xcp_count, $2, NULL); }
|
||||||
|
| EXCEPTION symbol_exception_name value ';'
|
||||||
|
{ $$ = make_node (nod_exception_stmt, e_xcp_count, $2, $3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
raise_statement : EXCEPTION ';'
|
||||||
|
{ $$ = make_node (nod_exception_stmt, e_xcp_count, NULL, NULL); }
|
||||||
|
;
|
||||||
|
|
||||||
exec_procedure : EXECUTE PROCEDURE symbol_procedure_name proc_inputs proc_outputs ';'
|
exec_procedure : EXECUTE PROCEDURE symbol_procedure_name proc_inputs proc_outputs ';'
|
||||||
{ $$ = make_node (nod_exec_procedure, e_exe_count, $3,
|
{ $$ = make_node (nod_exec_procedure, e_exe_count, $3,
|
||||||
$4, $5); }
|
$4, $5); }
|
||||||
@ -1542,12 +1550,12 @@ cursor_def : AS CURSOR symbol_cursor_name
|
|||||||
|
|
|
|
||||||
{ $$ = NULL; }
|
{ $$ = NULL; }
|
||||||
;
|
;
|
||||||
excp_statements : excp_statement
|
excp_hndl_statements : excp_hndl_statement
|
||||||
| excp_statements excp_statement
|
| excp_hndl_statements excp_hndl_statement
|
||||||
{ $$ = make_node (nod_list, 2, $1, $2); }
|
{ $$ = make_node (nod_list, 2, $1, $2); }
|
||||||
;
|
;
|
||||||
|
|
||||||
excp_statement : WHEN errors DO proc_block
|
excp_hndl_statement : WHEN errors DO proc_block
|
||||||
{ $$ = make_node (nod_on_error, e_err_count,
|
{ $$ = make_node (nod_on_error, e_err_count,
|
||||||
make_list ($2), $4); }
|
make_list ($2), $4); }
|
||||||
;
|
;
|
||||||
@ -3319,6 +3327,8 @@ value : column_name
|
|||||||
| current_role
|
| current_role
|
||||||
| internal_info
|
| internal_info
|
||||||
{ $$ = $1; }
|
{ $$ = $1; }
|
||||||
|
| proc_internal_info
|
||||||
|
{ $$ = $1; }
|
||||||
| DB_KEY
|
| DB_KEY
|
||||||
{ $$ = make_node (nod_dbkey, 1, NULL); }
|
{ $$ = make_node (nod_dbkey, 1, NULL); }
|
||||||
| symbol_table_alias_name '.' DB_KEY
|
| symbol_table_alias_name '.' DB_KEY
|
||||||
@ -3433,24 +3443,6 @@ u_constant : u_numeric_constant
|
|||||||
{ $$ = MAKE_constant ((STR) $2, CONSTANT_TIMESTAMP); }
|
{ $$ = MAKE_constant ((STR) $2, CONSTANT_TIMESTAMP); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
constant_list : constant
|
|
||||||
| parameter
|
|
||||||
| current_user
|
|
||||||
| current_role
|
|
||||||
| internal_info
|
|
||||||
| constant_list ',' constant
|
|
||||||
{ $$ = make_node (nod_list, 2, $1, $3); }
|
|
||||||
| constant_list ',' parameter
|
|
||||||
{ $$ = make_node (nod_list, 2, $1, $3); }
|
|
||||||
| constant_list ',' current_user
|
|
||||||
{ $$ = make_node (nod_list, 2, $1, $3); }
|
|
||||||
| constant_list ',' current_role
|
|
||||||
{ $$ = make_node (nod_list, 2, $1, $3); }
|
|
||||||
| constant_list ',' internal_info
|
|
||||||
{ $$ = make_node (nod_list, 2, $1, $3); }
|
|
||||||
;
|
|
||||||
|
|
||||||
parameter : '?'
|
parameter : '?'
|
||||||
{ $$ = make_node (nod_parameter, 0, NULL); }
|
{ $$ = make_node (nod_parameter, 0, NULL); }
|
||||||
;
|
;
|
||||||
@ -3467,10 +3459,21 @@ current_role : CURRENT_ROLE
|
|||||||
|
|
||||||
internal_info : CONNECTION_ID
|
internal_info : CONNECTION_ID
|
||||||
{ $$ = make_node (nod_internal_info, e_internal_info_count,
|
{ $$ = make_node (nod_internal_info, e_internal_info_count,
|
||||||
MAKE_constant ((STR) 1, CONSTANT_SLONG)); }
|
MAKE_constant ((STR) internal_connection_id, CONSTANT_SLONG)); }
|
||||||
| TRANSACTION_ID
|
| TRANSACTION_ID
|
||||||
{ $$ = make_node (nod_internal_info, e_internal_info_count,
|
{ $$ = make_node (nod_internal_info, e_internal_info_count,
|
||||||
MAKE_constant ((STR) 2, CONSTANT_SLONG)); }
|
MAKE_constant ((STR) internal_transaction_id, CONSTANT_SLONG)); }
|
||||||
|
;
|
||||||
|
|
||||||
|
proc_internal_info : GDSCODE
|
||||||
|
{ $$ = make_node (nod_proc_internal_info, e_internal_info_count,
|
||||||
|
MAKE_constant ((STR) internal_gdscode, CONSTANT_SLONG)); }
|
||||||
|
| SQLCODE
|
||||||
|
{ $$ = make_node (nod_proc_internal_info, e_internal_info_count,
|
||||||
|
MAKE_constant ((STR) internal_sqlcode, CONSTANT_SLONG)); }
|
||||||
|
| ROWS_AFFECTED
|
||||||
|
{ $$ = make_node (nod_proc_internal_info, e_internal_info_count,
|
||||||
|
MAKE_constant ((STR) internal_rows_affected, CONSTANT_SLONG)); }
|
||||||
;
|
;
|
||||||
|
|
||||||
sql_string : STRING /* string in current charset */
|
sql_string : STRING /* string in current charset */
|
||||||
|
@ -95,6 +95,10 @@
|
|||||||
* 2002.08.07 Dmitry Yemanov: Disabled BREAK statement in triggers
|
* 2002.08.07 Dmitry Yemanov: Disabled BREAK statement in triggers
|
||||||
*
|
*
|
||||||
* 2002.08.10 Dmitry Yemanov: ALTER VIEW
|
* 2002.08.10 Dmitry Yemanov: ALTER VIEW
|
||||||
|
*
|
||||||
|
* 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
|
||||||
|
* exception handling in SPs/triggers,
|
||||||
|
* implemented ROWS_AFFECTED system variable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "firebird.h"
|
#include "firebird.h"
|
||||||
@ -116,6 +120,7 @@
|
|||||||
#include "../dsql/make_proto.h"
|
#include "../dsql/make_proto.h"
|
||||||
#include "../dsql/metd_proto.h"
|
#include "../dsql/metd_proto.h"
|
||||||
#include "../dsql/pass1_proto.h"
|
#include "../dsql/pass1_proto.h"
|
||||||
|
#include "../dsql/misc_func.h"
|
||||||
#include "../jrd/dsc_proto.h"
|
#include "../jrd/dsc_proto.h"
|
||||||
#include "../jrd/thd_proto.h"
|
#include "../jrd/thd_proto.h"
|
||||||
|
|
||||||
@ -753,6 +758,16 @@ NOD PASS1_node(REQ request, NOD input, USHORT proc_flag)
|
|||||||
node->nod_desc = input->nod_desc;
|
node->nod_desc = input->nod_desc;
|
||||||
return node;
|
return node;
|
||||||
|
|
||||||
|
case nod_proc_internal_info:
|
||||||
|
{
|
||||||
|
internal_info_id id =
|
||||||
|
*reinterpret_cast<internal_info_id*>(input->nod_arg[0]->nod_desc.dsc_address);
|
||||||
|
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, InternalInfo::getAlias(id), 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1173,7 +1188,20 @@ NOD PASS1_statement(REQ request, NOD input, USHORT proc_flag)
|
|||||||
|
|
||||||
case nod_exception_stmt:
|
case nod_exception_stmt:
|
||||||
node = input;
|
node = input;
|
||||||
if (request->req_error_handlers) {
|
/* if exception value is defined,
|
||||||
|
pass value node */
|
||||||
|
if (input->nod_arg[e_xcp_msg])
|
||||||
|
{
|
||||||
|
node->nod_arg[e_xcp_msg] = PASS1_node(request,
|
||||||
|
input->nod_arg[e_xcp_msg],
|
||||||
|
proc_flag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node->nod_arg[e_xcp_msg] = 0;
|
||||||
|
}
|
||||||
|
if (request->req_error_handlers)
|
||||||
|
{
|
||||||
temp = MAKE_node(nod_list, 3);
|
temp = MAKE_node(nod_list, 3);
|
||||||
temp->nod_arg[0] = MAKE_node(nod_start_savepoint, 0);
|
temp->nod_arg[0] = MAKE_node(nod_start_savepoint, 0);
|
||||||
temp->nod_arg[1] = input;
|
temp->nod_arg[1] = input;
|
||||||
@ -1756,6 +1784,7 @@ static NOD copy_field( NOD field, CTX context)
|
|||||||
case nod_subtract2:
|
case nod_subtract2:
|
||||||
case nod_upcase:
|
case nod_upcase:
|
||||||
case nod_internal_info:
|
case nod_internal_info:
|
||||||
|
case nod_proc_internal_info:
|
||||||
case nod_extract:
|
case nod_extract:
|
||||||
case nod_list:
|
case nod_list:
|
||||||
temp = MAKE_node(field->nod_type, field->nod_count);
|
temp = MAKE_node(field->nod_type, field->nod_count);
|
||||||
@ -2254,6 +2283,7 @@ static BOOLEAN invalid_reference(REQ request, NOD node, NOD list, BOOLEAN exact_
|
|||||||
case nod_user_name:
|
case nod_user_name:
|
||||||
case nod_current_role:
|
case nod_current_role:
|
||||||
case nod_internal_info:
|
case nod_internal_info:
|
||||||
|
case nod_proc_internal_info:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,9 @@
|
|||||||
* Contributor(s): ______________________________________.
|
* Contributor(s): ______________________________________.
|
||||||
*
|
*
|
||||||
* Claudio Valderrama: 2001.6.18: Add blr_current_role.
|
* Claudio Valderrama: 2001.6.18: Add blr_current_role.
|
||||||
|
* 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
|
||||||
|
* exception handling in SPs/triggers,
|
||||||
|
* implemented ROWS_AFFECTED system variable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _JRD_BLR_H_
|
#ifndef _JRD_BLR_H_
|
||||||
@ -65,6 +68,8 @@
|
|||||||
#define blr_exception (unsigned char)2
|
#define blr_exception (unsigned char)2
|
||||||
#define blr_trigger_code (unsigned char)3
|
#define blr_trigger_code (unsigned char)3
|
||||||
#define blr_default_code (unsigned char)4
|
#define blr_default_code (unsigned char)4
|
||||||
|
#define blr_raise (unsigned char)5
|
||||||
|
#define blr_exception_msg (unsigned char)6
|
||||||
|
|
||||||
#define blr_version4 (unsigned char)4
|
#define blr_version4 (unsigned char)4
|
||||||
#define blr_version5 (unsigned char)5
|
#define blr_version5 (unsigned char)5
|
||||||
|
@ -28,9 +28,12 @@
|
|||||||
* if source is blob and should check implementation limits on field lengths.
|
* if source is blob and should check implementation limits on field lengths.
|
||||||
* 2002.02.25 Claudio Valderrama: concatenate() should be a civilized function.
|
* 2002.02.25 Claudio Valderrama: concatenate() should be a civilized function.
|
||||||
* This closes the heart of SF Bug #518282.
|
* This closes the heart of SF Bug #518282.
|
||||||
|
* 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
|
||||||
|
* exception handling in SPs/triggers,
|
||||||
|
* implemented ROWS_AFFECTED system variable
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
$Id: cmp.cpp,v 1.13 2002-09-27 22:59:23 skidder Exp $
|
$Id: cmp.cpp,v 1.14 2002-09-28 14:04:34 dimitr Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "firebird.h"
|
#include "firebird.h"
|
||||||
@ -299,6 +302,9 @@ REQ DLL_EXPORT CMP_clone_request(TDBB tdbb,
|
|||||||
clone->req_top_node = request->req_top_node;
|
clone->req_top_node = request->req_top_node;
|
||||||
clone->req_trg_name = request->req_trg_name;
|
clone->req_trg_name = request->req_trg_name;
|
||||||
clone->req_flags = request->req_flags & REQ_FLAGS_CLONE_MASK;
|
clone->req_flags = request->req_flags & REQ_FLAGS_CLONE_MASK;
|
||||||
|
clone->req_last_xcp.xcp_type = request->req_last_xcp.xcp_type;
|
||||||
|
clone->req_last_xcp.xcp_code = request->req_last_xcp.xcp_code;
|
||||||
|
clone->req_last_xcp.xcp_msg = request->req_last_xcp.xcp_msg;
|
||||||
|
|
||||||
rpb1 = clone->req_rpb;
|
rpb1 = clone->req_rpb;
|
||||||
end = rpb1 + clone->req_count;
|
end = rpb1 + clone->req_count;
|
||||||
@ -1736,6 +1742,8 @@ REQ DLL_EXPORT CMP_make_request(TDBB tdbb, CSB * csb_ptr)
|
|||||||
request->req_access = csb->csb_access;
|
request->req_access = csb->csb_access;
|
||||||
request->req_variables = csb->csb_variables;
|
request->req_variables = csb->csb_variables;
|
||||||
request->req_resources = csb->csb_resources;
|
request->req_resources = csb->csb_resources;
|
||||||
|
request->req_last_xcp.xcp_type = 0;
|
||||||
|
request->req_last_xcp.xcp_msg = 0;
|
||||||
if (csb->csb_g_flags & csb_blr_version4) {
|
if (csb->csb_g_flags & csb_blr_version4) {
|
||||||
request->req_flags |= req_blr_version4;
|
request->req_flags |= req_blr_version4;
|
||||||
}
|
}
|
||||||
@ -2151,6 +2159,8 @@ void DLL_EXPORT CMP_release(TDBB tdbb, REQ request)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete request->req_last_xcp.xcp_msg;
|
||||||
|
|
||||||
delete request->req_pool;
|
delete request->req_pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
*
|
*
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
* Contributor(s): ______________________________________.
|
* Contributor(s): ______________________________________.
|
||||||
* $Id: evl.cpp,v 1.17 2002-09-27 01:28:26 bellardo Exp $
|
* $Id: evl.cpp,v 1.18 2002-09-28 14:04:35 dimitr Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -54,6 +54,9 @@
|
|||||||
* 2002.2.15 Claudio Valderrama: divide2() should not mangle negative values.
|
* 2002.2.15 Claudio Valderrama: divide2() should not mangle negative values.
|
||||||
* 2002.04.16 Paul Beach HP10 Port - (UCHAR*) desc.dsc_address = p; modified for HP
|
* 2002.04.16 Paul Beach HP10 Port - (UCHAR*) desc.dsc_address = p; modified for HP
|
||||||
* Compiler
|
* Compiler
|
||||||
|
* 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
|
||||||
|
* exception handling in SPs/triggers,
|
||||||
|
* implemented ROWS_AFFECTED system variable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "firebird.h"
|
#include "firebird.h"
|
||||||
@ -105,6 +108,7 @@
|
|||||||
#include "../jrd/align.h"
|
#include "../jrd/align.h"
|
||||||
#include "../jrd/met_proto.h"
|
#include "../jrd/met_proto.h"
|
||||||
#include "../jrd/cvt_proto.h"
|
#include "../jrd/cvt_proto.h"
|
||||||
|
#include "../jrd/misc_func_ids.h"
|
||||||
//#include "../jrd/authenticate.h"
|
//#include "../jrd/authenticate.h"
|
||||||
|
|
||||||
#if defined(WIN_NT) && defined(_MSC_VER)
|
#if defined(WIN_NT) && defined(_MSC_VER)
|
||||||
@ -126,15 +130,6 @@
|
|||||||
extern double MTH$CVT_D_G(), MTH$CVT_G_D();
|
extern double MTH$CVT_D_G(), MTH$CVT_G_D();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Internal info request types */
|
|
||||||
|
|
||||||
enum internal_info_req
|
|
||||||
{
|
|
||||||
connection_id = 1,
|
|
||||||
transaction_id = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* *** DANGER DANGER WILL ROBINSON ***
|
/* *** DANGER DANGER WILL ROBINSON ***
|
||||||
* add(), multiply(), and divide() all take the same three arguments, but
|
* add(), multiply(), and divide() all take the same three arguments, but
|
||||||
* they don't all take them in the same order. Be careful out there.
|
* they don't all take them in the same order. Be careful out there.
|
||||||
@ -3931,7 +3926,6 @@ static DSC *lock_state(TDBB tdbb, NOD node, VLU impure)
|
|||||||
struct lck temp_lock;
|
struct lck temp_lock;
|
||||||
/* fill out a lock block, zeroing it out first */
|
/* fill out a lock block, zeroing it out first */
|
||||||
|
|
||||||
MOVE_CLEAR(&temp_lock, sizeof(struct lck));
|
|
||||||
temp_lock.lck_parent = dbb->dbb_lock;
|
temp_lock.lck_parent = dbb->dbb_lock;
|
||||||
temp_lock.lck_type = LCK_attachment;
|
temp_lock.lck_type = LCK_attachment;
|
||||||
temp_lock.lck_owner_handle =
|
temp_lock.lck_owner_handle =
|
||||||
@ -5035,17 +5029,30 @@ static DSC *internal_info(TDBB tdbb, DSC * value, VLU impure)
|
|||||||
**************************************/
|
**************************************/
|
||||||
EVL_make_value(tdbb, value, impure);
|
EVL_make_value(tdbb, value, impure);
|
||||||
|
|
||||||
internal_info_req request =
|
internal_info_id id =
|
||||||
*reinterpret_cast<internal_info_req*>(impure->vlu_desc.dsc_address);
|
*reinterpret_cast<internal_info_id*>(impure->vlu_desc.dsc_address);
|
||||||
|
|
||||||
switch (request)
|
switch (id)
|
||||||
{
|
{
|
||||||
case connection_id:
|
case internal_connection_id:
|
||||||
impure->vlu_misc.vlu_long = PAG_attachment_id();
|
impure->vlu_misc.vlu_long = PAG_attachment_id();
|
||||||
break;
|
break;
|
||||||
case transaction_id:
|
case internal_transaction_id:
|
||||||
impure->vlu_misc.vlu_long = tdbb->tdbb_transaction->tra_number;
|
impure->vlu_misc.vlu_long = tdbb->tdbb_transaction->tra_number;
|
||||||
break;
|
break;
|
||||||
|
case internal_gdscode:
|
||||||
|
impure->vlu_misc.vlu_long =
|
||||||
|
(tdbb->tdbb_request->req_last_xcp.xcp_type == xcp_gds_code) ?
|
||||||
|
tdbb->tdbb_request->req_last_xcp.xcp_code : 0;
|
||||||
|
break;
|
||||||
|
case internal_sqlcode:
|
||||||
|
impure->vlu_misc.vlu_long =
|
||||||
|
(tdbb->tdbb_request->req_last_xcp.xcp_type == xcp_sql_code) ?
|
||||||
|
tdbb->tdbb_request->req_last_xcp.xcp_code : 0;
|
||||||
|
break;
|
||||||
|
case internal_rows_affected:
|
||||||
|
impure->vlu_misc.vlu_long = tdbb->tdbb_request->req_records_affected;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
BUGCHECK(232); /* msg 232 EVL_expr: invalid operation */
|
BUGCHECK(232); /* msg 232 EVL_expr: invalid operation */
|
||||||
}
|
}
|
||||||
|
163
src/jrd/exe.cpp
163
src/jrd/exe.cpp
@ -29,9 +29,12 @@
|
|||||||
* being reported instead of one.
|
* being reported instead of one.
|
||||||
* 2001.12.03 Claudio Valderrama: new visit to the same issue: views need
|
* 2001.12.03 Claudio Valderrama: new visit to the same issue: views need
|
||||||
* to count virtual operations, not real I/O on the underlying tables.
|
* to count virtual operations, not real I/O on the underlying tables.
|
||||||
|
* 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
|
||||||
|
* exception handling in SPs/triggers,
|
||||||
|
* implemented ROWS_AFFECTED system variable
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
$Id: exe.cpp,v 1.19 2002-09-27 01:28:26 bellardo Exp $
|
$Id: exe.cpp,v 1.20 2002-09-28 14:04:35 dimitr Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "firebird.h"
|
#include "firebird.h"
|
||||||
@ -129,10 +132,10 @@ static void seek_rsb(TDBB, REQ, RSB, USHORT, SLONG);
|
|||||||
#endif
|
#endif
|
||||||
static NOD selct(TDBB, register NOD);
|
static NOD selct(TDBB, register NOD);
|
||||||
static NOD send_msg(TDBB, register NOD);
|
static NOD send_msg(TDBB, register NOD);
|
||||||
static void set_error(TDBB, XCP);
|
static void set_error(TDBB, XCP, NOD);
|
||||||
static NOD stall(TDBB, register NOD);
|
static NOD stall(TDBB, register NOD);
|
||||||
static NOD store(TDBB, register NOD, SSHORT);
|
static NOD store(TDBB, register NOD, SSHORT);
|
||||||
static BOOLEAN test_error(TDBB, const XCP);
|
static BOOLEAN test_and_fixup_error(TDBB, const XCP, REQ);
|
||||||
static void trigger_failure(TDBB, REQ);
|
static void trigger_failure(TDBB, REQ);
|
||||||
static void validate(TDBB, NOD);
|
static void validate(TDBB, NOD);
|
||||||
|
|
||||||
@ -215,7 +218,6 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void EXE_assignment(TDBB tdbb, NOD node)
|
void EXE_assignment(TDBB tdbb, NOD node)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
@ -1234,10 +1236,12 @@ static NOD erase(TDBB tdbb, NOD node, SSHORT which_trig)
|
|||||||
if (relation == request->req_top_view_erase) {
|
if (relation == request->req_top_view_erase) {
|
||||||
if (which_trig == ALL_TRIGS || which_trig == POST_TRIG) {
|
if (which_trig == ALL_TRIGS || which_trig == POST_TRIG) {
|
||||||
request->req_records_deleted++;
|
request->req_records_deleted++;
|
||||||
|
request->req_records_affected++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (relation->rel_file || !relation->rel_view_rse) {
|
else if (relation->rel_file || !relation->rel_view_rse) {
|
||||||
request->req_records_deleted++;
|
request->req_records_deleted++;
|
||||||
|
request->req_records_affected++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transaction != dbb->dbb_sys_trans) {
|
if (transaction != dbb->dbb_sys_trans) {
|
||||||
@ -1293,6 +1297,7 @@ static void execute_looper(
|
|||||||
|
|
||||||
request->req_flags &= ~req_stall;
|
request->req_flags &= ~req_stall;
|
||||||
request->req_operation = next_state;
|
request->req_operation = next_state;
|
||||||
|
|
||||||
looper(tdbb, request, request->req_next);
|
looper(tdbb, request, request->req_next);
|
||||||
|
|
||||||
/* If any requested modify/delete/insert ops have completed, forget them */
|
/* If any requested modify/delete/insert ops have completed, forget them */
|
||||||
@ -1806,6 +1811,8 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
|
|||||||
|
|
||||||
// Execute stuff until we drop
|
// Execute stuff until we drop
|
||||||
|
|
||||||
|
request->req_records_affected = 0;
|
||||||
|
|
||||||
while (node && !(request->req_flags & req_stall))
|
while (node && !(request->req_flags & req_stall))
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@ -1820,6 +1827,7 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
|
|||||||
#if defined(DEBUG_GDS_ALLOC) && FALSE
|
#if defined(DEBUG_GDS_ALLOC) && FALSE
|
||||||
int node_type = node->nod_type;
|
int node_type = node->nod_type;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (node->nod_type) {
|
switch (node->nod_type) {
|
||||||
case nod_asn_list:
|
case nod_asn_list:
|
||||||
if (request->req_operation == req::req_evaluate) {
|
if (request->req_operation == req::req_evaluate) {
|
||||||
@ -1936,7 +1944,34 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
|
|||||||
case nod_abort:
|
case nod_abort:
|
||||||
switch (request->req_operation) {
|
switch (request->req_operation) {
|
||||||
case req::req_evaluate:
|
case req::req_evaluate:
|
||||||
set_error(tdbb, reinterpret_cast < xcp * >(node->nod_arg[0]));
|
{
|
||||||
|
XCP xcp_node = reinterpret_cast<XCP>(node->nod_arg[0]);
|
||||||
|
if (xcp_node)
|
||||||
|
{
|
||||||
|
/* XCP is defined,
|
||||||
|
so throw an exception */
|
||||||
|
set_error(tdbb, xcp_node, node->nod_arg[1]);
|
||||||
|
}
|
||||||
|
else if (request->req_last_xcp.xcp_type != 0)
|
||||||
|
{
|
||||||
|
/* XCP is undefined, but there was a known exception before,
|
||||||
|
so re-initiate it */
|
||||||
|
struct xcp last_error;
|
||||||
|
last_error.xcp_count = 1;
|
||||||
|
last_error.xcp_rpt[0].xcp_type = request->req_last_xcp.xcp_type;
|
||||||
|
last_error.xcp_rpt[0].xcp_code = request->req_last_xcp.xcp_code;
|
||||||
|
last_error.xcp_rpt[0].xcp_msg = request->req_last_xcp.xcp_msg;
|
||||||
|
request->req_last_xcp.xcp_type = 0;
|
||||||
|
request->req_last_xcp.xcp_msg = 0;
|
||||||
|
set_error(tdbb, &last_error, node->nod_arg[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* XCP is undefined and there weren't any exceptions before,
|
||||||
|
so just do nothing */
|
||||||
|
request->req_operation = req::req_return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
node = node->nod_parent;
|
node = node->nod_parent;
|
||||||
@ -2051,16 +2086,18 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
|
|||||||
end = ptr + handlers->nod_count; ptr < end;
|
end = ptr + handlers->nod_count; ptr < end;
|
||||||
ptr++)
|
ptr++)
|
||||||
{
|
{
|
||||||
const XCP pXcp =
|
const XCP xcp_node =
|
||||||
reinterpret_cast<XCP>((*ptr)->nod_arg[e_err_conditions]);
|
reinterpret_cast<XCP>((*ptr)->nod_arg[e_err_conditions]);
|
||||||
if (test_error(tdbb, pXcp))
|
if (test_and_fixup_error(tdbb, xcp_node, request))
|
||||||
{
|
{
|
||||||
request->req_operation = req::req_evaluate;
|
request->req_operation = req::req_evaluate;
|
||||||
node = (*ptr)->nod_arg[e_err_action];
|
node = (*ptr)->nod_arg[e_err_action];
|
||||||
error_pending = FALSE;
|
error_pending = FALSE;
|
||||||
|
|
||||||
/* On entering looper old_request etc. are saved.
|
/* On entering looper old_request etc. are saved.
|
||||||
On recursive calling we will loose the actual old
|
On recursive calling we will loose the actual old
|
||||||
request for that invocation of looper. Avoid this. */
|
request for that invocation of looper. Avoid this. */
|
||||||
|
|
||||||
tdbb->tdbb_default = old_pool;
|
tdbb->tdbb_default = old_pool;
|
||||||
tdbb->tdbb_request = old_request;
|
tdbb->tdbb_request = old_request;
|
||||||
|
|
||||||
@ -2091,8 +2128,10 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
|
|||||||
|
|
||||||
tdbb->tdbb_default = request->req_pool;
|
tdbb->tdbb_default = request->req_pool;
|
||||||
tdbb->tdbb_request = request;
|
tdbb->tdbb_request = request;
|
||||||
|
|
||||||
/* The error is dealt with by the application, cleanup
|
/* The error is dealt with by the application, cleanup
|
||||||
this block's savepoint. */
|
this block's savepoint. */
|
||||||
|
|
||||||
if (transaction != dbb->dbb_sys_trans)
|
if (transaction != dbb->dbb_sys_trans)
|
||||||
{
|
{
|
||||||
for (save_point = transaction->tra_save_point;
|
for (save_point = transaction->tra_save_point;
|
||||||
@ -2144,6 +2183,7 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
|
|||||||
node = node->nod_parent;
|
node = node->nod_parent;
|
||||||
if (request->req_operation == req::req_unwind)
|
if (request->req_operation == req::req_unwind)
|
||||||
node = node->nod_parent;
|
node = node->nod_parent;
|
||||||
|
request->req_last_xcp.xcp_type = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nod_label:
|
case nod_label:
|
||||||
@ -2788,10 +2828,12 @@ static NOD modify(TDBB tdbb, register NOD node, SSHORT which_trig)
|
|||||||
if (relation == request->req_top_view_modify) {
|
if (relation == request->req_top_view_modify) {
|
||||||
if (which_trig == ALL_TRIGS || which_trig == POST_TRIG) {
|
if (which_trig == ALL_TRIGS || which_trig == POST_TRIG) {
|
||||||
request->req_records_updated++;
|
request->req_records_updated++;
|
||||||
|
request->req_records_affected++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (relation->rel_file || !relation->rel_view_rse) {
|
else if (relation->rel_file || !relation->rel_view_rse) {
|
||||||
request->req_records_updated++;
|
request->req_records_updated++;
|
||||||
|
request->req_records_affected++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (which_trig != PRE_TRIG) {
|
if (which_trig != PRE_TRIG) {
|
||||||
@ -3374,7 +3416,7 @@ static NOD set_bookmark(TDBB tdbb, NOD node)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void set_error(TDBB tdbb, XCP condition)
|
static void set_error(TDBB tdbb, XCP condition, NOD node)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
@ -3388,9 +3430,32 @@ static void set_error(TDBB tdbb, XCP condition)
|
|||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
register REQ request;
|
register REQ request;
|
||||||
TEXT name[32], relation_name[32], message[82], *s, *r;
|
TEXT name[32], relation_name[32], message[82], temp[82], *s, *r;
|
||||||
|
UCHAR *string = 0;
|
||||||
|
USHORT length = 0;
|
||||||
|
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
|
|
||||||
|
if (condition->xcp_rpt[0].xcp_msg)
|
||||||
|
{
|
||||||
|
/* pick up message from already initiated exception */
|
||||||
|
length = condition->xcp_rpt[0].xcp_msg->str_length;
|
||||||
|
memcpy(message, condition->xcp_rpt[0].xcp_msg->str_data, length);
|
||||||
|
delete condition->xcp_rpt[0].xcp_msg;
|
||||||
|
condition->xcp_rpt[0].xcp_msg = 0;
|
||||||
|
}
|
||||||
|
else if (node)
|
||||||
|
{
|
||||||
|
/* evaluate exception message and convert it to string */
|
||||||
|
length = MOV_make_string(EVL_expr(tdbb, node),
|
||||||
|
ttype_none,
|
||||||
|
&string,
|
||||||
|
reinterpret_cast<VARY*>(temp),
|
||||||
|
sizeof(temp));
|
||||||
|
memcpy(message, string, length);
|
||||||
|
}
|
||||||
|
message[length] = 0;
|
||||||
|
|
||||||
request = tdbb->tdbb_request;
|
request = tdbb->tdbb_request;
|
||||||
|
|
||||||
switch (condition->xcp_rpt[0].xcp_type) {
|
switch (condition->xcp_rpt[0].xcp_type) {
|
||||||
@ -3414,9 +3479,11 @@ static void set_error(TDBB tdbb, XCP condition)
|
|||||||
|
|
||||||
case xcp_xcp_code:
|
case xcp_xcp_code:
|
||||||
MET_lookup_exception(tdbb, condition->xcp_rpt[0].xcp_code,
|
MET_lookup_exception(tdbb, condition->xcp_rpt[0].xcp_code,
|
||||||
name, message);
|
name, temp);
|
||||||
if (message[0])
|
if (message[0])
|
||||||
s = message;
|
s = message;
|
||||||
|
else if (temp[0])
|
||||||
|
s = temp;
|
||||||
else if (name[0])
|
else if (name[0])
|
||||||
s = name;
|
s = name;
|
||||||
else
|
else
|
||||||
@ -3629,10 +3696,12 @@ static NOD store(TDBB tdbb, register NOD node, SSHORT which_trig)
|
|||||||
if (relation == request->req_top_view_store) {
|
if (relation == request->req_top_view_store) {
|
||||||
if (which_trig == ALL_TRIGS || which_trig == POST_TRIG) {
|
if (which_trig == ALL_TRIGS || which_trig == POST_TRIG) {
|
||||||
request->req_records_inserted++;
|
request->req_records_inserted++;
|
||||||
|
request->req_records_affected++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (relation->rel_file || !relation->rel_view_rse) {
|
else if (relation->rel_file || !relation->rel_view_rse) {
|
||||||
request->req_records_inserted++;
|
request->req_records_inserted++;
|
||||||
|
request->req_records_affected++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transaction != dbb->dbb_sys_trans) {
|
if (transaction != dbb->dbb_sys_trans) {
|
||||||
@ -3729,29 +3798,48 @@ static NOD stream(TDBB tdbb, register NOD node)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static BOOLEAN test_error(TDBB tdbb, const XCP conditions)
|
static BOOLEAN test_and_fixup_error(TDBB tdbb, XCP conditions, REQ request)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
* t e s t _ e r r o r
|
* t e s t _ a n d _ f i x u p _ e r r o r
|
||||||
*
|
*
|
||||||
**************************************
|
**************************************
|
||||||
*
|
*
|
||||||
* Functional description
|
* Functional description
|
||||||
* Test for match of current state with list of error conditions.
|
* Test for match of current state with list of error conditions.
|
||||||
|
* Fix type and code of the exception.
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
|
SSHORT i, sqlcode;
|
||||||
|
STATUS *status_vector;
|
||||||
|
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
STATUS* status_vector = tdbb->tdbb_status_vector;
|
status_vector = tdbb->tdbb_status_vector;
|
||||||
SSHORT sqlcode = gds__sqlcode(status_vector);
|
sqlcode = gds__sqlcode(status_vector);
|
||||||
|
|
||||||
for (SSHORT i = 0; i < conditions->xcp_count; ++i)
|
const SLONG XCP_SQLCODE = -836;
|
||||||
|
|
||||||
|
delete request->req_last_xcp.xcp_msg;
|
||||||
|
request->req_last_xcp.xcp_msg = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < conditions->xcp_count; i++)
|
||||||
{
|
{
|
||||||
switch (conditions->xcp_rpt[i].xcp_type)
|
switch (conditions->xcp_rpt[i].xcp_type)
|
||||||
{
|
{
|
||||||
case xcp_sql_code:
|
case xcp_sql_code:
|
||||||
if (sqlcode == conditions->xcp_rpt[i].xcp_code) {
|
if (sqlcode == conditions->xcp_rpt[i].xcp_code)
|
||||||
|
{
|
||||||
|
if ((sqlcode != XCP_SQLCODE) || (status_vector[1] != gds_except))
|
||||||
|
{
|
||||||
|
request->req_last_xcp.xcp_type = xcp_sql_code;
|
||||||
|
request->req_last_xcp.xcp_code = sqlcode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
request->req_last_xcp.xcp_type = xcp_xcp_code;
|
||||||
|
request->req_last_xcp.xcp_code = status_vector[3];
|
||||||
|
}
|
||||||
status_vector[0] = 0;
|
status_vector[0] = 0;
|
||||||
status_vector[1] = 0;
|
status_vector[1] = 0;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -3759,7 +3847,10 @@ static BOOLEAN test_error(TDBB tdbb, const XCP conditions)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case xcp_gds_code:
|
case xcp_gds_code:
|
||||||
if (status_vector[1] == conditions->xcp_rpt[i].xcp_code) {
|
if (status_vector[1] == conditions->xcp_rpt[i].xcp_code)
|
||||||
|
{
|
||||||
|
request->req_last_xcp.xcp_type = xcp_gds_code;
|
||||||
|
request->req_last_xcp.xcp_code = status_vector[1];
|
||||||
status_vector[0] = 0;
|
status_vector[0] = 0;
|
||||||
status_vector[1] = 0;
|
status_vector[1] = 0;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -3770,6 +3861,16 @@ static BOOLEAN test_error(TDBB tdbb, const XCP conditions)
|
|||||||
if ((status_vector[1] == gds_except) &&
|
if ((status_vector[1] == gds_except) &&
|
||||||
(status_vector[3] == conditions->xcp_rpt[i].xcp_code))
|
(status_vector[3] == conditions->xcp_rpt[i].xcp_code))
|
||||||
{
|
{
|
||||||
|
request->req_last_xcp.xcp_type = xcp_xcp_code;
|
||||||
|
request->req_last_xcp.xcp_code = status_vector[3];
|
||||||
|
TEXT *msg = reinterpret_cast<TEXT*>(status_vector[7]);
|
||||||
|
if (msg)
|
||||||
|
{
|
||||||
|
USHORT len = strlen(msg);
|
||||||
|
request->req_last_xcp.xcp_msg = FB_NEW_RPT(*getDefaultMemoryPool(), len + 1) str();
|
||||||
|
request->req_last_xcp.xcp_msg->str_length = len;
|
||||||
|
memcpy(request->req_last_xcp.xcp_msg->str_data, msg, len + 1);
|
||||||
|
}
|
||||||
status_vector[0] = 0;
|
status_vector[0] = 0;
|
||||||
status_vector[1] = 0;
|
status_vector[1] = 0;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -3777,11 +3878,37 @@ static BOOLEAN test_error(TDBB tdbb, const XCP conditions)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case xcp_default:
|
case xcp_default:
|
||||||
|
if (sqlcode && (sqlcode != XCP_SQLCODE))
|
||||||
|
{
|
||||||
|
request->req_last_xcp.xcp_type = xcp_sql_code;
|
||||||
|
request->req_last_xcp.xcp_code = sqlcode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (status_vector[1] != gds_except)
|
||||||
|
{
|
||||||
|
request->req_last_xcp.xcp_type = xcp_gds_code;
|
||||||
|
request->req_last_xcp.xcp_code = status_vector[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
request->req_last_xcp.xcp_type = xcp_xcp_code;
|
||||||
|
request->req_last_xcp.xcp_code = status_vector[3];
|
||||||
|
TEXT *msg = reinterpret_cast<TEXT*>(status_vector[7]);
|
||||||
|
if (msg)
|
||||||
|
{
|
||||||
|
USHORT len = strlen(msg);
|
||||||
|
request->req_last_xcp.xcp_msg = FB_NEW_RPT(*getDefaultMemoryPool(), len + 1) str();
|
||||||
|
request->req_last_xcp.xcp_msg->str_length = len;
|
||||||
|
memcpy(request->req_last_xcp.xcp_msg->str_data, msg, len + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
status_vector[0] = 0;
|
status_vector[0] = 0;
|
||||||
status_vector[1] = 0;
|
status_vector[1] = 0;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,9 @@
|
|||||||
* Contributor(s): ______________________________________.
|
* Contributor(s): ______________________________________.
|
||||||
*
|
*
|
||||||
* 2001.07.28: Added rse_skip to struct rse to support LIMIT.
|
* 2001.07.28: Added rse_skip to struct rse to support LIMIT.
|
||||||
|
* 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
|
||||||
|
* exception handling in SPs/triggers,
|
||||||
|
* implemented ROWS_AFFECTED system variable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _JRD_EXE_H_
|
#ifndef _JRD_EXE_H_
|
||||||
@ -522,11 +525,11 @@ struct csb_repeat
|
|||||||
|
|
||||||
struct idx* csb_idx; /* Packed description of indices */
|
struct idx* csb_idx; /* Packed description of indices */
|
||||||
struct str* csb_idx_allocation; /* Memory allocated to hold index descriptions */
|
struct str* csb_idx_allocation; /* Memory allocated to hold index descriptions */
|
||||||
nod* csb_message; /* Msg for send/receive */
|
nod* csb_message; /* Msg for send/receive */
|
||||||
struct fmt* csb_format; /* Default fmt for stream */
|
struct fmt* csb_format; /* Default fmt for stream */
|
||||||
struct sbm* csb_fields; /* Fields referenced */
|
struct sbm* csb_fields; /* Fields referenced */
|
||||||
float csb_cardinality; /* Cardinality of relation */
|
float csb_cardinality; /* Cardinality of relation */
|
||||||
nod* csb_plan; /* user-specified plan for this relation */
|
nod* csb_plan; /* user-specified plan for this relation */
|
||||||
UCHAR* csb_map; /* Stream map for views */
|
UCHAR* csb_map; /* Stream map for views */
|
||||||
struct rsb** csb_rsb_ptr; /* point to rsb for nod_stream */
|
struct rsb** csb_rsb_ptr; /* point to rsb for nod_stream */
|
||||||
};
|
};
|
||||||
@ -607,12 +610,13 @@ typedef Csb* CSB;
|
|||||||
#define csb_update 16384 /* Erase or modify for relation */
|
#define csb_update 16384 /* Erase or modify for relation */
|
||||||
#define csb_made_river 32768 /* stream has been included in a river */
|
#define csb_made_river 32768 /* stream has been included in a river */
|
||||||
|
|
||||||
|
|
||||||
/* Exception condition list */
|
/* Exception condition list */
|
||||||
struct xcp_repeat {
|
|
||||||
SSHORT xcp_type;
|
struct xcp_repeat {
|
||||||
SLONG xcp_code;
|
SSHORT xcp_type;
|
||||||
};
|
SLONG xcp_code;
|
||||||
|
class str *xcp_msg;
|
||||||
|
};
|
||||||
|
|
||||||
class xcp : public pool_alloc_rpt<xcp_repeat, type_xcp>
|
class xcp : public pool_alloc_rpt<xcp_repeat, type_xcp>
|
||||||
{
|
{
|
||||||
|
40
src/jrd/misc_func_ids.h
Normal file
40
src/jrd/misc_func_ids.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* PROGRAM: Miscellaneous internal functions support (JRD layer)
|
||||||
|
* MODULE: misc_func_ids.h
|
||||||
|
* DESCRIPTION: Constants.
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Interbase Public
|
||||||
|
* License Version 1.0 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy
|
||||||
|
* of the License at http://www.Inprise.com/IPL.html
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an
|
||||||
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code was created by Inprise Corporation
|
||||||
|
* and its predecessors. Portions created by Inprise Corporation are
|
||||||
|
* Copyright (C) Inprise Corporation.
|
||||||
|
*
|
||||||
|
* All Rights Reserved.
|
||||||
|
* Contributor(s): ______________________________________
|
||||||
|
*
|
||||||
|
* 2002.09.20 Dmitry Yemanov: Created all this stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _JRD_MISC_FUNC_IDS_H_
|
||||||
|
#define _JRD_MISC_FUNC_IDS_H_
|
||||||
|
|
||||||
|
enum internal_info_id
|
||||||
|
{
|
||||||
|
internal_unknown = 0,
|
||||||
|
internal_connection_id = 1,
|
||||||
|
internal_transaction_id = 2,
|
||||||
|
internal_gdscode = 3,
|
||||||
|
internal_sqlcode = 4,
|
||||||
|
internal_rows_affected = 5,
|
||||||
|
max_internal_id
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _JRD_MISC_FUNC_IDS_H_
|
@ -23,9 +23,12 @@
|
|||||||
* 27-May-2001 Claudio Valderrama: par_plan() no longer uppercases
|
* 27-May-2001 Claudio Valderrama: par_plan() no longer uppercases
|
||||||
* an index's name before doing a lookup of such index.
|
* an index's name before doing a lookup of such index.
|
||||||
* 2001.07.28: Added parse code for blr_skip to support LIMIT.
|
* 2001.07.28: Added parse code for blr_skip to support LIMIT.
|
||||||
|
* 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
|
||||||
|
* exception handling in SPs/triggers,
|
||||||
|
* implemented ROWS_AFFECTED system variable
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
$Id: par.cpp,v 1.12 2002-09-25 17:12:10 skidder Exp $
|
$Id: par.cpp,v 1.13 2002-09-28 14:04:35 dimitr Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "firebird.h"
|
#include "firebird.h"
|
||||||
@ -783,9 +786,18 @@ static XCP par_condition(TDBB tdbb, CSB * csb)
|
|||||||
|
|
||||||
/* allocate a node to represent the conditions list */
|
/* allocate a node to represent the conditions list */
|
||||||
|
|
||||||
|
code_type = BLR_BYTE;
|
||||||
|
|
||||||
|
/* don't create XCP if blr_raise is used,
|
||||||
|
just return NULL */
|
||||||
|
if (code_type == blr_raise)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
exception_list = FB_NEW_RPT(*tdbb->tdbb_default, 1) xcp();
|
exception_list = FB_NEW_RPT(*tdbb->tdbb_default, 1) xcp();
|
||||||
exception_list->xcp_count = 1;
|
exception_list->xcp_count = 1;
|
||||||
code_type = BLR_BYTE;
|
|
||||||
switch (code_type) {
|
switch (code_type) {
|
||||||
case blr_sql_code:
|
case blr_sql_code:
|
||||||
exception_list->xcp_rpt[0].xcp_type = xcp_sql_code;
|
exception_list->xcp_rpt[0].xcp_type = xcp_sql_code;
|
||||||
@ -805,6 +817,7 @@ static XCP par_condition(TDBB tdbb, CSB * csb)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case blr_exception:
|
case blr_exception:
|
||||||
|
case blr_exception_msg:
|
||||||
exception_list->xcp_rpt[0].xcp_type = xcp_xcp_code;
|
exception_list->xcp_rpt[0].xcp_type = xcp_xcp_code;
|
||||||
par_name(csb, name);
|
par_name(csb, name);
|
||||||
if (!(exception_list->xcp_rpt[0].xcp_code =
|
if (!(exception_list->xcp_rpt[0].xcp_code =
|
||||||
@ -823,6 +836,8 @@ static XCP par_condition(TDBB tdbb, CSB * csb)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exception_list->xcp_rpt[0].xcp_msg = 0;
|
||||||
|
|
||||||
return exception_list;
|
return exception_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2632,8 +2647,15 @@ static NOD parse(TDBB tdbb, register CSB * csb, USHORT expected)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case blr_abort:
|
case blr_abort:
|
||||||
|
{
|
||||||
|
bool flag = (BLR_PEEK == blr_exception_msg);
|
||||||
node->nod_arg[0] = (NOD) par_condition(tdbb, csb);
|
node->nod_arg[0] = (NOD) par_condition(tdbb, csb);
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
node->nod_arg[1] = parse(tdbb, csb, sub_type);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case blr_if:
|
case blr_if:
|
||||||
node->nod_arg[e_if_boolean] = parse(tdbb, csb, BOOL);
|
node->nod_arg[e_if_boolean] = parse(tdbb, csb, BOOL);
|
||||||
|
@ -19,6 +19,10 @@
|
|||||||
*
|
*
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
* Contributor(s): ______________________________________.
|
* Contributor(s): ______________________________________.
|
||||||
|
*
|
||||||
|
* 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
|
||||||
|
* exception handling in SPs/triggers,
|
||||||
|
* implemented ROWS_AFFECTED system variable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _JRD_REQ_H_
|
#ifndef _JRD_REQ_H_
|
||||||
@ -27,6 +31,8 @@
|
|||||||
#include "../jrd/jrd_blks.h"
|
#include "../jrd/jrd_blks.h"
|
||||||
#include "../include/fb_blk.h"
|
#include "../include/fb_blk.h"
|
||||||
|
|
||||||
|
#include "../jrd/exe.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/* record parameter block */
|
/* record parameter block */
|
||||||
@ -151,6 +157,8 @@ public:
|
|||||||
ULONG req_records_updated; /* count of records updated by request */
|
ULONG req_records_updated; /* count of records updated by request */
|
||||||
ULONG req_records_deleted; /* count of records deleted by request */
|
ULONG req_records_deleted; /* count of records deleted by request */
|
||||||
|
|
||||||
|
ULONG req_records_affected; /* count of records affected by the last statement */
|
||||||
|
|
||||||
USHORT req_view_flags; /* special flags for virtual ops on views */
|
USHORT req_view_flags; /* special flags for virtual ops on views */
|
||||||
struct rel* req_top_view_store; /* the top view in store(), if any */
|
struct rel* req_top_view_store; /* the top view in store(), if any */
|
||||||
struct rel* req_top_view_modify; /* the top view in modify(), if any */
|
struct rel* req_top_view_modify; /* the top view in modify(), if any */
|
||||||
@ -175,6 +183,8 @@ public:
|
|||||||
req_unwind
|
req_unwind
|
||||||
} req_operation; /* operation for next node */
|
} req_operation; /* operation for next node */
|
||||||
|
|
||||||
|
struct xcp_repeat req_last_xcp; /* last known exception */
|
||||||
|
|
||||||
rpb req_rpb[1]; /* record parameter blocks */
|
rpb req_rpb[1]; /* record parameter blocks */
|
||||||
};
|
};
|
||||||
typedef req *REQ;
|
typedef req *REQ;
|
||||||
|
Loading…
Reference in New Issue
Block a user