mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 06:03:02 +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.
|
||||
@ -2046,6 +2046,7 @@ void DSQL_pretty(NOD node, int column)
|
||||
verb = "insert";
|
||||
break;
|
||||
case nod_internal_info:
|
||||
case nod_proc_internal_info:
|
||||
verb = "internal info";
|
||||
break;
|
||||
case nod_join:
|
||||
|
@ -246,3 +246,4 @@
|
||||
#define USING 502
|
||||
#define NULLS 503
|
||||
#define LAST 504
|
||||
#define ROWS_AFFECTED 505
|
||||
|
@ -20,12 +20,14 @@
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________
|
||||
* 2001.6.21 Claudio Valderrama: BREAK and SUBSTRING.
|
||||
* 2001.07.28: John Bellardo: Added code to generate blr_skip.
|
||||
* 2002.07.30: Arno Brinkman: Added code, procedures to generate COALESCE, CASE
|
||||
*
|
||||
* 2001.07.28 John Bellardo: Added code to generate blr_skip.
|
||||
* 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"
|
||||
@ -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/make_proto.h"
|
||||
#include "../dsql/metd_proto.h"
|
||||
#include "../dsql/misc_func.h"
|
||||
#include "../jrd/thd_proto.h"
|
||||
#include "../jrd/dsc_proto.h"
|
||||
#include "gen/iberror.h"
|
||||
@ -83,15 +86,6 @@ static CONST SCHAR db_key_name[] = "DB_KEY";
|
||||
#define NEGATE_VALUE TRUE
|
||||
#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)
|
||||
{
|
||||
/**************************************
|
||||
@ -440,6 +434,7 @@ void GEN_expr( REQ request, NOD node)
|
||||
break;
|
||||
|
||||
case nod_internal_info:
|
||||
case nod_proc_internal_info:
|
||||
operator_ = blr_internal_info;
|
||||
break;
|
||||
case nod_upcase:
|
||||
@ -889,8 +884,7 @@ void GEN_statement( REQ request, NOD node)
|
||||
NOD temp, *ptr, *end;
|
||||
CTX context;
|
||||
MSG message;
|
||||
STR name;
|
||||
STR string;
|
||||
STR name, string;
|
||||
TEXT *p;
|
||||
ULONG id_length;
|
||||
|
||||
@ -1048,8 +1042,8 @@ void GEN_statement( REQ request, NOD node)
|
||||
return;
|
||||
|
||||
case nod_breakleave:
|
||||
STUFF (blr_leave);
|
||||
STUFF ((int) node->nod_arg [e_break_number]);
|
||||
STUFF(blr_leave);
|
||||
STUFF((int) node->nod_arg[e_break_number]);
|
||||
return;
|
||||
|
||||
case nod_store:
|
||||
@ -1077,17 +1071,46 @@ void GEN_statement( REQ request, NOD node)
|
||||
|
||||
case nod_exception_stmt:
|
||||
STUFF(blr_abort);
|
||||
STUFF(blr_exception);
|
||||
string = (STR) node->nod_arg[0];
|
||||
if (!(string->str_flags & STR_delimited_id)) {
|
||||
string = (STR) node->nod_arg[e_xcp_name];
|
||||
temp = node->nod_arg[e_xcp_msg];
|
||||
/* 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;
|
||||
for (p = reinterpret_cast < char *>(string->str_data); *p;
|
||||
id_length--) {
|
||||
for (p = reinterpret_cast<char*>(string->str_data); *p;
|
||||
id_length--)
|
||||
{
|
||||
*p = UPPER(*p);
|
||||
*p++;
|
||||
}
|
||||
}
|
||||
STUFF_CSTRING(string->str_data);
|
||||
/* if exception value is defined,
|
||||
generate appropriate BLR verbs */
|
||||
if (temp)
|
||||
{
|
||||
GEN_expr(request, temp);
|
||||
}
|
||||
return;
|
||||
|
||||
case nod_while:
|
||||
@ -2198,20 +2221,11 @@ static void gen_select( REQ request, NOD rse)
|
||||
parameter->par_name = parameter->par_alias = "USER";
|
||||
else if (item->nod_type == nod_current_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 =
|
||||
*reinterpret_cast<internal_info_req*>(item->nod_arg[0]->nod_desc.dsc_address);
|
||||
|
||||
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;
|
||||
}
|
||||
internal_info_id id =
|
||||
*reinterpret_cast<internal_info_id*>(item->nod_arg[0]->nod_desc.dsc_address);
|
||||
parameter->par_name = parameter->par_alias = InternalInfo::getAlias(id);
|
||||
}
|
||||
else if (item->nod_type == nod_substr) {
|
||||
/* CVC: SQL starts at 1 but C starts at zero. */
|
||||
|
@ -28,7 +28,7 @@
|
||||
* 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},
|
||||
{ROLE, "ROLE", 1},
|
||||
{ROLLBACK, "ROLLBACK", 1},
|
||||
{ROWS_AFFECTED, "ROWS_AFFECTED", 2},
|
||||
{DATABASE, "SCHEMA", 1}, /* Alias of DATABASE */
|
||||
{SECOND, "SECOND", 2},
|
||||
{SEGMENT, "SEGMENT", 1},
|
||||
|
@ -929,6 +929,7 @@ void MAKE_desc( DSC * desc, NOD node)
|
||||
return;
|
||||
|
||||
case nod_internal_info:
|
||||
case nod_proc_internal_info:
|
||||
desc->dsc_dtype = dtype_long;
|
||||
desc->dsc_scale = 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_exec_sql, /* EXECUTE VARCHAR */
|
||||
nod_internal_info, /* internal engine info */
|
||||
nod_proc_internal_info,
|
||||
nod_searched_case, /* searched CASE function */
|
||||
nod_simple_case, /* simple CASE function */
|
||||
nod_coalesce, /* COALESCE function */
|
||||
@ -436,6 +437,10 @@ typedef nod *NOD;
|
||||
#define e_internal_info 0 /* nod_internal_info */
|
||||
#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_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.31 Dmitry Yemanov: allowed user-defined index names for PK/FK/UK constraints
|
||||
* 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)
|
||||
#include <windows.h>
|
||||
/*#include <wincon.h>*/
|
||||
@ -78,9 +80,9 @@
|
||||
#include "../dsql/make_proto.h"
|
||||
#include "../dsql/parse_proto.h"
|
||||
#include "../dsql/keywords.h"
|
||||
#include "../dsql/misc_func.h"
|
||||
#include "../jrd/gds_proto.h"
|
||||
#include "../jrd/thd_proto.h"
|
||||
/* #include "../jrd/err_proto.h" */
|
||||
#include "../wal/wal.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 NULLS
|
||||
%token LAST
|
||||
%token ROWS_AFFECTED
|
||||
|
||||
/* precedence declarations for expression evaluation */
|
||||
|
||||
@ -1434,23 +1437,18 @@ proc_block : proc_statement
|
||||
| full_proc_block
|
||||
;
|
||||
|
||||
full_proc_block : BEGIN
|
||||
END
|
||||
{ $$ = make_node (nod_block, e_blk_count,
|
||||
NULL, NULL);}
|
||||
| BEGIN
|
||||
proc_statements
|
||||
END
|
||||
{ $$ = make_node (nod_block, e_blk_count,
|
||||
make_list ($2), NULL);}
|
||||
| BEGIN
|
||||
proc_statements
|
||||
excp_statements
|
||||
END
|
||||
{ $$ = make_node (nod_block, e_blk_count,
|
||||
make_list ($2), make_list ($3));}
|
||||
full_proc_block : BEGIN full_proc_block_body END
|
||||
{ $$ = $2; }
|
||||
;
|
||||
|
||||
full_proc_block_body : proc_statements
|
||||
{ $$ = make_node (nod_block, e_blk_count, make_list ($1), NULL); }
|
||||
| proc_statements excp_hndl_statements
|
||||
{ $$ = make_node (nod_block, e_blk_count, make_list ($1), make_list ($2)); }
|
||||
|
|
||||
{ $$ = make_node (nod_block, e_blk_count, NULL, NULL);}
|
||||
;
|
||||
|
||||
proc_statements : proc_block
|
||||
| proc_statements proc_block
|
||||
{ $$ = make_node (nod_list, 2, $1, $2); }
|
||||
@ -1458,8 +1456,8 @@ proc_statements : proc_block
|
||||
|
||||
proc_statement : assignment ';'
|
||||
| delete ';'
|
||||
| EXCEPTION symbol_exception_name ';'
|
||||
{ $$ = make_node (nod_exception_stmt, 1, $2); }
|
||||
| excp_statement
|
||||
| raise_statement
|
||||
| exec_procedure
|
||||
| exec_sql
|
||||
| for_select
|
||||
@ -1478,6 +1476,16 @@ proc_statement : assignment ';'
|
||||
{ $$ = 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 ';'
|
||||
{ $$ = make_node (nod_exec_procedure, e_exe_count, $3,
|
||||
$4, $5); }
|
||||
@ -1542,12 +1550,12 @@ cursor_def : AS CURSOR symbol_cursor_name
|
||||
|
|
||||
{ $$ = NULL; }
|
||||
;
|
||||
excp_statements : excp_statement
|
||||
| excp_statements excp_statement
|
||||
excp_hndl_statements : excp_hndl_statement
|
||||
| excp_hndl_statements excp_hndl_statement
|
||||
{ $$ = 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_list ($2), $4); }
|
||||
;
|
||||
@ -3319,6 +3327,8 @@ value : column_name
|
||||
| current_role
|
||||
| internal_info
|
||||
{ $$ = $1; }
|
||||
| proc_internal_info
|
||||
{ $$ = $1; }
|
||||
| DB_KEY
|
||||
{ $$ = make_node (nod_dbkey, 1, NULL); }
|
||||
| symbol_table_alias_name '.' DB_KEY
|
||||
@ -3433,24 +3443,6 @@ u_constant : u_numeric_constant
|
||||
{ $$ = 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 : '?'
|
||||
{ $$ = make_node (nod_parameter, 0, NULL); }
|
||||
;
|
||||
@ -3467,10 +3459,21 @@ current_role : CURRENT_ROLE
|
||||
|
||||
internal_info : CONNECTION_ID
|
||||
{ $$ = 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
|
||||
{ $$ = 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 */
|
||||
|
@ -95,6 +95,10 @@
|
||||
* 2002.08.07 Dmitry Yemanov: Disabled BREAK statement in triggers
|
||||
*
|
||||
* 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"
|
||||
@ -116,6 +120,7 @@
|
||||
#include "../dsql/make_proto.h"
|
||||
#include "../dsql/metd_proto.h"
|
||||
#include "../dsql/pass1_proto.h"
|
||||
#include "../dsql/misc_func.h"
|
||||
#include "../jrd/dsc_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;
|
||||
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:
|
||||
break;
|
||||
}
|
||||
@ -1173,7 +1188,20 @@ NOD PASS1_statement(REQ request, NOD input, USHORT proc_flag)
|
||||
|
||||
case nod_exception_stmt:
|
||||
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->nod_arg[0] = MAKE_node(nod_start_savepoint, 0);
|
||||
temp->nod_arg[1] = input;
|
||||
@ -1756,6 +1784,7 @@ static NOD copy_field( NOD field, CTX context)
|
||||
case nod_subtract2:
|
||||
case nod_upcase:
|
||||
case nod_internal_info:
|
||||
case nod_proc_internal_info:
|
||||
case nod_extract:
|
||||
case nod_list:
|
||||
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_current_role:
|
||||
case nod_internal_info:
|
||||
case nod_proc_internal_info:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,9 @@
|
||||
* Contributor(s): ______________________________________.
|
||||
*
|
||||
* 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_
|
||||
@ -65,6 +68,8 @@
|
||||
#define blr_exception (unsigned char)2
|
||||
#define blr_trigger_code (unsigned char)3
|
||||
#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_version5 (unsigned char)5
|
||||
|
@ -28,9 +28,12 @@
|
||||
* if source is blob and should check implementation limits on field lengths.
|
||||
* 2002.02.25 Claudio Valderrama: concatenate() should be a civilized function.
|
||||
* 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"
|
||||
@ -299,6 +302,9 @@ REQ DLL_EXPORT CMP_clone_request(TDBB tdbb,
|
||||
clone->req_top_node = request->req_top_node;
|
||||
clone->req_trg_name = request->req_trg_name;
|
||||
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;
|
||||
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_variables = csb->csb_variables;
|
||||
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) {
|
||||
request->req_flags |= req_blr_version4;
|
||||
}
|
||||
@ -2151,6 +2159,8 @@ void DLL_EXPORT CMP_release(TDBB tdbb, REQ request)
|
||||
break;
|
||||
}
|
||||
|
||||
delete request->req_last_xcp.xcp_msg;
|
||||
|
||||
delete request->req_pool;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* 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.04.16 Paul Beach HP10 Port - (UCHAR*) desc.dsc_address = p; modified for HP
|
||||
* Compiler
|
||||
* 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
|
||||
* exception handling in SPs/triggers,
|
||||
* implemented ROWS_AFFECTED system variable
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
@ -105,6 +108,7 @@
|
||||
#include "../jrd/align.h"
|
||||
#include "../jrd/met_proto.h"
|
||||
#include "../jrd/cvt_proto.h"
|
||||
#include "../jrd/misc_func_ids.h"
|
||||
//#include "../jrd/authenticate.h"
|
||||
|
||||
#if defined(WIN_NT) && defined(_MSC_VER)
|
||||
@ -126,15 +130,6 @@
|
||||
extern double MTH$CVT_D_G(), MTH$CVT_G_D();
|
||||
#endif
|
||||
|
||||
/* Internal info request types */
|
||||
|
||||
enum internal_info_req
|
||||
{
|
||||
connection_id = 1,
|
||||
transaction_id = 2
|
||||
};
|
||||
|
||||
|
||||
/* *** DANGER DANGER WILL ROBINSON ***
|
||||
* 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.
|
||||
@ -3931,7 +3926,6 @@ static DSC *lock_state(TDBB tdbb, NOD node, VLU impure)
|
||||
struct lck temp_lock;
|
||||
/* 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_type = LCK_attachment;
|
||||
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);
|
||||
|
||||
internal_info_req request =
|
||||
*reinterpret_cast<internal_info_req*>(impure->vlu_desc.dsc_address);
|
||||
internal_info_id id =
|
||||
*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();
|
||||
break;
|
||||
case transaction_id:
|
||||
case internal_transaction_id:
|
||||
impure->vlu_misc.vlu_long = tdbb->tdbb_transaction->tra_number;
|
||||
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:
|
||||
BUGCHECK(232); /* msg 232 EVL_expr: invalid operation */
|
||||
}
|
||||
|
165
src/jrd/exe.cpp
165
src/jrd/exe.cpp
@ -29,9 +29,12 @@
|
||||
* being reported instead of one.
|
||||
* 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.
|
||||
* 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"
|
||||
@ -129,10 +132,10 @@ static void seek_rsb(TDBB, REQ, RSB, USHORT, SLONG);
|
||||
#endif
|
||||
static NOD selct(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 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 validate(TDBB, NOD);
|
||||
|
||||
@ -215,7 +218,6 @@ private:
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
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 (which_trig == ALL_TRIGS || which_trig == POST_TRIG) {
|
||||
request->req_records_deleted++;
|
||||
request->req_records_affected++;
|
||||
}
|
||||
}
|
||||
else if (relation->rel_file || !relation->rel_view_rse) {
|
||||
request->req_records_deleted++;
|
||||
request->req_records_affected++;
|
||||
}
|
||||
|
||||
if (transaction != dbb->dbb_sys_trans) {
|
||||
@ -1293,6 +1297,7 @@ static void execute_looper(
|
||||
|
||||
request->req_flags &= ~req_stall;
|
||||
request->req_operation = next_state;
|
||||
|
||||
looper(tdbb, request, request->req_next);
|
||||
|
||||
/* 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
|
||||
|
||||
request->req_records_affected = 0;
|
||||
|
||||
while (node && !(request->req_flags & req_stall))
|
||||
{
|
||||
try {
|
||||
@ -1820,6 +1827,7 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
|
||||
#if defined(DEBUG_GDS_ALLOC) && FALSE
|
||||
int node_type = node->nod_type;
|
||||
#endif
|
||||
|
||||
switch (node->nod_type) {
|
||||
case nod_asn_list:
|
||||
if (request->req_operation == req::req_evaluate) {
|
||||
@ -1936,7 +1944,34 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
|
||||
case nod_abort:
|
||||
switch (request->req_operation) {
|
||||
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:
|
||||
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;
|
||||
ptr++)
|
||||
{
|
||||
const XCP pXcp =
|
||||
const XCP xcp_node =
|
||||
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;
|
||||
node = (*ptr)->nod_arg[e_err_action];
|
||||
error_pending = FALSE;
|
||||
|
||||
/* On entering looper old_request etc. are saved.
|
||||
On recursive calling we will loose the actual old
|
||||
request for that invocation of looper. Avoid this. */
|
||||
|
||||
tdbb->tdbb_default = old_pool;
|
||||
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_request = request;
|
||||
|
||||
/* The error is dealt with by the application, cleanup
|
||||
this block's savepoint. */
|
||||
|
||||
if (transaction != dbb->dbb_sys_trans)
|
||||
{
|
||||
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;
|
||||
if (request->req_operation == req::req_unwind)
|
||||
node = node->nod_parent;
|
||||
request->req_last_xcp.xcp_type = 0;
|
||||
break;
|
||||
|
||||
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 (which_trig == ALL_TRIGS || which_trig == POST_TRIG) {
|
||||
request->req_records_updated++;
|
||||
request->req_records_affected++;
|
||||
}
|
||||
}
|
||||
else if (relation->rel_file || !relation->rel_view_rse) {
|
||||
request->req_records_updated++;
|
||||
request->req_records_affected++;
|
||||
}
|
||||
|
||||
if (which_trig != PRE_TRIG) {
|
||||
@ -3374,7 +3416,7 @@ static NOD set_bookmark(TDBB tdbb, NOD node)
|
||||
#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;
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
switch (condition->xcp_rpt[0].xcp_type) {
|
||||
@ -3414,9 +3479,11 @@ static void set_error(TDBB tdbb, XCP condition)
|
||||
|
||||
case xcp_xcp_code:
|
||||
MET_lookup_exception(tdbb, condition->xcp_rpt[0].xcp_code,
|
||||
name, message);
|
||||
name, temp);
|
||||
if (message[0])
|
||||
s = message;
|
||||
else if (temp[0])
|
||||
s = temp;
|
||||
else if (name[0])
|
||||
s = name;
|
||||
else
|
||||
@ -3629,10 +3696,12 @@ static NOD store(TDBB tdbb, register NOD node, SSHORT which_trig)
|
||||
if (relation == request->req_top_view_store) {
|
||||
if (which_trig == ALL_TRIGS || which_trig == POST_TRIG) {
|
||||
request->req_records_inserted++;
|
||||
request->req_records_affected++;
|
||||
}
|
||||
}
|
||||
else if (relation->rel_file || !relation->rel_view_rse) {
|
||||
request->req_records_inserted++;
|
||||
request->req_records_affected++;
|
||||
}
|
||||
|
||||
if (transaction != dbb->dbb_sys_trans) {
|
||||
@ -3729,29 +3798,48 @@ static NOD stream(TDBB tdbb, register NOD node)
|
||||
#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
|
||||
* 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);
|
||||
STATUS* status_vector = tdbb->tdbb_status_vector;
|
||||
SSHORT sqlcode = gds__sqlcode(status_vector);
|
||||
status_vector = tdbb->tdbb_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)
|
||||
{
|
||||
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[1] = 0;
|
||||
return TRUE;
|
||||
@ -3759,7 +3847,10 @@ static BOOLEAN test_error(TDBB tdbb, const XCP conditions)
|
||||
break;
|
||||
|
||||
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[1] = 0;
|
||||
return TRUE;
|
||||
@ -3770,6 +3861,16 @@ static BOOLEAN test_error(TDBB tdbb, const XCP conditions)
|
||||
if ((status_vector[1] == gds_except) &&
|
||||
(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[1] = 0;
|
||||
return TRUE;
|
||||
@ -3777,11 +3878,37 @@ static BOOLEAN test_error(TDBB tdbb, const XCP conditions)
|
||||
break;
|
||||
|
||||
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[1] = 0;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -21,6 +21,9 @@
|
||||
* Contributor(s): ______________________________________.
|
||||
*
|
||||
* 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_
|
||||
@ -522,11 +525,11 @@ struct csb_repeat
|
||||
|
||||
struct idx* csb_idx; /* Packed description of indices */
|
||||
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 sbm* csb_fields; /* Fields referenced */
|
||||
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 */
|
||||
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_made_river 32768 /* stream has been included in a river */
|
||||
|
||||
|
||||
/* Exception condition list */
|
||||
struct xcp_repeat {
|
||||
SSHORT xcp_type;
|
||||
SLONG xcp_code;
|
||||
};
|
||||
|
||||
struct xcp_repeat {
|
||||
SSHORT xcp_type;
|
||||
SLONG xcp_code;
|
||||
class str *xcp_msg;
|
||||
};
|
||||
|
||||
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
|
||||
* an index's name before doing a lookup of such index.
|
||||
* 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"
|
||||
@ -783,9 +786,18 @@ static XCP par_condition(TDBB tdbb, CSB * csb)
|
||||
|
||||
/* 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->xcp_count = 1;
|
||||
code_type = BLR_BYTE;
|
||||
|
||||
switch (code_type) {
|
||||
case blr_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;
|
||||
|
||||
case blr_exception:
|
||||
case blr_exception_msg:
|
||||
exception_list->xcp_rpt[0].xcp_type = xcp_xcp_code;
|
||||
par_name(csb, name);
|
||||
if (!(exception_list->xcp_rpt[0].xcp_code =
|
||||
@ -823,6 +836,8 @@ static XCP par_condition(TDBB tdbb, CSB * csb)
|
||||
break;
|
||||
}
|
||||
|
||||
exception_list->xcp_rpt[0].xcp_msg = 0;
|
||||
|
||||
return exception_list;
|
||||
}
|
||||
|
||||
@ -2632,8 +2647,15 @@ static NOD parse(TDBB tdbb, register CSB * csb, USHORT expected)
|
||||
break;
|
||||
|
||||
case blr_abort:
|
||||
{
|
||||
bool flag = (BLR_PEEK == blr_exception_msg);
|
||||
node->nod_arg[0] = (NOD) par_condition(tdbb, csb);
|
||||
if (flag)
|
||||
{
|
||||
node->nod_arg[1] = parse(tdbb, csb, sub_type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case blr_if:
|
||||
node->nod_arg[e_if_boolean] = parse(tdbb, csb, BOOL);
|
||||
|
@ -19,6 +19,10 @@
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* 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_
|
||||
@ -27,6 +31,8 @@
|
||||
#include "../jrd/jrd_blks.h"
|
||||
#include "../include/fb_blk.h"
|
||||
|
||||
#include "../jrd/exe.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/* record parameter block */
|
||||
@ -151,6 +157,8 @@ public:
|
||||
ULONG req_records_updated; /* count of records updated 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 */
|
||||
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 */
|
||||
@ -175,6 +183,8 @@ public:
|
||||
req_unwind
|
||||
} req_operation; /* operation for next node */
|
||||
|
||||
struct xcp_repeat req_last_xcp; /* last known exception */
|
||||
|
||||
rpb req_rpb[1]; /* record parameter blocks */
|
||||
};
|
||||
typedef req *REQ;
|
||||
|
Loading…
Reference in New Issue
Block a user